home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / c / scsidrvr.arc / driver3.c < prev    next >
C/C++ Source or Header  |  1989-01-06  |  7KB  |  451 lines

  1. #include <dos.h>
  2. #include "driver.h"
  3. #include "scsi.h"
  4.  
  5.  
  6. #define NUNITS 2
  7.  
  8. struct reqhdr far *request;
  9.  
  10. /* command dispatch table */
  11. extern int (*(dispatch[]))();
  12.  
  13. #define max_command 16
  14.  
  15. char msg[100];
  16.  
  17. char *get_sense();
  18.  
  19. void dointr(req)
  20. struct reqhdr far *req;
  21. {
  22.     static int x;
  23.  
  24.     request = req;
  25.  
  26.     x = request->command;
  27.     if (x < 0 || x > max_command)
  28.     {
  29.         request->status = 0x8103;
  30.         return;
  31.     }
  32.  
  33.     request->status = (*(dispatch[x]))();
  34.     request->status |= 0x0100;
  35. }
  36.  
  37.  
  38. biosputs(s)
  39. char *s;
  40. {
  41.     static char c;
  42.     static int oldbp;
  43.  
  44.     while (*s)
  45.     {
  46.         c = *s++;
  47.         if (c == '\n')
  48.         {
  49.             oldbp = _BP;
  50.             _AL = '\r';
  51.             _AH = 0x0e;
  52.             _BH = 0;
  53.             geninterrupt(0x10);
  54.             _BP = oldbp;
  55.         }
  56.  
  57.         oldbp = _BP;
  58.         _AL = c;
  59.         _AH = 0x0e;
  60.         _BH = 0;
  61.         geninterrupt(0x10);
  62.         _BP = oldbp;
  63.     }
  64. }
  65.  
  66. /* Following are the individual routines for each function */
  67.  
  68.  
  69. badfun()
  70. {
  71.     return (0x8003);
  72. }
  73.  
  74. nullfun()
  75. {
  76.     return (0);
  77. }
  78.  
  79.  
  80.  
  81. /* This is returned by the initialization function */
  82.  
  83. struct bpb bpb_list[NUNITS];
  84.  
  85. struct bpb *bpb_array[NUNITS] = { &bpb_list[0], &bpb_list[1] };
  86.  
  87.  
  88. static struct boot_sector init_buf;
  89.  
  90. init()
  91. {
  92.     extern char edata;
  93.     static struct scsireq s;
  94.     int j;
  95.     static char cmd[6];
  96.  
  97.  
  98.     sprintf(msg,
  99.             "\nHard disk driver ver. 3 compiled %s %s installed at %X:0000\n",
  100.             __DATE__, __TIME__, _CS);
  101.     biosputs(msg);
  102.  
  103.     for (j=0; j < NUNITS; j++)
  104.     {
  105.  
  106.         cmd[0] = 0x08;
  107.         cmd[1] = (j&01) << 5;
  108.         cmd[2] = 0;
  109.         cmd[3] = 0;
  110.         cmd[4] = 1;
  111.         cmd[5] = 0;
  112.  
  113.         s.busid = 1;
  114.         s.dptr = (char far *)&init_buf;
  115.         s.dlen = 512;
  116.         s.cptr = (char far *)cmd;
  117.  
  118.         scsiop(&s);
  119.  
  120.         if (s.error == 0)
  121.         {
  122.             *bpb_array[j] = init_buf.disk_bpb;
  123.             sprintf(msg, "LUN %d, name %s with %u blocks online as %c:\n", j,
  124.                     init_buf.disk_name,
  125.                     bpb_array[j]->nsectors,
  126.                     'A' + j + request->padding[0]);
  127.             biosputs(msg);
  128.         }
  129.         else
  130.         {
  131.             sprintf(msg, "LUN %d is not available\n", j);
  132.             biosputs(msg);
  133.             break;
  134.         }
  135.     }
  136.  
  137.     biosputs("\n");
  138.  
  139.     request->media = j;   /* # of drives  */
  140.     request->address = (char far *)&edata;
  141.     request->count = (unsigned)bpb_array;
  142.     request->sector = (unsigned)_CS;
  143.     return (0);
  144. }
  145.  
  146.  
  147. media_chk()
  148. {
  149.     request->address = (char far *)1;
  150.     return (0);
  151. }
  152.  
  153.  
  154. build_bpb()
  155. {
  156.     request->count = (unsigned)(bpb_array[request->unit]);
  157.     request->sector = (unsigned)_CS;
  158.     return (0);
  159. }
  160.  
  161.  
  162.  
  163. read()
  164. {
  165.     static struct scsireq s;
  166.     int lun;
  167.     static char cmd[6];
  168.  
  169.     /*
  170.     sprintf(msg, "Read of %u sectors from %u to %Fp\n", request->count,
  171.         request->sector, request->address);
  172.     biosputs(msg);
  173.     */
  174.  
  175.     lun = request->unit;
  176.  
  177.     cmd[0] = 0x08;
  178.     cmd[1] = (lun&01) << 5;
  179.     cmd[2] = request->sector >> 8;
  180.     cmd[3] = request->sector & 0xff;
  181.     cmd[4] = request->count;
  182.     cmd[5] = 0;
  183.  
  184.     s.busid = 1;
  185.     s.dptr = (char far *)request->address;
  186.     s.dlen = request->count * 512;
  187.     s.cptr = (char far *)cmd;
  188.  
  189.     scsiop(&s);
  190.  
  191.     if (s.error != 0)
  192.     {
  193.         sprintf(msg, "Bad read of %u sectors from %u to %Fp\n", request->count,
  194.             request->sector, request->address);
  195.         biosputs(msg);
  196.         sprintf(msg, "LUN %d. SCSI error code 0x%x.\n", lun, s.error);
  197.         biosputs(msg);
  198.         perr(lun);
  199.     }
  200.  
  201.     return (s.error? 0x8004 : 0);
  202. }
  203.  
  204.  
  205. write_vfy()
  206. {
  207.     return (write());
  208. }
  209.  
  210. write()
  211. {
  212.     static struct scsireq s;
  213.     int lun;
  214.     static char cmd[6];
  215.  
  216. retry:
  217.  
  218.     /* 
  219.     sprintf(msg, "Write of %u sectors from %u to %Fp\n", request->count,
  220.         request->sector, request->address);
  221.     biosputs(msg);
  222.     */
  223.  
  224.     lun = request->unit;
  225.  
  226.     cmd[0] = 0x0a;
  227.     cmd[1] = (lun&01) << 5;
  228.     cmd[2] = request->sector >> 8;
  229.     cmd[3] = request->sector & 0xff;
  230.     cmd[4] = request->count;
  231.     cmd[5] = 0;
  232.  
  233.     s.busid = 1;
  234.     s.dptr = (char far *)request->address;
  235.     s.dlen = request->count * 512;
  236.     s.cptr = (char far *)cmd;
  237.  
  238.     scsiop(&s);
  239.  
  240.     if (s.error != 0)
  241.     {
  242.         sprintf(msg, "Bad write of %u sectors from %u to %Fp\n", request->count,
  243.             request->sector, request->address);
  244.         biosputs(msg);
  245.         sprintf(msg, "LUN %d. SCSI error code 0x%x.\n", lun, s.error);
  246.         biosputs(msg);
  247.         if (perr(lun) == 0x12)
  248.             goto retry;
  249.     }
  250.  
  251.     return (s.error? 0x8004 : 0);
  252. }
  253.  
  254.  
  255. int (*(dispatch[]))() = {
  256.     init,
  257.     media_chk,
  258.     build_bpb,
  259.     badfun,
  260.     read,
  261.     badfun,
  262.     badfun,
  263.     nullfun,
  264.     write,
  265.     write_vfy,
  266.     badfun,
  267.     nullfun,
  268.     badfun,
  269.     badfun,
  270.     badfun,
  271.     nullfun,
  272.     badfun,
  273. };
  274.  
  275.  
  276. abort()
  277. {
  278.     biosputs("Driver aborted\n");
  279.     for(;;);
  280. }
  281.  
  282.  
  283.  
  284.  
  285. char sensedata[10];
  286.  
  287. unsigned
  288. logadr()
  289. {
  290.     int ladr,hadr;
  291.  
  292.     hadr = sensedata[2];
  293.     ladr = sensedata[3];
  294.     return ((hadr<<8)+(ladr&0xff));
  295. }
  296.  
  297.  
  298. perr(lun)
  299. int lun;
  300. {
  301.     int code;
  302.     unsigned phadr;
  303.  
  304.     getsense(lun);
  305.  
  306.     code = sensedata[0];
  307.  
  308.     biosputs("\nDISK ERROR\n");
  309.     prerror(code & 0x7f);
  310.     biosputs("\n");
  311.     if (code & 0x80)
  312.     {
  313.         code &= 0x7f;
  314.         sprintf(msg,  "Logical address: %x\n",logadr());
  315.         biosputs(msg);
  316.         if (code != 0x14 && code != 0x10)
  317.         {
  318.             phadr = xlate(lun, logadr());
  319.             sprintf(msg,  "Physical address: %x\n",phadr);
  320.             biosputs(msg);
  321.         }
  322.     }
  323.     else
  324.         biosputs("No address\n");
  325.  
  326.     return (code);
  327. }
  328.  
  329.  
  330.  
  331. static char *errcodes[] = {
  332.  
  333.         "No error",
  334.         "No index signal",
  335.         "No seek complete",
  336.         "Drive fault",
  337.         "Drive not ready",
  338.         0,
  339.         "No track 00",
  340.         0,
  341.         0,
  342.         0,
  343.         0,
  344.         0,
  345.         "Write fault",
  346.         0,
  347.         0,
  348.         0,
  349.         "ID CRC error",
  350.         "Uncorrectable data error",
  351.         0,
  352.         "Data address mark not found",
  353.         "Record not found",
  354.         "Seek error",
  355.         0,
  356.         0,
  357.         "Corrected data error",
  358.         0,
  359.         "Format error",
  360.         0,
  361.         0,
  362.         0,
  363.         0,
  364.         0,
  365.         "Invalid command",
  366.         "Illegal block address",
  367.         "Command aborted",
  368.         "Invalid parameters",
  369.         0,
  370.         "Controller error",
  371.         0,
  372.         0,
  373.         0,
  374.         0,
  375.         0,
  376.         0,
  377.         0,
  378.         0,
  379.         0,
  380.         0  };
  381.  
  382. static prerror(n)
  383. int n;
  384. {
  385.     if (n<0 || n >= 48)
  386.         biosputs("Invalid error code");
  387.     else if (errcodes[n] == 0)
  388.     {
  389.         sprintf(msg, "Unknown error code %.2x",n);
  390.         biosputs(msg);
  391.     }
  392.     else
  393.     {
  394.         sprintf(msg, "Error %.2x: %s",n,errcodes[n]);
  395.         biosputs(msg);
  396.     }
  397. }
  398.  
  399.  
  400. static xlate(lun,blk)
  401. int lun;
  402. unsigned blk;
  403. {
  404.     static char cmd[4];
  405.     static char data[4];
  406.     static struct scsireq s;
  407.  
  408.     cmd[0] = 0x0f;
  409.     cmd[1] = (lun&01) << 5;
  410.     cmd[2] = blk >> 8;
  411.     cmd[3] = blk & 0xff;
  412.     cmd[4] = cmd[5] = 0;
  413.  
  414.  
  415.     s.busid = 1;
  416.     s.cptr = (char far *)cmd;
  417.     s.dptr = (char far *)data;
  418.     s.dlen = 4;
  419.  
  420.     scsiop(&s);
  421.  
  422.     if (s.error != 0)
  423.         return(-1);
  424.     else
  425.         return(data[2] * 256 + (data[3] & 0xff));
  426.  
  427. }
  428.  
  429.  
  430. getsense(lun)
  431. int lun;
  432. {
  433.     static char cmd[] = { 3, 0, 0, 0, 4, 0 };
  434.     static struct scsireq s;
  435.  
  436.     cmd[1] = (lun&01) << 5;
  437.  
  438.     s.busid = 1;
  439.     s.cptr = (char far *)cmd;
  440.     s.dptr = (char far *)sensedata;
  441.     s.dlen = 4;
  442.  
  443.     scsiop(&s);
  444.  
  445.     return (s.error);
  446. }
  447.  
  448.  
  449. int _realcvtvector;
  450.  
  451.