home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * $Id: main.c,v 1.4 1992/12/02 23:58:56 ak Exp $
- *****************************************************************************
- * $Log: main.c,v $
- * Revision 1.4 1992/12/02 23:58:56 ak
- * Display trace info when unit is locked by other driver.
- *
- * Revision 1.3 1992/09/29 09:35:14 ak
- * Must allow multiple DrvOpen calls. dup() seems to reopen the driver.
- *
- * Revision 1.2 1992/09/26 19:29:12 ak
- * IOCtlTrace fixed.
- *
- * Revision 1.1.1.1 1992/09/02 18:58:27 ak
- * Initial checkin of OS/2 ADD based SCSI tape device driver.
- *
- * Revision 1.1 1992/09/02 18:58:25 ak
- * Initial revision
- *
- *****************************************************************************/
-
- static char _far rcsid[] = "$Id: main.c,v 1.4 1992/12/02 23:58:56 ak Exp $";
-
- #include "addtape.h"
- #include "tapedrvr.h"
- #ifdef __ZTC__
- #include <ztc.h>
- #else
- #include <memory.h>
- #endif
- #include <string.h>
-
- #define packError(x) ((x) >> 4 & 0xF0 | (x) & 0x0F)
-
- farptr _far _loadds
- post(farptr iorb)
- {
- PUTS(4, " POST\n");
- Run((dword)reqpkt);
- return iorb;
- }
-
- /*
- * Abort current operation.
- */
- void
- abort(void)
- {
- IORB_DEVICE_CONTROL *iorb = (IORB_DEVICE_CONTROL *)iorb2;
- if (!(iorb->iorbh.Status & IORB_DONE))
- return;
- iorb->iorbh.Length = sizeof(IORB_DEVICE_CONTROL);
- iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
- iorb->iorbh.CommandCode = IOCC_DEVICE_CONTROL;
- iorb->iorbh.CommandModifier = IOCM_ABORT;
- iorb->iorbh.RequestControl = IORB_DISABLE_RETRY;
- iorb->iorbh.Status = 0;
- iorb->iorbh.Timeout = -1;
- iorb->Flags = 0;
- callADD(&iorb->iorbh);
- }
-
- /*
- * Call ADD. Wait until done.
- */
- void
- callADDwait(IORBH *iorb)
- {
- iorb->RequestControl |= IORB_ASYNC_POST;
- iorb->NotifyAddress = post;
- callADD(iorb);
- int_off();
- while (!(iorb->Status & IORB_DONE)) {
- PUTS(4, " Waiting for POST\n");
- if (Block((dword)reqpkt, Infinite, 1)) {
- PUTS(1, "Abort\n");
- abort();
- continue;
- }
- int_off();
- }
- int_on();
- }
-
- /*
- * Get IORB. Wait until available.
- * -> errcode if interrupted.
- */
- word
- getIORB(ReqPtr p)
- {
- int_off();
- while (reqpkt) {
- PUTS(4, " Waiting for IORB\n");
- ++waiting;
- if (Block(paddr_iorb1, Infinite, 1))
- return ERROR+DONE+Interrupted;
- int_off();
- }
- int_on();
- reqpkt = p;
- return 0;
- }
-
- /*
- * Release IORB.
- * Wakeup threads waiting.
- */
- void
- relIORB(void)
- {
- reqpkt = 0;
- if (waiting) {
- waiting = 0;
- Run(paddr_iorb1);
- }
- }
-
- #ifdef DEBUG
-
- void
- dump(byte _far *p, int n)
- {
- int i;
-
- for (i = 0; i < n; ++i) {
- putc(' ');
- putx(p[i]);
- }
- }
-
- void
- result(IORBH *iorb)
- {
- puts("\tIORB Status ");
- putx(iorb->Status);
- puts(", ErrorCode ");
- putx(iorb->ErrorCode);
- if (iorb->Status & IORB_STATUSBLOCK_AVAIL) {
- puts("\n\t status:");
- dump((farptr)&status, SizeofStatus);
- if (status.sense_len && status.sense_ptr) {
- puts("\n\t sense:");
- dump(status.sense_ptr, 18);
- }
- }
- putc('\n');
- }
-
- #endif
-
- word
- mapIORBerror(word errcode)
- {
- switch (errcode & ~IOERR_RETRY) {
- case IOERR_CMD_NOT_SUPPORTED:
- case IOERR_CMD_SYNTAX:
- return ERROR+DONE+InvalidCommand;
- case IOERR_CMD_ABORTED:
- return ERROR+DONE+Interrupted;
- case IOERR_UNIT_NOT_ALLOCATED:
- case IOERR_UNIT_NOT_READY:
- case IOERR_UNIT_PWR_OFF:
- case IOERR_ADAPTER_TIMEOUT:
- case IOERR_ADAPTER_DEVICE_TIMEOUT:
- case IOERR_MEDIA_NOT_PRESENT:
- return ERROR+DONE+DeviceNotReady;
- case IOERR_RBA_LIMIT:
- return ERROR+DONE+WriteFault;
- case IOERR_RBA_CRC_ERROR:
- return ERROR+DONE+CRCError;
- case IOERR_MEDIA_WRITE_PROTECT:
- return ERROR+DONE+WriteProtected;
- case IOERR_MEDIA_NOT_FORMATTED:
- case IOERR_MEDIA_NOT_SUPPORTED:
- return ERROR+DONE+UnknownMedia;
- case IOERR_MEDIA_CHANGED:
- return ERROR+DONE+ChangeDisk;
- default:
- return ERROR+DONE+GeneralFailure;
- }
- }
-
-
- word
- rw(ReqPtr p, word flags)
- {
- word rc;
- dword count, nb;
- IORB_ADAPTER_PASSTHRU *iorb = (IORB_ADAPTER_PASSTHRU *)iorb1;
-
- count = p->u.rw.count;
- p->u.rw.count = 0;
-
- if (stickyEOF) {
- PUTS(4, " still EOF\n");
- return DONE;
- }
-
- if (blocksize) {
- dword rem;
- switch (blocksize) {
- case 512:
- nb = count >> 9;
- rem = count & 0x1FF;
- break;
- case 1024:
- nb = count >> 10;
- rem = count & 0x3FF;
- break;
- default:
- nb = count / blocksize;
- rem = count % blocksize;
- }
- if (rem)
- return ERROR+DONE+InvalidParam;
- } else
- nb = count;
-
- if ((rc = getIORB(p)) != 0)
- return rc;
-
- cdb[0] = (flags & PT_DIRECTION_IN) ? SeqRead : SeqWrite;
- cdb[1] = blocksize ? 1 : 0;
- cdb[2] = nb >> 16;
- cdb[3] = nb >> 8;
- cdb[4] = nb;
- cdb[5] = 0;
-
- sglist[0].ppXferBuf = p->u.rw.addr;
- sglist[0].XferBufLen = count;
-
- memset(&status, 0, SizeofStatus);
- status.sense_len = sizeof sense;
- status.sense_ptr = sense;
-
- iorb->iorbh.Length = sizeof(IORB_ADAPTER_PASSTHRU);
- iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
- iorb->iorbh.CommandCode = IOCC_ADAPTER_PASSTHRU;
- iorb->iorbh.CommandModifier = IOCM_EXECUTE_CDB;
- iorb->iorbh.RequestControl = IORB_DISABLE_RETRY+IORB_REQ_STATUSBLOCK;
- iorb->iorbh.StatusBlockLen = SizeofStatus;
- iorb->iorbh.pStatusBlock = (nearptr)&status;
- iorb->iorbh.Status = 0;
- iorb->iorbh.Timeout = -1;
- iorb->cSGList = 1;
- iorb->pSGList = sglist;
- iorb->ppSGList = paddr_sglist;
- iorb->ControllerCmdLen = 6;
- iorb->pControllerCmd = cdb;
- iorb->Flags = flags;
-
- #ifdef DEBUG
- if (trace >= 3) {
- puts(" R/W CDB:");
- dump(cdb, 6);
- putc('\n');
- }
- #endif
-
- callADDwait(&iorb->iorbh);
-
- #ifdef DEBUG
- if (trace && iorb->iorbh.Status & ERROR || trace >= 3)
- result(&iorb->iorbh);
- #endif
-
- relIORB();
-
- p->u.rw.count = blocksize ? nb * blocksize : nb;
-
- if (iorb->iorbh.Status & IORB_STATUSBLOCK_AVAIL
- && status.sense_len && status.sense_ptr) {
- if (sense[2] & (FM|EOM)) {
- PUTS(4, " EOF\n");
- stickyEOF = 1;
- }
- if (sense[0] & VADD) {
- dword info = 0;
- for (rc = 3; rc <= 6; ++rc) {
- info <<= 8;
- info |= sense[rc];
- }
- switch (blocksize) {
- case 512:
- info <<= 9;
- break;
- case 1024:
- info <<= 10;
- break;
- default:
- info *= blocksize;
- case 0: ;
- }
- p->u.rw.count -= info;
- PUTS(4, " result count=");
- PUTD(4, p->u.rw.count);
- PUTC(4, '\n');
- }
- rc = 1;
- } else
- rc = 0;
-
- if (!(iorb->iorbh.Status & IORB_ERROR))
- return DONE;
- if (!rc)
- return mapIORBerror(iorb->iorbh.ErrorCode);
-
- if (senseMode == Sensekey) {
- switch (sense[2] & 0x0F) {
- case NoSense:
- case BlankCheck:
- return DONE;
- case RecoveredData:
- return ERROR+DONE+CRCError;
- case NotReady:
- case Hardware:
- case UnitAttention:
- return ERROR+DONE+DeviceNotReady;
- case MediaError:
- return ERROR+DONE+ReadFault;
- case WriteProtected:
- return ERROR+DONE+WriteProtect;
- case MediaOverflow:
- return ERROR+DONE+NoPaper;
- case AbortedCommand:
- return ERROR+DONE+Interrupted;
- default:
- return ERROR+DONE+GeneralFailure;
- }
- }
- if ((sense[0] & ~0x81) != 0x70)
- rc = sense[0];
- else
- switch (senseMode) {
- case TDC3600:
- rc = sense[14];
- break;
- default:
- rc = sense[12];
- }
- switch (senseMode) {
- case TDC3600:
- switch (rc) {
- case 0x00: /* ok */
- return DONE;
- case 0x02: /* hardware error */
- case 0x04: /* not ready */
- case 0x09: /* not loaded */
- return ERROR+DONE+DeviceNotReady;
- case 0x0A: /* insufficient capacity */
- return ERROR+DONE+NoPaper;
- case 0x11: /* uncorrectable data error */
- return ERROR+DONE+ReadFault;
- case 0x14: /* empty cartridge */
- case 0x1C: /* file mark detected */
- case 0x34: /* read EOM */
- PUTS(4, " EOF\n");
- stickyEOF = 1;
- return DONE;
- case 0x17: /* write protected */
- return ERROR+DONE+WriteProtect;
- case 0x19: /* bad block found */
- return ERROR+DONE+WriteFault;
- case 0x30:
- return ERROR+DONE+ChangeDisk;
- case 0x33: /* append error */
- return ERROR+DONE+SeekError;
- default:
- return ERROR+DONE+GeneralFailure;
- }
- case SCSI2:
- switch (rc) {
- case 0x00: /* end-of-data */
- case 0x14: /* end-of-data not found / filemark */
- PUTS(4, " EOF\n");
- stickyEOF = 1;
- return DONE;
- case 0x30: /* cannot read medium */
- return ERROR+DONE+UnknownMedia;
- case 0x52: /* cartridge fault */
- case 0x05: /* selection failure */
- case 0x40: /* device failure */
- case 0x04: /* not ready */
- case 0x25: /* LUN not supported */
- case 0x3A: /* medium not present */
- return ERROR+DONE+DeviceNotReady;
- case 0x03: /* excessive write errors */
- case 0x0C: /* write error */
- return ERROR+DONE+WriteFault;
- case 0x21: /* block address out of range */
- case 0x15: /* positioning error */
- case 0x50: /* write append error */
- return ERROR+DONE+SeekError;
- case 0x53: /* media load failed */
- case 0x29: /* power-up or reset */
- return ERROR+DONE+ChangeDisk;
- case 0x31: /* media format corrupted */
- case 0x11: /* read retries exhausted */
- return ERROR+DONE+ReadFault;
- case 0x17: /* recovered error */
- return ERROR+DONE+CRCError;
- case 0x27: /* write protected */
- return ERROR+DONE+WriteProtect;
- default:
- return ERROR+DONE+GeneralFailure;
- }
- default:
- return ERROR+DONE+GeneralFailure;
- }
- }
-
- word
- DrvOpen(ReqPtr p)
- {
- IORB_UNIT_CONTROL *iorb = (IORB_UNIT_CONTROL *)iorb1;
-
- if (!callADD) {
- word rc = startup();
- if (rc != DONE)
- return rc;
- }
-
- PUTS(3, "Open\n");
- if (open_count) {
- ++open_count;
- return DONE;
- }
-
- iorb->iorbh.Length = sizeof(IORB_UNIT_CONTROL);
- iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
- iorb->iorbh.CommandCode = IOCC_UNIT_CONTROL;
- iorb->iorbh.CommandModifier = IOCM_ALLOCATE_UNIT;
- iorb->iorbh.RequestControl = IORB_DISABLE_RETRY;
- iorb->iorbh.Status = 0;
- iorb->iorbh.Timeout = -1;
- iorb->Flags = 0;
- callADDwait(&iorb->iorbh);
-
- #ifdef DEBUG
- if (trace && iorb->iorbh.Status & ERROR || trace >= 3)
- result(&iorb->iorbh);
- #endif
-
- stickyEOF = 0;
-
- if (iorb->iorbh.Status & IORB_ERROR) {
- if (iorb->iorbh.ErrorCode != IOERR_UNIT_ALLOCATED)
- return mapIORBerror(iorb->iorbh.ErrorCode);
- PUTS(3, "Unit allocated by another driver\n");
- return ERROR+DONE+DeviceNotReady;
- }
- PUTS(3, "Unit allocated\n");
- open_count = 1;
- return DONE;
- }
-
- word
- DrvClose(ReqPtr p)
- {
- IORB_UNIT_CONTROL *iorb = (IORB_UNIT_CONTROL *)iorb1;
-
- PUTS(3, "Close\n");
-
- if (--open_count)
- return DONE;
-
- iorb->iorbh.Length = sizeof(IORB_UNIT_CONTROL);
- iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
- iorb->iorbh.CommandCode = IOCC_UNIT_CONTROL;
- iorb->iorbh.CommandModifier = IOCM_DEALLOCATE_UNIT;
- iorb->iorbh.RequestControl = IORB_DISABLE_RETRY;
- iorb->iorbh.Status = 0;
- iorb->iorbh.Timeout = -1;
- iorb->Flags = 0;
- callADDwait(&iorb->iorbh);
-
- #ifdef DEBUG
- if (trace && iorb->iorbh.Status & ERROR || trace >= 3)
- result(&iorb->iorbh);
- #endif
-
- if (iorb->iorbh.Status & ERROR)
- return mapIORBerror(iorb->iorbh.ErrorCode);
-
- PUTS(3, "Unit deallocated\n");
- return DONE;
- }
-
- word
- DrvRead(ReqPtr p)
- {
- PUTS(3, "Read\n");
- return rw(p, PT_DIRECTION_IN);
- }
-
- word
- DrvWrite(ReqPtr p, int vfy)
- {
- PUTS(3, "Write\n");
- return rw(p, 0);
- }
-
- word
- DrvIOCtl(ReqPtr p)
- {
- handle dataLock;
- byte flags;
- word rc;
-
- if (p->u.ioc.cat < 0x80)
- return ERROR+DONE+InvalidCommand;
- if (p->u.ioc.cat != 0x80)
- return ERROR+DONE+TapeInvalidFcn;
-
- stickyEOF = 0;
-
- switch (p->u.ioc.fcn) {
-
- case IOCtlBusReset:
- case IOCtlDevReset:
- {
- IORB_DEVICE_CONTROL *iorb = (IORB_DEVICE_CONTROL *)iorb1;
-
- PUTS(3, "IOCtl Reset\n");
-
- senseValid = 0;
-
- if ((rc = getIORB(p)) != 0)
- return rc;
-
- iorb->iorbh.Length = sizeof(IORB_DEVICE_CONTROL);
- iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
- iorb->iorbh.CommandCode = IOCC_DEVICE_CONTROL;
- iorb->iorbh.CommandModifier = IOCM_RESET;
- iorb->iorbh.RequestControl = IORB_DISABLE_RETRY;
- iorb->iorbh.Status = 0;
- iorb->iorbh.Timeout = -1;
- iorb->Flags = 0;
- callADDwait(&iorb->iorbh);
- relIORB();
-
- if (iorb->iorbh.Status & ERROR)
- return ERROR+DONE+packError(iorb->iorbh.ErrorCode);
- return DONE;
- }
-
- case IOCtlLevel:
- PUTS(3, "IOCtl Level\n");
- if (VerifyAccess(p->u.ioc.data, 2, VerifyWrite))
- return ERROR+DONE+InvalidParam;
- ((byte _far *)p->u.ioc.data)[0] = 3;
- ((byte _far *)p->u.ioc.data)[1] = senseMode;
- return DONE;
-
- case IOCtlTrace:
- PUTS(3, "IOCtl Trace\n");
- if (p->u.ioc.dlen >= 1) {
- if (VerifyAccess(p->u.ioc.data, 1, VerifyWrite))
- return ERROR+DONE+InvalidParam;
- *(byte _far *)p->u.ioc.data = trace;
- }
- if (p->u.ioc.plen >= 1) {
- if (VerifyAccess(p->u.ioc.parm, 1, VerifyRead))
- return ERROR+DONE+InvalidParam;
- trace = *(byte _far *)p->u.ioc.parm;
- }
- #ifdef DEBUG
- if (trace >= 1) {
- puts("Trace level ");
- putd(trace);
- putc('\n');
- }
- #endif
- return DONE;
-
- case IOCtlBlocksize:
- PUTS(3, "IOCtl Blocksize\n");
- if (p->u.ioc.dlen >= 4) {
- if (VerifyAccess(p->u.ioc.data, 4, VerifyWrite))
- return ERROR+DONE+InvalidParam;
- *(dword _far *)p->u.ioc.data = blocksize;
- }
- if (p->u.ioc.plen >= 4) {
- if (VerifyAccess(p->u.ioc.parm, 4, VerifyRead))
- return ERROR+DONE+InvalidParam;
- blocksize = *(dword _far *)p->u.ioc.data;
- }
- return DONE;
-
- case IOCtlRead+IOCtlSlow:
- case IOCtlRead+IOCtlFast:
- PUTS(3, "IOCtl Read\n");
- read: flags = PT_DIRECTION_IN;
- if (VerifyAccess(p->u.ioc.parm, p->u.ioc.plen, VerifyRead))
- return ERROR+DONE+TapeInvalidParm;
- if (p->u.ioc.dlen
- && VerifyAccess(p->u.ioc.data, p->u.ioc.dlen, VerifyWrite))
- return ERROR+DONE+TapeInvalidData;
- goto checked;
- case IOCtlWrite+IOCtlSlow:
- case IOCtlWrite+IOCtlFast:
- PUTS(3, "IOCtl Write\n");
- flags = 0;
- if (VerifyAccess(p->u.ioc.parm, p->u.ioc.plen, VerifyRead))
- return ERROR+DONE+TapeInvalidParm;
- if (p->u.ioc.dlen
- && VerifyAccess(p->u.ioc.data, p->u.ioc.dlen, VerifyRead))
- return ERROR+DONE+TapeInvalidData;
- checked:
- { IORB_ADAPTER_PASSTHRU *iorb = (IORB_ADAPTER_PASSTHRU *)iorb1;
-
- if (p->u.ioc.plen < 6 || p->u.ioc.plen > 12)
- return ERROR+DONE+TapeInvalidParm;
- if ((rc = getIORB(p)) != 0)
- return rc;
- _fmemcpy(cdb, p->u.ioc.parm, p->u.ioc.plen);
-
- dataLock = Lock(Segment(p->u.ioc.data), LockShort);
- sglist[0].ppXferBuf = VirtToPhys(p->u.ioc.data);
- sglist[0].XferBufLen = p->u.ioc.dlen;
-
- senseValid = 0;
- memset(&status, 0, SizeofStatus);
- status.sense_len = sizeof sense;
- status.sense_ptr = sense;
-
- iorb->iorbh.Length = sizeof(IORB_ADAPTER_PASSTHRU);
- iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
- iorb->iorbh.CommandCode = IOCC_ADAPTER_PASSTHRU;
- iorb->iorbh.CommandModifier = IOCM_EXECUTE_CDB;
- iorb->iorbh.RequestControl = IORB_REQ_STATUSBLOCK + IORB_DISABLE_RETRY;
- iorb->iorbh.StatusBlockLen = SizeofStatus;
- iorb->iorbh.pStatusBlock = (nearptr)&status;
- iorb->iorbh.Status = 0;
- iorb->iorbh.Timeout = -1;
- iorb->cSGList = 1;
- iorb->pSGList = sglist;
- iorb->ppSGList = paddr_sglist;
- iorb->ControllerCmdLen = p->u.ioc.plen;
- iorb->pControllerCmd = cdb;
- iorb->Flags = flags;
-
- #ifdef DEBUG
- if (trace >= 3) {
- puts(" CDB:");
- dump(cdb, p->u.ioc.plen);
- putc('\n');
- }
- #endif
-
- callADDwait(&iorb->iorbh);
-
- #ifdef DEBUG
- if (trace && iorb->iorbh.Status & ERROR || trace >= 3)
- result(&iorb->iorbh);
- #endif
-
- relIORB();
- Unlock(dataLock);
-
- if (iorb->iorbh.Status & IORB_STATUSBLOCK_AVAIL)
- senseValid = 1;
- if (iorb->iorbh.Status & IORB_ERROR)
- return ERROR+DONE+packError(iorb->iorbh.ErrorCode);
- return DONE;
- }
-
- case IOCtlSense:
- PUTS(3, "IOCtl Sense\n");
- if (!senseValid) {
- PUTS(3, " No sense data\n");
- return ERROR+DONE+TapeNoSenseData;
- }
- PUTS(3, " Valid sense data\n");
- if (p->u.ioc.dlen > sizeof sense)
- return ERROR+DONE+TapeInvalidData;
- _fmemcpy((farptr)p->u.ioc.data, sense, p->u.ioc.dlen);
- return DONE;
-
- default:
- return ERROR+DONE+TapeInvalidFcn;
- }
- }
-