X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=changer-src%2Fscsi-changer-driver.c;fp=changer-src%2Fscsi-changer-driver.c;h=0000000000000000000000000000000000000000;hb=b116e9366c7b2ea2c2eb53b0a13df4090e176235;hp=8693bf39709ca48b6da071c1fac04a3c08fdb82a;hpb=fd48f3e498442f0cbff5f3606c7c403d0566150e;p=debian%2Famanda diff --git a/changer-src/scsi-changer-driver.c b/changer-src/scsi-changer-driver.c deleted file mode 100644 index 8693bf3..0000000 --- a/changer-src/scsi-changer-driver.c +++ /dev/null @@ -1,6633 +0,0 @@ -static char rcsid[] = "$Id: scsi-changer-driver.c,v 1.52 2006/07/21 00:25:50 martinea Exp $"; -/* - * Interface to control a tape robot/library connected to the SCSI bus - * - * Copyright (c) Thomas Hepper th@ant.han.de - */ - -#include "amanda.h" - -#include "arglist.h" - -#include "scsi-defs.h" - -#include "device.h" - -extern FILE *debug_file; -extern changer_t *changer; /* Needed for the infos about emubarcode and labelfile */ - -int PrintInquiry(SCSIInquiry_T *); -int GenericElementStatus(int DeviceFD, int InitStatus); -int SDXElementStatus(int DeviceFD, int InitStatus); -int DLT448ElementStatus(int DeviceFD, int InitStatus); -ElementInfo_T *LookupElement(int addr); -int GenericResetStatus(int DeviceFD); -int RequestSense(int, ExtendedRequestSense_T *, int ); -void dump_hex(u_char *, size_t, int, int); -void TerminateString(char *string, size_t length); -void ChgExit(char *, char *, int); -int BarCode(int fd); -int LogSense(int fd); -int SenseHandler(int fd, u_char flag, u_char SenseKey, u_char AdditionalSenseCode, u_char AdditionalSenseCodeQualifier, RequestSense_T *buffer); - -int SCSI_AlignElements(int DeviceFD, size_t MTE, size_t DTE, size_t STE); - -int DoNothing0(void); -int DoNothing1(int); -int DoNothing2(int, int); -int DoNothing3(int, int, int); - -int GenericMove(int, int, int); -int SDXMove(int, int, int); -int CheckMove(ElementInfo_T *from, ElementInfo_T *to); -int GenericRewind(int); -/* int GenericStatus(void); */ -int GenericFree(void); -int TapeStatus(void); /* Is the tape loaded ? */ -int DLT4000Eject(char *Device, int type); -int GenericEject(char *Device, int type); -int SCSI_LogSenseClean(char *Device); /* Does the tape need a clean */ -int GenericClean(char *Device); /* Does the tape need a clean */ -int GenericBarCode(int DeviceFD); /* Do we have Barcode reader support */ -int NoBarCode(int DeviceFD); - -int GenericSearch(void); -void Inventory(char *labelfile, int drive, int eject, int start, int stop, int clean); - -int TreeFrogBarCode(int DeviceFD); -int EXB_BarCode(int DeviceFD); -int GenericSenseHandler(int fd, u_char flags, u_char SenseKey, u_char AdditionalSenseCode, u_char AdditionalSenseCodeQualifier, RequestSense_T *); - -ElementInfo_T *LookupElement(int address); -int eject_tape(char *tapedev, int type); -int unload(int fd, int drive, int slot); -int load(int fd, int drive, int slot); -int GetElementStatus(int DeviceFD); -int drive_loaded(int fd, int drivenum); - -/* - * Log Pages Decode - */ -void WriteErrorCountersPage(LogParameter_T *, size_t); -void ReadErrorCountersPage(LogParameter_T *, size_t); -void C1553APage30(LogParameter_T *, size_t); -void C1553APage37(LogParameter_T *, size_t); -void EXB85058HEPage39(LogParameter_T *, size_t); -void EXB85058HEPage3c(LogParameter_T *, size_t); -int Decode(LogParameter_T *, unsigned *); -int DecodeModeSense(u_char *buffer, size_t offset, char *pstring, char block, FILE *out); - -int SCSI_Run(int DeviceFD, - Direction_T Direction, - CDB_T CDB, - size_t CDB_Length, - void *DataBuffer, - size_t DataBufferLength, - RequestSense_T *pRequestSense, - size_t RequestSenseLength); - -int SCSI_Move(int DeviceFD, u_char chm, int from, int to); -int SCSI_LoadUnload(int DeviceFD, RequestSense_T *pRequestSense, u_char byte1, u_char load); -int SCSI_TestUnitReady(int, RequestSense_T *); -int SCSI_ModeSense(int DeviceFD, u_char *buffer, u_char size, u_char byte1, u_char byte2); -int SCSI_ModeSelect(int DeviceFD, - u_char *buffer, - u_char length, - u_char save, - u_char mode, - u_char lun); - -int SCSI_ReadElementStatus(int DeviceFD, - u_char type, - u_char lun, - u_char VolTag, - int StartAddress, - size_t NoOfElements, - size_t DescriptorSize, - u_char **data); - -FILE *StatFile; -static int barcode; /* cache the result from the BarCode function */ - -SC_COM_T SCSICommand[] = { - {0x00, - 6, - "TEST UNIT READY"}, - {0x01, - 6, - "REWIND"}, - {0x03, - 6, - "REQUEST SENSE"}, - {0x07, - 6, - "INITIALIZE ELEMENT STATUS"}, - {0x12, - 6, - "INQUIRY"}, - {0x13, - 6, - "ERASE"}, - {0x15, - 6, - "MODE SELECT"}, - {0x1A, - 6, - "MODE SENSE"}, - {0x1B, - 6, - "UNLOAD"}, - {0x4D, - 10, - "LOG SENSE"}, - {0xA5, - 12, - "MOVE MEDIUM"}, - { 0xE5, - 12, - "VENDOR SPECIFIC"}, - {0xB8, - 12, - "READ ELEMENT STATUS"}, - {0, 0, 0} -}; - -ChangerCMD_T ChangerIO[] = { - {"generic_changer", - "Generic driver changer [generic_changer]", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - /* HP Devices */ - {"C1553A", - "HP Auto Loader [C1553A]", - GenericMove, - GenericElementStatus, - DoNothing1, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - /* Exabyte Devices */ - {"EXB-10e", - "Exabyte Robot [EXB-10e]", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - {"EXB-120", - "Exabyte Robot [EXB-120]", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - EXB_BarCode, - GenericSearch, - GenericSenseHandler}, - {"EXB-210", - "Exabyte Robot [EXB-210]", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - EXB_BarCode, - GenericSearch, - GenericSenseHandler}, - {"EXB-85058HE-0000", - "Exabyte Tape [EXB-85058HE-0000]", - DoNothing3, - DoNothing2, - DoNothing1, - DoNothing0, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - /* Tandberg Devices */ - {"TDS 1420", - "Tandberg Robot (TDS 1420)", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - /* ADIC Devices */ - {"VLS DLT", - "ADIC VLS DLT Library [VLS DLT]", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - {"VLS SDX", - "ADIC VLS DLT Library [VLS SDX]", - SDXMove, - SDXElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - {"FastStor DLT", - "ADIC FastStor DLT Library [FastStor DLT]", - SDXMove, - DLT448ElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - {"Scalar DLT 448", - "ADIC DLT 448 [Scalar DLT 448]", - GenericMove, - DLT448ElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - /* Sepctra Logic Devices */ - {"215", - "Spectra Logic TreeFrog[215]", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - TreeFrogBarCode, - GenericSearch, - GenericSenseHandler}, - /* BreeceHill Q7 */ - {"Quad 7", - "Breece Hill Quad 7", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - /* Quantum Devices */ - {"L500", - "ATL [L500]", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - /* - * And now the tape devices - */ - /* The generic handler if nothing matches */ - {"generic_tape", - "Generic driver tape [generic_tape]", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - GenericClean, - GenericRewind, - NoBarCode, - GenericSearch, - GenericSenseHandler}, - {"DLT8000", - "DLT Tape [DLT8000]", - DoNothing3, - DoNothing2, - DoNothing1, - DoNothing0, - DLT4000Eject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - {"DLT7000", - "DLT Tape [DLT7000]", - DoNothing3, - DoNothing2, - DoNothing1, - DoNothing0, - DLT4000Eject, - GenericClean, - GenericRewind, - GenericBarCode, - GenericSearch, - GenericSenseHandler}, - {"DLT4000", - "DLT Tape [DLT4000]", - DoNothing3, - DoNothing2, - DoNothing1, - DoNothing0, - DLT4000Eject, - GenericClean, - GenericRewind, - NoBarCode, - GenericSearch, - GenericSenseHandler}, - {"SLR100", - "Tandberg SLR100", - GenericMove, - GenericElementStatus, - GenericResetStatus, - GenericFree, - GenericEject, - SCSI_LogSenseClean, - GenericRewind, - NoBarCode, - GenericSearch, - GenericSenseHandler}, - {NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} -}; - - -LogPageDecode_T DecodePages[] = { - {2, - "C1553A", - WriteErrorCountersPage}, - {3, - "C1553A", - ReadErrorCountersPage}, - {0x30, - "C1553A", - C1553APage30}, - {0x37, - "C1553A", - C1553APage37}, - {2, - "*", - WriteErrorCountersPage}, - {3, - "*", - ReadErrorCountersPage}, - {0x39, - "EXB-85058HE-0000", - EXB85058HEPage39}, - {0x3c, - "EXB-85058HE-0000", - EXB85058HEPage3c}, - {0, NULL, NULL} -}; - - -int ElementStatusValid = 0; /* Set if the READ ELEMENT STATUS was OK, an no error is pending */ -int LibModeSenseValid = 0; /* Set if we did an scussefull MODE SENSE */ - -char *SlotArgs = 0; -/* Pointer to MODE SENSE Pages */ -u_char *pModePage = NULL; -EAAPage_T *pEAAPage = NULL; -DeviceCapabilitiesPage_T *pDeviceCapabilitiesPage = NULL; -u_char *pVendorUnique = NULL; - -/* - * New way, every element type has its on array - * which is dynamic allocated by the ElementStatus function, -*/ -ElementInfo_T *pMTE = NULL; /*Medium Transport Element */ -ElementInfo_T *pSTE = NULL; /*Storage Element */ -ElementInfo_T *pIEE = NULL; /*Import Export Element */ -ElementInfo_T *pDTE = NULL; /*Data Transfer Element */ -size_t MTE = 0; /*Counter for the above element types */ -size_t STE = 0; -size_t IEE = 0; -size_t DTE = 0; - -char *chgscsi_datestamp = NULL; /* Result pointer for tape_rdlabel */ -char *chgscsi_label = NULL; /* Result pointer for tape_rdlabel */ -char *chgscsi_result = NULL; /* Needed for the result string of MapBarCode */ - -/* - * This used to be in tape-src/tapeio.c; this is the Device API version. - */ - -static char * -tape_rdlabel( - char *devname, - char **datestamp, - char **label) -{ - Device *dev; - char *r = NULL; - - dev = device_open(devname); - if (dev->status != DEVICE_STATUS_SUCCESS) { - r = g_strdup(device_error_or_status(dev)); - g_object_unref(dev); - return r; - } - - if (!device_configure(dev, TRUE) || !device_read_label(dev)) { - r = g_strdup(device_error_or_status(dev)); - g_object_unref(dev); - return r; - } - - *datestamp = g_strdup(dev->volume_time); - *label = g_strdup(dev->volume_label); - - return NULL; -} - -/* - * First all functions which are called from extern - */ - - -/* - * Print the scsi-changer-driver version - */ - -void -ChangerDriverVersion(void) -{ - DebugPrint(DEBUG_ERROR, SECTION_INFO, "scsi-changer-driver: %s\n",rcsid); - SCSI_OS_Version(); -} - -/* - * Try to generate an template which can be used as an example for the config file - * - */ -void -PrintConf(void) -{ - extern OpenFiles_T *pDev; - int count; - char *cwd; - - g_printf(_("# Please replace every ??? with the correct parameter.\n")); - g_printf(_("# It is not possible to guess everything :-)\n")); - g_printf(_("# Remove the line if the option is not needed.")); - g_printf(_("# Example: cleanmax if you have no cleaning tape")); - g_printf(_("#\n")); - g_printf(_( - "number_configs 1 # Number of configs, you can have more than 1 config\n" - " # if you have for example more than one drive, or you\n" - " # to split your lib to use different dump levels\n" - " #\n")); - g_printf(_( - "emubarcode 1 # If you drive has no barcode reader this will try\n" - " # keep an inventory of your tapes to find them faster\n" - " #\n")); - g_printf(_( - "havebarcode 0 # Set this to 1 if you have a library with a\n" - " # barcode reader\n" - " #\n")); - g_printf(_( - "debuglevel 0:0 # For debuging, see the docs /docs/TAPE-CHANGER\n" - " #\n")); - g_printf(_( - "eject ??? # set this to 1 if your drive needs an eject before move\n" - " #\n")); - g_printf(_( - "sleep ??? # How long to wait after an eject command before moving\n" - " # the tape\n" - " #\n")); - - for (count = 0; count < CHG_MAXDEV ; count++) - { - if (pDev[count].dev) - { - if (pDev[count].inquiry != NULL && pDev[count].inquiry->type == TYPE_CHANGER) - { - g_printf(_("changerdev %s # This is the device to communicate with the robot\n"), pDev[count].dev); - break; - } - } - } - - /* - * Did we reach the end of the list ? - * If no we found an changer and now we try to - * get the element status for the count of slots - */ - if (count < CHG_MAXDEV) - { - pDev[count].functions->function_status(count, 1); - } else { - g_printf(_("changerdev ??? # Ups nothing found. Please check the docs\n")); - } - - g_printf(_( - " #\n")); - g_printf(_( - " # Here now comes the config for the first tape\n")); - g_printf(_( - "config 0 # This value is the one which is used in the amanda\n" - " # config file to tell the chg-scsi programm which tape\n" - " # and which slots to use\n" - " #\n")); - g_printf(_( - "cleancart ??? # The slot where the cleaning tape is located\n" - " # remove it if you have no cleaning tape\n" - " #\n")); - g_printf(_( - "drivenum 0 # Which tape drive to use if there are more than one drive\n" - " #\n")); - g_printf(_( - "dev ??? # Which is the raw device to read/write data from the tape\n" - " # It is important to use the non rewinding tape, like\n" - " # /dev/nrst0 on linux, /dev/nrsa0 on BSD ....\n" - " #\n")); - - /* - * OK now lets see if we have an direct SCSI channel - * to the tape - * If not thats not a problem - */ - for (count = 0; count < CHG_MAXDEV; count++) - { - if (pDev[count].dev) - { - if (pDev[count].inquiry != NULL && pDev[count].inquiry->type == TYPE_TAPE) - { - g_printf(_( - "scsitapedev %s # This is the device to communicate with the tape\n" - " # to get some device stats, not so important, and\n" - " # if you run into problems delete it completely\n" - " #\n"), pDev[count].dev); - break; - } - } - } - - - if (STE != 0) - { - g_printf(_( - "startuse 0 # Which is the first slot to use\n" - " #\n")); - g_printf(_( - "enduse %zu # Which is the last slot to use.\n"), STE); - } else { - g_printf(_( - "startuse ??? # Which is the first slot to use\n" - " #\n")); - g_printf(_( - "enduse ??? # Which is the last slot to use.\n")); - } - g_printf(_( - " # Decrement this value by 1 if you have a\n" - " # cleaning tape in the last slot\n" - " #\n")); - - if ((cwd = getcwd(NULL, 0)) == NULL) { - cwd = _(""); - } - - g_printf(_("statfile %s/tape0-slot #\n"),cwd); - g_printf(_("cleanfile %s/tape0-clean #\n"), cwd); - g_printf(_("usagecount %s/tape0-totaltime #\n"), cwd); - g_printf(_("tapestatus %s/tape0-tapestatus #\n"), cwd); - g_printf(_("labelfile %s/labelfile #\n"), cwd); -} - - - -/* - * Try to create a list of tapes and labels which are in the current - * magazin. The drive must be empty !! - * - * labelfile -> file name of the db - * drive -> which drive should we use - * eject -> the tape device needs an eject before move - * start -> start at slot start - * stop -> stop at slot stop - * clean -> if we have an cleaning tape than this is the slot number of it - * - * return - * 0 -> fail - * 1 -> successfull - * - * ToDo: - * Check if the tape/changer is ready for the next move - * If an tape is loaded unload it and do initialize element status to - * get all labels if an bar code reader is installed - */ -void -Inventory( - char * labelfile, - int drive, - int eject, - int start, - int stop, - int clean) -{ - extern OpenFiles_T *pDev; - size_t x; - static int inv_done = 0; /* Inventory function called ?, marker to disable recursion */ - MBC_T *pbarcoderes; /* Here we will pass the parameter to MapBarCode and get the result */ - - (void)start; /* Quiet unused parameter warning */ - (void)stop; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE, _("##### START Inventory\n")); - pbarcoderes = alloc(SIZEOF(MBC_T)); - memset(pbarcoderes, 0 , SIZEOF(MBC_T)); - - if (inv_done != 0) - { - DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE, _("##### STOP inv_done -> %d Inventory\n"),inv_done); - free(pbarcoderes); - return; - /*NOTREACHED*/ - } - inv_done = 1; - barcode = BarCode(INDEX_CHANGER); - - pbarcoderes->action = RESET_VALID; - - MapBarCode(labelfile,pbarcoderes); - - /* - * Check if an tape is loaded, if yes unload it - * and do an INIT ELEMENT STATUS - */ - - if (pDTE[0].status == 'F') - { - if (eject) - { - (void)eject_tape("", eject); - } - (void)unload(INDEX_TAPE, 0, 0); - } - - GenericResetStatus(INDEX_CHANGER); - - for (x = 0; x < STE; x++) - { - if (x == (size_t)clean) - { - continue; - } - - /* - * Load the tape, on error try the next - * error could be an empty slot for example - */ - if (load(INDEX_CHANGER, drive, x ) != 0) - { - DebugPrint(DEBUG_ERROR,SECTION_MAP_BARCODE, _("Load drive(%d) from(%d) failed\n"), drive, x); - continue; - } - - /* - * Wait until the tape is ready - */ - Tape_Ready(INDEX_TAPECTL, 60); - - SCSI_CloseDevice(INDEX_TAPE); - - if ((chgscsi_result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label)) == NULL) - { - pbarcoderes->action = UPDATE_SLOT; - strncpy(pbarcoderes->data.voltag, chgscsi_label, - SIZEOF(pbarcoderes->data.voltag)); - pbarcoderes->data.slot = x; - pbarcoderes->data.from = 0; - pbarcoderes->data.LoadCount = 1; - if (BarCode(INDEX_CHANGER) == 1) - { - strncpy(pbarcoderes->data.barcode, pDTE[drive].VolTag, - SIZEOF(pbarcoderes->data.barcode)); - MapBarCode(labelfile, pbarcoderes); - } else { - MapBarCode(labelfile, pbarcoderes); - } - } else { - DebugPrint(DEBUG_ERROR,SECTION_MAP_BARCODE, _("Read label failed\n")); - } - - if (eject) - { - (void)eject_tape("", eject); - } - - (void)unload(INDEX_TAPE, drive, x); - } - DebugPrint(DEBUG_INFO,SECTION_MAP_BARCODE, _("##### STOP Inventory\n")); - free(pbarcoderes); -} - -/* - * Check if the slot ist empty - * slot -> slot number to check - */ -int -isempty( - int fd, - int slot) -{ - extern OpenFiles_T *pDev; - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### START isempty\n")); - - if (ElementStatusValid == 0) - { - if ( pDev[fd].functions->function_status(fd, 1) != 0) - { - DebugPrint(DEBUG_ERROR,SECTION_TAPE,_("##### STOP isempty [-1]\n")); - return(-1); - /*NOTREACHED*/ - } - } - - if (pSTE[slot].status == 'E') - { - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP isempty [1]\n")); - return(1); - /*NOTREACHED*/ - } - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP isempty [0]\n")); - return(0); -} - -int -get_clean_state( - char *tapedev) -{ - extern OpenFiles_T *pDev; - /* Return 1 if cleaning is needed */ - int ret; - - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### START get_clean_state\n")); - - if (pDev[INDEX_TAPECTL].SCSI == 0) - { - DebugPrint(DEBUG_ERROR,SECTION_TAPE,_("##### STOP get_clean_state [-1]\n")); - return(-1); - /*NOTREACHED*/ - } - ret=pDev[INDEX_TAPECTL].functions->function_clean(tapedev); - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP get_clean_state [%d]\n"), ret); - return(ret); -} - -/* - * eject the tape - * The parameter tapedev is not used. - * Type describes if we should force the SCSI eject if available - * normal eject is done with the ioctl - */ -/* This function ejects the tape from the drive */ - -int -eject_tape( - char * tapedev, - int type) -{ - extern OpenFiles_T *pDev; - int ret; - - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### START eject_tape %s\n"),tapedev); - if (pDev[INDEX_TAPECTL].functions == NULL) - return(-1); - - /* - * Try to read the label - */ - if (pDev[INDEX_TAPE].avail == 1 && (changer->emubarcode == 1 || BarCode(INDEX_CHANGER))) - { - - if (pDev[INDEX_TAPECTL].SCSI == 1 && pDev[INDEX_TAPECTL].avail) { - DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### eject_tape rewind\n"); - pDev[INDEX_TAPECTL].functions->function_rewind(INDEX_TAPECTL); - } else { - DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### eject_tape rewind2\n"); - pDev[INDEX_TAPE].functions->function_rewind(INDEX_TAPE); - } - - if (pDev[INDEX_TAPE].devopen == 1) - { - DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### eject_tape close\n"); - SCSI_CloseDevice(INDEX_TAPE); - } - - DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### tape_eject tape_rdlabel\n"); - chgscsi_result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label); - } - - if (pDev[INDEX_TAPECTL].SCSI == 1 && pDev[INDEX_TAPECTL].avail == 1 && type == 1) - { - DebugPrint(DEBUG_INFO,SECTION_TAPE,"##### tape_eject eject\n"); - ret=pDev[INDEX_TAPECTL].functions->function_eject(tapedev, type); - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP (SCSI)eject_tape [%d]\n"), ret); - return(ret); - /*NOTREACHED*/ - } - - if (pDev[INDEX_TAPE].avail == 1) - { - ret=Tape_Ioctl(INDEX_TAPE, IOCTL_EJECT); - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP (ioctl)eject_tape [%d]\n"), ret); - return(ret); - /*NOTREACHED*/ - } - - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("##### STOP eject_tape [-1]\n")); - return(-1); -} - - -/* Find an empty slot, starting at start, ending at start+count */ -int -find_empty( - int fd, - int start, - int count) -{ - extern OpenFiles_T *pDev; - size_t x; - size_t end; - - DebugPrint(DEBUG_INFO,SECTION_ELEMENT,_("###### START find_empty\n")); - - if (ElementStatusValid == 0) - { - if ( pDev[fd].functions->function_status(fd , 1) != 0) - { - DebugPrint(DEBUG_ERROR,SECTION_ELEMENT, - _("###### END find_empty [-1]\n")); - return((ssize_t)-1); - /*NOTREACHED*/ - } - } - - if (count == 0) - { - end = STE; - } else { - end = start + count; - } - - if (end > STE) - { - end = STE; - } - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT, - _("start at %zu, end at %zu\n"), - (size_t)start, - (size_t)end); - - for (x = start; x < end; x++) - { - if (pSTE[x].status == 'E') - { - DebugPrint(DEBUG_INFO,SECTION_ELEMENT, - _("###### END find_empty [%lu]\n"), x); - return((ssize_t)x); - /*NOTREACHED*/ - } - } - DebugPrint(DEBUG_ERROR,SECTION_ELEMENT,_("###### END find_empty [-1]\n")); - return((ssize_t)-1); -} - -/* - * See if the tape is loaded based on the information we - * got back from the ReadElementStatus - * return values - * -1 -> Error (Fatal) - * 0 -> drive is empty - * 1 -> drive is loaded - */ -int -drive_loaded( - int fd, - int drivenum) -{ - extern OpenFiles_T *pDev; - - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("###### START drive_loaded\n")); - DebugPrint(DEBUG_INFO,SECTION_TAPE, - _(" drive_loaded : fd %d drivenum %d \n"), fd, drivenum); - - - if (ElementStatusValid == 0) - { - if (pDev[INDEX_CHANGER].functions->function_status(INDEX_CHANGER, 1) != 0) - { - DebugPrint(DEBUG_ERROR,SECTION_TAPE,_("Fatal error\n")); - return(-1); - /*NOTREACHED*/ - } - } - - if (pDTE[drivenum].status == 'E') { - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("###### STOP drive_loaded (empty)\n")); - return(0); - /*NOTREACHED*/ - } - DebugPrint(DEBUG_INFO,SECTION_TAPE,_("###### STOP drive_loaded (not empty)\n")); - return(1); -} - - -/* - * unload the specified drive into the specified slot - * (storage element) - * - * TODO: - * Check if the MTE is empty - */ -int -unload( - int fd, - int drive, - int slot) -{ - extern OpenFiles_T *pDev; - extern int do_inventory; - MBC_T *pbarcoderes; - - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("###### START unload\n")); - DebugPrint(DEBUG_INFO, SECTION_TAPE, - _(" unload : fd %d, slot %d, drive %d \n"), - fd, slot, drive); - pbarcoderes = alloc(SIZEOF(MBC_T)); - memset(pbarcoderes, 0, SIZEOF(MBC_T)); - - /* - * If the Element Status is not valid try to - * init it - */ - if (ElementStatusValid == 0) - { - if (pDev[INDEX_CHANGER].functions->function_status(INDEX_CHANGER , 1) != 0) - { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("Element Status not valid, reset failed\n")); - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("##### STOP unload (-1)\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - } - - DebugPrint(DEBUG_INFO, SECTION_TAPE, - _(" unload : unload drive %d[%d] slot %d[%d]\n"), - drive, pDTE[drive].address, slot, pSTE[slot].address); - - /* - * Unloading an empty tape unit makes no sense - * so return with an error - */ - if (pDTE[drive].status == 'E') - { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("unload : Drive %d address %d is empty\n"), drive, pDTE[drive].address); - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("##### STOP unload (-1)\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - - /* - * If the destination slot is full - * try to find an enpty slot - */ - if (pSTE[slot].status == 'F') - { - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("unload : Slot %d address %d is full\n"), drive, pSTE[slot].address); - if ( ElementStatusValid == 0) - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("unload: Element Status not valid, can't find an empty slot\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - - slot = find_empty(fd, 0, 0); - if (slot == -1 ) - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("unload: No Empty slot found\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("unload : found empty one, try to unload to slot %d\n"), slot); - } - - - - /* - * If eject is not set we must read the label info - */ - - if (changer->eject == 0) - { - if (pDev[INDEX_TAPE].avail == 1 && (changer->emubarcode == 1 || BarCode(INDEX_CHANGER))) - { - - if (pDev[INDEX_TAPECTL].SCSI == 1 && pDev[INDEX_TAPECTL].avail) { - pDev[INDEX_TAPECTL].functions->function_rewind(INDEX_TAPECTL); - } else { - pDev[INDEX_TAPE].functions->function_rewind(INDEX_TAPE); - } - - if (pDev[INDEX_TAPE].devopen == 1) - { - SCSI_CloseDevice(INDEX_TAPE); - } - - chgscsi_result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label); - } - } - - /* - * Do the unload/move - */ - if (pDev[INDEX_CHANGER].functions->function_move(INDEX_CHANGER, - pDTE[drive].address, pSTE[slot].address) != 0) { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("##### STOP unload (-1 move failed)\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - - - /* - * Update the Status - */ - if (pDev[INDEX_CHANGER].functions->function_status(INDEX_CHANGER , 1) != 0) - { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("##### STOP unload (-1 update status failed)\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - - /* - * Did we get an error from tape_rdlabel - * if no update the vol/label mapping - * If chgscsi_label is NULL don't do it - */ - if (chgscsi_result == NULL && chgscsi_label != NULL && changer->labelfile != NULL) - { - /* - * OK this is only needed if we have emubarcode set - * There we need an exact inventory to get the search function working - * and returning correct results - */ - if (BarCode(INDEX_CHANGER) == 0 && changer->emubarcode == 1) - { - /* - * We got something, update the db - * but before check if the db has as entry the slot - * to where we placed the tape, if no force an inventory - */ - pbarcoderes->action = FIND_SLOT; - strncpy(pbarcoderes->data.voltag, chgscsi_label, - SIZEOF(pbarcoderes->data.voltag)); - strncpy(pbarcoderes->data.barcode, pSTE[slot].VolTag, - SIZEOF(pbarcoderes->data.barcode)); - pbarcoderes->data.slot = 0; - pbarcoderes->data.from = 0; - pbarcoderes->data.LoadCount = 0; - - - if ( MapBarCode(changer->labelfile, pbarcoderes) == 0) /* Nothing known about this, do an Inventory */ - { - do_inventory = 1; - } else { - if (slot != pbarcoderes->data.slot) - { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("Slot DB out of sync, slot %d != map %d"),slot, pbarcoderes->data.slot); - do_inventory = 1; - } - } - } - } - - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP unload(0)\n")); - free(pbarcoderes); - return(0); -} - - -/* - * load the media from the specified element (slot) into the - * specified data transfer unit (drive) - * fd -> pointer to the internal device structure pDev - * driver -> which drive in the library - * slot -> the slot number from where to load - * - * return -> 0 = success - * !0 = failure - */ -int -load( - int fd, - int drive, - int slot) -{ - char *result = NULL; /* Needed for the result of tape_rdlabel */ - int ret; - extern OpenFiles_T *pDev; - extern int do_inventory; - MBC_T *pbarcoderes; - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("###### START load\n")); - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("%-20s : fd %d, drive %d, slot %d \n"), "load", fd, drive, slot); - pbarcoderes = alloc(SIZEOF(MBC_T)); - memset(pbarcoderes, 0 , SIZEOF(MBC_T)); - - if (ElementStatusValid == 0) - { - if (pDev[fd].functions->function_status(fd, 1) != 0) - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("##### STOP load (-1)\n")); - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("##### STOP load (-1 update status failed)\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - } - - /* - * Check if the requested slot is in the range of available slots - * The library starts counting at 1, we start at 0, so if the request slot - * is ge than the value we got from the ModeSense fail with an return value - * of 2 - */ - if ((size_t)slot >= STE) - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("load : slot %d ge STE %d\n"),slot, STE); - ChgExit("load", _("slot >= STE"), FATAL); - /*NOTREACHED*/ - } - - /* - * And the same for the tape drives - */ - if (drive >= (int)DTE) - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("load : drive %d ge DTE %d\n"),drive, DTE); - ChgExit("load", _("drive >= DTE"), FATAL); - /*NOTREACHED*/ - } - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("load : load drive %d[%d] slot %d[%d]\n"),drive, - pDTE[drive].address, - slot, - pSTE[slot].address); - - if (pDTE[drive].status == 'F') - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("load : Drive %d address %d is full\n"), drive, pDTE[drive].address); - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("##### STOP load (-1 update status failed)\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - - if (pSTE[slot].status == 'E') - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("load : Slot %d address %d is empty\n"), drive, pSTE[slot].address); - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("##### STOP load (-1 update status failed)\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - - ret = pDev[fd].functions->function_move(fd, pSTE[slot].address, pDTE[drive].address); - - /* - * Update the Status - */ - if (pDev[fd].functions->function_status(fd, 1) != 0) - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("##### STOP load (-1 update status failed)\n")); - free(pbarcoderes); - return(-1); - /*NOTREACHED*/ - } - - /* - * Try to read the label - * and update the label/slot database - */ - if (pDev[INDEX_TAPE].avail == 1 && (changer->emubarcode == 1 || BarCode(INDEX_CHANGER))) - { - - if (pDev[INDEX_TAPECTL].SCSI == 1 && pDev[INDEX_TAPECTL].avail) { - pDev[INDEX_TAPECTL].functions->function_rewind(INDEX_TAPECTL); - } else { - pDev[INDEX_TAPE].functions->function_rewind(INDEX_TAPE); - } - - if (pDev[INDEX_TAPE].devopen == 1) - { - SCSI_CloseDevice(INDEX_TAPE); - } - - result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label); - } - - /* - * Did we get an error from tape_rdlabel - * if no update the vol/label mapping - */ - if (result == NULL && changer->labelfile != NULL && chgscsi_label != NULL ) - { - /* - * We got something, update the db - * but before check if the db has as entry the slot - * to where we placed the tape, if no force an inventory - */ - strncpy(pbarcoderes->data.voltag, chgscsi_label, - SIZEOF(pbarcoderes->data.voltag)); - pbarcoderes->data.slot = 0; - pbarcoderes->data.from = 0; - pbarcoderes->data.LoadCount = 0; - - - /* - * If we have an barcode reader we only do an update - * If emubarcode is set we check if the - * info in the DB is up to date, if no we set the do_inventory flag - */ - - if (BarCode(INDEX_CHANGER) == 1 && changer->emubarcode == 0) - { - pbarcoderes->action = UPDATE_SLOT; - strncpy(pbarcoderes->data.barcode, pDTE[drive].VolTag, - SIZEOF(pbarcoderes->data.barcode)); - pbarcoderes->data.LoadCount = 1; - pbarcoderes->data.slot = slot; - MapBarCode(changer->labelfile, pbarcoderes); - } - - if (BarCode(INDEX_CHANGER) == 0 && changer->emubarcode == 1) - { - pbarcoderes->action = FIND_SLOT; - if (MapBarCode(changer->labelfile, pbarcoderes) == 0) /* Nothing found, do an inventory */ - { - do_inventory = 1; - } else { /* We got something, is it correct ? */ - if (slot != pbarcoderes->data.slot && do_inventory == 0) - { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("Slot DB out of sync, slot %d != map %d"),slot, pbarcoderes->data.slot); - ChgExit("Load", _("Label DB out of sync"), FATAL); - /*NOTREACHED*/ - } else { /* OK, so increment the load count */ - pbarcoderes->action = UPDATE_SLOT; - pbarcoderes->data.LoadCount = 1; - pbarcoderes->data.slot = slot; - MapBarCode(changer->labelfile, pbarcoderes); - } - } - } - - if (BarCode(INDEX_CHANGER) == 1 && changer->emubarcode == 1) - { - ChgExit("Load", _("BarCode == 1 and emubarcode == 1"), FATAL); - /*NOTREACHED*/ - } - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("##### STOP load (%d)\n"),ret); - free(pbarcoderes); - return(ret); - /*NOTREACHED*/ - } - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("##### STOP load (%d)\n"),ret); - free(pbarcoderes); - return(ret); -} - -/* - * Returns the number of Storage Slots which the library has - * fd -> pointer to the internal devie structure pDev - * return -> Number of slots - */ -int -get_slot_count( - int fd) -{ - extern OpenFiles_T *pDev; - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("###### START get_slot_count\n")); - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("%-20s : fd %d\n"), "get_slot_count", fd); - - if (ElementStatusValid == 0) - { - pDev[fd].functions->function_status(fd, 1); - } - DebugPrint(DEBUG_INFO, SECTION_ELEMENT, - _("##### STOP get_slot_count (%zu)\n"), STE); - return((ssize_t)STE); - /* - * return the number of slots in the robot - * to the caller - */ -} - - -/* - * retreive the number of data-transfer devices /Tape drives) - * fd -> pointer to the internal devie structure pDev - * return -> -1 on failure - */ -int -get_drive_count( - int fd) -{ - - extern OpenFiles_T *pDev; - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("###### START get_drive_count\n")); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-20s : fd %d\n"), "get_drive_count", fd); - - if (ElementStatusValid == 0) - { - if ( pDev[fd].functions->function_status(fd, 1) != 0) - { - DebugPrint(DEBUG_ERROR, SECTION_SCSI, _("Error getting drive count\n")); - DebugPrint(DEBUG_ERROR, SECTION_SCSI, _("##### STOP get_drive_count (-1)\n")); - return(-1); - /*NOTREACHED*/ - } - } - DebugPrint(DEBUG_INFO, SECTION_SCSI, - _("###### STOP get_drive_count (%zu drives)\n"), DTE); - return((ssize_t)DTE); -} - -/* - * Now the internal functions - */ - -/* - * Open the device and placeit in the list of open files - * The OS has to decide if it is an SCSI Commands capable device - */ - -int -OpenDevice( - int ip, - char * DeviceName, - char * ConfigName, - char * ident) -{ - extern OpenFiles_T *pDev; - char tmpstr[16]; - ChangerCMD_T *p = (ChangerCMD_T *)&ChangerIO; - - if (!ConfigName) - return 1; - if (!DeviceName) - return 1; - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START OpenDevice\n")); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("OpenDevice : %s\n"), DeviceName); - - pDev[ip].ConfigName = strdup(ConfigName); - pDev[ip].dev = strdup(DeviceName); - - if (SCSI_OpenDevice(ip) != 0 ) - { - if (ident != NULL) /* Override by config */ - { - while(p->ident != NULL) - { - if (strcmp(ident, p->ident) == 0) - { - pDev[ip].functions = p; - strncpy(pDev[ip].ident, ident, 17); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("override using ident = %s, type = %s\n"),p->ident, p->type); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP OpenDevice\n")); - return(1); - /*NOTREACHED*/ - } - p++; - } - ChgExit("OpenDevice", _("ident not found"), FATAL); - /*NOTREACHED*/ - } else { - while(p->ident != NULL) - { - if (strcmp(pDev[ip].ident, p->ident) == 0) - { - pDev[ip].functions = p; - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("using ident = %s, type = %s\n"),p->ident, p->type); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP OpenDevice\n")); - return(1); - /*NOTREACHED*/ - } - p++; - } - } - /* Nothing matching found, try generic */ - /* divide generic in generic_type, where type is the */ - /* num returned by the inquiry command */ - p = (ChangerCMD_T *)&ChangerIO; - g_snprintf(&tmpstr[0], SIZEOF(tmpstr), "%s_%s","generic",pDev[0].type); - DebugPrint(DEBUG_INFO, SECTION_SCSI,"##### OpenDevice trying GENERIC Device %s\n",tmpstr); - while(p->ident != NULL) - { - if (strcmp(tmpstr, p->ident) == 0) - { - pDev[ip].functions = p; - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("using ident = %s, type = %s\n"),p->ident, p->type); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP OpenDevice\n")); - return(1); - /*NOTREACHED*/ - } - p++; - } - } else { /* Something failed, lets see what */ - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("##### STOP OpenDevice failed\n")); - } - pDev[ip].functions = NULL; - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP OpenDevice (nothing found) !!\n")); - return(0); -} - - -/* - * This functions checks if the library has an barcode reader. - * fd -> pointer to the internal devie structure pDev - */ -int -BarCode( - int fd) -{ - int ret; - extern OpenFiles_T *pDev; - - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("##### START BarCode\n")); - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("%-20s : fd %d\n"), "BarCode", fd); - - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("Ident = [%s], function = [%s]\n"), pDev[fd].ident, - pDev[fd].functions->ident); - ret = pDev[fd].functions->function_barcode(fd); - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("##### STOP BarCode (%d)\n"),ret); - return(ret); -} - - -/* - * This functions check if the tape drive is ready - * - * fd -> pointer to the internal devie structure pDev - * wait -> time to wait for the ready status - * - */ -int -Tape_Ready( - int fd, - time_t wait_time) -{ - extern OpenFiles_T *pDev; - int done; - int ret; - time_t cnt = 0; - - RequestSense_T *pRequestSense; - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### START Tape_Ready\n")); - - /* - * Which device should we use to get the - * tape status - */ - - /* - * First the ioctl tapedevice - */ - if (pDev[INDEX_TAPE].avail == 1) - { - fd = INDEX_TAPE; - } - - /* - * But if available and can do SCSI - * the scsitapedev - */ - if (pDev[INDEX_TAPECTL].avail == 1 && pDev[INDEX_TAPECTL].SCSI == 1) - { - fd = INDEX_TAPECTL; - } - - if (pDev[fd].avail == 1 && pDev[fd].SCSI == 0) - { - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("Tape_Ready : Can't send SCSI commands, try ioctl\n")); - /* - * Do we get an non negative result. - * If yes this function is available - * and we can use it to get the status - * of the tape - */ - ret = Tape_Status(fd); - if (ret >= 0) - { - while (cnt < wait_time) - { - if ( ret & TAPE_ONLINE) - { - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("Tape_Ready : Ready after %d seconds\n"),cnt); - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP Tape_Ready\n")); - return(0); - /*NOTREACHED*/ - } - cnt++; - sleep(1); - ret = Tape_Status(fd); - } - - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("Tape_Ready : not ready, stop after %d seconds\n"),cnt); - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP Tape_Ready\n")); - return(0); - /*NOTREACHED*/ - - } - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("Tape_Ready : no ioctl interface, will sleep for %d seconds\n"), wait_time); - sleep(wait_time); - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP Tape_Ready\n")); - return(0); - /*NOTREACHED*/ - } - - pRequestSense = alloc(SIZEOF(RequestSense_T)); - - /* - * Ignore errors at this point - */ - GenericRewind(fd); - - /* - * Wait until we get an ready condition - */ - - done = 0; - while (!done && (cnt < wait_time)) - { - ret = SCSI_TestUnitReady(fd, pRequestSense ); - switch (ret) - { - case SCSI_OK: - done = 1; - break; - case SCSI_SENSE: - switch (SenseHandler(fd, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_NO: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeReady (TestUnitReady) SENSE_NO\n")); - done = 1; - break; - case SENSE_TAPE_NOT_ONLINE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeReady (TestUnitReady) SENSE_TAPE_NOT_ONLINE\n")); - break; - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeReady (TestUnitReady) SENSE_IGNORE\n")); - done = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("TapeReady (TestUnitReady) SENSE_ABORT\n")); - amfree(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeReady (TestUnitReady) SENSE_RETRY\n")); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeReady (TestUnitReady) default (SENSE)\n")); - done = 1; - break; - } - break; - case SCSI_ERROR: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("TapeReady (TestUnitReady) SCSI_ERROR\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SCSI_BUSY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeReady (TestUnitReady) SCSI_BUSY\n")); - break; - case SCSI_CHECK: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeReady (TestUnitReady) SCSI_CHECK\n")); - break; - default: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("TapeReady (TestUnitReady) unknown (%d)\n"),ret); - break; - } - sleep(1); - cnt++; - } - - amfree(pRequestSense); - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("Tape_Ready after %d sec\n"), cnt); - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP Tape_Ready\n")); - return(0); -} - - -int -DecodeSCSI( - CDB_T CDB, - char * string) -{ - SC_COM_T *pSCSICommand; - int x; - - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("##### START DecodeSCSI\n")); - pSCSICommand = (SC_COM_T *)&SCSICommand; - - while (pSCSICommand->name != NULL) - { - if (CDB[0] == pSCSICommand->command) - { - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%s %s"), string, pSCSICommand->name); - for (x=0; x < pSCSICommand->length; x++) - { - DebugPrint(DEBUG_INFO, SECTION_SCSI," %02X", CDB[x]); - } - DebugPrint(DEBUG_INFO, SECTION_SCSI,"\n"); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP DecodeSCSI\n")); - return(0); - /*NOTREACHED*/ - } - pSCSICommand++; - } - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("Not found %X\n"), CDB[0]); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP DecodeSCSI\n")); - return(0); -} - -int -DecodeModeSense( - u_char * buffer, - size_t offset, - char * pstring, - char block, - FILE * out) -{ - ReadWriteErrorRecoveryPage_T *prp; - DisconnectReconnectPage_T *pdrp; - size_t length = (size_t)buffer[0] - 4 - offset; - - (void)pstring; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START DecodeModeSense\n")); - - dump_hex(buffer, 255, DEBUG_INFO, SECTION_SCSI); - - /* Jump over the Parameter List header and an offset if we have something - * Unknown at the start (ADIC-218) at the moment - * - */ - buffer = buffer + 4 + offset; - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("buffer length = %d\n"), length); - - if (block) /* Do we have an block descriptor page ?*/ - { - if (out != NULL) - g_fprintf(out, _("DecodeModeSense : Density Code %x\n"), (unsigned)buffer[0]); - buffer++; - - if (out != NULL) - g_fprintf(out, _("DecodeModeSense : Number of Blocks %d\n"), V3(buffer)); - buffer = buffer + 4; - - if (out != NULL) - g_fprintf(out, _("DecodeModeSense : Block Length %d\n"), V3(buffer)); - buffer = buffer + 3; - } - - while (length > 0) - { - switch (*buffer & 0x3f) - { - case 0: - pVendorUnique = buffer; - buffer++; - break; - case 0x1: - prp = (ReadWriteErrorRecoveryPage_T *)buffer; - if (out != NULL) - { - g_fprintf(out, _("DecodeModeSense : Read/Write Error Recovery Page\n")); - g_fprintf(out,_("\tTransfer Block %d\n"), prp->tb); - g_fprintf(out,_("\tEnable Early Recovery %d\n"), prp->eer); - g_fprintf(out,_("\tPost Error %d\n"), prp->per); - g_fprintf(out,_("\tDisable Transfer on Error %d\n"), prp->dte); - g_fprintf(out,_("\tDisable ECC Correction %d\n"), prp->dcr); - g_fprintf(out,_("\tRead Retry Count %d\n"), prp->ReadRetryCount); - g_fprintf(out,_("\tWrite Retry Count %d\n"), prp->WriteRetryCount); - } - buffer++; - break; - case 0x2: - pdrp = (DisconnectReconnectPage_T *)buffer; - if (out != NULL) - { - g_fprintf(out, _("DecodeModeSense : Disconnect/Reconnect Page\n")); - g_fprintf(out,_("\tBuffer Full Ratio %d\n"), pdrp->BufferFullRatio); - g_fprintf(out,_("\tBuffer Empty Ratio %d\n"), pdrp->BufferEmptyRatio); - g_fprintf(out,_("\tBus Inactivity Limit %d\n"), - V2(pdrp->BusInactivityLimit)); - g_fprintf(out,_("\tDisconnect Time Limit %d\n"), - V2(pdrp->DisconnectTimeLimit)); - g_fprintf(out,_("\tConnect Time Limit %d\n"), - V2(pdrp->ConnectTimeLimit)); - g_fprintf(out,_("\tMaximum Burst Size %d\n"), - V2(pdrp->MaximumBurstSize)); - g_fprintf(out,_("\tDTDC %d\n"), pdrp->DTDC); - } - buffer++; - break; - case 0x1d: - pEAAPage = (EAAPage_T *)buffer; - if (out != NULL) - { - g_fprintf(out,_("DecodeModeSense : Element Address Assignment Page\n")); - g_fprintf(out,_("\tMedium Transport Element Address %d\n"), - V2(pEAAPage->MediumTransportElementAddress)); - g_fprintf(out,_("\tNumber of Medium Transport Elements %d\n"), - V2(pEAAPage->NoMediumTransportElements)); - g_fprintf(out, _("\tFirst Storage Element Address %d\n"), - V2(pEAAPage->FirstStorageElementAddress)); - g_fprintf(out, _("\tNumber of Storage Elements %d\n"), - V2(pEAAPage->NoStorageElements)); - g_fprintf(out, _("\tFirst Import/Export Element Address %d\n"), - V2(pEAAPage->FirstImportExportElementAddress)); - g_fprintf(out, _("\tNumber of ImportExport Elements %d\n"), - V2(pEAAPage->NoImportExportElements)); - g_fprintf(out, _("\tFirst Data Transfer Element Address %d\n"), - V2(pEAAPage->FirstDataTransferElementAddress)); - g_fprintf(out, _("\tNumber of Data Transfer Elements %d\n"), - V2(pEAAPage->NoDataTransferElements)); - } - buffer++; - break; - case 0x1f: - pDeviceCapabilitiesPage = (DeviceCapabilitiesPage_T *)buffer; - if (out != NULL) - { - g_fprintf(out, _("DecodeModeSense : MT can store data cartridges %d\n"), - pDeviceCapabilitiesPage->MT); - g_fprintf(out, _("DecodeModeSense : ST can store data cartridges %d\n"), - pDeviceCapabilitiesPage->ST); - g_fprintf(out, _("DecodeModeSense : IE can store data cartridges %d\n"), - pDeviceCapabilitiesPage->IE); - g_fprintf(out, _("DecodeModeSense : DT can store data cartridges %d\n"), - pDeviceCapabilitiesPage->DT); - g_fprintf(out, _("DecodeModeSense : MT to MT %d\n"), - pDeviceCapabilitiesPage->MT2MT); - g_fprintf(out, _("DecodeModeSense : MT to ST %d\n"), - pDeviceCapabilitiesPage->MT2ST); - g_fprintf(out, _("DecodeModeSense : MT to IE %d\n"), - pDeviceCapabilitiesPage->MT2IE); - g_fprintf(out, _("DecodeModeSense : MT to DT %d\n"), - pDeviceCapabilitiesPage->MT2DT); - g_fprintf(out, _("DecodeModeSense : ST to MT %d\n"), - pDeviceCapabilitiesPage->ST2ST); - g_fprintf(out, _("DecodeModeSense : ST to MT %d\n"), - pDeviceCapabilitiesPage->ST2ST); - g_fprintf(out, _("DecodeModeSense : ST to DT %d\n"), - pDeviceCapabilitiesPage->ST2DT); - g_fprintf(out, _("DecodeModeSense : IE to MT %d\n"), - pDeviceCapabilitiesPage->IE2MT); - g_fprintf(out, _("DecodeModeSense : IE to ST %d\n"), - pDeviceCapabilitiesPage->IE2IE); - g_fprintf(out, _("DecodeModeSense : IE to ST %d\n"), - pDeviceCapabilitiesPage->IE2DT); - g_fprintf(out, _("DecodeModeSense : IE to ST %d\n"), - pDeviceCapabilitiesPage->IE2DT); - g_fprintf(out, _("DecodeModeSense : DT to MT %d\n"), - pDeviceCapabilitiesPage->DT2MT); - g_fprintf(out, _("DecodeModeSense : DT to ST %d\n"), - pDeviceCapabilitiesPage->DT2ST); - g_fprintf(out, _("DecodeModeSense : DT to IE %d\n"), - pDeviceCapabilitiesPage->DT2IE); - g_fprintf(out, _("DecodeModeSense : DT to DT %d\n"), - pDeviceCapabilitiesPage->DT2DT); - } - buffer++; - break; - default: - buffer++; /* set pointer to the length information */ - break; - } - /* Error if *buffer (length) is 0 */ - if (*buffer == 0) - { - /* EAAPage = NULL; */ - /* DeviceCapabilitiesPage = NULL; */ - return(-1); - /*NOTREACHED*/ - } - length = length - (size_t)*buffer - 2; - buffer = buffer + (size_t)*buffer + 1; - } - return(0); -} - -int -DecodeSense( - RequestSense_T * sense, - char * pstring, - FILE * out) -{ - if (out == NULL) - { - return(0); - /*NOTREACHED*/ - } - g_fprintf(out,_("##### START DecodeSense\n")); - g_fprintf(out,_("%sSense Keys\n"), pstring); - if (sense->ErrorCode == 0x70) - { - g_fprintf(out,_("\tExtended Sense \n")); - } else { - g_fprintf(out,_("\tErrorCode %02x\n"), sense->ErrorCode); - g_fprintf(out,_("\tValid %d\n"), sense->Valid); - } - g_fprintf(out,_("\tASC %02X\n"), sense->AdditionalSenseCode); - g_fprintf(out,_("\tASCQ %02X\n"), sense->AdditionalSenseCodeQualifier); - g_fprintf(out,_("\tSense key %02X\n"), sense->SenseKey); - switch (sense->SenseKey) - { - case 0: - g_fprintf(out,_("\t\tNo Sense\n")); - break; - case 1: - g_fprintf(out,_("\t\tRecoverd Error\n")); - break; - case 2: - g_fprintf(out,_("\t\tNot Ready\n")); - break; - case 3: - g_fprintf(out,_("\t\tMedium Error\n")); - break; - case 4: - g_fprintf(out,_("\t\tHardware Error\n")); - break; - case 5: - g_fprintf(out,_("\t\tIllegal Request\n")); - break; - case 6: - g_fprintf(out,_("\t\tUnit Attention\n")); - break; - case 7: - g_fprintf(out,_("\t\tData Protect\n")); - break; - case 8: - g_fprintf(out,_("\t\tBlank Check\n")); - break; - case 9: - g_fprintf(out,_("\t\tVendor uniq\n")); - break; - case 0xa: - g_fprintf(out,_("\t\tCopy Aborted\n")); - break; - case 0xb: - g_fprintf(out,_("\t\tAborted Command\n")); - break; - case 0xc: - g_fprintf(out,_("\t\tEqual\n")); - break; - case 0xd: - g_fprintf(out,_("\t\tVolume Overflow\n")); - break; - case 0xe: - g_fprintf(out,_("\t\tMiscompare\n")); - break; - case 0xf: - g_fprintf(out,_("\t\tReserved\n")); - break; - } - return(0); -} - -int -DecodeExtSense( - ExtendedRequestSense_T * sense, - char * pstring, - FILE * out) -{ - ExtendedRequestSense_T *p; - - g_fprintf(out,_("##### START DecodeExtSense\n")); - p = sense; - - g_fprintf(out,_("%sExtended Sense\n"), pstring); - DecodeSense((RequestSense_T *)p, pstring, out); - g_fprintf(out,_("\tLog Parameter Page Code %02X\n"), sense->LogParameterPageCode); - g_fprintf(out,_("\tLog Parameter Code %02X\n"), sense->LogParameterCode); - g_fprintf(out,_("\tUnderrun/Overrun Counter %02X\n"), sense->UnderrunOverrunCounter); - g_fprintf(out,_("\tRead/Write Error Counter %d\n"), V3((char *)sense->ReadWriteDataErrorCounter)); - if (sense->AdditionalSenseLength > (u_char)sizeof(RequestSense_T)) - { - if (sense->PF) - g_fprintf(out,_("\tPower Fail\n")); - if (sense->BPE) - g_fprintf(out,_("\tSCSI Bus Parity Error\n")); - if (sense->FPE) - g_fprintf(out,_("\tFormatted Buffer parity Error\n")); - if (sense->ME) - g_fprintf(out,_("\tMedia Error\n")); - if (sense->ECO) - g_fprintf(out,_("\tError Counter Overflow\n")); - if (sense->TME) - g_fprintf(out,_("\tTapeMotion Error\n")); - if (sense->TNP) - g_fprintf(out,_("\tTape Not Present\n")); - if (sense->LBOT) - g_fprintf(out,_("\tLogical Beginning of tape\n")); - if (sense->TMD) - g_fprintf(out,_("\tTape Mark Detect Error\n")); - if (sense->WP) - g_fprintf(out,_("\tWrite Protect\n")); - if (sense->FMKE) - g_fprintf(out,_("\tFilemark Error\n")); - if (sense->URE) - g_fprintf(out,_("\tUnder Run Error\n")); - if (sense->WEI) - g_fprintf(out,_("\tWrite Error 1\n")); - if (sense->SSE) - g_fprintf(out,_("\tServo System Error\n")); - if (sense->FE) - g_fprintf(out,_("\tFormatter Error\n")); - if (sense->UCLN) - g_fprintf(out,_("\tCleaning Cartridge is empty\n")); - if (sense->RRR) - g_fprintf(out,_("\tReverse Retries Required\n")); - if (sense->CLND) - g_fprintf(out,_("\tTape Drive has been cleaned\n")); - if (sense->CLN) - g_fprintf(out,_("\tTape Drive needs to be cleaned\n")); - if (sense->PEOT) - g_fprintf(out,_("\tPhysical End of Tape\n")); - if (sense->WSEB) - g_fprintf(out,_("\tWrite Splice Error\n")); - if (sense->WSEO) - g_fprintf(out,_("\tWrite Splice Error\n")); - g_fprintf(out,_("\tRemaing 1024 byte tape blocks %d\n"), V3((char *)sense->RemainingTape)); - g_fprintf(out,_("\tTracking Retry Counter %02X\n"), sense->TrackingRetryCounter); - g_fprintf(out,_("\tRead/Write Retry Counter %02X\n"), sense->ReadWriteRetryCounter); - g_fprintf(out,_("\tFault Sympton Code %02X\n"), sense->FaultSymptomCode); - } - return(0); -} - -int -PrintInquiry( - SCSIInquiry_T * SCSIInquiry) -{ - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START PrintInquiry\n")); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %x\n"), "qualifier", SCSIInquiry->qualifier); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %x\n"), "type", SCSIInquiry->type); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %x\n"), "data_format", SCSIInquiry->data_format); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %X\n"), "ansi_version", SCSIInquiry->ansi_version); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %X\n"), "ecma_version", SCSIInquiry->ecma_version); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %X\n"), "iso_version", SCSIInquiry->iso_version); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %X\n"), "type_modifier", SCSIInquiry->type_modifier); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %x\n"), "removable", SCSIInquiry->removable); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %.8s\n"), "vendor_info", SCSIInquiry->vendor_info); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %.16s\n"), "prod_ident", SCSIInquiry->prod_ident); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %.4s\n"), "prod_version", SCSIInquiry->prod_version); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("%-15s %.19s\n"), "vendor_specific", SCSIInquiry->vendor_specific); - return(0); -} - - -int -DoNothing0(void) -{ - dbprintf(_("##### START DoNothing\n")); - return(0); -} - -int -DoNothing1( - int unused1) -{ - (void)unused1; /* Quiet unused parameter warning */ - - dbprintf(_("##### START DoNothing\n")); - return(0); -} - -int -DoNothing2( - int unused1, - int unused2) -{ - (void)unused1; /* Quiet unused parameter warning */ - (void)unused2; /* Quiet unused parameter warning */ - - dbprintf(_("##### START DoNothing\n")); - return(0); -} - -int -DoNothing3( - int unused1, - int unused2, - int unused3) -{ - (void)unused1; /* Quiet unused parameter warning */ - (void)unused2; /* Quiet unused parameter warning */ - (void)unused3; /* Quiet unused parameter warning */ - - dbprintf(_("##### START DoNothing\n")); - return(0); -} - -int -GenericFree(void) -{ - dbprintf(_("##### START GenericFree\n")); - return(0); -} - -int -GenericSearch(void) -{ - dbprintf(_("##### START GenericSearch\n")); - return(0); -} - -int -TreeFrogBarCode( - int DeviceFD) -{ - extern OpenFiles_T *pDev; - - ModePageTreeFrogVendorUnique_T *pVendor; - - dbprintf(_("##### START TreeFrogBarCode\n")); - if (pModePage == NULL) - { - pModePage = alloc(0xff); - } - - if (SCSI_ModeSense(DeviceFD, pModePage, 0xff, 0x0, 0x3f) == 0) - { - DecodeModeSense(pModePage, 0, _("TreeFrogBarCode :"), 0, debug_file); - - if (pVendorUnique == NULL) - { - dbprintf(_("TreeFrogBarCode : no pVendorUnique\n")); - return(0); - /*NOTREACHED*/ - } - pVendor = ( ModePageTreeFrogVendorUnique_T *)pVendorUnique; - - dbprintf(_("TreeFrogBarCode : EBARCO %d\n"), pVendor->EBARCO); - dbprintf(_("TreeFrogCheckSum : CHKSUM %d\n"), pVendor->CHKSUM); - - dump_hex((u_char *)pDev[INDEX_CHANGER].inquiry, INQUIRY_SIZE, DEBUG_INFO, SECTION_ELEMENT); - return(pVendor->EBARCO); - /*NOTREACHED*/ - } - return(0); -} - -int -EXB_BarCode( - int DeviceFD) -{ - extern OpenFiles_T *pDev; - - ModePageEXB120VendorUnique_T *pVendor; - ModePageEXB120VendorUnique_T *pVendorWork; - - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("##### START EXB_BarCode\n")); - if (pModePage == NULL && LibModeSenseValid == 0) - { - pModePage = alloc(0xff); - - if (SCSI_ModeSense(DeviceFD, pModePage, 0xff, 0x8, 0x3f) == 0) - { - DecodeModeSense(pModePage, 0, _("EXB_BarCode :"), 0, debug_file); - LibModeSenseValid = 1; - } else { - LibModeSenseValid = -1; - } - } - - if (LibModeSenseValid == 1) - { - if (pVendorUnique == NULL) - { - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("EXB_BarCode : no pVendorUnique\n")); - return(0); - /*NOTREACHED*/ - } - pVendor = ( ModePageEXB120VendorUnique_T *)pVendorUnique; - - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("EXB_BarCode : NBL %d\n"), pVendor->NBL); - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("EXB_BarCode : PS %d\n"), pVendor->PS); - if (pVendor->NBL == 1 && pVendor->PS == 1 ) - { - pVendorWork = alloc((size_t)pVendor->ParameterListLength + 2); - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("EXB_BarCode : setting NBL to 1\n")); - memcpy(pVendorWork, pVendor, (size_t)pVendor->ParameterListLength + 2); - pVendorWork->NBL = 0; - pVendorWork->PS = 0; - pVendorWork->RSVD0 = 0; - if (SCSI_ModeSelect(DeviceFD, (u_char *)pVendorWork, (u_char)(pVendorWork->ParameterListLength + 2), 0, 1, 0) == 0) - { - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("EXB_BarCode : SCSI_ModeSelect OK\n")); - /* Hack !!!!!! - */ - pVendor->NBL = 0; - - /* And now again !!! - */ - GenericResetStatus(DeviceFD); - } else { - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("EXB_BarCode : SCSI_ModeSelect failed\n")); - } - amfree(pVendorWork); - } - dump_hex((u_char *)pDev[INDEX_CHANGER].inquiry, INQUIRY_SIZE, DEBUG_INFO, SECTION_BARCODE); - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("EXB_BarCode : vendor_specific[19] %x\n"), - pDev[INDEX_CHANGER].inquiry->vendor_specific[19]); - } - return(1); -} - -int -NoBarCode( - int DeviceFD) -{ - (void)DeviceFD; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("##### START NoBarCode\n")); - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("##### STOP NoBarCode\n")); - return(0); -} - -int -GenericBarCode( - int DeviceFD) -{ - (void)DeviceFD; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("##### START GenericBarCode\n")); - if ( changer->havebarcode >= 1) - { - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("##### STOP GenericBarCode (havebarcode) => %d\n"),changer->havebarcode); - return(1); - /*NOTREACHED*/ - } - DebugPrint(DEBUG_INFO, SECTION_BARCODE,_("##### STOP GenericBarCode => 0\n")); - return(0); -} - -int -SenseHandler( - int DeviceFD, - u_char flag, - u_char SenseKey, - u_char AdditionalSenseCode, - u_char AdditionalSenseCodeQualifier, - RequestSense_T * buffer) -{ - extern OpenFiles_T *pDev; - int ret = 0; - dbprintf(_("##### START SenseHandler\n")); - if (pDev[DeviceFD].inqdone == 1) - { - dbprintf(_("Ident = [%s], function = [%s]\n"), pDev[DeviceFD].ident, - pDev[DeviceFD].functions->ident); - ret = pDev[DeviceFD].functions->function_error(DeviceFD, flag, SenseKey, AdditionalSenseCode, AdditionalSenseCodeQualifier, buffer); - } else { - dbprintf(_(" Ups no sense\n")); - } - dbprintf(_("#### STOP SenseHandler\n")); - return(ret); -} - -/* - * Try to get information about the tape, - * Tape loaded ? Online etc - * Use the mtio ioctl to get the information if no SCSI Path - * to the tape drive is available. - * - * TODO: - * Pass an parameter to identify which unit to use - * if there are more than one - * Implement the SCSI path if available -*/ -int -TapeStatus(void) -{ - extern OpenFiles_T *pDev; - int ret; - int done; - int cnt; - RequestSense_T *pRequestSense; - - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### START TapeStatus\n")); - - /* - * If it is an device which understand SCSI commands the - * normal ioctl (MTIOCGET for example) may fail - * So try an Inquiry - */ - if (pDev[INDEX_TAPECTL].SCSI == 1) - { - pRequestSense = alloc(SIZEOF(RequestSense_T)); - memset(pRequestSense, 0, SIZEOF(RequestSense_T)); - - for (done = 0, cnt = 0; !done && (cnt < 60); cnt++) - { - ret = SCSI_TestUnitReady(INDEX_TAPECTL, pRequestSense); - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("TapeStatus TestUnitReady ret %d\n"),ret); - switch (ret) - { - case SCSI_OK: - case SCSI_SENSE: - switch (SenseHandler(INDEX_TAPECTL, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_IGNORE: - case SENSE_NO: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeStatus (TestUnitReady) SENSE_NO\n")); - pDTE[0].status = 'F'; - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### FULL\n")); - done = 1; - break; - - case SENSE_TAPE_NOT_ONLINE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeStatus (TestUnitReady) SENSE_TAPE_NOT_ONLINE\n")); - pDTE[0].status = 'E'; - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### EMPTY\n")); - done = 1; - break; - - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("TapeStatus (TestUnitReady) SENSE_ABORT\n")); - done = 1; - break; - - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeStatus (TestUnitReady) SENSE_RETRY\n")); - break; - - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeStatus (TestUnitReady) default (SENSE)\n")); - break; - } - break; - - case SCSI_ERROR: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("TapeStatus (TestUnitReady) SCSI_ERROR\n")); - done = 1; - break; - - case SCSI_BUSY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeStatus (TestUnitReady) SCSI_BUSY\n")); - break; - - case SCSI_CHECK: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("TapeStatus (TestUnitReady) SCSI_CHECK\n")); - break; - - default: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("TapeStatus (TestUnitReady) unknown (%d)\n"),ret); - break; - - } - if (!done) - sleep(2); - } - amfree(pRequestSense); - } else { - ret = Tape_Status(INDEX_TAPE); - if ( ret & TAPE_ONLINE) - { - pDTE[0].status ='F'; - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### FULL\n")); - } else { - pDTE[0].status = 'E'; - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### EMPTY\n")); - } - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP TapeStatus\n")); - } - return(0); -} - -int -DLT4000Eject( - char * Device, - int type) -{ - extern OpenFiles_T *pDev; - - RequestSense_T *pRequestSense; - ExtendedRequestSense_T *pExtendedRequestSense; - int ret; - int cnt = 0; - int done; - - (void)Device; /* Quiet unused parameter warning */ - - dbprintf(_("##### START DLT4000Eject\n")); - - pRequestSense = alloc(SIZEOF(RequestSense_T)); - pExtendedRequestSense = alloc(SIZEOF(ExtendedRequestSense_T)); - - if ( type > 1) - { - dbprintf(_("DLT4000Eject : use mtio ioctl for eject on %s\n"), pDev[INDEX_TAPE].dev); - free(pExtendedRequestSense); - free(pRequestSense); - return(Tape_Ioctl(INDEX_TAPE, IOCTL_EJECT)); - /*NOTREACHED*/ - } - - - - if (pDev[INDEX_TAPECTL].SCSI == 0) - { - dbprintf(_("DLT4000Eject : Device %s not able to receive SCSI commands\n"), pDev[INDEX_TAPE].dev); - free(pExtendedRequestSense); - free(pRequestSense); - return(Tape_Ioctl(INDEX_TAPE, IOCTL_EJECT)); - /*NOTREACHED*/ - } - - - dbprintf(_("DLT4000Eject : SCSI eject on %s = %s\n"), pDev[INDEX_TAPECTL].dev, pDev[INDEX_TAPECTL].ConfigName); - - RequestSense(INDEX_TAPECTL, pExtendedRequestSense, 0); - DecodeExtSense(pExtendedRequestSense, _("DLT4000Eject : "), debug_file); - /* Unload the tape, 0 == wait for success - * 0 == unload - */ - ret = SCSI_LoadUnload(INDEX_TAPECTL, pRequestSense, 0, 0); - - RequestSense(INDEX_TAPECTL, pExtendedRequestSense, 0); - DecodeExtSense(pExtendedRequestSense, _("DLT4000Eject : "), debug_file); - - /* < 0 == fatal */ - if (ret >= 0) { - free(pExtendedRequestSense); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - } - - done = 0; - while (!done && cnt < 300) - { - ret = SCSI_TestUnitReady(INDEX_TAPECTL, pRequestSense); - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("DLT4000Eject TestUnitReady ret %d\n"),ret); - switch (ret) - { - case SCSI_OK: - done = 1; - break; - case SCSI_SENSE: - switch (SenseHandler(INDEX_TAPECTL, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_NO: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) SENSE_NO\n")); - done = 1; - break; - case SENSE_TAPE_NOT_ONLINE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) SENSE_TAPE_NOT_ONLINE\n")); - done = 1; - break; - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) SENSE_IGNORE\n")); - done = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) SENSE_ABORT\n")); - free(pExtendedRequestSense); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) SENSE_RETRY\n")); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) default (SENSE)\n")); - done = 1; - break; - } - break; - case SCSI_ERROR: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) SCSI_ERROR\n")); - free(pExtendedRequestSense); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SCSI_BUSY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) SCSI_BUSY\n")); - break; - case SCSI_CHECK: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) SCSI_CHECK\n")); - break; - default: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("DLT4000Eject (TestUnitReady) unknown (%d)\n"),ret); - break; - } - - cnt++; - sleep(2); - } - - dbprintf(_("DLT4000Eject : Ready after %d sec, done = %d\n"), cnt * 2, done); - - free(pExtendedRequestSense); - free(pRequestSense); - - return(0); -} - -/* - * Ejects an tape either with the ioctl interface - * or by using the SCSI interface if available. - * - * TODO: - * Before unload check if there is an tape in the drive - * - */ -int -GenericEject( - char * Device, - int type) -{ - extern OpenFiles_T *pDev; - RequestSense_T *pRequestSense; - int ret; - int cnt = 0; - int done; - - (void)Device; /* Quiet unused parameter warning */ - (void)type; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO, SECTION_TAPE, _("##### START GenericEject\n")); - - pRequestSense = alloc(SIZEOF(RequestSense_T)); - - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("GenericEject : SCSI eject on %s = %s\n"), - pDev[INDEX_TAPECTL].dev, pDev[INDEX_TAPECTL].ConfigName); - - /* - * Can we use SCSI commands ? - */ - if (pDev[INDEX_TAPECTL].SCSI == 1) - { - LogSense(INDEX_TAPECTL); - /* - * Unload the tape, 1 == don't wait for success - * 0 == unload - */ - ret = SCSI_LoadUnload(INDEX_TAPECTL, pRequestSense, 1, 0); - - /* < 0 == fatal */ - if (ret < 0) { - DebugPrint(DEBUG_INFO, SECTION_SCSI,"GenericEject SCSI_LoadUnload failed\n"); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - } - - done = 0; - while (!done && cnt < 300) - { - ret = SCSI_TestUnitReady(INDEX_TAPECTL, pRequestSense); - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("GenericEject TestUnitReady ret %d\n"),ret); - switch (ret) - { - case SCSI_OK: - case SCSI_SENSE: - switch (SenseHandler(INDEX_TAPECTL, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_NO: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericEject (TestUnitReady) SENSE_NO\n")); - break; - case SENSE_TAPE_NOT_ONLINE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericEject (TestUnitReady) SENSE_TAPE_NOT_ONLINE\n")); - done = 1; - break; - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericEject (TestUnitReady) SENSE_IGNORE\n")); - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("GenericEject (TestUnitReady) SENSE_ABORT\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericEject (TestUnitReady) SENSE_RETRY\n")); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericEject (TestUnitReady) default (SENSE)\n")); - break; - } - break; - case SCSI_ERROR: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("GenericEject (TestUnitReady) SCSI_ERROR\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SCSI_BUSY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericEject (TestUnitReady) SCSI_BUSY\n")); - break; - case SCSI_CHECK: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericEject (TestUnitReady) SCSI_CHECK\n")); - break; - default: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("GenericEject (TestUnitReady) unknown (%d)\n"),ret); - break; - } - cnt++; - sleep(2); - } - } else { - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("GenericEject : Device can't understand SCSI try ioctl\n")); - Tape_Ioctl(INDEX_TAPECTL, IOCTL_EJECT); - } - DebugPrint(DEBUG_INFO, SECTION_TAPE, - _("GenericEject : Ready after %d sec\n"), cnt * 2); - free(pRequestSense); - return(0); -} - -/* - * Rewind the tape - * - * TODO: - * Make the retry counter an config option, - * - * Return: - * -1 -> error - * 0 -> success - */ -int -GenericRewind( - int DeviceFD) -{ - CDB_T CDB; - extern OpenFiles_T *pDev; - RequestSense_T *pRequestSense; - int ret; - int cnt = 0; - int done; - - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### START GenericRewind pDEV -> %d\n"),DeviceFD); - - - /* - * If we can use the SCSI device than use it, else use the ioctl - * function - */ - if (pDev[DeviceFD].SCSI == 1) - { - pRequestSense = alloc(SIZEOF(RequestSense_T)); - - /* - * Before doing the rewind check if the tape is ready to accept commands - */ - - done = 0; - while (!done) - { - ret = SCSI_TestUnitReady(DeviceFD, (RequestSense_T *)pRequestSense ); - DebugPrint(DEBUG_INFO, SECTION_TAPE, _("GenericRewind (TestUnitReady) ret %d\n"),ret); - switch (ret) - { - case SCSI_OK: - done = 1; - break; - case SCSI_SENSE: - switch (SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_NO: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_NO\n")); - done = 1; - break; - case SENSE_TAPE_NOT_ONLINE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_TAPE_NOT_ONLINE\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_IGNORE\n")); - done = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_ABORT\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_RETRY\n")); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) default (SENSE)\n")); - done = 1; - break; - } /* switch (SenseHandler(DeviceFD, 0, pRequestSense->SenseKey.... */ - break; - - case SCSI_ERROR: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("GenericRewind (TestUnitReady) SCSI_ERROR\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - - case SCSI_BUSY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SCSI_BUSY\n")); - break; - case SCSI_CHECK: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SCSI_CHECK\n")); - break; - default: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("GenericRewind (TestUnitReady) unknown (%d)\n"),ret); - break; - } - - sleep(1); - DebugPrint(DEBUG_INFO, SECTION_TAPE,_(" Wait .... (%d)\n"),cnt); - if (cnt > 180) - { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("##### STOP GenericRewind (-1)\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - } - } /* while !done */ - - cnt = 0; - - CDB[0] = SC_COM_REWIND; - CDB[1] = 1; - CDB[2] = 0; - CDB[3] = 0; - CDB[4] = 0; - CDB[5] = 0; - - done = 0; - while (!done) - { - ret = SCSI_Run(DeviceFD, Input, CDB, 6, - NULL, 0, - pRequestSense, - SIZEOF(RequestSense_T)); - - DecodeSense(pRequestSense, _("GenericRewind : "), debug_file); - - if (ret > 0) - { - if (pRequestSense->SenseKey != UNIT_ATTENTION) - { - done = 1; - } - } - if (ret == 0) - { - done = 1; - } - if (ret < 0) - { - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("GenericRewind : failed %d\n"), ret); - done = 1; - } - } - - done = 0; - while (!done && (cnt < 300)) - { - ret = SCSI_TestUnitReady(DeviceFD, pRequestSense); - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("GenericRewind TestUnitReady ret %d\n"),ret); - switch (ret) - { - case SCSI_OK: - done = 1; - break; - case SCSI_SENSE: - switch (SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_NO: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_NO\n")); - done = 1; - break; - case SENSE_TAPE_NOT_ONLINE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_TAPE_NOT_ONLINE\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_IGNORE\n")); - done = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_ABORT\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SENSE_RETRY\n")); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) default (SENSE)\n")); - done = 1; - break; - } - break; - case SCSI_ERROR: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("GenericRewind (TestUnitReady) SCSI_ERROR\n")); - return(-1); - /*NOTREACHED*/ - - case SCSI_BUSY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SCSI_BUSY\n")); - break; - case SCSI_CHECK: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("GenericRewind (TestUnitReady) SCSI_CHECK\n")); - break; - default: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("GenericRewind (TestUnitReady) unknown (%d)\n"),ret); - break; - } - - cnt++; - sleep(2); - } - - amfree(pRequestSense); - - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("GenericRewind : Ready after %d sec, " - "done = %d\n"), cnt * 2, done); - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP GenericRewind (0)\n")); - } else { - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("GenericRewind : use ioctl rewind\n")); - if (pDev[DeviceFD].devopen == 1) - { - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("Close Device\n")); - SCSI_CloseDevice(DeviceFD); - } - /* no actual rewind operation here -- the device itself will handle that */ - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP GenericRewind (0)\n")); - } - - return(0); -} - - -/* - * Check if the tape has the tape clean - * bit set in the return of an request sense - * - */ -int -GenericClean( - char * Device) -{ - extern OpenFiles_T *pDev; - ExtendedRequestSense_T ExtRequestSense; - int ret = 0; - - (void)Device; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### START GenericClean\n")); - if (pDev[INDEX_TAPECTL].SCSI == 0) - { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("GenericClean : can't send SCSI commands\n")); - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("##### STOP GenericClean\n")); - return(0); - /*NOTREACHED*/ - } - - /* - * Request Sense Data, reset the counter - */ - if ( RequestSense(INDEX_TAPECTL, &ExtRequestSense, 1) == 0) - { - - DecodeExtSense(&ExtRequestSense, _("GenericClean : "), debug_file); - if(ExtRequestSense.CLN) { - ret = 1; - } else { - ret = 0; - } - } else { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,_("Got error from RequestSense\n")); - } - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP GenericClean (%d)\n"),ret); - return(ret); -} - -int -SCSI_LogSenseClean( - char * Device) -{ - extern OpenFiles_T *pDev; - CDB_T CDB; - RequestSense_T *pRequestSense; - int ret = 0; - u_char *buffer; - size_t size = 128; - - (void)Device; /* Quiet unused parameter warning */ - DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### START SCSI_LogSenseClean\n"); - if (pDev[INDEX_TAPECTL].SCSI == 0) - { - DebugPrint(DEBUG_ERROR, SECTION_TAPE,"SCSILogSenseClean : can't send SCSI commands\n"); - DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP SCSI_LogSenseClean\n"); - return(0); - /*NOTREACHED*/ - } - - if (NULL == (buffer = alloc(size))){ - DebugPrint(DEBUG_ERROR, SECTION_TAPE,"SCSI_LogSenseClean : can't alloc buffer\n"); - DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP SCSI_LogSenseClean\n"); - return(0); - } - if (NULL == (pRequestSense = alloc(SIZEOF(RequestSense_T)))){ - DebugPrint(DEBUG_ERROR, SECTION_TAPE,"SCSI_LogSenseClean : can't alloc memory\n"); - DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP SCSI_LogSenseClean\n"); - return(0); - } - - memset(buffer, 0, size); - CDB[0] = SC_COM_LOG_SENSE; - CDB[1] = 0; - CDB[2] = (u_char)(0x40 | 0x33);/* 0x40 for current values 0x33 Head Cleaning Page*/ - CDB[3] = 0; - CDB[4] = 0; - CDB[5] = 0; - CDB[6] = 00; - MSB2(&CDB[7], size); - CDB[9] = 0; - - if (SCSI_Run(INDEX_TAPECTL, Input, CDB, 10, - buffer, - size, - pRequestSense, - SIZEOF(RequestSense_T)) != 0) - { - DecodeSense(pRequestSense, "SCSI_LogSenseClean : ",debug_file); - free(pRequestSense); - free(buffer); - DebugPrint(DEBUG_ERROR, SECTION_TAPE,"##### STOP SCSI_LogSenseClean (0) Page could not be read.\n"); - return(0); - /*NOTREACHED*/ - } - if (1==(0x1 & buffer[8])){ /* Bit 0 of the 4th byte in the Clean Head Log Parameter, which are the bytes */ - /* 4 to 8 on the Log Sense Page 0x33 */ - ret = 1; - }else { - ret = 0; - } - DebugPrint(DEBUG_INFO, SECTION_TAPE,"##### STOP SCSI_LogSenseClean (%d)\n",ret); - free(pRequestSense); - free(buffer); - return(ret); -} - -int -GenericResetStatus( - int DeviceFD) -{ - CDB_T CDB; - RequestSense_T *pRequestSense; - int ret = 0; - int retry = 1; - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT, _("##### START GenericResetStatus\n")); - - pRequestSense = alloc(SIZEOF(RequestSense_T)); - - while (retry) - { - CDB[0] = SC_COM_IES; /* */ - CDB[1] = 0; - CDB[2] = 0; - CDB[3] = 0; - CDB[4] = 0; - CDB[5] = 0; - - - ret = SCSI_Run(DeviceFD, Input, CDB, 6, - NULL, 0, - pRequestSense, - SIZEOF(RequestSense_T)); - - if (ret < 0) - { - /* g_fprintf(stderr, _("%s: Request Sense[Inquiry]: %02X"), */ - /* "chs", ((u_char *) &pRequestSense)[0]); */ - /* for (i = 1; i < SIZEOF(RequestSense_T); i++) */ - /* g_fprintf(stderr, " %02X", ((u_char *) &pRequestSense)[i]); */ - /* g_fprintf(stderr, "\n"); */ - free(pRequestSense); - return(ret); - /*NOTREACHED*/ - } - if ( ret > 0 ) - { - switch (SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_IGNORE: - free(pRequestSense); - return(0); - /*NOTREACHED*/ - case SENSE_ABORT: - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - case SENSE_RETRY: - retry++; - if (retry < MAX_RETRIES ) - { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT, _("GenericResetStatus : retry %d\n"), retry); - sleep(2); - } else { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("GenericResetStatus : return (-1)\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - } - break; - default: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("GenericResetStatus : (default) return (-1)\n")); - free(pRequestSense); - return(-1); - /*NOTREACHED*/ - } - } - if (ret == 0) - retry = 0; - } - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("##### STOP GenericResetStatus (%d)\n"),ret); - free(pRequestSense); - return(ret); -} - -/* GenericSenseHandler - * Handles the conditions/sense wich is returned by an SCSI command - * pwork is an pointer to the structure OpenFiles_T, which is filled with information - * about the device to which we talk. Information are for example - * The vendor, the ident, which fd, etc. This strucure is filled when we open the - * device - * flag tells how to handle the information passed in the buffer, - * 0 -> Sense Key available - * 1 -> No Sense key available - * buffer is a pointer to the data from the request sense result. - * - * TODO: - * Limit recursion, may run in an infinite loop - */ -int -GenericSenseHandler( - int ip, - u_char flag, - u_char SenseKey, - u_char AdditionalSenseCode, - u_char AdditionalSenseCodeQualifier, - RequestSense_T * pRequestSense) -{ - extern OpenFiles_T *pDev; - int ret; - char *info = NULL; - - dbprintf(_("##### START GenericSenseHandler\n")); - - DecodeSense(pRequestSense, _("GenericSenseHandler : "), debug_file); - - ret = Sense2Action(pDev[ip].ident, - pDev[ip].inquiry->type, - flag, SenseKey, - AdditionalSenseCode, - AdditionalSenseCodeQualifier, - &info); - - dbprintf(_("##### STOP GenericSenseHandler: %s\n"), _(info)); - return(ret); -} - -/* - * Do the move. We don't address the MTE element (the gripper) - * here. We assume that the library use the right MTE. - * The difference to GenericMove is that we do an align element - * before the move. - * - * Return: - * == 0 -> success - * != 0 -> error either from the SCSI command or from - * the element handling - * TODO: -*/ -int -SDXMove( - int DeviceFD, - int from, - int to) -{ - extern OpenFiles_T *pDev; - ElementInfo_T *pfrom; - ElementInfo_T *pto; - int ret; - int tapestat; - int moveok; - int SDX_MTE = 0; /* This are parameters passed */ - int SDX_STE = -1; /* to */ - int SDX_DTE = -1; /* AlignElements */ - - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### START SDXMove\n")); - - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("%-20s : from = %d, to = %d\n"), "SDXMove", from, to); - - - if ((pfrom = LookupElement(from)) == NULL) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("SDXMove : ElementInfo for %d not found\n"), from); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP SDXMove\n")); - return(-1); - /*NOTREACHED*/ - } - - if ((pto = LookupElement(to)) == NULL) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("SDXMove : ElementInfo for %d not found\n"), to); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP SDXMove\n")); - return(-1); - /*NOTREACHED*/ - } - - if (pfrom->status == 'E') - { - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("SDXMove : from %d is empty\n"), from); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP SDXMove\n")); - return(-1); - /*NOTREACHED*/ - } - - if (pto->status == 'F') - { - switch (pto->status) - { - case CHANGER: - break; - case STORAGE: - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("SDXMove : Destination Element %d Type %d is full\n"), - pto->address, pto->type); - to = find_empty(DeviceFD, 0, 0); - if (to == -1 ) - { - DebugPrint(DEBUG_ERROR, SECTION_MOVE,_("SDXMove : no empty slot found for unload\n")); - return(-1); - /*NOTREACHED*/ - } - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("SDXMove : Unload to %d\n"), to); - if ((pto = LookupElement(to)) == NULL) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("SDXMove : ElementInfo for %d not found\n"), to); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP SDXMove\n")); - return(-1); - /*NOTREACHED*/ - } - break; - case IMPORT: - break; - case TAPETYPE: - break; - } - } - - moveok = CheckMove(pfrom, pto); - - switch (pto->type) - { - case TAPETYPE: - SDX_DTE = pto->address; - break; - case STORAGE: - SDX_STE = pto->address; - break; - case IMPORT: - SDX_STE = pto->address; - break; - } - - switch (pfrom->type) - { - case TAPETYPE: - SDX_DTE = pfrom->address; - break; - case STORAGE: - SDX_STE = pfrom->address; - break; - case IMPORT: - SDX_STE = pfrom->address; - break; - } - - if (SDX_DTE >= 0 && SDX_STE >= 0) - { - ret = SCSI_AlignElements(DeviceFD, SDX_MTE, SDX_DTE, SDX_STE); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### SCSI_AlignElemnts ret = %d\n"),ret); - if (ret != 0 ) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP SDXMove\n")); - return(-1); - /*NOTREACHED*/ - } - } else { - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### Error setting STE/DTE %d/%d\n"), SDX_STE, SDX_DTE); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP SDXMove\n")); - return(-1); - /*NOTREACHED*/ - } - - /* - * If from is a tape we must check if it is loaded - * and if yes we have to eject it - */ - if (pfrom->type == TAPETYPE) - { - tapestat = Tape_Status(INDEX_TAPE); - if ( tapestat & TAPE_ONLINE) - { - if (pDev[INDEX_TAPECTL].SCSI == 1) - { - ret = eject_tape(pDev[INDEX_TAPECTL].dev,1); - } else { - ret = eject_tape(pDev[INDEX_TAPE].dev,2); - } - } - } - - if ((ret == 0) && moveok) - { - ret = SCSI_Move(DeviceFD, 0, from, to); - } else { - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP SDXMove\n")); - return(ret); - /*NOTREACHED*/ - } - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP SDXMove\n")); - return(ret); -} - -/* - * Do the move. We don't address the MTE element (the gripper) - * here. We assume that the library use the right MTE - * - * Return: - * == 0 -> success - * != 0 -> error either from the SCSI command or from - * the element handling - * TODO: -*/ -int -GenericMove( - int DeviceFD, - int from, - int to) -{ - ElementInfo_T *pfrom; - ElementInfo_T *pto; - int ret = 0; - - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("##### START GenericMove\n")); - - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("%-20s : from = %d, to = %d\n"), "GenericMove", from, to); - - - if ((pfrom = LookupElement(from)) == NULL) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("GenericMove : ElementInfo for %d not found\n"), from); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP GenericMove\n")); - return(-1); - /*NOTREACHED*/ - } - - if ((pto = LookupElement(to)) == NULL) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("GenericMove : ElementInfo for %d not found\n"), to); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP GenericMove\n")); - return(-1); - /*NOTREACHED*/ - } - - if (pfrom->status == 'E') - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("GenericMove : from %d is empty\n"), from); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP GenericMove\n")); - return(-1); - /*NOTREACHED*/ - } - - if (pto->status == 'F') - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("GenericMove : Destination Element %d Type %d is full\n"), - pto->address, pto->type); - to = find_empty(DeviceFD, 0, 0); - if ( to == -1) - { - DebugPrint(DEBUG_ERROR, SECTION_MOVE, _("GenericMove : no empty slot found\n")); - return(-1); - /*NOTREACHED*/ - } - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("GenericMove : Unload to %d\n"), to); - if ((pto = LookupElement(to)) == NULL) - { - DebugPrint(DEBUG_ERROR, SECTION_MOVE, _(" Ups should not happen\n")); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP GenericMove\n")); - return(-1); - /*NOTREACHED*/ - } - } - - if (CheckMove(pfrom, pto)) - { - ret = SCSI_Move(DeviceFD, 0, from, to); - } - - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("GenericMove : SCSI_Move return (%d)\n"), ret); - DebugPrint(DEBUG_INFO, SECTION_MOVE,_("##### STOP GenericMove\n")); - return(ret); -} - -/* - * Check if a move based on the information we got from the Mode Sense command - * is legal - * Return Values: - * 1 => OK - * 0 => Not OK - */ - -int -CheckMove( - ElementInfo_T * from, - ElementInfo_T * to) -{ - int moveok = 0; - - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("##### START CheckMove\n")); - if (pDeviceCapabilitiesPage != NULL ) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("CheckMove : checking if move from %d to %d is legal\n"), from->address, to->address); - switch (from->type) - { - case CHANGER: - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("CheckMove : MT2")); - switch (to->type) - { - case CHANGER: - if (pDeviceCapabilitiesPage->MT2MT == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("MT\n")); - moveok = 1; - } - break; - case STORAGE: - if (pDeviceCapabilitiesPage->MT2ST == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("ST\n")); - moveok = 1; - } - break; - case IMPORT: - if (pDeviceCapabilitiesPage->MT2IE == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("IE\n")); - moveok = 1; - } - break; - case TAPETYPE: - if (pDeviceCapabilitiesPage->MT2DT == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("DT\n")); - moveok = 1; - } - break; - default: - break; - } - break; - case STORAGE: - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("CheckMove : ST2")); - switch (to->type) - { - case CHANGER: - if (pDeviceCapabilitiesPage->ST2MT == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("MT\n")); - moveok = 1; - } - break; - case STORAGE: - if (pDeviceCapabilitiesPage->ST2ST == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("ST\n")); - moveok = 1; - } - break; - case IMPORT: - if (pDeviceCapabilitiesPage->ST2IE == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("IE\n")); - moveok = 1; - } - break; - case TAPETYPE: - if (pDeviceCapabilitiesPage->ST2DT == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("DT\n")); - moveok = 1; - } - break; - default: - break; - } - break; - case IMPORT: - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("CheckMove : IE2")); - switch (to->type) - { - case CHANGER: - if (pDeviceCapabilitiesPage->IE2MT == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("MT\n")); - moveok = 1; - } - break; - case STORAGE: - if (pDeviceCapabilitiesPage->IE2ST == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("ST\n")); - moveok = 1; - } - break; - case IMPORT: - if (pDeviceCapabilitiesPage->IE2IE == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("IE\n")); - moveok = 1; - } - break; - case TAPETYPE: - if (pDeviceCapabilitiesPage->IE2DT == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("DT\n")); - moveok = 1; - } - break; - default: - break; - } - break; - case TAPETYPE: - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("CheckMove : DT2")); - switch (to->type) - { - case CHANGER: - if (pDeviceCapabilitiesPage->DT2MT == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("MT\n")); - moveok = 1; - } - break; - case STORAGE: - if (pDeviceCapabilitiesPage->DT2ST == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("ST\n")); - moveok = 1; - } - break; - case IMPORT: - if (pDeviceCapabilitiesPage->DT2IE == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("IE\n")); - moveok = 1; - } - break; - case TAPETYPE: - if (pDeviceCapabilitiesPage->DT2DT == 1) - { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("DT\n")); - moveok = 1; - } - break; - default: - break; - } - break; - default: - break; - } - } else { - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("CheckMove : pDeviceCapabilitiesPage == NULL")); - /* - ChgExit("CheckMove", _("DeviceCapabilitiesPage == NULL"), FATAL); - */ - moveok=1; - } - - DebugPrint(DEBUG_INFO, SECTION_MOVE, _("###### STOP CheckMove\n")); - return(moveok); -} - -/* - */ - -int -GetCurrentSlot( - int fd, - int drive) -{ - extern OpenFiles_T *pDev; - size_t x; - dbprintf(_("##### START GetCurrentSlot\n")); - - (void)fd; /* Quiet unused parameter warning */ - - if (pDev[0].SCSI == 0) - { - dbprintf(_("GetCurrentSlot : can't send SCSI commands\n")); - return(-1); - /*NOTREACHED*/ - } - - if (ElementStatusValid == 0) - { - if (pDev[0].functions->function_status(0, 1) != 0) - { - return(-1); - /*NOTREACHED*/ - } - } - - /* If the from address is the as the same as the tape address skip it */ - if (pDTE[drive].from >= 0 && pDTE[drive].from != pDTE[drive].address) - { - for (x = 0; x < STE;x++) - { - if (pSTE[x].address == pDTE[drive].from) - return(x); - /*NOTREACHED*/ - } - return(-1); - /*NOTREACHED*/ - } - - for (x = 0; x < STE;x++) - { - if (pSTE[x].status == 'E') { - return(x); - /*NOTREACHED*/ - } - } - - /* Ups nothing loaded */ - return(-1); -} - - - -/* - * Reworked function to get the ElementStatus - * This function will first call the GetElementStatus - * function to get the Element status, - * and than check if there are abnormal conditions. - * - * If there are error conditions try to fix them - * - */ -int -GenericElementStatus( - int DeviceFD, - int InitStatus) -{ - int MTEError = 0; - int STEError = 0; - int IEEError = 0; - int DTEError = 0; - - extern OpenFiles_T *pDev; - - int error = 0; /* If set do an INIT ELEMENT STATUS */ - size_t x; /* The standard loop counter :-) */ - int retry = 2; /* Redo it if an error has been reset */ - - (void)InitStatus; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT, _("##### START GenericElementStatus\n")); - - if (pEAAPage == NULL) - { - /* - * If this pointer is null - * then try to read the parameter with MODE SENSE - * - */ - if (pModePage == NULL && LibModeSenseValid == 0) - { - pModePage = alloc(0xff); - - if (SCSI_ModeSense(DeviceFD, pModePage, 0xff, 0x8, 0x3f) == 0) - { - LibModeSenseValid = 1; - DecodeModeSense(pModePage, 0, _("GenericElementStatus :"), 0, debug_file); - } else { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("GetElementStatus : failed SCSI_ModeSense\n")); - LibModeSenseValid = -1; - } - } - } - - while ((GetElementStatus(DeviceFD) == 0) && (retry-- > 0)) - { - for (x = 0; x < MTE; x++) - { - if (pMTE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pMTE[x].ASC, pMTE[x].ASCQ, (RequestSense_T *)&pMTE[x])) - { - case SENSE_IES: - MTEError = 1; - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("GenericElementStatus : Abort on MTE\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - for (x = 0; x < IEE; x++) - { - if (pIEE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pIEE[x].ASC, pIEE[x].ASCQ, (RequestSense_T *)&pIEE[x])) - { - case SENSE_IES: - IEEError = 1; - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("GenericElementStatus : Abort on IEE\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - - for (x = 0; x < STE; x++) - { - if (pSTE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pSTE[x].ASC, pSTE[x].ASCQ, (RequestSense_T *)&pSTE[x])) - { - case SENSE_IES: - STEError = 1; - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("GenericElementStatus : Abort on IES\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - for (x = 0; x < DTE; x++) - { - if (pDTE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pDTE[x].ASC, pDTE[x].ASCQ, (RequestSense_T *)&pDTE[x])) - { - case SENSE_IES: - DTEError = 1; - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("GenericElementStatus : Abort on DTE\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - /* - * OK, we have an error, do an INIT ELMENT - * For the tape if not handled by the robot we have - * to do some extra checks - */ - if (error == 1) - { - if (GenericResetStatus(DeviceFD) != 0) - { - ElementStatusValid = 0; - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("GenericElementStatus : Can't init status STEError(%d) MTEError(%d) DTEError(%d) IEEError(%d)\n"), STEError, MTEError, DTEError, IEEError); - return(-1); - /*NOTREACHED*/ - } - error = 0; - } - - if (DTEError == 1) - { - TapeStatus(); - /* - * If the status is empty to an move from tape to tape - * This is if the tape is ejected, but not unloaded - */ - if (pDTE[0].status == 'E') - { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT, _("GenericElementStatus : try to move tape to tape drive\n")); - pDev[DeviceFD].functions->function_move(DeviceFD, pDTE[0].address, pDTE[0].address); - } - } - /* Done GetElementStatus */ - } - - if (error != 0) - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("GenericElementStatus : Can't init status (after loop)\n")); - return(-1); - /*NOTREACHED*/ - } - - ElementStatusValid = 1; - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("#### STOP GenericElementStatus\n")); - return(0); -} - - -/* - * This is for the ADIC changer, it seems that they have an diferent - * offset in the mode sense data before the first mode page (+12) - */ -int -DLT448ElementStatus( - int DeviceFD, - int InitStatus) -{ - int DTEError = 0; - - extern OpenFiles_T *pDev; - - int error = 0; /* If set do an INIT ELEMENT STATUS */ - size_t x; /* The standard loop counter :-) */ - int loop = 2; /* Redo it if an error has been reset */ - - (void)InitStatus; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT, _("##### START DLT448ElementStatus\n")); - - if (pEAAPage == NULL) - { - /* - * If this pointer is null - * then try to read the parameter with MODE SENSE - * - */ - if (pModePage == NULL && LibModeSenseValid == 0) - { - pModePage = alloc(0xff); - - if (SCSI_ModeSense(DeviceFD, pModePage, 0xff, 0x8, 0x3f) == 0) - { - LibModeSenseValid = 1; - DecodeModeSense(pModePage, 12, _("DLT448ElementStatus :"), 0, debug_file); - } else { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("DLT448ElementStatus : failed SCSI_ModeSense\n")); - LibModeSenseValid = -1; - } - } - } - - while (GetElementStatus(DeviceFD) == 0 && loop-- > 0) - { - for (x = 0; x < MTE; x++) - { - if (pMTE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pMTE[x].ASC, pMTE[x].ASCQ, (RequestSense_T *)&pMTE[x])) - { - case SENSE_IES: - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("DLT448ElementStatus : Abort on MTE\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - for (x = 0; x < IEE; x++) - { - if (pIEE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pIEE[x].ASC, pIEE[x].ASCQ, (RequestSense_T *)&pIEE[x])) - { - case SENSE_IES: - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("DLT448ElementStatus : Abort on IEE\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - - for (x = 0; x < STE; x++) - { - /* - * Needed for the hack to guess the tape status if an error - * for the tape is pending - */ - if (pSTE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pSTE[x].ASC, pSTE[x].ASCQ, (RequestSense_T *)&pSTE[x])) - { - case SENSE_IES: - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("DLT448ElementStatus : Abort on IES\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - for (x = 0; x < DTE; x++) - { - if (pDTE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pDTE[x].ASC, pDTE[x].ASCQ, (RequestSense_T *)&pDTE[x])) - { - case SENSE_IES: - DTEError = 1; - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("DLT448ElementStatus : Abort on DTE\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - /* - * OK, we have an error, do an INIT ELMENT - * For the tape if not handled by the robot we have - * to do some extra checks - */ - if (error == 1) - { - if (GenericResetStatus(DeviceFD) != 0) - { - ElementStatusValid = 0; - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("DLT448ElementStatus : Can't init status\n")); - return(-1); - /*NOTREACHED*/ - } - error = 0; - } - - if (DTEError == 1) - { - TapeStatus(); - /* - * If the status is empty to an move from tape to tape - * This is if the tape is ejected, but not unloaded - */ - if (pDTE[0].status == 'E') - { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT, _("DLT448ElementStatus : try to move tape to tape drive\n")); - pDev[DeviceFD].functions->function_move(DeviceFD, pDTE[0].address, pDTE[0].address); - } - } - /* Done GetElementStatus */ - } - - if (error != 0) - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("DLT448ElementStatus : Can't init status (after loop)\n")); - return(-1); - /*NOTREACHED*/ - } - - ElementStatusValid = 1; - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("#### STOP DLT448ElementStatus\n")); - return(0); -} - - -/* - * Much the same like GenericElementStatus but - * it seemes that for the STE Elements ASC/ASCQ is not set - * on an error, only the except bit is set -*/ -int -SDXElementStatus( - int DeviceFD, - int InitStatus) -{ - int error = 0; /* If set do an INIT ELEMENT STATUS */ - size_t x; /* The standard loop counter :-) */ - int loop = 2; /* Redo it if an error has been reset */ - - (void)InitStatus; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT, _("##### START SDXElementStatus\n")); - - if (pEAAPage == NULL) - { - /* - * If this pointer is null - * then try to read the parameter with MODE SENSE - * - */ - if (pModePage == NULL && LibModeSenseValid == 0) - { - pModePage = alloc(0xff); - - if (SCSI_ModeSense(DeviceFD, pModePage, 0xff, 0x8, 0x3f) == 0) - { - LibModeSenseValid = 1; - DecodeModeSense(pModePage, 0, _("SDXElementStatus :"), 0, debug_file); - } else { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("SDXElementStatus : failed SCSI_ModeSense\n")); - LibModeSenseValid = -1; - } - } - } - - while (GetElementStatus(DeviceFD) == 0 && loop--) - { - error = 0; - for (x = 0; x < MTE; x++) - { - if (pMTE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pMTE[x].ASC, pMTE[x].ASCQ, (RequestSense_T *)&pMTE[x])) - { - case SENSE_IES: - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("SDXElementStatus : Abort on MTE\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - for (x = 0; x < IEE; x++) - { - if (pIEE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pIEE[x].ASC, pIEE[x].ASCQ, (RequestSense_T *)&pIEE[x])) - { - case SENSE_IES: - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("SDXElementStatus : Abort on IEE\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - - for (x = 0; x < STE; x++) - { - if (pSTE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pSTE[x].ASC, pSTE[x].ASCQ, (RequestSense_T *)&pSTE[x])) - { - case SENSE_IES: - error = 1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("SDXElementStatus : Abort on IES\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - for (x = 0; x < DTE; x++) - { - if (pDTE[x].ASC > 0) - { - switch(SenseHandler(DeviceFD, 0, SENSE_CHG_ELEMENT_STATUS, pDTE[x].ASC, pDTE[x].ASCQ, (RequestSense_T *)&pDTE[x])) - { - case SENSE_IES: - /* - error = 1; - */ - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("SDXElementStatus : Abort on DTE\n")); - return(-1); - /*NOTREACHED*/ - } - } - } - - /* - * OK, we have an error, do an INIT ELMENT - * For the tape if not handled by the robot we have - * to do some extra checks - */ - if (error == 1) - { - if (GenericResetStatus(DeviceFD) != 0) - { - ElementStatusValid = 0; - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("SDXElementStatus : Can't init status\n")); - return(-1); - /*NOTREACHED*/ - } - } - - /* Done GetElementStatus */ - } - - if (error != 0) - { - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("SDXElementStatus : Can't init status\n")); - return(-1); - /*NOTREACHED*/ - } - - ElementStatusValid = 1; - TapeStatus(); - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT, _("#### STOP SDXElementStatus\n")); - return(0); -} - - -/* - * Reads the element information from the library. There are 2 ways to do this. - * Either check the result from the mode sense page to see which types of elements - * are available (STE/DTE/MTE....), or do an read element status with the option give - * me all and than check what is available. - * - * Only do the read, error handling is done by the calling function - * - * Return Values: - * < 0 -> Error - * == 0 -> OK - * - * TODO: - */ -int -GetElementStatus( - int DeviceFD) -{ - u_char *DataBuffer = NULL; - size_t DataBufferLength; - ElementStatusData_T *ElementStatusData; - ElementStatusPage_T *ElementStatusPage; - MediumTransportElementDescriptor_T *MediumTransportElementDescriptor; - StorageElementDescriptor_T *StorageElementDescriptor; - DataTransferElementDescriptor_T *DataTransferElementDescriptor; - ImportExportElementDescriptor_T *ImportExportElementDescriptor; - size_t x; - size_t offset; - size_t length; /* Length of an Element */ - size_t NoOfElements; - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("##### START GetElementStatus\n")); - - barcode = BarCode(DeviceFD); - - /* - * If the MODE_SENSE was successfull we use this Information to read the Elelement Info - */ - if (pEAAPage != NULL) - { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Reading Element Status with the info from mode sense\n")); - /* First the Medim Transport*/ - if (V2(pEAAPage->NoMediumTransportElements) > 0) - { - MTE = V2(pEAAPage->NoMediumTransportElements) ; - pMTE = alloc(SIZEOF(ElementInfo_T) * MTE); - memset(pMTE, 0, SIZEOF(ElementInfo_T) * MTE); - - if (SCSI_ReadElementStatus(DeviceFD, - CHANGER, - 0, - (u_char)barcode, - V2(pEAAPage->MediumTransportElementAddress), - (MTE + (size_t)1), - SIZEOF(MediumTransportElementDescriptor_T), - &DataBuffer) != 0) - { - ChgExit("genericElementStatus",_("Can't read MTE status"), FATAL); - /*NOTREACHED*/ - } - // ElementStatusData = (ElementStatusData_T *)DataBuffer; - offset = SIZEOF(ElementStatusData_T); - - ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset]; - offset = offset + SIZEOF(ElementStatusPage_T); - length = V2(ElementStatusPage->length); - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("MTE Length %d(%d)\n"), length, - SIZEOF(MediumTransportElementDescriptor_T)); - - for (x = 0; x < MTE; x++) - { - MediumTransportElementDescriptor = (MediumTransportElementDescriptor_T *)&DataBuffer[offset]; - - if (ElementStatusPage->pvoltag == 1) - { - strncpy((char *)pMTE[x].VolTag, - (char *)MediumTransportElementDescriptor->pvoltag, - TAG_SIZE); - TerminateString(pMTE[x].VolTag, TAG_SIZE+1); - } - - pMTE[x].type = ElementStatusPage->type; - pMTE[x].address = V2(MediumTransportElementDescriptor->address); - pMTE[x].except = MediumTransportElementDescriptor->except; - pMTE[x].full = MediumTransportElementDescriptor->full; - if (MediumTransportElementDescriptor->full > 0) - { - pMTE[x].status = 'F'; - } else { - pMTE[x].status = 'E'; - } - - if (length >= 5) - { - pMTE[x].ASC = MediumTransportElementDescriptor->asc; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASC MTE\n")); - } - - if (length >= 6) - { - pMTE[x].ASCQ = MediumTransportElementDescriptor->ascq; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASCQ MTE\n")); - } - - if (length >= 0xa) - { - if (MediumTransportElementDescriptor->svalid == 1) - { - pMTE[x].from = V2(MediumTransportElementDescriptor->source); - } else { - pMTE[x].from = -1; - } - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip source MTE\n")); - } - offset = offset + length; - } - free(DataBuffer); - DataBuffer = NULL; - } - /* - * Storage Elements - */ - if ( V2(pEAAPage->NoStorageElements) > 0) - { - free(pSTE); - STE = V2(pEAAPage->NoStorageElements); - pSTE = alloc(SIZEOF(ElementInfo_T) * STE); - memset(pSTE, 0, SIZEOF(ElementInfo_T) * STE); - - if (SCSI_ReadElementStatus(DeviceFD, - STORAGE, - 0, - (u_char)barcode, - V2(pEAAPage->FirstStorageElementAddress), - STE, - SIZEOF(StorageElementDescriptor_T), - &DataBuffer) != 0) - { - ChgExit("GetElementStatus", _("Can't read STE status"), FATAL); - /*NOTREACHED*/ - } - assert(DataBuffer != NULL); - - // ElementStatusData = (ElementStatusData_T *)DataBuffer; - offset = SIZEOF(ElementStatusData_T); - - ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset]; - offset = offset + SIZEOF(ElementStatusPage_T); - length = V2(ElementStatusPage->length); - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("STE Length %d\n"),length); - - for (x = 0; x < STE; x++) - { - StorageElementDescriptor = (StorageElementDescriptor_T *)&DataBuffer[offset]; - if (ElementStatusPage->pvoltag == 1) - { - strncpy(pSTE[x].VolTag, - (char *)StorageElementDescriptor->pvoltag, - TAG_SIZE); - TerminateString(pSTE[x].VolTag, TAG_SIZE+1); - } - - - pSTE[x].type = ElementStatusPage->type; - pSTE[x].address = V2(StorageElementDescriptor->address); - pSTE[x].except = StorageElementDescriptor->except; - pSTE[x].full = StorageElementDescriptor->full; - if (StorageElementDescriptor->full > 0) - { - pSTE[x].status = 'F'; - } else { - pSTE[x].status = 'E'; - } - - if (length >= 5) - { - pSTE[x].ASC = StorageElementDescriptor->asc; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASC STE\n")); - } - - if (length >= 6) - { - pSTE[x].ASCQ = StorageElementDescriptor->ascq; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASCQ STE\n")); - } - - if (length >= 0xa) - { - if (StorageElementDescriptor->svalid == 1) - { - pSTE[x].from = V2(StorageElementDescriptor->source); - } else { - pSTE[x].from = -1; - } - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip source STE\n")); - } - - offset = offset + length; - } - free(DataBuffer); - DataBuffer = NULL; - } - /* - * Import/Export Elements - */ - if ( V2(pEAAPage->NoImportExportElements) > 0) - { - free(pIEE); - IEE = V2(pEAAPage->NoImportExportElements); - pIEE = alloc(SIZEOF(ElementInfo_T) * IEE); - memset(pIEE, 0, SIZEOF(ElementInfo_T) * IEE); - - if (SCSI_ReadElementStatus(DeviceFD, - IMPORT, - 0, - (u_char)barcode, - V2(pEAAPage->FirstImportExportElementAddress), - IEE, - SIZEOF(ImportExportElementDescriptor_T), - &DataBuffer) != 0) - { - ChgExit("GetElementStatus", _("Can't read IEE status"), FATAL); - /*NOTREACHED*/ - } - assert(DataBuffer != NULL); - - // ElementStatusData = (ElementStatusData_T *)DataBuffer; - offset = SIZEOF(ElementStatusData_T); - - ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset]; - offset = offset + SIZEOF(ElementStatusPage_T); - length = V2(ElementStatusPage->length); - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("IEE Length %d\n"),length); - - for (x = 0; x < IEE; x++) - { - ImportExportElementDescriptor = (ImportExportElementDescriptor_T *)&DataBuffer[offset]; - if (ElementStatusPage->pvoltag == 1) - { - strncpy(pIEE[x].VolTag, - (char *)ImportExportElementDescriptor->pvoltag, - TAG_SIZE); - TerminateString(pIEE[x].VolTag, TAG_SIZE+1); - } - pIEE[x].type = ElementStatusPage->type; - pIEE[x].address = V2(ImportExportElementDescriptor->address); - pIEE[x].except = ImportExportElementDescriptor->except; - pIEE[x].full = ImportExportElementDescriptor->full; - if (ImportExportElementDescriptor->full > 0) - { - pIEE[x].status = 'F'; - } else { - pIEE[x].status = 'E'; - } - - if (length >= 5) - { - pIEE[x].ASC = ImportExportElementDescriptor->asc; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASC IEE\n")); - } - - if (length >= 6) - { - pIEE[x].ASCQ = ImportExportElementDescriptor->ascq; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASCQ IEE\n")); - } - - if (length >= 0xa) - { - if (ImportExportElementDescriptor->svalid == 1) - { - pIEE[x].from = V2(ImportExportElementDescriptor->source); - } else { - pIEE[x].from = -1; - } - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip source IEE\n")); - } - - offset = offset + length; - } - free(DataBuffer); - DataBuffer = NULL; - } - /* - * Data Transfer Elements - */ - if (V2(pEAAPage->NoDataTransferElements) >0) - { - free(pDTE); - DTE = V2(pEAAPage->NoDataTransferElements) ; - pDTE = alloc(SIZEOF(ElementInfo_T) * DTE); - memset(pDTE, 0, SIZEOF(ElementInfo_T) * DTE); - - if (SCSI_ReadElementStatus(DeviceFD, - TAPETYPE, - 0, - (u_char)barcode, - V2(pEAAPage->FirstDataTransferElementAddress), - DTE, - SIZEOF(DataTransferElementDescriptor_T), - &DataBuffer) != 0) - { - ChgExit("GenericElementStatus", _("Can't read DTE status"), FATAL); - /*NOTREACHED*/ - } - assert(DataBuffer != NULL); - - // ElementStatusData = (ElementStatusData_T *)DataBuffer; - offset = SIZEOF(ElementStatusData_T); - - ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset]; - offset = offset + SIZEOF(ElementStatusPage_T); - length = V2(ElementStatusPage->length); - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("DTE Length %d\n"),length); - - for (x = 0; x < DTE; x++) - { - DataTransferElementDescriptor = (DataTransferElementDescriptor_T *)&DataBuffer[offset]; - if (ElementStatusPage->pvoltag == 1) - { - strncpy(pDTE[x].VolTag, - (char *)DataTransferElementDescriptor->pvoltag, - TAG_SIZE); - TerminateString(pDTE[x].VolTag, TAG_SIZE+1); - } - pDTE[x].type = ElementStatusPage->type; - pDTE[x].address = V2(DataTransferElementDescriptor->address); - pDTE[x].except = DataTransferElementDescriptor->except; - pDTE[x].scsi = DataTransferElementDescriptor->scsi; - pDTE[x].full = DataTransferElementDescriptor->full; - if (DataTransferElementDescriptor->full > 0) - { - pDTE[x].status = 'F'; - } else { - pDTE[x].status = 'E'; - } - - if (length >= 5) - { - pDTE[x].ASC = DataTransferElementDescriptor->asc; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASC DTE\n")); - } - - if (length >= 6) - { - pDTE[x].ASCQ = DataTransferElementDescriptor->ascq; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASCQ DTE\n")); - } - - if (length >= 0xa) - { - if (DataTransferElementDescriptor->svalid == 1) - { - pDTE[x].from = V2(DataTransferElementDescriptor->source); - } else { - pDTE[x].from = -1; - } - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip source STE\n")); - } - - offset = offset + length; - } - free(DataBuffer); - DataBuffer = NULL; - } - } else { - /* - * And now the old way, when we get here the read mode sense page has failed ... - */ - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Reading Element Status the old way .... (max 255 elements)\n")); - if (SCSI_ReadElementStatus(DeviceFD, - 0, - 0, - (u_char)barcode, - 0, - (size_t)0xff, - (size_t)0x7f, - &DataBuffer) != 0) - { - ChgExit("GenericElementStatus",_("Can't get ElementStatus"), FATAL); - /*NOTREACHED*/ - } - assert(DataBuffer != NULL); - - ElementStatusData = (ElementStatusData_T *)DataBuffer; - DataBufferLength = V3(ElementStatusData->count); - - offset = SIZEOF(ElementStatusData_T); - - while (offset < DataBufferLength) - { - ElementStatusPage = (ElementStatusPage_T *)&DataBuffer[offset]; - NoOfElements = V3(ElementStatusPage->count) / V2(ElementStatusPage->length); - offset = offset + SIZEOF(ElementStatusPage_T); - length = V2(ElementStatusPage->length); - - switch (ElementStatusPage->type) - { - case CHANGER: - free(pMTE); - MTE = NoOfElements; - pMTE = alloc(SIZEOF(ElementInfo_T) * MTE); - memset(pMTE, 0, SIZEOF(ElementInfo_T) * MTE); - - for (x = 0; x < NoOfElements; x++) - { - MediumTransportElementDescriptor = (MediumTransportElementDescriptor_T *)&DataBuffer[offset]; - if (ElementStatusPage->pvoltag == 1) - { - strncpy(pMTE[x].VolTag, - (char *)MediumTransportElementDescriptor->pvoltag, - TAG_SIZE); - TerminateString(pMTE[x].VolTag, TAG_SIZE+1); - } - pMTE[x].type = ElementStatusPage->type; - pMTE[x].address = V2(MediumTransportElementDescriptor->address); - pMTE[x].except = MediumTransportElementDescriptor->except; - pMTE[x].full = MediumTransportElementDescriptor->full; - if (MediumTransportElementDescriptor->full > 0) - { - pMTE[x].status = 'F'; - } else { - pMTE[x].status = 'E'; - } - - if (length >= 5) - { - pMTE[x].ASC = MediumTransportElementDescriptor->asc; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASC MTE\n")); - } - - if (length >= 6) - { - pMTE[x].ASCQ = MediumTransportElementDescriptor->ascq; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASCQ MTE\n")); - } - - if (length >= 0xa) - { - if (MediumTransportElementDescriptor->svalid == 1) - { - pMTE[x].from = V2(MediumTransportElementDescriptor->source); - } else { - pMTE[x].from = -1; - } - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip source MTE\n")); - } - - offset = offset + length; - } - break; - case STORAGE: - free(pSTE); - STE = NoOfElements; - pSTE = alloc(SIZEOF(ElementInfo_T) * STE); - memset(pSTE, 0, SIZEOF(ElementInfo_T) * STE); - - for (x = 0; x < NoOfElements; x++) - { - StorageElementDescriptor = (StorageElementDescriptor_T *)&DataBuffer[offset]; - if (ElementStatusPage->pvoltag == 1) - { - strncpy(pSTE[x].VolTag, - (char *)StorageElementDescriptor->pvoltag, - TAG_SIZE); - TerminateString(pSTE[x].VolTag, TAG_SIZE+1); - } - - pSTE[x].type = ElementStatusPage->type; - pSTE[x].address = V2(StorageElementDescriptor->address); - pSTE[x].except = StorageElementDescriptor->except; - pSTE[x].full = StorageElementDescriptor->full; - if (StorageElementDescriptor->full > 0) - { - pSTE[x].status = 'F'; - } else { - pSTE[x].status = 'E'; - } - - if (length >= 5) - { - pSTE[x].ASC = StorageElementDescriptor->asc; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASC STE\n")); - } - - if (length >= 6) - { - pSTE[x].ASCQ = StorageElementDescriptor->ascq; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASCQ STE\n")); - } - - if (length >= 0xa) - { - if (StorageElementDescriptor->svalid == 1) - { - pSTE[x].from = V2(StorageElementDescriptor->source); - } else { - pSTE[x].from = -1; - } - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip source STE\n")); - } - - offset = offset + length; - } - break; - case IMPORT: - free(pIEE); - IEE = NoOfElements; - pIEE = alloc(SIZEOF(ElementInfo_T) * IEE); - memset(pIEE, 0, SIZEOF(ElementInfo_T) * IEE); - - for (x = 0; x < NoOfElements; x++) - { - ImportExportElementDescriptor = (ImportExportElementDescriptor_T *)&DataBuffer[offset]; - if (ElementStatusPage->pvoltag == 1) - { - strncpy(pIEE[x].VolTag, - (char *)ImportExportElementDescriptor->pvoltag, - TAG_SIZE); - TerminateString(pIEE[x].VolTag, TAG_SIZE+1); - } - ImportExportElementDescriptor = (ImportExportElementDescriptor_T *)&DataBuffer[offset]; - pIEE[x].type = ElementStatusPage->type; - pIEE[x].address = V2(ImportExportElementDescriptor->address); - pIEE[x].except = ImportExportElementDescriptor->except; - pIEE[x].full = ImportExportElementDescriptor->full; - if (ImportExportElementDescriptor->full > 0) - { - pIEE[x].status = 'F'; - } else { - pIEE[x].status = 'E'; - } - - if (length >= 5) - { - pIEE[x].ASC = ImportExportElementDescriptor->asc; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASC IEE\n")); - } - - if (length >= 6) - { - pIEE[x].ASCQ = ImportExportElementDescriptor->ascq; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASCQ IEE\n")); - } - - if (length >= 0xa) - { - if (ImportExportElementDescriptor->svalid == 1) - { - pIEE[x].from = V2(ImportExportElementDescriptor->source); - } else { - pIEE[x].from = -1; - } - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip source IEE\n")); - } - - offset = offset + length; - } - break; - case TAPETYPE: - free(pDTE); - DTE = NoOfElements; - pDTE = alloc(SIZEOF(ElementInfo_T) * DTE); - memset(pDTE, 0, SIZEOF(ElementInfo_T) * DTE); - - for (x = 0; x < NoOfElements; x++) - { - DataTransferElementDescriptor = (DataTransferElementDescriptor_T *)&DataBuffer[offset]; - if (ElementStatusPage->pvoltag == 1) - { - strncpy(pSTE[x].VolTag, - (char *)DataTransferElementDescriptor->pvoltag, - TAG_SIZE); - TerminateString(pSTE[x].VolTag, TAG_SIZE+1); - } - pDTE[x].type = ElementStatusPage->type; - pDTE[x].address = V2(DataTransferElementDescriptor->address); - pDTE[x].except = DataTransferElementDescriptor->except; - pDTE[x].scsi = DataTransferElementDescriptor->scsi; - pDTE[x].full = DataTransferElementDescriptor->full; - if (DataTransferElementDescriptor->full > 0) - { - pDTE[x].status = 'F'; - } else { - pDTE[x].status = 'E'; - } - - if (length >= 5) - { - pDTE[x].ASC = DataTransferElementDescriptor->asc; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASC DTE\n")); - } - - if (length >= 6) - { - pDTE[x].ASCQ = DataTransferElementDescriptor->ascq; - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip ASCQ DTE\n")); - } - - if (length >= 0xa) - { - if (DataTransferElementDescriptor->svalid == 1) - { - pDTE[x].from = V2(DataTransferElementDescriptor->source); - } else { - pDTE[x].from = -1; - } - } else { - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("Skip source STE\n")); - } - - offset = offset + length; - } - break; - default: - offset = offset + length; - DebugPrint(DEBUG_ERROR, SECTION_ELEMENT,_("GetElementStatus : UnGknown Type %d\n"),ElementStatusPage->type); - break; - } - } - free(DataBuffer); - } - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("\n\n\tMedia Transport Elements (robot arms) :\n")); - - for ( x = 0; x < MTE; x++) - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("\t\tElement #%04d %c\n\t\t\tEXCEPT = %02x\n\t\t\tASC = %02X ASCQ = %02X\n\t\t\tType %d From = %04d\n\t\t\tTAG = %s\n"), - pMTE[x].address, pMTE[x].status, pMTE[x].except, pMTE[x].ASC, - pMTE[x].ASCQ, pMTE[x].type, pMTE[x].from, pMTE[x].VolTag); - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("\n\n\tStorage Elements (Media slots) :\n")); - - for ( x = 0; x < STE; x++) - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("\t\tElement #%04d %c\n\t\t\tEXCEPT = %02X\n\t\t\tASC = %02X ASCQ = %02X\n\t\t\tType %d From = %04d\n\t\t\tTAG = %s\n"), - pSTE[x].address, pSTE[x].status, pSTE[x].except, pSTE[x].ASC, - pSTE[x].ASCQ, pSTE[x].type, pSTE[x].from, pSTE[x].VolTag); - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("\n\n\tData Transfer Elements (tape drives) :\n")); - - for ( x = 0; x < DTE; x++) - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("\t\tElement #%04d %c\n\t\t\tEXCEPT = %02X\n\t\t\tASC = %02X ASCQ = %02X\n\t\t\tType %d From = %04d\n\t\t\tTAG = %s\n\t\t\tSCSI ADDRESS = %d\n"), - pDTE[x].address, pDTE[x].status, pDTE[x].except, pDTE[x].ASC, - pDTE[x].ASCQ, pDTE[x].type, pDTE[x].from, pDTE[x].VolTag,pDTE[x].scsi); - - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("\n\n\tImport/Export Elements :\n")); - - for ( x = 0; x < IEE; x++) - DebugPrint(DEBUG_INFO, SECTION_ELEMENT,_("\t\tElement #%04d %c\n\t\t\tEXCEPT = %02X\n\t\t\t\tASC = %02X ASCQ = %02X\n\t\t\tType %d From = %04d\n\t\t\tTAG = %s\n"), - pIEE[x].address, pIEE[x].status, pIEE[x].except, pIEE[x].ASC, - pIEE[x].ASCQ, pIEE[x].type, pIEE[x].from, pIEE[x].VolTag); - - - - return(0); -} - -/* - * Get sense data - * If ClearErrorCounters is set the counters will be reset. - * Used by GenericClean for example - * - * TODO - */ -int -RequestSense( - int DeviceFD, - ExtendedRequestSense_T * ExtendedRequestSense, - int ClearErrorCounters) -{ - CDB_T CDB; - int ret; - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START RequestSense\n")); - - CDB[0] = SC_COM_REQUEST_SENSE; /* REQUEST SENSE */ - CDB[1] = 0; /* Logical Unit Number = 0, Reserved */ - CDB[2] = 0; /* Reserved */ - CDB[3] = 0; /* Reserved */ - CDB[4] = (u_char)sizeof(ExtendedRequestSense_T); /* Allocation Length */ - CDB[5] = (u_char)((ClearErrorCounters << 7) & 0x80); /* */ - - memset(ExtendedRequestSense, 0, SIZEOF(ExtendedRequestSense_T)); - - ret = SCSI_Run(DeviceFD, Input, CDB, 6, - (char *) ExtendedRequestSense, - SIZEOF(ExtendedRequestSense_T), - (RequestSense_T *) ExtendedRequestSense, - SIZEOF(ExtendedRequestSense_T)); - - - if (ret < 0) - { - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP RequestSense (%d)\n"),ret); - return(ret); - /*NOTREACHED*/ - } - - if ( ret > 0) - { - DecodeExtSense(ExtendedRequestSense, "RequestSense : ",debug_file); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP RequestSense (%d)\n"), ExtendedRequestSense->SenseKey); - return(ExtendedRequestSense->SenseKey); - /*NOTREACHED*/ - } - - dump_hex((u_char *)ExtendedRequestSense , - SIZEOF(ExtendedRequestSense_T), - DEBUG_INFO, SECTION_SCSI); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP RequestSense (0)\n")); - return(0); -} - - -/* - * Lookup function pointer for device .... - */ - - -ElementInfo_T * -LookupElement( - int address) -{ - size_t x; - - dbprintf(_("##### START LookupElement\n")); - - if (DTE > 0) - { - for (x = 0; x < DTE; x++) - { - if (pDTE[x].address == address) - { - dbprintf(_("##### STOP LookupElement (DTE)\n")); - return(&pDTE[x]); - /*NOTREACHED*/ - } - } - } - - if (MTE > 0) - { - for (x = 0; x < MTE; x++) - { - if (pMTE[x].address == address) - { - dbprintf(_("##### STOP LookupElement (MTE)\n")); - return(&pMTE[x]); - /*NOTREACHED*/ - } - } - } - - if (STE > 0) - { - for (x = 0; x < STE; x++) - { - if (pSTE[x].address == address) - { - dbprintf(_("##### STOP LookupElement (STE)\n")); - return(&pSTE[x]); - /*NOTREACHED*/ - } - } - } - - if (IEE > 0) - { - for ( x = 0; x < IEE; x++) - { - if (pIEE[x].address == address) - { - dbprintf(_("##### STOP LookupElement (IEE)\n")); - return(&pIEE[x]); - /*NOTREACHED*/ - } - } - } - return(NULL); -} - -/* - * Here comes everything what decode the log Pages - * - * TODO: - * Fix the result handling from TestUnitReady - * - */ -int -LogSense( - int DeviceFD) -{ - extern OpenFiles_T *pDev; - CDB_T CDB; - RequestSense_T *pRequestSense; - LogSenseHeader_T *LogSenseHeader; - LogParameter_T *LogParameter; - struct LogPageDecode *p; - int found; - extern char *tapestatfile; - int i; - unsigned ParameterCode; - unsigned value; - size_t length; - int count; - u_char *buffer; - u_char *logpages; - size_t nologpages; - size_t size = 128; - - (void)DeviceFD; /* Quiet unused parameter warning */ - - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### START LogSense\n")); - - if ((tapestatfile != NULL) && (pDev[INDEX_TAPECTL].SCSI == 1) && - ((StatFile = fopen(tapestatfile,"a")) != NULL)) - { - pRequestSense = alloc(SIZEOF(RequestSense_T)); - - if (GenericRewind(INDEX_TAPECTL) < 0) - { - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("LogSense : Rewind failed\n")); - free(pRequestSense); - fclose(StatFile); - return(0); - /*NOTREACHED*/ - } - /* - * Try to read the tape label - */ - if (pDev[INDEX_TAPE].inqdone == 1) - { - if (pDev[INDEX_TAPE].devopen == 1) - { - SCSI_CloseDevice(INDEX_TAPE); - } - - if ((chgscsi_result = (char *)tape_rdlabel(pDev[INDEX_TAPE].dev, &chgscsi_datestamp, &chgscsi_label)) == NULL) - { - g_fprintf(StatFile, _("==== %s ==== %s ====\n"), chgscsi_datestamp, chgscsi_label); - } else { - g_fprintf(StatFile, "%s\n", chgscsi_result); - } - } - - buffer = alloc(size); - memset(buffer, 0, size); - /* - * Get the known log pages - */ - - CDB[0] = SC_COM_LOG_SENSE; - CDB[1] = 0; - CDB[2] = 0x40; /* 0x40 for current values */ - CDB[3] = 0; - CDB[4] = 0; - CDB[5] = 0; - CDB[6] = 00; - MSB2(&CDB[7], size); - CDB[9] = 0; - - if (SCSI_Run(INDEX_TAPECTL, Input, CDB, 10, - buffer, - size, - pRequestSense, - SIZEOF(RequestSense_T)) != 0) - { - DecodeSense(pRequestSense, "LogSense : ",debug_file); - free(pRequestSense); - free(buffer); - fclose(StatFile); - return(0); - /*NOTREACHED*/ - } - - LogSenseHeader = (LogSenseHeader_T *)buffer; - nologpages = V2(LogSenseHeader->PageLength); - logpages = alloc(nologpages); - - memcpy(logpages, buffer + SIZEOF(LogSenseHeader_T), nologpages); - - for (count = 0; count < (int)nologpages; count++) { - if (logpages[count] != 0 ) { - memset(buffer, 0, size); - CDB[0] = SC_COM_LOG_SENSE; - CDB[1] = 0; - CDB[2] = (u_char)(0x40 | logpages[count]);/* 0x40 for current values */ - CDB[3] = 0; - CDB[4] = 0; - CDB[5] = 0; - CDB[6] = 00; - MSB2(&CDB[7], size); - CDB[9] = 0; - - if (SCSI_Run(INDEX_TAPECTL, Input, CDB, 10, - buffer, - size, - pRequestSense, - SIZEOF(RequestSense_T)) != 0) - { - DecodeSense(pRequestSense, "LogSense : ",debug_file); - free(pRequestSense); - free(logpages); - free(buffer); - fclose(StatFile); - return(0); - /*NOTREACHED*/ - } - LogSenseHeader = (LogSenseHeader_T *)buffer; - length = V2(LogSenseHeader->PageLength); - LogParameter = (LogParameter_T *)(buffer + SIZEOF(LogSenseHeader_T)); - /* - * Decode the log pages - */ - p = (struct LogPageDecode *)&DecodePages; - found = 0; - - dump_hex((u_char *)LogParameter, 64, DEBUG_INFO, SECTION_SCSI); - - while(p->ident != NULL) { - if ((strcmp(pDev[INDEX_TAPECTL].ident, p->ident) == 0 ||strcmp("*", p->ident) == 0) && p->LogPage == logpages[count]) { - p->decode(LogParameter, length); - found = 1; - g_fprintf(StatFile, "\n"); - break; - } - p++; - } - - if (!found) { - g_fprintf(StatFile, _("Logpage No %d = %x\n"), count ,logpages[count]); - - while ((u_char *)LogParameter < (buffer + length)) { - i = LogParameter->ParameterLength; - ParameterCode = V2(LogParameter->ParameterCode); - switch (i) { - case 1: - value = V1((u_char *)LogParameter + SIZEOF(LogParameter_T)); - g_fprintf(StatFile, _("ParameterCode %02X = %u(%d)\n"), ParameterCode, value, i); - break; - case 2: - value = V2((u_char *)LogParameter + SIZEOF(LogParameter_T)); - g_fprintf(StatFile, _("ParameterCode %02X = %u(%d)\n"), ParameterCode, value, i); - break; - case 3: - value = V3((u_char *)LogParameter + SIZEOF(LogParameter_T)); - g_fprintf(StatFile, _("ParameterCode %02X = %u(%d)\n"), ParameterCode, value, i); - break; - case 4: - value = V4((u_char *)LogParameter + SIZEOF(LogParameter_T)); - g_fprintf(StatFile, _("ParameterCode %02X = %u(%d)\n"), ParameterCode, value, i); - break; - case 5: - value = V5((u_char *)LogParameter + SIZEOF(LogParameter_T)); - g_fprintf(StatFile, _("ParameterCode %02X = %u(%d)\n"), ParameterCode, value, i); - break; - default: - g_fprintf(StatFile, _("ParameterCode %02X size %d\n"), ParameterCode, i); - } - LogParameter = (LogParameter_T *)((u_char *)LogParameter + SIZEOF(LogParameter_T) + i); - } - g_fprintf(StatFile, "\n"); - } - } - } - - /* - * Test only !!!! - * Reset the cumulative counters - */ - CDB[0] = SC_COM_LOG_SELECT; - CDB[1] = 2; - CDB[2] = 0xc0; - CDB[3] = 0; - CDB[4] = 0; - CDB[5] = 0; - CDB[6] = 0; - CDB[7] = 0; - CDB[8] = 0; - CDB[9] = 0; - - if (SCSI_Run(INDEX_TAPECTL, Input, CDB, 10, - buffer, - size, - pRequestSense, - SIZEOF(RequestSense_T)) != 0) - { - DecodeSense(pRequestSense, "LogSense : ",debug_file); - free(pRequestSense); - free(logpages); - /*@ignore@*/ - free(buffer); - /*@end@*/ - fclose(StatFile); - return(0); - /*NOTREACHED*/ - } - - free(pRequestSense); - free(logpages); - /*@ignore@*/ - free(buffer); - /*@end@*/ - fclose(StatFile); - } - DebugPrint(DEBUG_INFO, SECTION_TAPE,_("##### STOP LogSense\n")); - return(0); -} - -void -WriteErrorCountersPage( - LogParameter_T * buffer, - size_t length) -{ - int i; - unsigned value; - LogParameter_T *LogParameter; - unsigned ParameterCode; - LogParameter = buffer; - - g_fprintf(StatFile, _("\tWrite Error Counters Page\n")); - - while ((u_char *)LogParameter < ((u_char *)buffer + length)) { - i = LogParameter->ParameterLength; - ParameterCode = V2(LogParameter->ParameterCode); - - value = 0; - if (Decode(LogParameter, &value) == 0) { - switch (ParameterCode) { - case 2: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Rewrites"), - value); - break; - case 3: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Errors Corrected"), - value); - break; - case 4: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Times E. Processed"), - value); - break; - case 5: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Bytes Processed"), - value); - break; - case 6: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Unrecoverable Errors"), - value); - break; - default: - g_fprintf(StatFile, _("Unknown ParameterCode %02X = %u(%d)\n"), - ParameterCode, - value, i); - break; - } - } else { - g_fprintf(StatFile, _("Error decoding Result\n")); - } - LogParameter = (LogParameter_T *)((u_char *)LogParameter + SIZEOF(LogParameter_T) + i); - } -} - -void -ReadErrorCountersPage( - LogParameter_T * buffer, - size_t length) -{ - int i; - unsigned value; - LogParameter_T *LogParameter; - unsigned ParameterCode; - LogParameter = buffer; - - g_fprintf(StatFile, _("\tRead Error Counters Page\n")); - - while ((u_char *)LogParameter < ((u_char *)buffer + length)) { - i = LogParameter->ParameterLength; - ParameterCode = V2(LogParameter->ParameterCode); - - value = 0; - if (Decode(LogParameter, &value) == 0) { - switch (ParameterCode) { - case 2: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Rereads"), - value); - break; - case 3: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Errors Corrected"), - value); - break; - case 4: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Times E. Processed"), - value); - break; - case 5: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Bytes Processed"), - value); - break; - case 6: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Unrecoverable Errors"), - value); - break; - default: - g_fprintf(StatFile, _("Unknown ParameterCode %02X = %u(%d)\n"), - ParameterCode, - value, i); - break; - } - } else { - g_fprintf(StatFile, _("Error decoding Result\n")); - } - LogParameter = (LogParameter_T *)((u_char *)LogParameter + SIZEOF(LogParameter_T) + i); - } -} - -void -C1553APage30( - LogParameter_T * buffer, - size_t length) -{ - int i; - unsigned value; - LogParameter_T *LogParameter; - unsigned ParameterCode; - LogParameter = buffer; - - g_fprintf(StatFile, _("\tData compression transfer Page\n")); - - while ((u_char *)LogParameter < ((u_char *)buffer + length)) { - i = LogParameter->ParameterLength; - ParameterCode = V2(LogParameter->ParameterCode); - - value = 0; - if (Decode(LogParameter, &value) == 0) { - switch (ParameterCode) { - default: - g_fprintf(StatFile, _("Unknown ParameterCode %02X = %u(%d)\n"), - ParameterCode, - value, i); - break; - } - } - LogParameter = (LogParameter_T *)((u_char *)LogParameter + SIZEOF(LogParameter_T) + i); - } -} - -void -C1553APage37( - LogParameter_T * buffer, - size_t length) -{ - int i; - unsigned value; - LogParameter_T *LogParameter; - unsigned ParameterCode; - LogParameter = buffer; - - g_fprintf(StatFile, _("\tDrive Counters Page\n")); - - while ((u_char *)LogParameter < ((unsigned char *)buffer + length)) { - i = LogParameter->ParameterLength; - ParameterCode = V2(LogParameter->ParameterCode); - - value = 0; - if (Decode(LogParameter, &value) == 0) { - switch (ParameterCode) { - case 1: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total loads"), - value); - break; - case 2: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total write drive errors"), - value); - break; - case 3: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total read drive errors"), - value); - break; - default: - g_fprintf(StatFile, _("Unknown ParameterCode %02X = %u(%d)\n"), - ParameterCode, - value, i); - break; - } - } - LogParameter = (LogParameter_T *)((u_char *)LogParameter + SIZEOF(LogParameter_T) + i); - } -} - -void -EXB85058HEPage39( - LogParameter_T * buffer, - size_t length) -{ - int i; - unsigned value; - LogParameter_T *LogParameter; - unsigned ParameterCode; - LogParameter = buffer; - - g_fprintf(StatFile, _("\tData Compression Page\n")); - - while ((u_char *)LogParameter < ((unsigned char *)buffer + length)) { - i = LogParameter->ParameterLength; - ParameterCode = V2(LogParameter->ParameterCode); - - value = 0; - if (Decode(LogParameter, &value) == 0) { - switch (ParameterCode) { - case 5: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("KB to Compressor"), - value); - break; - case 7: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("KB to tape"), - value); - break; - default: - g_fprintf(StatFile, _("Unknown ParameterCode %02X = %u(%d)\n"), - ParameterCode, - value, i); - break; - } - } - LogParameter = (LogParameter_T *)((u_char *)LogParameter + SIZEOF(LogParameter_T) + i); - } -} - -void -EXB85058HEPage3c( - LogParameter_T * buffer, - size_t length) -{ - int i; - unsigned value; - LogParameter_T *LogParameter; - unsigned ParameterCode; - LogParameter = buffer; - - g_fprintf(StatFile, _("\tDrive Usage Information Page\n")); - - while ((u_char *)LogParameter < ((unsigned char *)buffer + length)) { - i = LogParameter->ParameterLength; - ParameterCode = V2(LogParameter->ParameterCode); - - value = 0; - if (Decode(LogParameter, &value) == 0) { - switch (ParameterCode) { - case 1: - case 2: - case 3: - case 4: - case 5: - break; - case 6: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Total Load Count"), - value); - break; - case 7: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("MinutesSince Last Clean"), - value); - break; - case 8: - case 9: - break; - case 0xa: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Cleaning Count"), - value); - break; - case 0xb: - case 0xc: - case 0xd: - case 0xe: - case 0xf: - case 0x10: - break; - case 0x11: - g_fprintf(StatFile, _("%-30s = %u\n"), - _("Time to clean"), - value); - break; - case 0x12: - case 0x13: - case 0x14: - break; - default: - g_fprintf(StatFile, _("Unknown ParameterCode %02X = %u(%d)\n"), - ParameterCode, - value, i); - break; - } - } - LogParameter = (LogParameter_T *)((u_char *)LogParameter + SIZEOF(LogParameter_T) + i); - } -} - -int -Decode( - LogParameter_T * LogParameter, - unsigned * value) -{ - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START Decode\n")); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("Decode Parameter with length %d\n"), LogParameter->ParameterLength); - - *value = 0; - switch (LogParameter->ParameterLength) { - case 1: - *value = V1((u_char *)LogParameter + SIZEOF(LogParameter_T)); - break; - case 2: - *value = V2((u_char *)LogParameter + SIZEOF(LogParameter_T)); - break; - case 3: - *value = V3((u_char *)LogParameter + SIZEOF(LogParameter_T)); - break; - case 4: - *value = V4((u_char *)LogParameter + SIZEOF(LogParameter_T)); - break; - case 5: - *value = V5((u_char *)LogParameter + SIZEOF(LogParameter_T)); - break; - case 6: - *value = V6((u_char *)LogParameter + SIZEOF(LogParameter_T)); - break; - default: - g_fprintf(StatFile, _("Can't decode ParameterCode %02X size %d\n"), - V2(LogParameter->ParameterCode), LogParameter->ParameterLength); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP Decode (1)\n")); - return(1); - /*NOTREACHED*/ - } - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("Result = %d\n"), *value); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP Decode(0)\n")); - return(0); -} - -void -DumpDev( - OpenFiles_T * p, - char * device) -{ - if (p != NULL) - { - g_printf(_("%s Devicefd %d\n"), device, p->fd); - g_printf(_("%s Can SCSI %d\n"), device, p->SCSI); - g_printf(_("%s Device %s\n"), device, (p->dev != NULL)? p->dev:_("No set")); - g_printf(_("%s ConfigName %s\n"), device, (p->ConfigName != NULL) ? p->ConfigName:_("Not ser")); - } else { - g_printf(_("%s Null Pointer ....\n"), device); - } - g_printf(_("\n")); -} - -void -ChangerReplay( - char * option) -{ - u_char buffer[1024]; - FILE *ip; - int x; - unsigned bufferx; - - (void)option; /* Quiet unused parameter warning */ - - if ((ip=fopen("/tmp/chg-scsi-trace", "r")) == NULL) - { - exit(1); - } - - for (x = 0; x < 1024; x++) - { - if (fscanf(ip, "%2x", &bufferx) == EOF) - { - break; - /*NOTREACHED*/ - } - buffer[x] = (u_char)bufferx; - x++; - } - - DecodeModeSense(&buffer[0], 12, "DLT448ElementStatus :", 0, debug_file); - fclose(ip); -} - -/* - * Display all Information we can get about the library.... - */ -void -ChangerStatus( - char * option, - char * labelfile, - int HasBarCode, - char * changer_file, - char * changer_dev, - char * tape_device) -{ - extern OpenFiles_T *pDev; - size_t x; - FILE *out; - ExtendedRequestSense_T ExtRequestSense; - MBC_T *pbarcoderes; - - ChangerCMD_T *p = (ChangerCMD_T *)&ChangerIO; - pbarcoderes = alloc(SIZEOF(MBC_T)); - memset(pbarcoderes, 0, SIZEOF(MBC_T)); - - if (pModePage == NULL) { - pModePage = alloc(0xff); - } - - if ((out = fdopen(1 , "w")) == NULL) - { - g_printf(_("Error fdopen stdout\n")); - free(pbarcoderes); - return; - /*NOTREACHED*/ - } - - if (strcmp("types", option) == 0 || strcmp("all", option) == 0) - { - while(p->ident != NULL) - { - g_printf (_("Ident = %s, type = %s\n"),p->ident, p->type); - p++; - } - DumpSense(); - } - - if (strcmp("robot", option) == 0 || strcmp("all", option) == 0) - { - if (ElementStatusValid == 0) - { - if (pDev[INDEX_CHANGER].functions->function_status(pDev[INDEX_CHANGER].fd, 1) != 0) - { - g_printf(_("Can not initialize changer status\n")); - free(pbarcoderes); - fclose(out); - return; - /*NOTREACHED*/ - } - } - /* 0123456789012345678901234567890123456789012 */ - if (HasBarCode) - { - g_printf(_("Address Type Status From Barcode Label\n")); - } else { - g_printf(_("Address Type Status From\n")); - } - g_printf(_("-------------------------------------------\n")); - - - for ( x = 0; x < MTE; x++) - if (HasBarCode) - { - g_printf(_("%07d MTE %s %04d %s "),pMTE[x].address, - (pMTE[x].full ? _("Full ") :_("Empty")), - pMTE[x].from, pMTE[x].VolTag); - - if (pMTE[x].full == 1) - { - pbarcoderes->action = BARCODE_BARCODE; - strncpy(pbarcoderes->data.barcode, pMTE[x].VolTag, - SIZEOF(pbarcoderes->data.barcode)); - - if (MapBarCode(labelfile, pbarcoderes) == 0 ) - { - g_printf(_("No mapping\n")); - } else { - g_printf(_("%s \n"),pbarcoderes->data.voltag); - } - } else { - g_printf("\n"); - } - } else { - g_printf(_("%07d MTE %s %04d \n"),pMTE[x].address, - (pMTE[x].full ? _("Full ") :_("Empty")), - pMTE[x].from); - } - - - for ( x = 0; x < STE; x++) - if (HasBarCode) - { - g_printf(_("%07d STE %s %04d %s "),pSTE[x].address, - (pSTE[x].full ? _("Full "):_("Empty")), - pSTE[x].from, pSTE[x].VolTag); - - if (pSTE[x].full == 1) - { - pbarcoderes->action = BARCODE_BARCODE; - strncpy(pbarcoderes->data.barcode, pSTE[x].VolTag, - SIZEOF(pbarcoderes->data.barcode)); - - if (MapBarCode(labelfile, pbarcoderes) == 0 ) - { - g_printf(_("No mapping\n")); - } else { - g_printf(_("%s \n"),pbarcoderes->data.voltag); - } - } else { - g_printf("\n"); - } - } else { - g_printf(_("%07d STE %s %04d %s\n"),pSTE[x].address, - (pSTE[x].full ? _("Full"):_("Empty")), - pSTE[x].from, pSTE[x].VolTag); - } - - - for ( x = 0; x < DTE; x++) - if (HasBarCode) - { - g_printf(_("%07d DTE %s %04d %s "),pDTE[x].address, - (pDTE[x].full ? _("Full") : _("Empty")), - pDTE[x].from, pDTE[x].VolTag); - - if (pDTE[x].full == 1) - { - pbarcoderes->action = BARCODE_BARCODE; - strncpy(pbarcoderes->data.barcode, pDTE[x].VolTag, - SIZEOF(pbarcoderes->data.barcode)); - - if (MapBarCode(labelfile, pbarcoderes) == 0 ) - { - g_printf(_("No mapping\n")); - } else { - g_printf("%s \n",pbarcoderes->data.voltag); - } - } else { - g_printf("\n"); - } - - } else { - g_printf(_("%07d DTE %s %04d %s\n"),pDTE[x].address, - (pDTE[x].full ?_( "Full ") : _("Empty")), - pDTE[x].from, pDTE[x].VolTag); - } - - for ( x = 0; x < IEE; x++) - if (HasBarCode) - { - g_printf(_("%07d IEE %s %04d %s "),pIEE[x].address, - (pIEE[x].full ? _("Full ") : _("Empty")), - pIEE[x].from, pIEE[x].VolTag); - - if (pIEE[x].full == 1) - { - pbarcoderes->action = BARCODE_BARCODE; - strncpy(pbarcoderes->data.barcode, pIEE[x].VolTag, - SIZEOF(pbarcoderes->data.barcode)); - - if (MapBarCode(labelfile, pbarcoderes) == 0 ) - { - g_printf(_("No mapping\n")); - } else { - g_printf(_("%s \n"),pbarcoderes->data.voltag); - } - } else { - g_printf("\n"); - } - - } else { - g_printf(_("%07d IEE %s %04d %s\n"),pIEE[x].address, - (pIEE[x].full ? _("Full ") : _("Empty")), - pIEE[x].from, pIEE[x].VolTag); - } - - } - - if (strcmp("sense", option) == 0 || strcmp("all", option) == 0) - { - if (pDev[INDEX_CHANGER].SCSI == 1) - { - g_printf(_("\nSense Status from robot:\n")); - RequestSense(INDEX_CHANGER , &ExtRequestSense, 0); - DecodeExtSense(&ExtRequestSense, "", out); - } - - if (pDev[INDEX_TAPE].SCSI == 1) - { - g_printf("\n"); - g_printf(_("Sense Status from tape (tapectl):\n")); - RequestSense(INDEX_TAPE, &ExtRequestSense, 0); - DecodeExtSense(&ExtRequestSense, "", out); - } - - if (pDev[INDEX_TAPECTL].SCSI == 1) - { - g_printf("\n"); - g_printf(_("Sense Status from tape (tapectl):\n")); - RequestSense(INDEX_TAPECTL, &ExtRequestSense, 0); - DecodeExtSense(&ExtRequestSense, "", out); - } - } - - if (strcmp("ModeSenseRobot", option) == 0 || strcmp("all", option) == 0) - { - g_printf("\n"); - if (SCSI_ModeSense(INDEX_CHANGER, pModePage, 0xff, 0x08, 0x3f) == 0) - { - DecodeModeSense(pModePage, 0, "Changer :" , 0, out); - } - } - - if (strcmp("ModeSenseTape", option) == 0 || strcmp("all", option) == 0) - { - if (pDev[INDEX_TAPECTL].SCSI == 1) - { - g_printf("\n"); - if (SCSI_ModeSense(INDEX_TAPECTL, pModePage, 0xff, 0x0, 0x3f) == 0) - { - DecodeModeSense(pModePage, 0, "Tape :" , 1, out); - } - } - } - - if (strcmp("fd", option) == 0 || strcmp("all", option) == 0) - { - g_printf("changer_dev %s\n",changer_dev); - g_printf("changer_file %s\n", changer_file); - g_printf("tape_device %s\n\n", tape_device); - DumpDev(&pDev[INDEX_TAPE], "pTapeDev"); - DumpDev(&pDev[INDEX_TAPECTL], "pTapeDevCtl"); - DumpDev(&pDev[INDEX_CHANGER], "pChangerDev"); - } - - if (GenericClean("") == 1) - g_printf(_("Tape needs cleaning\n")); - - free(pbarcoderes); - fclose(out); -} - -void -dump_hex( - u_char * p, - size_t size, - int level, - int section) -{ - size_t row_count = 0; - int x; - - while (row_count < size) - { - DebugPrint(level, section,"%02X ", (u_char)p[row_count]); - if (((row_count + 1) % 16) == 0) - { - dbprintf(" "); - for (x = 16; x > 0; x--) - { - if (isalnum((u_char)p[row_count - x + 1 ])) - DebugPrint(level, section,"%c",(u_char)p[row_count - x + 1]); - else - DebugPrint(level, section,"."); - } - DebugPrint(level, section,"\n"); - } - row_count++; - } - DebugPrint(level, section,"\n"); -} - -void -TerminateString( - char * string, - size_t length) -{ - ssize_t x; - - for (x = (ssize_t)length; x >= 0 && !isalnum((int)string[x]); x--) - string[x] = '\0'; -} - -void -ChgExit( - char * where, - char * reason, - int level) -{ - (void)level; /* Quiet unused parameter warning */ - - dbprintf(_("ChgExit in %s, reason %s\n"), where, reason); - g_fprintf(stderr,"%s\n",reason); - exit(2); -} - -/* OK here starts a new set of functions. - * Every function is for one SCSI command. - * Prefix is SCSI_ and then the SCSI command name -*/ - -/* - * SCSI_Run is an wrapper arround SCSI_ExecuteCommand - * It seems to be an good idea to check first if the device - * is ready for accepting commands, and if this is true send - * the command - */ -int -SCSI_Run( - int DeviceFD, - Direction_T Direction, - CDB_T CDB, - size_t CDB_Length, - void * DataBuffer, - size_t DataBufferLength, - RequestSense_T * pRequestSense, - size_t RequestSenseLength) -{ - int ret = 0; - int ok = 0; - int maxtries = 0; - RequestSense_T *pRqS; - - /* Basic sanity checks */ - assert(CDB_Length <= UCHAR_MAX); - assert(RequestSenseLength <= UCHAR_MAX); - - pRqS = (RequestSense_T *)pRequestSense; - - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("SCSI_Run TestUnitReady\n")); - while (!ok && maxtries < MAXTRIES) - { - ret = SCSI_TestUnitReady(DeviceFD, (RequestSense_T *)pRequestSense ); - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("SCSI_Run TestUnitReady ret %d\n"),ret); - switch (ret) - { - case SCSI_OK: - ok=1; - break; - case SCSI_SENSE: - switch (SenseHandler(DeviceFD, 0, pRqS->SenseKey, pRqS->AdditionalSenseCode, pRqS->AdditionalSenseCodeQualifier, pRqS)) - { - case SENSE_NO: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run (TestUnitReady) SENSE_NO\n")); - ok=1; - break; - case SENSE_TAPE_NOT_ONLINE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run (TestUnitReady) SENSE_TAPE_NOT_ONLINE\n")); - ok=1; - break; - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run (TestUnitReady) SENSE_IGNORE\n")); - ok=1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("SCSI_Run (TestUnitReady) SENSE_ABORT\n")); - return(-1); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run (TestUnitReady) SENSE_RETRY\n")); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run (TestUnitReady) default (SENSE)\n")); - ok=1; - break; - } - break; - case SCSI_ERROR: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("SCSI_Run (TestUnitReady) SCSI_ERROR\n")); - return(-1); - /*NOTREACHED*/ - case SCSI_BUSY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run (TestUnitReady) SCSI_BUSY\n")); - break; - case SCSI_CHECK: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run (TestUnitReady) SCSI_CHECK\n")); - break; - default: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("SCSI_Run (TestUnitReady) unknown (%d)\n"),ret); - break; - } - if (!ok) - { - sleep(1); - maxtries++; - } - } - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run TestUnitReady after %d sec:\n"),maxtries); - - if (ok != 1) - { - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("SCSI_Run Exit %d\n"),ret); - return(-1); - /*NOTREACHED*/ - } - - ok = 0; - maxtries = 0; - while (!ok && maxtries < MAXTRIES) - { - ret = SCSI_ExecuteCommand(DeviceFD, - Direction, - CDB, - CDB_Length, - DataBuffer, - DataBufferLength, - pRequestSense, - RequestSenseLength); - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run Exit %d\n"),ret); - switch (ret) - { - case SCSI_OK: - ok=1; - break; - case SCSI_SENSE: - switch (SenseHandler(DeviceFD, 0, pRqS->SenseKey, pRqS->AdditionalSenseCode, pRqS->AdditionalSenseCodeQualifier, pRqS)) - { - case SENSE_NO: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run SENSE_NO\n")); - ok=1; - break; - case SENSE_TAPE_NOT_ONLINE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run SENSE_TAPE_NOT_ONLINE\n")); - ok=1; - break; - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run SENSE_IGNORE\n")); - ok=1; - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("SCSI_Run SENSE_ABORT\n")); - return(-1); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run SENSE_RETRY\n")); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run default (SENSE)\n")); - ok=1; - break; - } - break; - case SCSI_ERROR: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("SCSI_Run SCSI_ERROR\n")); - return(-1); - /*NOTREACHED*/ - case SCSI_BUSY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run SCSI_BUSY\n")); - break; - case SCSI_CHECK: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Run (TestUnitReady) SCSI_CHECK\n")); - break; - default: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("SCSI_Run (TestUnitReady) unknown (%d)\n"),ret); - break; - } - maxtries++; - sleep(1); - } - - if (ok == 1) - { - return(0); - /*NOTREACHED*/ - } - return(-1); -} - -/* - * This a vendor specific command !!!!!! - * First seen at AIT :-) - */ -int -SCSI_AlignElements( - int DeviceFD, - size_t AE_MTE, - size_t AE_DTE, - size_t AE_STE) -{ - RequestSense_T *pRequestSense; - int retry; - CDB_T CDB; - int ret; - int i; - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START SCSI_AlignElements\n")); - - pRequestSense = alloc(SIZEOF(RequestSense_T)); - - for (retry = 0; retry < MAX_RETRIES; retry++) - { - CDB[0] = 0xE5; - CDB[1] = 0; - MSB2(&CDB[2],AE_MTE); /* Which MTE to use, default 0 */ - MSB2(&CDB[4],AE_DTE); /* Which DTE to use, no range check !! */ - MSB2(&CDB[6],AE_STE); /* Which STE to use, no range check !! */ - CDB[8] = 0; - CDB[9] = 0; - CDB[10] = 0; - CDB[11] = 0; - - ret = SCSI_Run(DeviceFD, Input, CDB, 12, - NULL, 0, pRequestSense, SIZEOF(RequestSense_T)); - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_AlignElements : SCSI_Run = %d\n"), ret); - DecodeSense(pRequestSense, _("SCSI_AlignElements :"),debug_file); - - if (ret < 0) - { - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("%s: Request Sense[Inquiry]: %02X"), - "chs", ((u_char *) &pRequestSense)[0]); - for (i = 1; i < (int)sizeof(RequestSense_T); i++) - DebugPrint(DEBUG_ERROR, SECTION_SCSI," %02X", ((u_char *) &pRequestSense)[i]); - DebugPrint(DEBUG_ERROR, SECTION_SCSI,"\n"); - return(ret); - /*NOTREACHED*/ - } - if ( ret > 0) - { - switch(SenseHandler(DeviceFD, 0 , pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_AlignElements : SENSE_IGNORE\n")); - return(0); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_AlignElements : SENSE_RETRY no %d\n"), retry); - break; - case SENSE_ABORT: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("SCSI_AlignElements : SENSE_ABORT\n")); - return(-1); - /*NOTREACHED*/ - case SENSE_TAPE_NOT_UNLOADED: - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("SCSI_AlignElements : Tape still loaded, eject failed\n")); - return(-1); - /*NOTREACHED*/ - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_AlignElements : end %d\n"), pRequestSense->SenseKey); - return(pRequestSense->SenseKey); - /*NOTREACHED*/ - } - } - if (ret == 0) - { - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_AlignElements : end %d\n"), ret); - return(ret); - /*NOTREACHED*/ - } - } - DebugPrint(DEBUG_ERROR, SECTION_SCSI, - _("SCSI_AlignElements: Retries exceeded = %d\n"), retry); - return(-1); -} - - -int -SCSI_Move( - int DeviceFD, - u_char chm, - int from, - int to) -{ - RequestSense_T *pRequestSense; - int retry; - CDB_T CDB; - int ret = -1; - int i; - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START SCSI_Move\n")); - - pRequestSense = alloc(SIZEOF(RequestSense_T)); - - for (retry = 0; (ret != 0) && (retry < MAX_RETRIES); retry++) - { - CDB[0] = SC_MOVE_MEDIUM; - CDB[1] = 0; - CDB[2] = 0; - CDB[3] = chm; /* Address of CHM */ - MSB2(&CDB[4],from); - MSB2(&CDB[6],to); - CDB[8] = 0; - CDB[9] = 0; - CDB[10] = 0; - CDB[11] = 0; - - ret = SCSI_Run(DeviceFD, Input, CDB, 12, - NULL, 0, pRequestSense, SIZEOF(RequestSense_T)); - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Move : SCSI_Run = %d\n"), ret); - DecodeSense(pRequestSense, _("SCSI_Move :"),debug_file); - - if (ret < 0) - { - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("%s: Request Sense[Inquiry]: %02X"), - "chs", ((u_char *) &pRequestSense)[0]); - for (i = 1; i < (int)sizeof(RequestSense_T); i++) - DebugPrint(DEBUG_ERROR, SECTION_SCSI," %02X", ((u_char *) &pRequestSense)[i]); - DebugPrint(DEBUG_INFO, SECTION_SCSI,"\n"); - return(ret); - /*NOTREACHED*/ - } - if ( ret > 0) - { - switch(SenseHandler(DeviceFD, 0 , pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_IGNORE: - dbprintf(_("SCSI_Move : SENSE_IGNORE\n")); - return(0); - /*NOTREACHED*/ - case SENSE_RETRY: - dbprintf(_("SCSI_Move : SENSE_RETRY no %d\n"), retry); - break; - case SENSE_ABORT: - dbprintf(_("SCSI_Move : SENSE_ABORT\n")); - return(-1); - /*NOTREACHED*/ - case SENSE_TAPE_NOT_UNLOADED: - dbprintf(_("SCSI_Move : Tape still loaded, eject failed\n")); - return(-1); - /*NOTREACHED*/ - default: - dbprintf(_("SCSI_Move : end %d\n"), pRequestSense->SenseKey); - return(pRequestSense->SenseKey); - /*NOTREACHED*/ - } - } - } - dbprintf(_("SCSI_Move : end %d\n"), ret); - return(ret); -} - -int -SCSI_LoadUnload( - int DeviceFD, - RequestSense_T * pRequestSense, - u_char byte1, - u_char load) -{ - CDB_T CDB; - int ret; - - dbprintf(_("##### START SCSI_LoadUnload\n")); - - CDB[0] = SC_COM_UNLOAD; - CDB[1] = byte1; - CDB[2] = 0; - CDB[3] = 0; - CDB[4] = load; - CDB[5] = 0; - - - ret = SCSI_Run(DeviceFD, Input, CDB, 6, - NULL, 0, - pRequestSense, - SIZEOF(RequestSense_T)); - - if (ret < 0) - { - dbprintf(_("SCSI_Unload : failed %d\n"), ret); - return(-1); - /*NOTREACHED*/ - } - - dbprintf(_("##### STOP SCSI_LoadUnload\n")); - return(ret); -} - -int -SCSI_TestUnitReady( - int DeviceFD, - RequestSense_T * pRequestSense) -{ - CDB_T CDB; - int ret; - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START SCSI_TestUnitReady\n")); - - CDB[0] = SC_COM_TEST_UNIT_READY; - CDB[1] = 0; - CDB[2] = 0; - CDB[3] = 0; - CDB[4] = 0; - CDB[5] = 0; - - ret = SCSI_ExecuteCommand(DeviceFD, Input, CDB, 6, - NULL, (size_t)0, - pRequestSense, - SIZEOF(RequestSense_T)); - - /* - * We got an error, so let the calling function handle this - */ - if (ret > 0) - { - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("###### STOP SCSI_TestUnitReady (1)\n")); - return(ret); - /*NOTREACHED*/ - } - - /* - * OK, no error condition - * If no sense is set, the Unit is ready - */ - if (pRequestSense->ErrorCode == 0 && pRequestSense->SenseKey == 0) - { - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("###### STOP SCSI_TestUnitReady (1)\n")); - return(0); - /*NOTREACHED*/ - } - - /* - * Some sense is set - */ - if (pRequestSense->ErrorCode != 0){ - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("###### STOP SCSI_TestUnitReady ErrorCode set\n")); - } - if (pRequestSense->SenseKey != 0) { - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("###### STOP SCSI_TestUnitReady Sense Key set\n")); - } - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("###### STOP SCSI_TestUnitReady (0)\n")); - return(SCSI_SENSE); -} - - -int -SCSI_ModeSelect( - int DeviceFD, - u_char * buffer, - u_char length, - u_char save, - u_char mode, - u_char lun) -{ - CDB_T CDB; - RequestSense_T *pRequestSense; - int ret = -1; - int retry; - u_char *sendbuf; - - dbprintf(_("##### START SCSI_ModeSelect\n")); - - dbprintf(_("SCSI_ModeSelect start length = %u:\n"), (unsigned)length); - pRequestSense = alloc(SIZEOF(RequestSense_T)); - sendbuf = alloc((size_t)length + 4); - memset(sendbuf, 0 , (size_t)length + 4); - - memcpy(&sendbuf[4], buffer, (size_t)length); - dump_hex(sendbuf, (size_t)length+4, DEBUG_INFO, SECTION_SCSI); - - for (retry = 0; (ret != 0) && (retry < MAX_RETRIES); retry++) - { - memset(pRequestSense, 0, SIZEOF(RequestSense_T)); - - CDB[0] = SC_COM_MODE_SELECT; - CDB[1] = (u_char)(((lun << 5) & 0xF0) | ((mode << 4) & 0x10) | (save & 1)); - CDB[2] = 0; - CDB[3] = 0; - CDB[4] = (u_char)(length + 4); - CDB[5] = 0; - ret = SCSI_Run(DeviceFD, Output, CDB, 6, - sendbuf, - (size_t)length + 4, - pRequestSense, - SIZEOF(RequestSense_T)); - if (ret < 0) - { - dbprintf(_("SCSI_ModeSelect : ret %d\n"), ret); - goto done; - /*NOTREACHED*/ - } - - if ( ret > 0) - { - switch(SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, - pRequestSense->AdditionalSenseCode, - pRequestSense->AdditionalSenseCodeQualifier, - pRequestSense)) - { - case SENSE_IGNORE: - dbprintf(_("SCSI_ModeSelect : SENSE_IGNORE\n")); - goto done; - /*NOTREACHED*/ - - case SENSE_RETRY: - dbprintf(_("SCSI_ModeSelect : SENSE_RETRY no %d\n"), retry); - break; - - default: - ret = pRequestSense->SenseKey; - goto end; - } - } - } -end: - dbprintf(_("SCSI_ModeSelect end: %d\n"), ret); - -done: - free(pRequestSense); - free(sendbuf); - return(ret); -} - - - -int -SCSI_ModeSense( - int DeviceFD, - u_char * buffer, - u_char size, - u_char byte1, - u_char byte2) -{ - CDB_T CDB; - RequestSense_T *pRequestSense; - int ret = 1; - int retry = 1; - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START SCSI_ModeSense\n")); - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense start length = %d:\n"), size); - pRequestSense = alloc(SIZEOF(RequestSense_T)); - - while (ret && retry < MAX_RETRIES) - { - memset(pRequestSense, 0, SIZEOF(RequestSense_T)); - memset(buffer, 0, size); - - CDB[0] = SC_COM_MODE_SENSE; - CDB[1] = byte1; - CDB[2] = byte2; - CDB[3] = 0; - CDB[4] = size; - CDB[5] = 0; - ret = SCSI_Run(DeviceFD, Input, CDB, 6, - buffer, - size, - pRequestSense, - SIZEOF(RequestSense_T)); - if (ret < 0) - { - return(ret); - /*NOTREACHED*/ - } - - if ( ret > 0) - { - switch(SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense : SENSE_IGNORE\n")); - return(0); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense : SENSE_RETRY no %d\n"), retry); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense : end %d\n"), pRequestSense->SenseKey); - return(pRequestSense->SenseKey); - /*NOTREACHED*/ - } - } - retry++; - } - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense end: %d\n"), ret); - return(ret); -} - -int -SCSI_Inquiry( - int DeviceFD, - SCSIInquiry_T * buffer, - size_t size) -{ - CDB_T CDB; - RequestSense_T *pRequestSense; - int i; - int ret = -1; - int retry = 1; - - assert(size <= UCHAR_MAX); - - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("##### START SCSI_Inquiry\n")); - - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("SCSI_Inquiry start length = %d:\n"), size); - - pRequestSense = alloc((size_t)size); - - while (retry > 0 && retry < MAX_RETRIES) - { - memset(buffer, 0, size); - CDB[0] = SC_COM_INQUIRY; - CDB[1] = 0; - CDB[2] = 0; - CDB[3] = 0; - CDB[4] = (u_char)size; - CDB[5] = 0; - - ret = SCSI_ExecuteCommand(DeviceFD, Input, CDB, 6, - buffer, - size, - pRequestSense, - SIZEOF(RequestSense_T)); - if (ret < 0) - { - DebugPrint(DEBUG_ERROR, SECTION_SCSI,_("%s: Request Sense[Inquiry]: %02X"), - "chs", ((u_char *) pRequestSense)[0]); - for (i = 1; i < (int)sizeof(RequestSense_T); i++) - DebugPrint(DEBUG_ERROR, SECTION_SCSI," %02X", ((u_char *) pRequestSense)[i]); - DebugPrint(DEBUG_ERROR, SECTION_SCSI, "\n"); - DebugPrint(DEBUG_ERROR, SECTION_SCSI, _("Inquiry end: %d\n"), ret); - return(ret); - /*NOTRACHED*/ - } - if ( ret > 0) - { - switch(SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Inquiry : SENSE_IGNORE\n")); - return(0); - /*NOTREACHED*/ - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("SCSI_Inquiry : SENSE_RETRY no %d\n"), retry); - break; - default: - DebugPrint(DEBUG_ERROR, SECTION_SCSI, _("SCSI_Inquiry : end %d\n"), pRequestSense->SenseKey); - return(pRequestSense->SenseKey); - /*NOTREACHED*/ - } - } - retry++; - if (ret == 0) - { - dump_hex((u_char *)buffer, size, DEBUG_INFO, SECTION_SCSI); - DebugPrint(DEBUG_INFO, SECTION_SCSI, _("SCSI_Inquiry : end %d\n"), ret); - return(ret); - /*NOTRACHED*/ - } - } - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_Inquiry end: %d\n"), ret); - return(ret); -} - -/* - * Read the Element Status. If DescriptorSize != 0 then - * allocate DescriptorSize * NoOfElements for the result from the - * Read Element Status command. - * If DescriptorSize == 0 than try to figure out how much space is needed - * by - * 1. do an read with an allocation size of 8 - * 2. from the result take the 'Byte Count of Descriptor Available' - * 3. do again an Read Element Status with the result from 2. - * - */ -int -SCSI_ReadElementStatus( - int DeviceFD, - u_char type, - u_char lun, - u_char VolTag, - int StartAddress, - size_t NoOfElements, - size_t DescriptorSize, - u_char ** data) -{ - CDB_T CDB; - size_t DataBufferLength; - ElementStatusData_T *ElementStatusData; - RequestSense_T *pRequestSense; - int retry = 1; - int ret = -1; - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### START SCSI_ReadElementStatus\n")); - - pRequestSense = alloc(SIZEOF(RequestSense_T)); - - /* - * How many elements, if <= 0 than exit with an fatal error - */ - if (NoOfElements == 0) - { - ChgExit("SCSI_ReadElementStatus",_("No of Elements passed are le 0"),FATAL); - /*NOTREACHED*/ - } - - VolTag = (u_char)((VolTag << 4) & 0x10); - type = (u_char)(type & 0xf); - lun = (u_char)((lun << 5) & 0xe0); - - /* if DescriptorSize == 0 - * try to get the allocation length for the second call - */ - if (DescriptorSize == 0) - { - *data = newalloc(*data, 8); - memset(*data, 0, 8); - - while (retry > 0 && retry < MAX_RETRIES) - { - memset(pRequestSense, 0, SIZEOF(RequestSense_T) ); - - CDB[0] = SC_COM_RES; /* READ ELEMENT STATUS */ - CDB[1] = (u_char)(VolTag | type | lun); /* Element Type Code , VolTag, LUN */ - MSB2(&CDB[2], StartAddress); /* Starting Element Address */ - MSB2(&CDB[4], NoOfElements); /* Number Of Element */ - CDB[6] = 0; /* Reserved */ - MSB3(&CDB[7],8); /* Allocation Length */ - CDB[10] = 0; /* Reserved */ - CDB[11] = 0; /* Control */ - - ret = SCSI_Run(DeviceFD, Input, CDB, 12, - *data, 8, - pRequestSense, SIZEOF(RequestSense_T)); - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ReadElementStatus : (1) SCSI_Run %d\n"), ret); - if (ret < 0) - { - DecodeSense(pRequestSense, "SCSI_ReadElementStatus :",debug_file); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP SCSI_ReadElementStatus (%d)\n"),ret); - return(ret); - /*NOTRACHED*/ - } - if ( ret > 0) - { - switch(SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense : SENSE_IGNORE\n")); - retry = 0; - break; - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense : SENSE_RETRY no %d\n"), retry); - sleep(2); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense : end %d\n"), pRequestSense->SenseKey); - return(pRequestSense->SenseKey); - /*NOTREACHED*/ - } - } - retry++; - if (ret == 0) - { - retry=0; - } - } - if (retry > 0) - { - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP SCSI_ReadElementStatus (%d)\n"),ret); - return(ret); - /*NOTRACHED*/ - } - - ElementStatusData = (ElementStatusData_T *)*data; - DataBufferLength = V3(ElementStatusData->count); - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ReadElementStatus: DataBufferLength %X, ret %d\n"),DataBufferLength, ret); - - dump_hex(*data, 8, DEBUG_INFO, SECTION_ELEMENT); - } else { /* DescriptorSize != 0 */ - DataBufferLength = NoOfElements * DescriptorSize; - } - - DataBufferLength = DataBufferLength + 8; - *data = newalloc(*data, DataBufferLength); - memset(*data, 0, DataBufferLength); - retry = 1; - - while (retry > 0 && retry < MAX_RETRIES) - { - memset(pRequestSense, 0, SIZEOF(RequestSense_T) ); - - CDB[0] = SC_COM_RES; /* READ ELEMENT STATUS */ - CDB[1] = (u_char)(VolTag | type | lun); /* Element Type Code, VolTag, LUN */ - MSB2(&CDB[2], StartAddress); /* Starting Element Address */ - MSB2(&CDB[4], NoOfElements); /* Number Of Element */ - CDB[6] = 0; /* Reserved */ - MSB3(&CDB[7],DataBufferLength); /* Allocation Length */ - CDB[10] = 0; /* Reserved */ - CDB[11] = 0; /* Control */ - - ret = SCSI_Run(DeviceFD, Input, CDB, 12, - *data, DataBufferLength, - pRequestSense, SIZEOF(RequestSense_T)); - - - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ReadElementStatus : (2) SCSI_Run %d\n"), ret); - if (ret < 0) - { - DecodeSense(pRequestSense, _("SCSI_ReadElementStatus :"),debug_file); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP SCSI_ReadElementStatus (%d)\n"),ret); - return(ret); - /*NOTRACHED*/ - } - if ( ret > 0) - { - switch(SenseHandler(DeviceFD, 0, pRequestSense->SenseKey, pRequestSense->AdditionalSenseCode, pRequestSense->AdditionalSenseCodeQualifier, pRequestSense)) - { - case SENSE_IGNORE: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense : SENSE_IGNORE\n")); - retry = 0; - break; - case SENSE_RETRY: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense : SENSE_RETRY no %d\n"), retry); - sleep(2); - break; - default: - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("SCSI_ModeSense : end %d\n"), pRequestSense->SenseKey); - return(pRequestSense->SenseKey); - /*NOTREACHED*/ - } - } - retry++; - if (ret == 0) - { - retry=0; - } - } - - if (retry > 0) - { - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP SCSI_ReadElementStatus (%d)\n"),ret); - return(ret); - /*NOTRACHED*/ - } - - dump_hex(*data, DataBufferLength, DEBUG_INFO, SECTION_SCSI); - DebugPrint(DEBUG_INFO, SECTION_SCSI,_("##### STOP SCSI_ReadElementStatus (%d)\n"),ret); - return(ret); -} - -printf_arglist_function2(void DebugPrint, int, level, int, section, char *, fmt) -{ - va_list argp; - char buf[1024]; - int dlevel; - int dsection = -1; - time_t ti = time(NULL); - - if (changer->debuglevel) - { - if (sscanf(changer->debuglevel,"%d:%d", &dlevel, &dsection) != 2) { - dbprintf(_("Parse error: line is '%s' expected [0-9]*:[0-9]*\n"), - changer->debuglevel); - dlevel=1; - dsection=1; - } - } else { - dlevel=1; - dsection=1; - } - - arglist_start(argp, fmt); - g_vsnprintf(buf, SIZEOF(buf), fmt, argp); - if (dlevel >= level) - { - if (section == dsection || dsection == 0) - { - if (strchr(buf, '\n') != NULL && strlen(buf) > 1) - { - dbprintf(_("%ld:%s"), (long)ti, buf); - } else { - dbprintf("%s", buf); - } - } - } - arglist_end(argp); -}