home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / gtak212b.zip / SOURCE.ZIP / OS2-ADD / main.c < prev    next >
C/C++ Source or Header  |  1992-12-03  |  16KB  |  685 lines

  1. /*****************************************************************************
  2.  * $Id: main.c,v 1.4 1992/12/02 23:58:56 ak Exp $
  3.  *****************************************************************************
  4.  * $Log: main.c,v $
  5.  * Revision 1.4  1992/12/02  23:58:56  ak
  6.  * Display trace info when unit is locked by other driver.
  7.  *
  8.  * Revision 1.3  1992/09/29  09:35:14  ak
  9.  * Must allow multiple DrvOpen calls. dup() seems to reopen the driver.
  10.  *
  11.  * Revision 1.2  1992/09/26  19:29:12  ak
  12.  * IOCtlTrace fixed.
  13.  *
  14.  * Revision 1.1.1.1  1992/09/02  18:58:27  ak
  15.  * Initial checkin of OS/2 ADD based SCSI tape device driver.
  16.  *
  17.  * Revision 1.1  1992/09/02  18:58:25  ak
  18.  * Initial revision
  19.  *
  20.  *****************************************************************************/
  21.  
  22. static char _far rcsid[] = "$Id: main.c,v 1.4 1992/12/02 23:58:56 ak Exp $";
  23.  
  24. #include "addtape.h"
  25. #include "tapedrvr.h"
  26. #ifdef __ZTC__
  27. #include <ztc.h>
  28. #else
  29. #include <memory.h>
  30. #endif
  31. #include <string.h>
  32.  
  33. #define packError(x) ((x) >> 4 & 0xF0 | (x) & 0x0F)
  34.  
  35. farptr _far _loadds
  36. post(farptr iorb)
  37. {
  38.     PUTS(4, "    POST\n");
  39.     Run((dword)reqpkt);
  40.     return iorb;
  41. }
  42.  
  43. /*
  44.  * Abort current operation.
  45.  */
  46. void
  47. abort(void)
  48. {
  49.     IORB_DEVICE_CONTROL *iorb = (IORB_DEVICE_CONTROL *)iorb2;
  50.     if (!(iorb->iorbh.Status & IORB_DONE))
  51.         return;
  52.     iorb->iorbh.Length = sizeof(IORB_DEVICE_CONTROL);
  53.     iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
  54.     iorb->iorbh.CommandCode = IOCC_DEVICE_CONTROL;
  55.     iorb->iorbh.CommandModifier = IOCM_ABORT;
  56.     iorb->iorbh.RequestControl = IORB_DISABLE_RETRY;
  57.     iorb->iorbh.Status = 0;
  58.     iorb->iorbh.Timeout = -1;
  59.     iorb->Flags = 0;
  60.     callADD(&iorb->iorbh);
  61. }
  62.  
  63. /*
  64.  * Call ADD. Wait until done.
  65.  */
  66. void
  67. callADDwait(IORBH *iorb)
  68. {
  69.     iorb->RequestControl |= IORB_ASYNC_POST;
  70.     iorb->NotifyAddress = post;
  71.     callADD(iorb);
  72.     int_off();
  73.     while (!(iorb->Status & IORB_DONE)) {
  74.         PUTS(4, "    Waiting for POST\n");
  75.         if (Block((dword)reqpkt, Infinite, 1)) {
  76.             PUTS(1, "Abort\n");
  77.             abort();
  78.             continue;
  79.         }
  80.         int_off();
  81.     }
  82.     int_on();
  83. }
  84.  
  85. /*
  86.  * Get IORB. Wait until available.
  87.  * -> errcode if interrupted.
  88.  */
  89. word
  90. getIORB(ReqPtr p)
  91. {
  92.     int_off();
  93.     while (reqpkt) {
  94.         PUTS(4, "    Waiting for IORB\n");
  95.         ++waiting;
  96.         if (Block(paddr_iorb1, Infinite, 1))
  97.             return ERROR+DONE+Interrupted;
  98.         int_off();
  99.     }
  100.     int_on();
  101.     reqpkt = p;
  102.     return 0;
  103. }
  104.  
  105. /*
  106.  * Release IORB.
  107.  * Wakeup threads waiting.
  108.  */
  109. void
  110. relIORB(void)
  111. {
  112.     reqpkt = 0;
  113.     if (waiting) {
  114.         waiting = 0;
  115.         Run(paddr_iorb1);
  116.     }
  117. }
  118.  
  119. #ifdef DEBUG
  120.  
  121. void
  122. dump(byte _far *p, int n)
  123. {
  124.     int i;
  125.  
  126.     for (i = 0; i < n; ++i) {
  127.         putc(' ');
  128.         putx(p[i]);
  129.     }
  130. }
  131.  
  132. void
  133. result(IORBH *iorb)
  134. {
  135.     puts("\tIORB Status ");
  136.     putx(iorb->Status);
  137.     puts(", ErrorCode ");
  138.     putx(iorb->ErrorCode);
  139.     if (iorb->Status & IORB_STATUSBLOCK_AVAIL) {
  140.         puts("\n\t  status:");
  141.         dump((farptr)&status, SizeofStatus);
  142.         if (status.sense_len && status.sense_ptr) {
  143.             puts("\n\t  sense:");
  144.             dump(status.sense_ptr, 18);
  145.         }
  146.     }
  147.     putc('\n');
  148. }
  149.  
  150. #endif
  151.  
  152. word
  153. mapIORBerror(word errcode)
  154. {
  155.     switch (errcode & ~IOERR_RETRY) {
  156.     case IOERR_CMD_NOT_SUPPORTED:
  157.     case IOERR_CMD_SYNTAX:
  158.         return ERROR+DONE+InvalidCommand;
  159.     case IOERR_CMD_ABORTED:
  160.         return ERROR+DONE+Interrupted;
  161.     case IOERR_UNIT_NOT_ALLOCATED:
  162.     case IOERR_UNIT_NOT_READY:
  163.     case IOERR_UNIT_PWR_OFF:
  164.     case IOERR_ADAPTER_TIMEOUT:
  165.     case IOERR_ADAPTER_DEVICE_TIMEOUT:
  166.     case IOERR_MEDIA_NOT_PRESENT:
  167.         return ERROR+DONE+DeviceNotReady;
  168.     case IOERR_RBA_LIMIT:
  169.         return ERROR+DONE+WriteFault;
  170.     case IOERR_RBA_CRC_ERROR:
  171.         return ERROR+DONE+CRCError;
  172.     case IOERR_MEDIA_WRITE_PROTECT:
  173.         return ERROR+DONE+WriteProtected;
  174.     case IOERR_MEDIA_NOT_FORMATTED:
  175.     case IOERR_MEDIA_NOT_SUPPORTED:
  176.         return ERROR+DONE+UnknownMedia;
  177.     case IOERR_MEDIA_CHANGED:
  178.         return ERROR+DONE+ChangeDisk;
  179.     default:
  180.         return ERROR+DONE+GeneralFailure;
  181.     }
  182. }
  183.  
  184.  
  185. word
  186. rw(ReqPtr p, word flags)
  187. {
  188.     word rc;
  189.     dword count, nb;
  190.     IORB_ADAPTER_PASSTHRU *iorb = (IORB_ADAPTER_PASSTHRU *)iorb1;
  191.  
  192.     count = p->u.rw.count;
  193.     p->u.rw.count = 0;
  194.  
  195.     if (stickyEOF) {
  196.         PUTS(4, "    still EOF\n");
  197.         return DONE;
  198.     }
  199.  
  200.     if (blocksize) {
  201.         dword rem;
  202.         switch (blocksize) {
  203.         case 512:
  204.             nb = count >> 9;
  205.             rem = count & 0x1FF;
  206.             break;
  207.         case 1024:
  208.             nb = count >> 10;
  209.             rem = count & 0x3FF;
  210.             break;
  211.         default:
  212.             nb = count / blocksize;
  213.             rem = count % blocksize;
  214.         }
  215.         if (rem)
  216.             return ERROR+DONE+InvalidParam;
  217.     } else
  218.         nb = count;
  219.  
  220.     if ((rc = getIORB(p)) != 0)
  221.         return rc;
  222.  
  223.     cdb[0] = (flags & PT_DIRECTION_IN) ? SeqRead : SeqWrite;
  224.     cdb[1] = blocksize ? 1 : 0;
  225.     cdb[2] = nb >> 16;
  226.     cdb[3] = nb >> 8;
  227.     cdb[4] = nb;
  228.     cdb[5] = 0;
  229.  
  230.     sglist[0].ppXferBuf = p->u.rw.addr;
  231.     sglist[0].XferBufLen = count;
  232.  
  233.     memset(&status, 0, SizeofStatus);
  234.     status.sense_len = sizeof sense;
  235.     status.sense_ptr = sense;
  236.  
  237.     iorb->iorbh.Length = sizeof(IORB_ADAPTER_PASSTHRU);
  238.     iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
  239.     iorb->iorbh.CommandCode = IOCC_ADAPTER_PASSTHRU;
  240.     iorb->iorbh.CommandModifier = IOCM_EXECUTE_CDB;
  241.     iorb->iorbh.RequestControl = IORB_DISABLE_RETRY+IORB_REQ_STATUSBLOCK;
  242.     iorb->iorbh.StatusBlockLen = SizeofStatus;
  243.     iorb->iorbh.pStatusBlock = (nearptr)&status;
  244.     iorb->iorbh.Status = 0;
  245.     iorb->iorbh.Timeout = -1;
  246.     iorb->cSGList = 1;
  247.     iorb->pSGList = sglist;
  248.     iorb->ppSGList = paddr_sglist;
  249.     iorb->ControllerCmdLen = 6;
  250.     iorb->pControllerCmd = cdb;
  251.     iorb->Flags = flags;
  252.  
  253. #ifdef DEBUG
  254.     if (trace >= 3) {
  255.         puts("    R/W CDB:");
  256.         dump(cdb, 6);
  257.         putc('\n');
  258.     }
  259. #endif
  260.  
  261.     callADDwait(&iorb->iorbh);
  262.  
  263. #ifdef DEBUG
  264.     if (trace && iorb->iorbh.Status & ERROR || trace >= 3)
  265.         result(&iorb->iorbh);
  266. #endif
  267.  
  268.     relIORB();
  269.  
  270.     p->u.rw.count = blocksize ? nb * blocksize : nb;
  271.  
  272.     if (iorb->iorbh.Status & IORB_STATUSBLOCK_AVAIL
  273.      && status.sense_len && status.sense_ptr) {
  274.         if (sense[2] & (FM|EOM)) {
  275.             PUTS(4, "    EOF\n");
  276.             stickyEOF = 1;
  277.         }
  278.         if (sense[0] & VADD) {
  279.             dword info = 0;
  280.             for (rc = 3; rc <= 6; ++rc) {
  281.                 info <<= 8;
  282.                 info |= sense[rc];
  283.             }
  284.             switch (blocksize) {
  285.             case 512:
  286.                 info <<= 9;
  287.                 break;
  288.             case 1024:
  289.                 info <<= 10;
  290.                 break;
  291.             default:
  292.                 info *= blocksize;
  293.             case 0:    ;
  294.             }
  295.             p->u.rw.count -= info;
  296.             PUTS(4, "    result count=");
  297.             PUTD(4, p->u.rw.count);
  298.             PUTC(4, '\n');
  299.         }
  300.         rc = 1;
  301.     } else
  302.         rc = 0;
  303.  
  304.     if (!(iorb->iorbh.Status & IORB_ERROR))
  305.         return DONE;
  306.     if (!rc)
  307.         return mapIORBerror(iorb->iorbh.ErrorCode);
  308.  
  309.     if (senseMode == Sensekey) {
  310.         switch (sense[2] & 0x0F) {
  311.         case NoSense:
  312.         case BlankCheck:
  313.             return DONE;
  314.         case RecoveredData:
  315.             return ERROR+DONE+CRCError;
  316.         case NotReady:
  317.         case Hardware:
  318.         case UnitAttention:
  319.             return ERROR+DONE+DeviceNotReady;
  320.         case MediaError:
  321.             return ERROR+DONE+ReadFault;
  322.         case WriteProtected:
  323.             return ERROR+DONE+WriteProtect;
  324.         case MediaOverflow:
  325.             return ERROR+DONE+NoPaper;
  326.         case AbortedCommand:
  327.             return ERROR+DONE+Interrupted;
  328.         default:
  329.             return ERROR+DONE+GeneralFailure;
  330.         }
  331.     }
  332.     if ((sense[0] & ~0x81) != 0x70)
  333.         rc = sense[0];
  334.     else
  335.         switch (senseMode) {
  336.         case TDC3600:
  337.             rc = sense[14];
  338.             break;
  339.         default:
  340.             rc = sense[12];
  341.         }
  342.     switch (senseMode) {
  343.     case TDC3600:
  344.         switch (rc) {
  345.         case 0x00:        /* ok */
  346.             return DONE;
  347.         case 0x02:        /* hardware error */
  348.         case 0x04:        /* not ready */
  349.         case 0x09:        /* not loaded */
  350.             return ERROR+DONE+DeviceNotReady;
  351.         case 0x0A:        /* insufficient capacity */
  352.             return ERROR+DONE+NoPaper;
  353.         case 0x11:        /* uncorrectable data error */
  354.             return ERROR+DONE+ReadFault;
  355.         case 0x14:        /* empty cartridge */
  356.         case 0x1C:        /* file mark detected */
  357.         case 0x34:        /* read EOM */
  358.             PUTS(4, "    EOF\n");
  359.             stickyEOF = 1;
  360.             return DONE;
  361.         case 0x17:        /* write protected */
  362.             return ERROR+DONE+WriteProtect;
  363.         case 0x19:        /* bad block found */
  364.             return ERROR+DONE+WriteFault;
  365.         case 0x30:
  366.             return ERROR+DONE+ChangeDisk;
  367.         case 0x33:        /* append error */
  368.             return ERROR+DONE+SeekError;
  369.         default:
  370.             return ERROR+DONE+GeneralFailure;
  371.         }
  372.     case SCSI2:
  373.         switch (rc) {
  374.         case 0x00:    /* end-of-data */
  375.         case 0x14:    /* end-of-data not found / filemark */
  376.             PUTS(4, "    EOF\n");
  377.             stickyEOF = 1;
  378.             return DONE;
  379.         case 0x30:    /* cannot read medium */
  380.             return ERROR+DONE+UnknownMedia;
  381.         case 0x52:    /* cartridge fault */
  382.         case 0x05:    /* selection failure */
  383.         case 0x40:    /* device failure */
  384.         case 0x04:    /* not ready */
  385.         case 0x25:    /* LUN not supported */
  386.         case 0x3A:    /* medium not present */
  387.             return ERROR+DONE+DeviceNotReady;
  388.         case 0x03:    /* excessive write errors */
  389.         case 0x0C:    /* write error */
  390.             return ERROR+DONE+WriteFault;
  391.         case 0x21:    /* block address out of range */
  392.         case 0x15:    /* positioning error */
  393.         case 0x50:    /* write append error */
  394.             return ERROR+DONE+SeekError;
  395.         case 0x53:    /* media load failed */
  396.         case 0x29:    /* power-up or reset */
  397.             return ERROR+DONE+ChangeDisk;
  398.         case 0x31:    /* media format corrupted */
  399.         case 0x11:    /* read retries exhausted */
  400.             return ERROR+DONE+ReadFault;
  401.         case 0x17:    /* recovered error */
  402.             return ERROR+DONE+CRCError;
  403.         case 0x27:    /* write protected */
  404.             return ERROR+DONE+WriteProtect;
  405.         default:
  406.             return ERROR+DONE+GeneralFailure;
  407.         }
  408.     default:
  409.         return ERROR+DONE+GeneralFailure;
  410.     }
  411. }
  412.  
  413. word
  414. DrvOpen(ReqPtr p)
  415. {
  416.     IORB_UNIT_CONTROL *iorb = (IORB_UNIT_CONTROL *)iorb1;
  417.  
  418.     if (!callADD) {
  419.         word rc = startup();
  420.         if (rc != DONE)
  421.             return rc;
  422.     }
  423.  
  424.     PUTS(3, "Open\n");
  425.     if (open_count) {
  426.         ++open_count;
  427.         return DONE;
  428.     }
  429.  
  430.     iorb->iorbh.Length = sizeof(IORB_UNIT_CONTROL);
  431.     iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
  432.     iorb->iorbh.CommandCode = IOCC_UNIT_CONTROL;
  433.     iorb->iorbh.CommandModifier = IOCM_ALLOCATE_UNIT;
  434.     iorb->iorbh.RequestControl = IORB_DISABLE_RETRY;
  435.     iorb->iorbh.Status = 0;
  436.     iorb->iorbh.Timeout = -1;
  437.     iorb->Flags = 0;
  438.     callADDwait(&iorb->iorbh);
  439.  
  440. #ifdef DEBUG
  441.     if (trace && iorb->iorbh.Status & ERROR || trace >= 3)
  442.         result(&iorb->iorbh);
  443. #endif
  444.  
  445.     stickyEOF = 0;
  446.  
  447.     if (iorb->iorbh.Status & IORB_ERROR) {
  448.         if (iorb->iorbh.ErrorCode != IOERR_UNIT_ALLOCATED)
  449.             return mapIORBerror(iorb->iorbh.ErrorCode);
  450.         PUTS(3, "Unit allocated by another driver\n");
  451.         return ERROR+DONE+DeviceNotReady;
  452.     }
  453.     PUTS(3, "Unit allocated\n");
  454.     open_count = 1;
  455.     return DONE;
  456. }
  457.  
  458. word
  459. DrvClose(ReqPtr p)
  460. {
  461.     IORB_UNIT_CONTROL *iorb = (IORB_UNIT_CONTROL *)iorb1;
  462.  
  463.     PUTS(3, "Close\n");
  464.  
  465.     if (--open_count)
  466.         return DONE;
  467.  
  468.     iorb->iorbh.Length = sizeof(IORB_UNIT_CONTROL);
  469.     iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
  470.     iorb->iorbh.CommandCode = IOCC_UNIT_CONTROL;
  471.     iorb->iorbh.CommandModifier = IOCM_DEALLOCATE_UNIT;
  472.     iorb->iorbh.RequestControl = IORB_DISABLE_RETRY;
  473.     iorb->iorbh.Status = 0;
  474.     iorb->iorbh.Timeout = -1;
  475.     iorb->Flags = 0;
  476.     callADDwait(&iorb->iorbh);
  477.  
  478. #ifdef DEBUG
  479.     if (trace && iorb->iorbh.Status & ERROR || trace >= 3)
  480.         result(&iorb->iorbh);
  481. #endif
  482.  
  483.     if (iorb->iorbh.Status & ERROR)
  484.         return mapIORBerror(iorb->iorbh.ErrorCode);
  485.  
  486.     PUTS(3, "Unit deallocated\n");
  487.     return DONE;
  488. }
  489.  
  490. word
  491. DrvRead(ReqPtr p)
  492. {
  493.     PUTS(3, "Read\n");
  494.     return rw(p, PT_DIRECTION_IN);
  495. }
  496.  
  497. word
  498. DrvWrite(ReqPtr p, int vfy)
  499. {
  500.     PUTS(3, "Write\n");
  501.     return rw(p, 0);
  502. }
  503.  
  504. word
  505. DrvIOCtl(ReqPtr p)
  506. {
  507.     handle dataLock;
  508.     byte flags;
  509.     word rc;
  510.  
  511.     if (p->u.ioc.cat < 0x80)
  512.         return ERROR+DONE+InvalidCommand;
  513.     if (p->u.ioc.cat != 0x80)
  514.         return ERROR+DONE+TapeInvalidFcn;
  515.  
  516.     stickyEOF = 0;
  517.  
  518.     switch (p->u.ioc.fcn) {
  519.  
  520.     case IOCtlBusReset:
  521.     case IOCtlDevReset:
  522.         {
  523.         IORB_DEVICE_CONTROL *iorb = (IORB_DEVICE_CONTROL *)iorb1;
  524.  
  525.         PUTS(3, "IOCtl Reset\n");
  526.  
  527.         senseValid = 0;
  528.  
  529.         if ((rc = getIORB(p)) != 0)
  530.             return rc;
  531.  
  532.         iorb->iorbh.Length = sizeof(IORB_DEVICE_CONTROL);
  533.         iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
  534.         iorb->iorbh.CommandCode = IOCC_DEVICE_CONTROL;
  535.         iorb->iorbh.CommandModifier = IOCM_RESET;
  536.         iorb->iorbh.RequestControl = IORB_DISABLE_RETRY;
  537.         iorb->iorbh.Status = 0;
  538.         iorb->iorbh.Timeout = -1;
  539.         iorb->Flags = 0;
  540.         callADDwait(&iorb->iorbh);
  541.         relIORB();
  542.  
  543.         if (iorb->iorbh.Status & ERROR)
  544.             return ERROR+DONE+packError(iorb->iorbh.ErrorCode);
  545.         return DONE;
  546.         }
  547.  
  548.     case IOCtlLevel:
  549.         PUTS(3, "IOCtl Level\n");
  550.         if (VerifyAccess(p->u.ioc.data, 2, VerifyWrite))
  551.             return ERROR+DONE+InvalidParam;
  552.         ((byte _far *)p->u.ioc.data)[0] = 3;
  553.         ((byte _far *)p->u.ioc.data)[1] = senseMode;
  554.         return DONE;
  555.  
  556.     case IOCtlTrace:
  557.         PUTS(3, "IOCtl Trace\n");
  558.         if (p->u.ioc.dlen >= 1) {
  559.             if (VerifyAccess(p->u.ioc.data, 1, VerifyWrite))
  560.                 return ERROR+DONE+InvalidParam;
  561.             *(byte _far *)p->u.ioc.data = trace;
  562.         }
  563.         if (p->u.ioc.plen >= 1) {
  564.             if (VerifyAccess(p->u.ioc.parm, 1, VerifyRead))
  565.                 return ERROR+DONE+InvalidParam;
  566.             trace = *(byte _far *)p->u.ioc.parm;
  567.         }
  568. #ifdef DEBUG
  569.         if (trace >= 1) {
  570.             puts("Trace level ");
  571.             putd(trace);
  572.             putc('\n');
  573.         }
  574. #endif
  575.         return DONE;
  576.  
  577.     case IOCtlBlocksize:
  578.         PUTS(3, "IOCtl Blocksize\n");
  579.         if (p->u.ioc.dlen >= 4) {
  580.             if (VerifyAccess(p->u.ioc.data, 4, VerifyWrite))
  581.                 return ERROR+DONE+InvalidParam;
  582.             *(dword _far *)p->u.ioc.data = blocksize;
  583.         }
  584.         if (p->u.ioc.plen >= 4) {
  585.             if (VerifyAccess(p->u.ioc.parm, 4, VerifyRead))
  586.                 return ERROR+DONE+InvalidParam;
  587.             blocksize = *(dword _far *)p->u.ioc.data;
  588.         }
  589.         return DONE;
  590.  
  591.     case IOCtlRead+IOCtlSlow:
  592.     case IOCtlRead+IOCtlFast:
  593.         PUTS(3, "IOCtl Read\n");
  594.     read:    flags = PT_DIRECTION_IN;
  595.         if (VerifyAccess(p->u.ioc.parm, p->u.ioc.plen, VerifyRead))
  596.             return ERROR+DONE+TapeInvalidParm;
  597.         if (p->u.ioc.dlen
  598.          && VerifyAccess(p->u.ioc.data, p->u.ioc.dlen, VerifyWrite))
  599.             return ERROR+DONE+TapeInvalidData;
  600.         goto checked;
  601.     case IOCtlWrite+IOCtlSlow:
  602.     case IOCtlWrite+IOCtlFast:
  603.         PUTS(3, "IOCtl Write\n");
  604.         flags = 0;
  605.         if (VerifyAccess(p->u.ioc.parm, p->u.ioc.plen, VerifyRead))
  606.             return ERROR+DONE+TapeInvalidParm;
  607.         if (p->u.ioc.dlen
  608.          && VerifyAccess(p->u.ioc.data, p->u.ioc.dlen, VerifyRead))
  609.             return ERROR+DONE+TapeInvalidData;
  610.     checked:
  611.         {    IORB_ADAPTER_PASSTHRU *iorb = (IORB_ADAPTER_PASSTHRU *)iorb1;
  612.  
  613.         if (p->u.ioc.plen < 6 || p->u.ioc.plen > 12)
  614.             return ERROR+DONE+TapeInvalidParm;
  615.         if ((rc = getIORB(p)) != 0)
  616.             return rc;
  617.         _fmemcpy(cdb, p->u.ioc.parm, p->u.ioc.plen);
  618.  
  619.         dataLock = Lock(Segment(p->u.ioc.data), LockShort);
  620.         sglist[0].ppXferBuf = VirtToPhys(p->u.ioc.data);
  621.         sglist[0].XferBufLen = p->u.ioc.dlen;
  622.  
  623.         senseValid = 0;
  624.         memset(&status, 0, SizeofStatus);
  625.         status.sense_len = sizeof sense;
  626.         status.sense_ptr = sense;
  627.  
  628.         iorb->iorbh.Length = sizeof(IORB_ADAPTER_PASSTHRU);
  629.         iorb->iorbh.UnitHandle = unitinfo->UnitHandle;
  630.         iorb->iorbh.CommandCode = IOCC_ADAPTER_PASSTHRU;
  631.         iorb->iorbh.CommandModifier = IOCM_EXECUTE_CDB;
  632.         iorb->iorbh.RequestControl = IORB_REQ_STATUSBLOCK + IORB_DISABLE_RETRY;
  633.         iorb->iorbh.StatusBlockLen = SizeofStatus;
  634.         iorb->iorbh.pStatusBlock = (nearptr)&status;
  635.         iorb->iorbh.Status = 0;
  636.         iorb->iorbh.Timeout = -1;
  637.         iorb->cSGList = 1;
  638.         iorb->pSGList = sglist;
  639.         iorb->ppSGList = paddr_sglist;
  640.         iorb->ControllerCmdLen = p->u.ioc.plen;
  641.         iorb->pControllerCmd = cdb;
  642.         iorb->Flags = flags;
  643.  
  644. #ifdef DEBUG
  645.         if (trace >= 3) {
  646.             puts("    CDB:");
  647.             dump(cdb, p->u.ioc.plen);
  648.             putc('\n');
  649.         }
  650. #endif
  651.  
  652.         callADDwait(&iorb->iorbh);
  653.  
  654. #ifdef DEBUG
  655.         if (trace && iorb->iorbh.Status & ERROR || trace >= 3)
  656.             result(&iorb->iorbh);
  657. #endif
  658.  
  659.         relIORB();
  660.         Unlock(dataLock);
  661.  
  662.         if (iorb->iorbh.Status & IORB_STATUSBLOCK_AVAIL)
  663.             senseValid = 1;
  664.         if (iorb->iorbh.Status & IORB_ERROR)
  665.             return ERROR+DONE+packError(iorb->iorbh.ErrorCode);
  666.         return DONE;
  667.         }
  668.  
  669.     case IOCtlSense:
  670.         PUTS(3, "IOCtl Sense\n");
  671.         if (!senseValid) {
  672.             PUTS(3, "    No sense data\n");
  673.             return ERROR+DONE+TapeNoSenseData;
  674.         }
  675.         PUTS(3, "    Valid sense data\n");
  676.         if (p->u.ioc.dlen > sizeof sense)
  677.             return ERROR+DONE+TapeInvalidData;
  678.         _fmemcpy((farptr)p->u.ioc.data, sense, p->u.ioc.dlen);
  679.         return DONE;
  680.  
  681.     default:
  682.         return ERROR+DONE+TapeInvalidFcn;
  683.     }
  684. }
  685.