📄 mtxl.c
字号:
flags->elementtype=StorageElement; /* sigh! */ DataBuffer=SendElementStatusRequest(MediumChangerFD,RequestSense, inquiry_info,flags, mode_sense->StorageStart, /* adjust for import/export. */ mode_sense->NumStorage-mode_sense->NumImportExport, mode_sense->MaxReadElementStatusData); if (!DataBuffer) { /* darn. Free up stuff and return. */ /****FIXME**** do a free on element data! */ FreeElementData(ElementStatus); return NULL; } ParseElementStatus(EmptyStorageElementAddress,&EmptyStorageElementCount, DataBuffer,ElementStatus,mode_sense); free(DataBuffer); /* sigh! */ /* --------------IMPORT/EXPORT--------------- */ /* Next let's see if we need to do Import/Export: */ if (mode_sense->NumImportExport > 0) { flags->elementtype=ImportExportElement; DataBuffer=SendElementStatusRequest(MediumChangerFD,RequestSense, inquiry_info,flags, mode_sense->ImportExportStart, mode_sense->NumImportExport, mode_sense->MaxReadElementStatusData); if (!DataBuffer) { /* darn. Free up stuff and return. */ /****FIXME**** do a free on element data! */ FreeElementData(ElementStatus); return NULL; } ParseElementStatus(EmptyStorageElementAddress,&EmptyStorageElementCount, DataBuffer,ElementStatus,mode_sense); } /* ----------------- DRIVES ---------------------- */ flags->elementtype=DataTransferElement; /* sigh! */ DataBuffer=SendElementStatusRequest(MediumChangerFD,RequestSense, inquiry_info,flags, mode_sense->DataTransferStart, mode_sense->NumDataTransfer, mode_sense->MaxReadElementStatusData); if (!DataBuffer) { /* darn. Free up stuff and return. */ /****FIXME**** do a free on element data! */ FreeElementData(ElementStatus); return NULL; } ParseElementStatus(EmptyStorageElementAddress,&EmptyStorageElementCount, DataBuffer,ElementStatus,mode_sense); free(DataBuffer); /* sigh! */ /* ----------------- Robot Arm(s) -------------------------- */ /* grr, damned brain dead HP doesn't report that it has any! */ if (!mode_sense->NumMediumTransport) { ElementStatus->TransportElementAddress=0; /* default it sensibly :-(. */ } else { flags->elementtype=MediumTransportElement; /* sigh! */ DataBuffer=SendElementStatusRequest(MediumChangerFD,RequestSense, inquiry_info,flags, mode_sense->MediumTransportStart, 1, /* only get 1, sigh. */ mode_sense->MaxReadElementStatusData); if (!DataBuffer) { /* darn. Free up stuff and return. */ /****FIXME**** do a free on element data! */ FreeElementData(ElementStatus); return NULL; } ParseElementStatus(EmptyStorageElementAddress,&EmptyStorageElementCount, DataBuffer,ElementStatus,mode_sense); free(DataBuffer); /* sigh! */ } /*---------------------- Sanity Checking ------------------- */ if (!ElementStatus->DataTransferElementCount) FatalError("no Data Transfer Element reported\n"); if (ElementStatus->StorageElementCount == 0) FatalError("no Storage Elements reported\n"); /* ---------------------- Reset SourceStorageElementNumbers ------- */ /* okay, re-write the SourceStorageElementNumber code *AGAIN*. * Pass1: * Translate from raw element # to our translated # (if possible). * First, check the SourceStorageElementNumbers against the list of * filled slots. If the slots indicated are empty, we accept that list as * valid. Otherwise decide the SourceStorageElementNumbers are invalid. * * Pass2: * * If we had some invalid (or unknown) SourceStorageElementNumbers * then we must search for free slots, and assign SourceStorageElementNumbers * to those free slots. We happen to already built a list of free * slots as part of the process of reading the storage element numbers * from the tape. So that's easy enough to do! */#ifdef DEBUG_TAPELIST fprintf(stderr,"empty slots: %d\n",EmptyStorageElementCount); if (EmptyStorageElementCount) { for (i=0; i<EmptyStorageElementCount; i++) { fprintf(stderr,"empty: %d\n",EmptyStorageElementAddress[i]); } }#endif /* Okay, now we re-assign origin slots if the "real" origin slot * is obviously defective: */ /* pass one: */ invalid_sources=0; /* no invalid sources yet! */ for (i=0;i<ElementStatus->DataTransferElementCount;i++) { int elnum; int translated_elnum = -1; /* if we have an element, then ... */ if (ElementStatus->DataTransferElementFull[i]) { elnum=ElementStatus->DataTransferElementSourceStorageElementNumber[i]; /* if we have an element number, then ... */ if (elnum >= 0) { /* Now to translate the elnum: */ for (j=0; j<ElementStatus->StorageElementCount; j++) { if (elnum == ElementStatus->StorageElementAddress[j]) { translated_elnum=j; } } /* now see if the element # is already occupied: */ if (ElementStatus->StorageElementFull[translated_elnum]) { invalid_sources=1; break; /* break out of the loop! */ } else { /* properly set the source... */ ElementStatus->DataTransferElementSourceStorageElementNumber[i]= translated_elnum; } } else { /* if element # was not >=0, then we had an invalid source anyhow! */ invalid_sources=1; } } }#ifdef DEBUG_TAPELIST fprintf(stderr,"invalid_sources=%d\n",invalid_sources);#endif /* Pass2: */ /* okay, we have invalid sources, so let's see what they should be: */ /* Note: If EmptyStorageElementCount is < # of drives, the leftover * drives will be assigned a -1 (see the initialization loop for * EmptyStorageElementAddress above), which will be reported as "slot 0" * by the user interface. This is an invalid value, but more useful for us * to have than just crapping out here :-(. */ if (invalid_sources) { empty_idx=0; for (i=0;i<ElementStatus->DataTransferElementCount;i++) { if (ElementStatus->DataTransferElementFull[i]) {#ifdef DEBUG_TAPELIST fprintf(stderr,"for drive %d, changing source %d to %d (empty slot #%d)\n", i, ElementStatus->DataTransferElementSourceStorageElementNumber[i], EmptyStorageElementAddress[empty_idx], empty_idx);#endif ElementStatus->DataTransferElementSourceStorageElementNumber[i]= EmptyStorageElementAddress[empty_idx++]; } } } /* and done! */ free(mode_sense); free(EmptyStorageElementAddress); return ElementStatus; }/*************************************************************************//* Now the actual media movement routine! */RequestSense_T *MoveMedium(DEVICE_TYPE MediumChangerFD, int SourceAddress, int DestinationAddress, ElementStatus_T *ElementStatus, Inquiry_T *inquiry_info, SCSI_Flags_T *flags){ RequestSense_T *RequestSense = xmalloc(sizeof(RequestSense_T)); CDB_T CDB; if ((inquiry_info->MChngr) && (inquiry_info->PeripheralDeviceType != MEDIUM_CHANGER_TYPE)) { /* if using the ATTACHED API */ CDB[0]=0xA7; /* MOVE_MEDIUM_ATTACHED */ } else { CDB[0] = 0xA5; /* MOVE MEDIUM */ } CDB[1] = 0; /* Reserved */ CDB[2] = (ElementStatus->TransportElementAddress >> 8) & 0xFF; /* Transport Element Address MSB */ CDB[3] = (ElementStatus->TransportElementAddress) & 0xff; /* Transport Element Address LSB */ CDB[4] = (SourceAddress >> 8) & 0xFF; /* Source Address MSB */ CDB[5] = SourceAddress & 0xFF; /* Source Address MSB */ CDB[6] = (DestinationAddress >> 8) & 0xFF; /* Destination Address MSB */ CDB[7] = DestinationAddress & 0xFF; /* Destination Address MSB */ CDB[8] = 0; /* Reserved */ CDB[9] = 0; /* Reserved */ if (flags->invert) { CDB[10] = 1; /* Reserved */ } else { CDB[10] = 0; } /* eepos controls the tray for import/export elements, sometimes. */ CDB[11] = 0 | (flags->eepos <<6); /* Control */ if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 12, NULL, 0, RequestSense) != 0) { return RequestSense; } free(RequestSense); return NULL; /* success! */}/* for Linux, this creates a way to do a short erase... the @#$%@ st.c * driver defaults to doing a long erase! */RequestSense_T *Erase(DEVICE_TYPE MediumChangerFD) { RequestSense_T *RequestSense = xmalloc(sizeof(RequestSense_T)); CDB_T CDB; CDB[0]=0x19; CDB[1]=0; /* Short! */ CDB[2]=CDB[3]=CDB[4]=CDB[5]=0; if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 6, NULL, 0, RequestSense) != 0) { return RequestSense; } free(RequestSense); return NULL; /* Success! */} #ifdef LONG_PRINT_REQUEST_SENSEstatic char *sense_keys[] = { "No Sense", /* 00 */ "Recovered Error", /* 01 */ "Not Ready", /* 02 */ "Medium Error", /* 03 */ "Hardware Error", /* 04 */ "Illegal Request", /* 05 */ "Unit Attention", /* 06 */ "Data Protect", /* 07 */ "Blank Check", /* 08 */ "0x09", /* 09 */ "0x0a", /* 0a */ "Aborted Command", /* 0b */ "0x0c", /* 0c */ "Volume Overflow", /* 0d */ "Miscompare", /* 0e */ "0x0f" /* 0f */};static char Yes[]="yes";static char No[]="no";void PrintRequestSense(RequestSense_T *RequestSense){ char *msg; fprintf(stderr, "mtx: Request Sense: Long Report=yes\n"); fprintf(stderr, "mtx: Request Sense: Valid Residual=%s\n", RequestSense->Valid ? Yes : No); if (RequestSense->ErrorCode==0x70) { msg = "Current" ; } else if (RequestSense->ErrorCode==0x71) { msg = "Deferred" ; } else { msg = "Unknown?!" ; } fprintf(stderr, "mtx: Request Sense: Error Code=%0x (%s)\n",RequestSense->ErrorCode,msg); fprintf(stderr, "mtx: Request Sense: Sense Key=%s\n",sense_keys[RequestSense->SenseKey]); fprintf(stderr, "mtx: Request Sense: FileMark=%s\n", RequestSense->Filemark ? Yes : No); fprintf(stderr, "mtx: Request Sense: EOM=%s\n", RequestSense->EOM ? Yes : No); fprintf(stderr, "mtx: Request Sense: ILI=%s\n", RequestSense->ILI ? Yes : No); if (RequestSense->Valid) { fprintf(stderr, "mtx: Request Sense: Residual = %02X %02X %02X %02X\n",RequestSense->Information[0],RequestSense->Information[1],RequestSense->Information[2],RequestSense->Information[3]); } fprintf(stderr,"mtx: Request Sense: Additional Sense Code = %02X\n", RequestSense->AdditionalSenseCode); fprintf(stderr,"mtx: Request Sense: Additional Sense Qualifier = %02X\n", RequestSense->AdditionalSenseCodeQualifier); if (RequestSense->SKSV) { fprintf(stderr,"mtx: Request Sense: Field in Error = %02X\n",RequestSense->BitPointer); } fprintf(stderr,"mtx: Request Sense: BPV=%s\n",RequestSense->BPV ? Yes : No); fprintf(stderr,"mtx: Request Sense: Error in CDB=%s\n",RequestSense->CommandData ? Yes : No); fprintf(stderr,"mtx: Request Sense: SKSV=%s\n",RequestSense->SKSV ? Yes : No); fflush(stderr); if (RequestSense->BPV || RequestSense -> SKSV) { fprintf(stderr,"mtx: Request Sense: Field Pointer = %02X %02X\n",RequestSense->FieldData[0],RequestSense->FieldData[1]); }}#elsevoid PrintRequestSense(RequestSense_T *RequestSense){ int i; fprintf(stderr, "mtx: Request Sense: %02X", ((unsigned char *) RequestSense)[0]); for (i = 1; i < sizeof(RequestSense_T); i++) fprintf(stderr, " %02X", ((unsigned char *) RequestSense)[i]); fprintf(stderr, "\n");}#endif/* $Date: 2002/09/27 17:23:28 $ * $Log: mtxl.c,v $ * Revision 1.8.2.7 2002/09/27 17:23:28 elgreen * Don't dereference pointer in barcode stuff * * Revision 1.8.2.6 2002/09/27 17:20:18 elgreen * doh, get rid of the + from the patch process! * * Revision 1.8.2.5 2002/09/27 17:17:13 elgreen * fix copy_barcode * * Revision 1.8.2.4 2002/09/27 16:49:43 elgreen * copy_barcode was off by one (sigh!) * * Revision 1.8.2.3 2002/02/05 16:51:11 elgreen * mtx 1.2.16pre3 * * Revision 1.8.2.2 2002/01/22 16:27:47 elgreen * Handle too-big transport element descriptor lengths * * Revision 1.8.2.1 2002/01/17 22:24:35 elgreen * Handle ADIC silliness of saying that it has 1 import/export element whose * descriptor is 0 bytes in length * * Revision 1.8 2001/06/25 23:06:22 elgreen * Readying this for 1.2.13 release * * Revision 1.7 2001/06/25 04:56:35 elgreen * Kai to the rescue *again* :-) * * Revision 1.6 2001/06/24 07:02:01 elgreen * Kai's fix was better than mine. * * Revision 1.5 2001/06/24 06:59:19 elgreen * Kai found bug in the barcode backoff. * * Revision 1.4 2001/06/15 18:56:54 elgreen * Arg, it doesn't help to check for 0 robot arms if you force it to 1! * * Revision 1.3 2001/06/15 14:26:09 elgreen * Fixed brain-dead case of HP loaders that report they have no robot arms. * * Revision 1.2 2001/06/09 17:26:26 elgreen * Added 'nobarcode' command to mtx (to skip the initial request asking for * barcodes for mtx status purposes). * * Revision 1.1.1.1 2001/06/05 17:10:25 elgreen * Initial import into SourceForge * * Revision 1.29 2001/05/01 01:39:23 eric * Remove the Exabyte special case code, which seemed to be barfing me :-(. * * Revision 1.28 2001/04/28 00:03:10 eric * update for 1.2.12. * * Revision 1.27 2001/04/18 19:27:39 eric * whoops, move ImportExport parser into the $#%!@ ImportExport test :-(. * * Revision 1.26 2001/04/18 18:55:44 eric * turn too many storage elements into a warning rather than a fatal error (sigh!) * * Revision 1.25 2001/04/18 18:46:54 eric * $%!@# "C" precedence rules. * * Revision 1.24 2001/04/18 17:58:04 eric * initialize EmptyStorageElementCount (sigh) * * Revision 1.23 2001/04/18 16:55:03 eric * hopefully get the initialization for element status straigtened out. * * Revision 1.22 2001/04/18 16:32:59 eric * Cleaned up all -Wall messages. * * Revision 1.21 2001/04/18 16:08:08 eric * after re-arranging & fixing bugs * * Revision 1.20 2001/04/17 21:28:43 eric * mtx 1.2.11 * * Revision 1.19 2001/04/02 20:12:48 eric * checkin, mtx 1.2.11pre6 * * Revision 1.18 2001/03/06 01:37:05 eric * Solaris changes * * Revision 1.17 2001/02/26 20:56:12 eric * added debugging, removed Makefile * * Revision 1.16 2001/02/19 23:22:28 eric * Add E2 bits * * Revision 1.15 2001/02/19 23:02:04 eric * Apply SPARC patch. * * Revision 1.14 2001/01/26 15:58:10 eric * Make work on solaris? * * Revision 1.13 2001/01/17 19:39:01 eric * Changed mtx.h and mtxl.c to use autoconf stuff to figure out which SCSI * routines to use (this way, if we ever port to an OS that has an identical * SCSI interface to one of the supported OS's, we don't have to do anything * special!). * * Revision 1.12 2001/01/17 16:36:26 eric * added date & revision strings as needed * * Revision 1.11 2000/11/30 20:35:18 eric * Added Erase command. * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -