home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * $Id: scsitape.c,v 1.4 1992/10/14 18:35:14 ak Exp $
- *****************************************************************************
- * $Log: scsitape.c,v $
- * Revision 1.4 1992/10/14 18:35:14 ak
- * IBM SCSI driver.
- *
- * Revision 1.3 1992/09/12 18:10:52 ak
- * Added scsi_name
- * Added device name support to tctl.c
- *
- * Revision 1.2 1992/09/02 19:05:43 ak
- * Version 2.0
- * - EMX version
- * - AIX version
- * - SCSI-2 commands
- * - ADD Driver
- * - blocksize support
- *
- * Revision 1.1.1.1 1992/01/06 20:27:14 ak
- * Interface now based on ST01 and ASPI.
- * AHA_DRVR no longer supported.
- * Files reorganized.
- *
- * Revision 1.1 1992/01/06 20:27:12 ak
- * Initial revision
- *
- *****************************************************************************/
-
- static char *rcsid = "$Id: scsitape.c,v 1.4 1992/10/14 18:35:14 ak Exp $";
-
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #define INCL_DOSFILEMGR
- #define INCL_DOSDEVICES
- #define INCL_DOSPROCESS
- #define INCL_DOSSEMAPHORES
- #define INCL_ERRORS
- #include <os2.h>
-
- #ifdef __EMX__
- #ifndef _far
- #define _far
- #endif
- #endif
-
- #include "scsi.h"
- #include "aspi.h"
- #include "tapedrvr.h"
-
- #define CDB_LEN 12
- #define SENSE_LEN 40
-
- #if OS2 >= 2
- typedef ULONG Word;
- #else
- typedef USHORT Word;
- #endif
-
- typedef struct SCB {
- void * cdb;
- void _far * data;
- long data_len;
- BYTE target;
- BYTE lun;
- BYTE cdb_len;
- BYTE sense_len;
- BYTE readflag;
- BYTE sense [SENSE_LEN];
- unsigned error;
- } SCB;
-
- static HFILE hdev;
- static BYTE sense_cmd[6] = { CmdRequestSense, 0, 0, 0, 0, 0 };
- static TID thread_id;
- #if OS2 >= 2
- static HMTX mutex;
- static HEV done;
- #else
- static BYTE thread_stack[4096];
- static ULONG sema;
- #endif
- static SCB *thread_scb;
- static BYTE trace = 0;
- static BYTE drvLevel = ST01driver;
- enum SenseMode senseMode = Sensekey;
-
- static void
- fatal(char *msg, ...)
- {
- va_list ap;
- fprintf(stderr, "Fatal SCSI error: ");
- va_start(ap, msg);
- vfprintf(stderr, msg, ap);
- va_end (ap);
- fprintf(stderr, "\n");
- exit (2);
- }
-
- command(BYTE *cdb, int len)
- {
- int i;
- fprintf(stderr, "SCSI op:");
- for (i = 0; i < len; ++i)
- fprintf(stderr, " %02X", cdb[i]);
- fprintf(stderr, "\n");
- }
-
- status(BYTE *sense, int len)
- {
- int i;
- fprintf(stderr, "SCSI status:");
- for (i = 0; i < len; ++i) {
- if (i && (i % 16) == 0)
- fprintf(stderr, "\n ");
- fprintf(stderr, " %02X", sense[i]);
- }
- fprintf(stderr, "\n");
- }
-
- static void
- init()
- {
- BYTE data[2];
- char *cp;
- #if OS2 >= 2
- ULONG datalen = 2;
-
- if (DosDevIOCtl(hdev, IOCtlCategory, IOCtlLevel,
- 0, 0, 0, data, datalen, &datalen) == 0)
- #else
- if (DosDevIOCtl2(data, 2, 0, 0, IOCtlLevel, IOCtlCategory, hdev) == 0)
- #endif
- {
- drvLevel = data[0];
- senseMode = data[1];
- if (trace)
- fprintf(stderr, "Device driver level: %d, sense mode: %d\n",
- drvLevel, senseMode);
- } else {
- if ((cp = getenv("TAPEMODE")) != NULL)
- senseMode = atoi(cp);
- if (trace)
- fprintf(stderr, "Device driver level: 0, sense mode: %d\n",
- senseMode);
- }
- }
-
- void
- scsi_file(int fd)
- {
- hdev = fd;
- init();
- }
-
- void
- scsi_name(char *name)
- {
- Word rc, action;
- char *cp;
-
- if (!name) {
- name = getenv("TAPE");
- if (name == NULL)
- fatal("Missing environment name TAPE\n");
- }
- while (*name == '+')
- ++name;
-
- #if OS2 >= 2
- rc = DosOpen((PSZ)name, &hdev, &action, 0L, 0,
- FILE_OPEN, OPEN_ACCESS_READWRITE+OPEN_SHARE_DENYNONE+OPEN_FLAGS_FAIL_ON_ERROR, 0);
- #else
- rc = DosOpen((PSZ)name, &hdev, &action, 0L, 0,
- FILE_OPEN, OPEN_ACCESS_READWRITE+OPEN_SHARE_DENYNONE+OPEN_FLAGS_FAIL_ON_ERROR, 0L);
- #endif
- if (rc)
- fatal("Cannot access device %s, return code %u", name, rc);
- init();
- }
-
- void
- scsi_init(void)
- {
- scsi_name(NULL);
- }
-
- void
- scsi_term(void)
- {
- DosClose(hdev);
- }
-
- void
- scsi_trace(int level)
- {
- trace = level;
- }
-
- void *
- scsi_alloc(void)
- {
- void *p = malloc(sizeof(SCB));
- if (p == NULL)
- fatal("No memory for SCSI Control Block\n");
- }
-
- void
- scsi_free(void *p)
- {
- free(p);
- }
-
- static int
- mapDriverError(unsigned rc)
- {
- if (rc < 0xFF00)
- return SystemError + ErrorCode(rc);
- rc &= 0xFF;
-
- switch (drvLevel) {
- case ST01driver:
- return DriverError + ErrST01Driver + (rc & ErrMask);
- case ADDdriver:
- if (rc < ErrTapeDriver)
- return MappedError + rc;
- break;
- case SCSIdriver:
- if (rc < 0x20)
- return DriverError + 0x100 + rc;
- if (rc < 0x40)
- return UnknownError + (rc - 0x20);
- if (rc < 0x50)
- return StatusError + ((rc - 0x40) << 1);
- if (rc < 0x80)
- return HostError + 0x100 + (rc - 0x50);
- if (rc < 0xA0)
- return DriverError + 0x100 + rc;
- }
-
- switch (rc & ErrSource) {
- case ErrTargetStatus:
- return StatusError + (rc & ErrMask);
- case ErrST01Driver:
- case ErrASPIDriver1:
- case ErrASPIDriver2:
- case ErrTapeDriver:
- return DriverError + rc;
- case ErrHostAdapter:
- return HostError + (rc & ErrMask);
- default:
- return UnknownError + rc;
- }
- }
-
- int
- scsi_cmd(int target, int lun,
- void *cdb, int cdb_len, void *sense, int sense_len,
- void _far *data, long data_len,
- int readflag)
- {
- BYTE cmd, *sptr;
- Word fcn, rc, rc2, len;
- #if OS2 >= 2
- ULONG parmlen, datalen;
- #endif
-
- if (cdb_len > CDB_LEN || sense_len > SENSE_LEN)
- return SenseKey+IllegalRequest;
-
- cmd = *(BYTE *)cdb;
- fcn = (cmd == SeqRead || cmd == SeqWrite) ? IOCtlFast : IOCtlSlow;
- if (drvLevel)
- fcn += readflag ? IOCtlRead : IOCtlWrite;
- if (trace) {
- fprintf(stderr, "\tIOCtl=%02X, ", fcn);
- command(cdb, cdb_len);
- }
- #if OS2 >= 2
- parmlen = cdb_len;
- datalen = data_len;
- rc = DosDevIOCtl(hdev, IOCtlCategory, fcn,
- cdb, parmlen, &parmlen, data, datalen, &datalen);
- #else
- if (data_len)
- rc = DosDevIOCtl2(data, (Word)data_len, cdb, cdb_len,
- fcn, IOCtlCategory, hdev);
- else
- rc = DosDevIOCtl2(0, 0, cdb, cdb_len,
- fcn, IOCtlCategory, hdev);
- #endif
-
- if (trace >= 2)
- fprintf(stderr, "IOCtl return %X\n", rc);
- if (drvLevel != ST01driver && rc == 0)
- return 0;
- if (cmd == CmdRequestSense)
- return rc ? mapDriverError(rc) : 0;
- if (rc)
- switch (drvLevel) {
- case ST01driver:
- if (rc != 0xFF00+CheckStatus)
- return mapDriverError(rc);
- break;
- case ASPIdriver:
- if (rc != 0xFF00+ErrTargetStatus+CheckStatus)
- return mapDriverError(rc);
- break;
- case SCSIdriver:
- if (rc != 0xFF41)
- return mapDriverError(rc);
- break;
- }
-
- #if OS2 >= 2
- parmlen = sizeof sense_cmd;
- datalen = sense_len;
- rc2 = DosDevIOCtl(hdev, IOCtlCategory, drvLevel ? IOCtlSense : IOCtlSlow,
- sense_cmd, parmlen, &parmlen, sense, datalen, &datalen);
- if (trace && sense_len != datalen) {
- fprintf(stderr, "Got %d sense bytes\n", datalen);
- sense_len = datalen;
- }
- #else
- rc2 = DosDevIOCtl2(sense, (Word)sense_len, sense_cmd, sizeof sense_cmd,
- drvLevel ? IOCtlSense : IOCtlSlow, IOCtlCategory, hdev);
- #endif
- if (rc2)
- return mapDriverError(rc ? rc : rc2);
-
- if (trace)
- status(sense, sense_len);
-
- sptr = (BYTE *)sense;
- if ((sptr[0] & 0x7E) != 0x70)
- return sptr[0] ? ExtendedError + (sptr[0] & 0x7F) : 0;
- if (sense_len <= 2)
- return UnknownError;
- return sptr[2] ? SenseKey + (sptr[2] & 0x0F) : 0;
- }
-
- #pragma check_stack(off)
-
- static void _far
- #if OS2 >= 2
- thread_fcn(ULONG dummy)
- #else
- thread_fcn(void)
- #endif
- {
- for (;;) {
- DosSuspendThread(thread_id);
- if (thread_scb) {
- thread_scb->error = scsi_cmd(thread_scb->target,
- thread_scb->lun,
- thread_scb->cdb, thread_scb->cdb_len,
- thread_scb->sense, thread_scb->sense_len,
- thread_scb->data, thread_scb->data_len,
- thread_scb->readflag);
- #if OS2 >= 2
- DosPostEventSem(done);
- DosReleaseMutexSem(mutex);
- #else
- DosSemClear((HSEM)&sema);
- #endif
- }
- }
- }
-
- #pragma check_stack()
-
- int
- scsi_start(void *dcb,
- int target, int lun,
- void *cdb, int cdb_len, int sense_len,
- void _far *data, long data_len,
- int readflag)
- {
- SCB *scb = (SCB *)dcb;
- #if OS2 >= 2
- ULONG npost;
- #endif
-
- if (sense_len > SENSE_LEN)
- return SenseKey+IllegalRequest;
-
- if (thread_id == 0) {
- Word rc;
- #if OS2 >= 2
- rc = DosCreateThread(&thread_id, thread_fcn, 0, 0, 8192);
- if (rc)
- fatal("Cannot create thread, return code %u", rc);
- rc = DosCreateMutexSem(0, &mutex, 0, 0);
- if (rc)
- fatal("Cannot create mutex sema, return code %u", rc);
- rc = DosCreateEventSem(0, &done, 0, 0);
- if (rc)
- fatal("Cannot create event sema, return code %u", rc);
- #else
- rc = DosCreateThread(thread_fcn, &thread_id, thread_stack+4096);
- if (rc)
- fatal("Cannot create thread, return code %u", rc);
- DosSemClear((HSEM)&sema);
- #endif
- }
-
- if (thread_scb)
- return SystemError+ErrorCode(ERROR_DEVICE_IN_USE);
-
- #if OS2 >= 2
- DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT);
- #else
- DosSemWait((HSEM)&sema, -1);
- #endif
-
- scb->target = target;
- scb->lun = lun;
- scb->cdb = cdb;
- scb->cdb_len = cdb_len;
- scb->data = data;
- scb->data_len = data_len;
- scb->sense_len = sense_len;
- scb->readflag = readflag;
- thread_scb = scb;
-
- #if OS2 >= 2
- DosResetEventSem(done, &npost);
- #else
- DosSemSet((HSEM)&sema);
- #endif
- DosResumeThread(thread_id);
-
- return ComeAgain;
- }
-
- int
- scsi_wait(void *dcb, void *sense, int wait)
- {
- SCB *scb = (SCB *)dcb;
- int r;
-
- if (scb != thread_scb)
- return SystemError+ErrorCode(ERROR_INVALID_HANDLE);
- #if OS2 >= 2
- if (DosWaitEventSem(done, SEM_INDEFINITE_WAIT))
- #else
- if (DosSemWait((HSEM)&sema, wait ? -1 : 0))
- #endif
- return ComeAgain;
- thread_scb = 0;
- memcpy(sense, scb->sense, scb->sense_len);
- r = scb->error;
- return r;
- }
-
- int
- scsi_reset(int target, int lun, int bus)
- {
- #if OS2 >= 2
- Word rc = DosDevIOCtl(hdev, IOCtlCategory, bus ? IOCtlBusReset : IOCtlDevReset,
- 0, 0, 0, 0, 0, 0);
- #else
- Word rc = DosDevIOCtl(0, 0,
- bus ? IOCtlBusReset : IOCtlDevReset, IOCtlCategory, hdev);
- #endif
- if (rc)
- return mapDriverError(rc);
- return NoError;
- }
-
- long
- scsi_get_blocksize(int target, int lun)
- {
- long sz;
- #if OS2 >= 2
- ULONG dlen;
- Word rc = DosDevIOCtl(hdev, IOCtlCategory, IOCtlBlocksize,
- 0, 0, 0, &sz, sizeof sz, &dlen);
- #else
- Word rc = DosDevIOCtl2(&sz, sizeof sz, 0, 0,
- IOCtlBlocksize, IOCtlCategory, hdev);
- #endif
- return rc ? mapDriverError(rc) : sz;
- }
-
- long
- scsi_set_blocksize(int target, int lun, long size)
- {
- long sz = size;
- #if OS2 >= 2
- ULONG plen, dlen;
- Word rc = DosDevIOCtl(hdev, IOCtlCategory, IOCtlBlocksize,
- &size, sizeof size, &plen, &sz, sizeof sz, &dlen);
- #else
- Word rc = DosDevIOCtl2(&sz, sizeof sz, &size, sizeof size,
- IOCtlBlocksize, IOCtlCategory, hdev);
- #endif
- return rc ? mapDriverError(rc) : sz;
- }
-
- int
- scsi_set_trace(int level)
- {
- unsigned char lvl = level;
- #if OS2 >= 2
- ULONG plen, dlen;
- Word rc = DosDevIOCtl(hdev, IOCtlCategory, IOCtlTrace,
- &level, sizeof level, &plen, &lvl, sizeof lvl, &dlen);
- #else
- Word rc = DosDevIOCtl2(&lvl, sizeof lvl, &level, sizeof level,
- IOCtlTrace, IOCtlCategory, hdev);
- #endif
- return rc ? mapDriverError(rc) : lvl;
- }
-
- char *
- scsi_error(int code)
- {
- static char text[80];
- static ErrorTable driverTab[] = {
- /* ST01 driver error codes */
- ErrST01Driver+0x02, "Device not ready",
- ErrST01Driver+0x0C, "Bus sequence error",
- ErrST01Driver+0x13, "Parameter error",
-
- /* ASPI status codes */
- ErrASPIDriver1+0x00, "Busy",
- ErrASPIDriver1+0x01, "Done",
- ErrASPIDriver1+0x02, "Aborted",
- ErrASPIDriver1+0x03, "Bad aborted",
- ErrASPIDriver1+0x04, "Error",
- ErrASPIDriver1+0x10, "Busy POST",
- ErrASPIDriver2+0x00, "Invalid ASPI request",
- ErrASPIDriver2+0x01, "Invalid host adapter",
- ErrASPIDriver2+0x02, "Device not installed",
-
- /* ASPITAPE driver error codes */
- TapeInvalidFcn, "Invalid ioctl cat/fcn code",
- TapeInvalidParm, "Invalid parm pointer/length",
- TapeInvalidData, "Invalid data pointer/length",
- TapeNoSenseData, "No sense data",
-
- /* OS2SCSI.DMD driver error codes */
- /* general driver error codes */
- 0x100, "Write protected",
- 0x101, "Unknown unit",
- 0x102, "Device not ready",
- 0x103, "Unknown command",
- 0x104, "CRC error",
- 0x105, "Bad request struct length",
- 0x10A, "Write fault",
- 0x10B, "Read fault",
- 0x10C, "Generail failure",
- 0x10D, "Change disk",
- 0x110, "Uncertain media",
- 0x114, "Device in use",
- /* OS2SCSI.DMD specific codes */
- 0x180, "Device error",
- 0x181, "Timeout error",
- 0x182, "Unusual wakeup",
- 0x183, "DevHlp error",
- 0x184, "Request block not available",
- 0x185, "Maximum device support exceeded",
- 0x186, "Interrupt level not available",
- 0x187, "Device not available",
- 0x188, "More IRQ levelsthan adapters",
- 0x189, "Device busy",
- 0x18A, "Request sense failed",
- 0x18B, "Intelligent buffer not supported",
-
- -1
- };
- static ErrorTable hostTab[] = {
- /* Adaptec 154x host adapter status */
- SRB_NoError, "No error",
- SRB_Timeout, "Selection timeout",
- SRB_DataLength, "Data length error",
- SRB_BusFree, "Unexpected bus free",
- SRB_BusSequence, "Target bus sequence failure",
- /* IBM SCSI adapter error */
- 0x101, "Bus reset",
- 0x102, "Interface fault",
- 0x110, "Selection timeout",
- 0x111, "Unexpected bus free",
- 0x113, "Bus sequence error",
- 0x120, "Short data",
- -1
- };
-
- if (code == 0)
- return "No error";
- if (code == ComeAgain)
- return "Busy";
- switch (ErrorClass(code)) {
- case ErrorClass(SenseKey):
- return senseTab[code & 0x0F];
- case ErrorClass(ExtendedError):
- switch (senseMode) {
- case TDC3600:
- sprintf(text, "Error code: %s",
- find_error(tdc3600ercd, ErrorCode(code)));
- break;
- default:
- sprintf(text, "Additional sense code: %02X",
- ErrorCode(code));
- }
- break;
- case ErrorClass(StatusError):
- sprintf(text, "Target status: %s",
- find_error(targetStatusTab, ErrorCode(code)));
- break;
- case ErrorClass(DriverError):
- sprintf(text, "Driver error: %s",
- find_error(driverTab, ErrorCode(code)));
- break;
- case ErrorClass(SystemError):
- sprintf(text, "System error: %u", ErrorCode(code));
- break;
- case ErrorClass(HostError):
- sprintf(text, "Host adapter error: %s",
- find_error(hostTab, ErrorCode(code)));
- break;
- case ErrorClass(MappedError):
- sprintf(text, "ADD error code: %s",
- find_error(addErrorTab, ErrorCode(code)));
- break;
- default:
- sprintf(text, "Other error: %04X", code);
- break;
- }
- return text;
- }
-