home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / gtak212b.zip / SOURCE.ZIP / OS2-ASPI / main.c < prev    next >
C/C++ Source or Header  |  1992-11-14  |  13KB  |  603 lines

  1. /*****************************************************************************
  2.  * $Id: main.c,v 2.1 1992/11/14 21:00:20 ak Exp $
  3.  *****************************************************************************
  4.  * $Log: main.c,v $
  5.  * Revision 2.1  1992/11/14  21:00:20  ak
  6.  * OS/2 2.00.1 ASPI
  7.  *
  8.  * Revision 1.1.1.1  1992/01/06  20:16:27  ak
  9.  * Alpha version.
  10.  *
  11.  * Revision 1.1  1992/01/06  20:16:25  ak
  12.  * Initial revision
  13.  *
  14.  *****************************************************************************/
  15.  
  16. static char _far rcsid[] = "$Id: main.c,v 2.1 1992/11/14 21:00:20 ak Exp $";
  17.  
  18. #include "aspitape.h"
  19. #include "tapedrvr.h"
  20. #include <libx.h>
  21. #include <ztc.h>
  22. #define INCL_DOSDEVICES
  23. #include <os2.h>
  24.  
  25. typedef void (_far *FcnPtr) (word, SRB _far *);
  26.  
  27. extern void _far postEntry (unsigned, unsigned long);
  28.  
  29. #define min(a,b) ((a) < (b) ? (a) : (b))
  30.  
  31. void
  32. aspi(SRB *p)
  33. {
  34.     if (aspiHandle)
  35.         DosDevIOCtl((PBYTE)0, (PBYTE)p, 0x40, 0x80, aspiHandle);
  36.     else if (inProtMode())
  37.         (*(FcnPtr)aspiEntry.prot)(aspiEntry.protDS, p);
  38.     else
  39.         (*(FcnPtr)aspiEntry.real)(aspiEntry.realDS, p);
  40. }
  41.  
  42. void
  43. post(dword paddrSRB)
  44. {
  45.     PUTS(4, "    POST\n");
  46.     Run((dword)reqpkt);
  47. }
  48.  
  49. /*
  50.  * Issue Abort SRB command.
  51.  */
  52. static void
  53. abort(dword paddr)
  54. {
  55.     if (srb2.status == SRB_Busy)
  56.         return;
  57.     srb2.cmd = SRB_Abort;
  58.     srb2.ha_num = adapter;
  59.     srb2.flags = 0;
  60.     srb2.u.abt.phys_addr_srb = paddr;
  61.     aspi(&srb2);
  62. }
  63.  
  64. /*
  65.  * Call ASPI. Wait until done.
  66.  */
  67. void
  68. aspiWait(SRB *p)
  69. {
  70.     srb.flags |= SRB_Post;
  71.     srb.u.cmd.realpost = Pointer(header.realCS, Offset((dword)postEntry));
  72.     srb.u.cmd.realDS = header.realDS;
  73.     srb.u.cmd.protpost = Pointer(header.protCS, Offset((dword)postEntry));
  74.     srb.u.cmd.protDS = header.protDS;
  75.     aspi(p);
  76.     int_off();
  77.     while (p->status == SRB_Busy || p->status == SRB_BusyPost) {
  78.         PUTS(4, "    Waiting for POST\n");
  79.         if (Block((dword)reqpkt, Infinite, 1)) {
  80.             PUTS(1, "Abort\n");
  81.             abort(paddrSRB);
  82.             continue;
  83.         }
  84.         int_off();
  85.     }
  86.     int_on();
  87. }
  88.  
  89. /*
  90.  * Get SRB. Wait until available.
  91.  * -> errcode if interrupted.
  92.  */
  93. word
  94. getSRB(ReqPtr p)
  95. {
  96.     int_off();
  97.     while (reqpkt) {
  98.         PUTS(4, "    Waiting for SRB\n");
  99.         ++waiting;
  100.         if (Block(paddrSRB, Infinite, 1))
  101.             return ERROR+DONE+Interrupted;
  102.         int_off();
  103.     }
  104.     int_on();
  105.     reqpkt = p;
  106.     return 0;
  107. }
  108.  
  109. /*
  110.  * Release SRB.
  111.  * Wakeup threads waiting.
  112.  */
  113. void
  114. relSRB(void)
  115. {
  116.     reqpkt = 0;
  117.     if (waiting) {
  118.         waiting = 0;
  119.         Run(paddrSRB);
  120.     }
  121. }
  122.  
  123. #ifdef DEBUG
  124.  
  125. static void
  126. dump(byte _far *p, int n)
  127. {
  128.     int i;
  129.  
  130.     for (i = 0; i < n; ++i) {
  131.         putc(' ');
  132.         putx(p[i]);
  133.     }
  134. }
  135.  
  136. static void
  137. status(SRB *p)
  138. {
  139.     puts("    ASPI status: ");
  140.     putx(p->status);
  141.     puts(", HA status: ");
  142.     putx(p->u.cmd.ha_status);
  143.     puts(", target status: ");
  144.     putx(p->u.cmd.target_status);
  145.     if (p->u.cmd.target_status == CheckStatus) {
  146.         puts(", sense data:\n\t");
  147.         dump(p->u.cmd.cdb_st + p->u.cmd.cdb_len,
  148.             min(p->u.cmd.sense_len, 16));
  149.     }
  150.     putc('\n');
  151. }
  152.  
  153. #endif
  154.  
  155. static word
  156. rw(ReqPtr p, byte flags)
  157. {
  158.     word rc;
  159.     dword count, nb;
  160.  
  161.     count = p->u.rw.count;
  162.     p->u.rw.count = 0;
  163.  
  164.     if (stickyEOF) {
  165.         PUTS(4, "    still EOF\n");
  166.         return DONE;
  167.     }
  168.  
  169.     if (blocksize) {
  170.         dword rem;
  171.         switch (blocksize) {
  172.         case 512:
  173.             nb = count >> 9;
  174.             rem = count & 0x1FF;
  175.             break;
  176.         case 1024:
  177.             nb = count >> 10;
  178.             rem = count & 0x3FF;
  179.             break;
  180.         default:
  181.             nb = count / blocksize;
  182.             rem = count % blocksize;
  183.         }
  184.         if (rem)
  185.             return ERROR+DONE+InvalidParam;
  186.     } else
  187.         nb = count;
  188.  
  189.     if ((rc = getSRB(p)) != 0)
  190.         return rc;
  191.  
  192.     srb.cmd = SRB_Command;
  193.     srb.ha_num = adapter;
  194.     srb.flags = flags;
  195.     srb.u.cmd.target = target;
  196.     srb.u.cmd.lun = 0;
  197.     srb.u.cmd.data_len = count;
  198.     srb.u.cmd.sense_len = 20;
  199.     srb.u.cmd.data_ptr = p->u.rw.addr;
  200.     srb.u.cmd.phys_addr_srb = paddrSRB;
  201.     srb.u.cmd.cdb_len = 6;
  202.     srb.u.cmd.cdb_st[0] = flags & SRB_Read ? SeqRead : SeqWrite;
  203.     srb.u.cmd.cdb_st[1] = blocksize ? 1 : 0;
  204.     srb.u.cmd.cdb_st[2] = nb >> 16;
  205.     srb.u.cmd.cdb_st[3] = nb >> 8;
  206.     srb.u.cmd.cdb_st[4] = nb;
  207.     srb.u.cmd.cdb_st[5] = 0x00;
  208.  
  209. #ifdef DEBUG
  210.     if (trace >= 3) {
  211.         puts("    R/W CDB:");
  212.         dump(srb.u.cmd.cdb_st, 6);
  213.         putc('\n');
  214.     }
  215. #endif
  216.  
  217.     aspiWait(&srb);
  218.  
  219. #ifdef DEBUG
  220.     if (trace >= 3)
  221.         status(&srb);
  222. #endif
  223.  
  224.     relSRB();
  225.  
  226.     switch (srb.status) {
  227.     case SRB_Done:
  228.         p->u.rw.count = count;
  229.         return DONE;
  230.     case SRB_Aborted:
  231.         return ERROR+DONE+Interrupted;
  232.     case SRB_Error:
  233.         break;
  234.     case SRB_InvalidHA:
  235.     case SRB_BadDevice:
  236.         return ERROR+DONE+DeviceNotReady;
  237.     default:
  238.         return ERROR+DONE+GeneralFailure;
  239.     }
  240.  
  241.     switch (srb.u.cmd.ha_status) {
  242.     case 0x00:    /* No host adapter detected error */
  243.         break;
  244.     case 0x11:    /* Selection timeout */
  245.         return ERROR+DONE+DeviceNotReady;
  246.     default:
  247.         return ERROR+DONE+GeneralFailure;
  248.     }
  249.  
  250.     switch (srb.u.cmd.target_status) {
  251.     case SRB_NoStatus:
  252.         p->u.rw.count = count;
  253.         return DONE;
  254.     case SRB_CheckStatus:
  255.         senseValid = 20;
  256.         break;
  257.     case SRB_LUN_Busy:
  258.     case SRB_Reserved:
  259.         return ERROR+DONE+DeviceNotReady;
  260.     default:
  261.         return ERROR+DONE+GeneralFailure;
  262.     }
  263.  
  264. #ifdef DEBUG
  265.     if (trace && trace < 3)
  266.         status(&srb);
  267. #endif
  268.  
  269.     if (srb.u.cmd.cdb_st[6+2] & VADD) {
  270.         dword info = 0;
  271.         for (rc = 6+3; rc <= 6+6; ++rc) {
  272.             info <<= 8;
  273.             info |= srb.u.cmd.cdb_st[rc];
  274.         }
  275.         switch (blocksize) {
  276.         case 512:
  277.             info <<= 9;
  278.             break;
  279.         case 1024:
  280.             info <<= 10;
  281.             break;
  282.         default:
  283.             info *= blocksize;
  284.         case 0:    ;
  285.         }
  286.         p->u.rw.count = count - (info << 9);
  287.  
  288.         PUTS(4, "    result count=");
  289.         PUTD(4, p->u.rw.count);
  290.         PUTC(4, '\n');
  291.     } else
  292.         p->u.rw.count = count;
  293.  
  294.     if (srb.u.cmd.cdb_st[6+2] & (FM|EOM)) {
  295.         PUTS(4, "    EOF\n");
  296.         stickyEOF = 1;
  297.     }
  298.     if (senseMode == Sensekey) {
  299.         switch (srb.u.cmd.cdb_st[6+2] & 0x0F) {
  300.         case NoSense:
  301.         case BlankCheck:
  302.             return DONE;
  303.         case RecoveredData:
  304.             return ERROR+DONE+CRCError;
  305.         case NotReady:
  306.         case Hardware:
  307.         case UnitAttention:
  308.             return ERROR+DONE+DeviceNotReady;
  309.         case MediaError:
  310.             return ERROR+DONE+ReadFault;
  311.         case WriteProtected:
  312.             return ERROR+DONE+WriteProtect;
  313.         case MediaOverflow:
  314.             return ERROR+DONE+NoPaper;
  315.         case AbortedCommand:
  316.             return ERROR+DONE+Interrupted;
  317.         default:
  318.             return ERROR+DONE+GeneralFailure;
  319.         }
  320.     }
  321.     if ((srb.u.cmd.cdb_st[6+0] & ~0x81) != 0x70)
  322.         rc = srb.u.cmd.cdb_st[6+0];
  323.     else
  324.         switch (senseMode) {
  325.         case TDC3600:
  326.             rc = srb.u.cmd.cdb_st[6+14];
  327.             break;
  328.         default:
  329.             rc = srb.u.cmd.cdb_st[6+12];
  330.         }
  331.     switch (senseMode) {
  332.     case TDC3600:
  333.         switch (rc) {
  334.         case 0x00:        /* ok */
  335.             return DONE;
  336.         case 0x02:        /* hardware error */
  337.         case 0x04:        /* not ready */
  338.         case 0x09:        /* not loaded */
  339.             return ERROR+DONE+DeviceNotReady;
  340.         case 0x0A:        /* insufficient capacity */
  341.             return ERROR+DONE+NoPaper;
  342.         case 0x11:        /* uncorrectable data error */
  343.             return ERROR+DONE+ReadFault;
  344.         case 0x14:        /* empty cartridge */
  345.         case 0x1C:        /* file mark detected */
  346.         case 0x34:        /* read EOM */
  347.             PUTS(4, "    EOF\n");
  348.             stickyEOF = 1;
  349.             return DONE;
  350.         case 0x17:        /* write protected */
  351.             return ERROR+DONE+WriteProtect;
  352.         case 0x19:        /* bad block found */
  353.             return ERROR+DONE+WriteFault;
  354.         case 0x30:
  355.             return ERROR+DONE+ChangeDisk;
  356.         case 0x33:        /* append error */
  357.             return ERROR+DONE+SeekError;
  358.         default:
  359.             return ERROR+DONE+GeneralFailure;
  360.         }
  361.     case SCSI2:
  362.         switch (rc) {
  363.         case 0x00:    /* end-of-data */
  364.         case 0x14:    /* end-of-data not found / filemark */
  365.             PUTS(4, "    EOF\n");
  366.             stickyEOF = 1;
  367.             return DONE;
  368.         case 0x30:    /* cannot read medium */
  369.             return ERROR+DONE+UnknownMedia;
  370.         case 0x52:    /* cartridge fault */
  371.         case 0x05:    /* selection failure */
  372.         case 0x40:    /* device failure */
  373.         case 0x04:    /* not ready */
  374.         case 0x25:    /* LUN not supported */
  375.         case 0x3A:    /* medium not present */
  376.             return ERROR+DONE+DeviceNotReady;
  377.         case 0x03:    /* excessive write errors */
  378.         case 0x0C:    /* write error */
  379.             return ERROR+DONE+WriteFault;
  380.         case 0x21:    /* block address out of range */
  381.         case 0x15:    /* positioning error */
  382.         case 0x50:    /* write append error */
  383.             return ERROR+DONE+SeekError;
  384.         case 0x53:    /* media load failed */
  385.         case 0x29:    /* power-up or reset */
  386.             return ERROR+DONE+ChangeDisk;
  387.         case 0x31:    /* media format corrupted */
  388.         case 0x11:    /* read retries exhausted */
  389.             return ERROR+DONE+ReadFault;
  390.         case 0x17:    /* recovered error */
  391.             return ERROR+DONE+CRCError;
  392.         case 0x27:    /* write protected */
  393.             return ERROR+DONE+WriteProtect;
  394.         default:
  395.             return ERROR+DONE+GeneralFailure;
  396.         }
  397.     default:
  398.         return ERROR+DONE+GeneralFailure;
  399.     }
  400. }
  401.  
  402. word
  403. DrvOpen(ReqPtr p)
  404. {
  405.     if (!inProtMode())
  406.         return ERROR+DONE+InvalidCommand;
  407.     senseValid = 0;
  408.     stickyEOF = 0;
  409.     return DONE;
  410. }
  411.  
  412. word
  413. DrvClose(ReqPtr p)
  414. {
  415.     return DONE;
  416. }
  417.  
  418. word
  419. DrvRead(ReqPtr p)
  420. {
  421.     return rw(p, SRB_Read);
  422. }
  423.  
  424. word
  425. DrvWrite(ReqPtr p, int vfy)
  426. {
  427.     return rw(p, SRB_Write);
  428. }
  429.  
  430. word
  431. DrvIOCtl(ReqPtr p)
  432. {
  433.     handle dataLock;
  434.     byte flags;
  435.     word rc;
  436.  
  437.     if (p->u.ioc.cat < 0x80)
  438.         return ERROR+DONE+InvalidCommand;
  439.     if (p->u.ioc.cat != 0x80)
  440.         return ERROR+DONE+TapeInvalidFcn;
  441.  
  442.     stickyEOF = 0;
  443.  
  444.     switch (p->u.ioc.fcn) {
  445.  
  446.     case IOCtlBusReset:
  447.     case IOCtlDevReset:
  448.         PUTS(3, "IOCtl Reset\n");
  449.  
  450.         senseValid = 0;
  451.  
  452.         if ((rc = getSRB(p)) != 0)
  453.             return rc;
  454.         srb.u.res.target = target;
  455.         srb.u.res.lun = 0;
  456.         aspiWait(&srb);
  457.         relSRB();
  458.  
  459.         if (srb.status == SRB_Done)
  460.             return DONE;
  461.         if (srb.status & 0x80)
  462.             return ERROR+DONE+ErrASPIDriver1+(srb.status & 0x1F);
  463.         return ERROR+DONE+ErrASPIDriver2+(srb.status & 0x1F);
  464.  
  465.     case IOCtlLevel:
  466.         PUTS(3, "IOCtl Level\n");
  467.         if (VerifyAccess(p->u.ioc.data, 2, VerifyWrite))
  468.             return ERROR+DONE+InvalidParam;
  469.         ((byte _far *)p->u.ioc.data)[0] = ASPIdriver;
  470.         ((byte _far *)p->u.ioc.data)[1] = senseMode;
  471.         return DONE;
  472.  
  473.     case IOCtlTrace:
  474.         PUTS(3, "IOCtl Trace\n");
  475.         if (p->u.ioc.dlen >= 1) {
  476.             if (VerifyAccess(p->u.ioc.data, 1, VerifyWrite))
  477.                 return ERROR+DONE+InvalidParam;
  478.             *(byte _far *)p->u.ioc.data = trace;
  479.         }
  480.         if (p->u.ioc.plen >= 1) {
  481.             if (VerifyAccess(p->u.ioc.parm, 1, VerifyRead))
  482.                 return ERROR+DONE+InvalidParam;
  483.             trace = *(byte _far *)p->u.ioc.parm;
  484.         }
  485.         return DONE;
  486.  
  487.     case IOCtlBlocksize:
  488.         PUTS(3, "IOCtl Blocksize\n");
  489.         if (p->u.ioc.dlen >= 4) {
  490.             if (VerifyAccess(p->u.ioc.data, 4, VerifyWrite))
  491.                 return ERROR+DONE+InvalidParam;
  492.             *(dword _far *)p->u.ioc.data = blocksize;
  493.         }
  494.         if (p->u.ioc.plen >= 4) {
  495.             if (VerifyAccess(p->u.ioc.parm, 4, VerifyRead))
  496.                 return ERROR+DONE+InvalidParam;
  497.             blocksize = *(dword _far *)p->u.ioc.data;
  498.         }
  499.         return DONE;
  500.  
  501.     case IOCtlSlow:
  502.     case IOCtlFast:
  503.         PUTS(3, "IOCtl Unchecked Command\n");
  504.         flags = 0;
  505.         goto unchecked;
  506.     case IOCtlRead+IOCtlSlow:
  507.     case IOCtlRead+IOCtlFast:
  508.         PUTS(3, "IOCtl Read\n");
  509.     read:    flags = SRB_Read;
  510.     unchecked:
  511.         if (VerifyAccess(p->u.ioc.parm, p->u.ioc.plen, VerifyRead))
  512.             return ERROR+DONE+TapeInvalidParm;
  513.         if (p->u.ioc.dlen
  514.          && VerifyAccess(p->u.ioc.data, p->u.ioc.dlen, VerifyWrite))
  515.             return ERROR+DONE+TapeInvalidData;
  516.         goto checked;
  517.     case IOCtlWrite+IOCtlSlow:
  518.     case IOCtlWrite+IOCtlFast:
  519.         PUTS(3, "IOCtl Write\n");
  520.         flags = SRB_Write;
  521.         if (VerifyAccess(p->u.ioc.parm, p->u.ioc.plen, VerifyRead))
  522.             return ERROR+DONE+TapeInvalidParm;
  523.         if (p->u.ioc.dlen
  524.          && VerifyAccess(p->u.ioc.data, p->u.ioc.dlen, VerifyRead))
  525.             return ERROR+DONE+TapeInvalidData;
  526.     checked:
  527.         if (p->u.ioc.plen < 6 || p->u.ioc.plen > 12)
  528.             return ERROR+DONE+TapeInvalidParm;
  529.         if ((rc = getSRB(p)) != 0)
  530.             return rc;
  531.         dataLock = Lock(Segment(p->u.ioc.data), LockShort);
  532.         senseValid = 0;
  533.         
  534.         srb.cmd = SRB_Command;
  535.         srb.status = 0;
  536.         srb.ha_num = adapter;
  537.         srb.flags = flags;
  538.         srb.u.cmd.target = target;
  539.         srb.u.cmd.lun = 0;
  540.         srb.u.cmd.data_len = p->u.ioc.dlen;
  541. #if SenseLength
  542.         srb.u.cmd.sense_len = SenseLength;
  543. #else
  544.         srb.u.cmd.sense_len = MaxCDBStatus - p->u.ioc.plen;
  545. #endif
  546.         if (p->u.ioc.dlen)
  547.             srb.u.cmd.data_ptr = VirtToPhys(p->u.ioc.data);
  548.         srb.u.cmd.phys_addr_srb = paddrSRB;
  549.         srb.u.cmd.cdb_len = p->u.ioc.plen;
  550.         _fmemcpy(srb.u.cmd.cdb_st, p->u.ioc.parm, p->u.ioc.plen);
  551.  
  552. #ifdef DEBUG
  553.         if (trace >= 3) {
  554.             puts("    CDB:");
  555.             dump(srb.u.cmd.cdb_st, srb.u.cmd.cdb_len);
  556.             putc('\n');
  557.         }
  558. #endif
  559.  
  560.         aspiWait(&srb);
  561.  
  562. #ifdef DEBUG
  563.         if (trace >= 3)
  564.             status(&srb);
  565. #endif
  566.  
  567.         relSRB();
  568.         Unlock(dataLock);
  569.  
  570.         if (srb.u.cmd.target_status == CheckStatus)
  571.             senseValid = srb.u.cmd.sense_len;
  572.  
  573.         if (srb.status != SRB_Done && srb.status != SRB_Error)
  574.             return ERROR+DONE
  575.                 +(srb.status & 0x80 ? ErrASPIDriver2 : ErrASPIDriver1)
  576.                 +(srb.status & 0x1F);
  577.         if (srb.u.cmd.ha_status)
  578.             return ERROR+DONE+ErrHostAdapter
  579.                 +(srb.u.cmd.ha_status & 0x1F);
  580.         if (srb.u.cmd.target_status)
  581.             return ERROR+DONE+ErrTargetStatus
  582.                 +(srb.u.cmd.target_status & 0x1F);
  583.         return DONE;
  584.  
  585.     case IOCtlSense:
  586.         PUTS(3, "IOCtl Sense\n");
  587.         if (!senseValid) {
  588.             PUTS(3, "    No sense data\n");
  589.             return ERROR+DONE+TapeNoSenseData;
  590.         }
  591.         PUTS(3, "    Valid sense data\n");
  592.         if (p->u.ioc.dlen > senseValid)
  593.             return ERROR+DONE+TapeInvalidData;
  594.         _fmemcpy((farptr)p->u.ioc.data,
  595.             srb.u.cmd.cdb_st + srb.u.cmd.cdb_len,
  596.             p->u.ioc.dlen);
  597.         return DONE;
  598.  
  599.     default:
  600.         return ERROR+DONE+TapeInvalidFcn;
  601.     }
  602. }
  603.