home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / drivers / scsi / futrdomn / samples / rw13.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-20  |  12.4 KB  |  419 lines

  1. /**************************** RW13.C ********************************/
  2.  
  3.   #include <string.h>
  4.   #include <dos.h>
  5.   #include <stdio.h>
  6.  
  7.   /* Structure for the disk definition table */
  8.   /* This format matchs the table in the ROM BIOS */
  9.  
  10.   struct
  11.     {
  12.     unsigned char bits         ;
  13.     int cylinders         ;     /* number of cylinders on the disk */
  14.     unsigned char heads      ;     /* number of heads */
  15.     unsigned char sectors    ;     /* sectors per track */
  16.     unsigned char select     ;     /* 0-2 = LUN, 3-5 = CONTROLLER */
  17.     unsigned char ready      ;     /* slot for drive ready signal */
  18.     unsigned char save_sense[4]; /* request sense data */
  19.     unsigned char err_cmd[10];     /* erroring command for sense data */
  20.     unsigned long capacity   ;     /* drive capacity */
  21.     unsigned char drivename[24]; /* drive name from inquiry command */
  22.     unsigned char unitno     ;
  23.     } romtbls [8] ;
  24.  
  25.   unsigned int physmax     ;      /* maximum allowed unit number */
  26.   unsigned int physcur     ;      /* current selected unit */
  27.   unsigned int physbase  ;      /* base address for drives, ie 80H */
  28.   unsigned char scratchbuf [512] ;  /* scratch buffer */
  29.   #define esc 0x1b          /* escape character */
  30.  
  31.   union REGS regs ;
  32.   struct SREGS segregs;
  33.  
  34.   char dosmsg [16] [25] =
  35.    {
  36.      {"Write Protect Error"},   /* 00 */
  37.      {"Unknown Unit"},          /* 01 */
  38.      {"Device Not Ready"},      /* 02 */
  39.      {"Unknown Command"},       /* 03 */
  40.      {"CRC Error"},             /* 04 */
  41.      {"Bad Req Struct Len"},    /* 05 */
  42.      {"Seek Error"},            /* 06 */
  43.      {"Unknown Media"},         /* 07 */
  44.      {"Sector Not Found"},      /* 08 */
  45.      {"Printer out of Paper"},  /* 09 */
  46.      {"Write Fault"},           /* 0A */
  47.      {"Read Fault"},            /* 0B */
  48.      {"General Failure"},       /* 0C */
  49.      {"Reserved"},              /* 0D */
  50.      {"Reserved"},              /* 0E */
  51.      {"Media Changed"},         /* 0F */
  52.    }    ;
  53.  
  54. /* RESPONSE DEFINITIONS */
  55.   char resp13 [] = "Abort, Retry, Ignore?" ;
  56.  
  57. /* int wrt13 (buffer,sector,length,unit)                     */
  58. /* int read13 (buffer,sector,length,unit)                     */
  59. /*     buffer - pointer to buffer for input/output of data             */
  60. /*     sector - absolute disk sector number for input/output             */
  61. /*     length - length of transfer in sectors                     */
  62. /*     unit   - disk unit number, ie 0, 1, ...                     */
  63. /*                                         */
  64. /* These procedures read/write disk using the int13 call to the ROM BIOS.    */
  65. /*   If there is an error of any kind, the user is asked for a prompt, ie    */
  66. /*   Abort, Retry, Ignore.  The retry is done internally, the abort returns  */
  67. /*   a value of 2 to the caller, and the ignore is completed the same as     */
  68. /*   a successful I/O request with a 0.                      */
  69. /*                                         */
  70.  
  71. read13 (buf,sect,len,unit) /* do int 13 call */
  72.   int buf, len, unit ;
  73.   unsigned long sect ;
  74.   {
  75.   int i,j;
  76.   do
  77.     {
  78.     if(do_13_parms(buf,sect,len,unit)!=0)return(2);  /* setup int13 parms */
  79.     regs.h.ah=2 ;  /* read request code */
  80.     int86x (0x13,®s,®s,&segregs) ;
  81.     i=err_13 (unit,0) ;    /* get error response */
  82.     } while (i==1) ;  /* retry check */
  83.   return (i)   ;      /* back to caller */
  84.   }
  85.  
  86. wrt13 (buf,sect,len,unit) /* do int 13 call */
  87.   int buf, len, unit ;
  88.   unsigned long sect ;
  89.   {
  90.   int i,j;
  91.   do
  92.     {
  93.     if(do_13_parms(buf,sect,len,unit)!=0)return(2);  /* setup int13 parms */
  94.     regs.h.ah=3 ;  /* read request code */
  95.     int86x (0x13,®s,®s,&segregs) ;
  96.     i=err_13 (unit,1) ;    /* get error response */
  97.     } while (i==1) ;  /* retry check */
  98.   return (i)   ;      /* back to caller */
  99.   }
  100.  
  101. rw13reset(unit)      /* reset the hard disk system */
  102.   {
  103.   int i;
  104.   regs.h.ah=0;         /* reset command */
  105.   regs.h.dl=romtbls[unit].unitno;
  106.   int86x (0x13,®s,®s,&segregs) ;
  107.   i=regs.h.ah&255 ;     /* get error response */
  108.   return(i);
  109.   }
  110.  
  111. do_13_parms (buf,sect,len,unit)  /* setup the int13 parameters */
  112.   unsigned int buf, len, unit ;
  113.   unsigned long sect ;
  114.   {
  115.   unsigned int i, j ;
  116.   unsigned int dskheads, dsksects ;
  117.   union
  118.     {
  119.     unsigned char ch[4] ;
  120.     unsigned int ii[2] ;
  121.     unsigned long longval ;
  122.     }  temp   ;
  123.   segread(&segregs) ;
  124.   segregs.es=segregs.ds ;    /* setup segments for int13 call */
  125.   regs.h.al=len ;       /* number of sectors */
  126.   temp.longval=0l;
  127.   dskheads=romtbls[unit].heads&255;
  128.   dsksects=romtbls[unit].sectors&255;
  129.   i=temp.ii[0]=dskheads*dsksects ;
  130.   if(i==0)return(2);         /* no valid disk unit */
  131.   temp.longval=sect/temp.longval ;
  132.   regs.h.ch=temp.ch[0] ; /* lsb of cylinder number */
  133.   regs.h.cl=temp.ch[1]<<6 ; /* msb of cylinder number */
  134.   temp.longval=0l;
  135.   temp.ii[0]=i;
  136.   temp.longval=sect%temp.longval ; /* get remainder */
  137.   j=temp.ii[0];
  138.   temp.ii[0]=j/dsksects; /* head number */
  139.   regs.h.dl=romtbls[unit].unitno;
  140.   regs.h.dh=temp.ch[0] ;
  141.   temp.ii[0]=j%dsksects+1;
  142.   regs.h.cl|=temp.ch[0] ;  /* put in sector number */
  143.   regs.x.bx=buf ;
  144.   return (0);
  145.   }
  146.  
  147. doformat (unit,interleave)   /* issue the format command to the drive */
  148.   int unit,interleave ;
  149.   {
  150.   int i ;
  151.   do
  152.     {
  153.     regs.x.ax=0x700+interleave;
  154.     regs.h.dl=romtbls[unit].unitno ; /* set up the unit number */
  155.     int86x (0x13,®s,®s,&segregs) ;
  156.     i=err_13(unit,2) ; /* get error message */
  157.     } while (i==1) ;
  158.   return (i) ;
  159.   }
  160.  
  161. domodesel (buf,unit)   /* issue the mode select command to drive */
  162.   int unit ;
  163.   {
  164.   int i ;
  165.   do
  166.     {
  167.     regs.x.ax=0x500 ;
  168.     regs.h.dl=romtbls[unit].unitno ; /* set up the unit number */
  169.     segread(&segregs) ;
  170.     segregs.es=segregs.ds ;    /* setup segments for int13 call */
  171.     regs.x.bx=buf ;
  172.     int86x (0x13,®s,®s,&segregs) ;
  173.     i=err_13(unit,4) ; /* get error message */
  174.     } while (i==1) ;
  175.   return (i) ;
  176.   }
  177.  
  178. dofmtcyl (buf,unit,interleave,cd) /* issue the format command to drive */
  179.   int unit ;
  180.   int buf;
  181.   int interleave;
  182.   char cd ;         /* code for format type */
  183.   {
  184.   int i ;
  185.   do
  186.     {
  187.     regs.x.ax=0x600+interleave ;
  188.     regs.h.dl=romtbls[unit].unitno ; /* set up the unit number */
  189.     regs.h.dh=cd;
  190.     segread(&segregs) ;
  191.     segregs.es=segregs.ds ;    /* setup segments for int13 call */
  192.     regs.x.bx=buf ;
  193.     int86x (0x13,®s,®s,&segregs) ;
  194.     i=err_13(unit,3) ; /* get error message */
  195.     } while (i==1) ;
  196.   return (i) ;
  197.   }
  198.  
  199. long rdcaptot (unit)   /* get total capacity read again with mode info */
  200.   int unit ;
  201.   {
  202.   int i ;
  203.   union
  204.     {
  205.     unsigned int ii[2] ;
  206.     unsigned long longval ;
  207.     }  temp   ;
  208.   do
  209.     {
  210.     regs.x.ax=0x1900 ;
  211.     regs.h.dl=romtbls[unit].unitno ; /* set up the unit number */
  212.     int86x (0x13,®s,®s,&segregs) ;
  213.     if(regs.h.al!=0)i=err_13(unit,5) ;      /* get error response */
  214.     else i=0;
  215.     temp.ii[0]=regs.x.dx ;
  216.     temp.ii[1]=regs.x.cx ;
  217.     } while (i==1) ;
  218.   if(i!=0)temp.longval=0l; /* on error, return length of 0 */
  219.   return (temp.longval) ;
  220.   }
  221.  
  222. err_13 (unit,rwcode)  /* get operator response for int 13 request */
  223.               /* return 0=no error
  224.              1=repeat
  225.              2=abort */
  226.   int unit,rwcode ;
  227.   {
  228.   int row,col ;
  229.   int i,k,j;
  230.   char msgline [70] ; /* build message line */
  231.   int ierr ;
  232. /******************************************************************************
  233. *THE ROM BIOS ERROR TYPE CODES ARE CONVERTED TO DOS ERROR CODES.  THE CONVER-
  234. *  SION IS AS FOLLOWS:
  235. *        03 - WRITE PROTECT (00)
  236. *        20 - UNKNOWN UNIT (01)
  237. *        FF - NOT READY (02)
  238. *        80 - NOT READY (02)
  239. *        01 - UNKNOWN COMMAND (03)
  240. *        10 - CRC ERROR (04)
  241. *        BB - BAD DRIVE REQUEST (05)
  242. *        40 - SEEK ERROR (06)
  243. *        04 - SECTOR NOT FOUND (08)
  244. *        0B - WRITE FAULT (0A)
  245. *        02 - READ FAULT (0B)
  246. *        07 - GENERAL FAILURE (0C)
  247. *        11 - DATA CORRECTED NOT REPORTED AS AN ERROR
  248. *        06 - MEDIA CHANGE (0F)
  249. ******************************************************************************/
  250.   switch (regs.h.ah) /* decode ROM error to DOS error */
  251.     {
  252.     case 0x03:       /* write protect */
  253.       ierr = 0 ;
  254.       break ;
  255.     case 0x20:       /* unknown unit */
  256.       ierr = 1 ;
  257.       break ;
  258.     case 0xFF:       /* not ready */
  259.       ierr = 2 ;
  260.       break ;
  261.     case 0x80:       /* not ready */
  262.       ierr = 2 ;
  263.       break ;
  264.     case 0x01:       /* unknown command */
  265.       ierr = 3 ;
  266.       break ;
  267.     case 0x10:       /* CRC Error */
  268.       ierr = 4 ;
  269.       break ;
  270.     case 0xBB:       /* bad drive request */
  271.       ierr = 5 ;
  272.       break ;
  273.     case 0x40:       /* seek error */
  274.       ierr = 6 ;
  275.       break ;
  276.     case 0x04:       /* sector not found */
  277.       ierr = 8 ;
  278.       break ;
  279.     case 0x0B:       /* write fault */
  280.       ierr = 10;
  281.       break ;
  282.     case 0x02:       /* read fault */
  283.       ierr = 11;
  284.       break ;
  285.     case 0x07:       /* general failure */
  286.       ierr = 12;
  287.       break ;
  288.     case 0x06:       /* media change error */
  289.       ierr = 15;
  290.       break;
  291.     default  :
  292.       ierr = -1 ;
  293.     }
  294.   if (ierr==-1) return (0) ;   /* no error */
  295.   strcpy (msgline,dosmsg[ierr]) ;
  296.   if (rwcode==0) strcat (msgline," Reading") ;
  297.   if (rwcode==1) strcat (msgline," Writing" ) ;
  298.   if (rwcode==2) strcat (msgline," Formatting") ;
  299.   if (rwcode==3) strcat (msgline," Formatting") ;
  300.   if (rwcode==4) strcat (msgline," Mode Select") ;
  301.   if (rwcode==5) strcat (msgline," Drive Capacity") ;
  302.   strcat (msgline," Drive ") ;
  303.   col=strlen(msgline) ;
  304.   msgline[col]=(unit&255)+'1';
  305.   msgline[col+1]=0;
  306.   row=20;
  307.   col=39-col/2 ;
  308.   printf("%s\n",msgline) ;
  309.   j=-1 ;
  310.   do
  311.     {
  312.     printf ("%s",resp13);
  313.     i = bdos (8,0,0) & 255  ;  /* input character from keyboard */
  314.     if(i==0)bdos(8,0,0);
  315.     msgline[0]=i ;
  316.     msgline[1]=8 ;
  317.     msgline[2]=0;
  318.     if(msgline[0]>0x1f)printf("%s\n",msgline) ; /* response character */
  319.     if(i==esc) j=2 ;
  320.     i|=0x20 ; /* eliminate case */
  321.     if (i==0x61) j=2 ; /* return 2 on abort */
  322.     if (i==0x69) j=0 ; /* return 0 on ignore */
  323.     if (i==0x72) j=1 ; /* return 1 on retry */
  324.     } while (j==-1) ;
  325.   return (j) ;
  326.   }
  327.  
  328. drive_ck ()       /* check for presence of SCSI drives in the system */
  329.   {
  330.   union
  331.     {
  332.     unsigned char (far *pointc) [] ;
  333.     int (far *point) [] ;
  334.     int ivalue[2]    ;
  335.     long value        ;
  336.     } low_mem;
  337.   union
  338.     {
  339.     int intval [2] ;
  340.     unsigned char charval [4] ;
  341.     long longval ;
  342.     } cnvtr ;
  343.   int num,i,ok;
  344.   char icx ;
  345.   if ((bdos(0x30,0,0)&255)<3)
  346.     {
  347.     printf ("\nInvalid DOS Version.\n") ;
  348.     printf ("SCSI disk System Requires DOS 3.x or higher\n");
  349.     exit (0) ;
  350.     }
  351.   segread(&segregs) ;      /* setup segment registers */
  352.   segregs.es=segregs.ds ;
  353.   low_mem.value=0l     ;  /* initialize pointer */
  354.   icx=(*low_mem.pointc)[0x475] ; /* base drive number */
  355.   ok=0;
  356.   do
  357.     {
  358.     regs.h.dl=icx+0x80; /* base drive number */
  359.     regs.h.dh=0 ;
  360.     regs.x.ax=0x1800    ;  /* get drive id and number of them */
  361.     int86x (0x13,®s,®s,&segregs) ;
  362.     if((regs.x.ax==0x4321)&&(regs.h.cl==10))ok=1;
  363.     icx--;
  364.     } while ((icx>=0)&&(ok==0));
  365.   if (ok==0)
  366.     {
  367.     printf ("\nNo SCSI host adapter in the system!\n");
  368.     exit (0) ;
  369.     }
  370.   if (regs.h.bh==0)   /* check for any units reported */
  371.     {
  372.     printf ("\nNo SCSI drives reported in system!\n");
  373.     exit (0) ;
  374.     }
  375.   cnvtr.charval[0]=regs.h.bh ;
  376.   cnvtr.charval[1]=0 ;
  377.   physmax=cnvtr.intval[0] ;
  378.   cnvtr.charval[0]=regs.h.dl ;
  379.   cnvtr.charval[0]=cnvtr.charval[0]-regs.h.bl ;
  380.   physbase=cnvtr.intval[0];
  381.   for(i=0;i<physmax;i++)drivetbl(physbase+i,i); /* move all tables to local */
  382.   return (0) ;
  383.   }
  384.  
  385. drivetbl (romunit,physunit) /* update the internal structure with drive table */
  386.              /* romunit is the desired unit 80-8n */
  387.              /* physunit is the internal physical unit number */
  388.              /* the table is moved into the correct slot in
  389.                 romtbls.                      */
  390.   int romunit, physunit ;
  391.   {
  392.   int i ;
  393.   union
  394.     {
  395.     unsigned char (far *pointc) [] ;
  396.     int (far *point) [] ;
  397.     long value        ;
  398.     int ivalue [2]    ;
  399.     } rom_ptr ;
  400.   regs.x.dx=romunit ;  /* unit selection */
  401.   regs.x.ax=0x1B00    ;        /* get rom table pointer */
  402.   int86x (0x13,®s,®s,&segregs) ;
  403.   rom_ptr.ivalue[0]=regs.x.bx ;
  404.   rom_ptr.ivalue[1]=segregs.es ;
  405.   for (i=0;i<sizeof romtbls;i++) scratchbuf[i]=(*rom_ptr.pointc)[i];
  406.   mvstruct (&romtbls[physunit],&scratchbuf[0],sizeof romtbls);
  407.   romtbls[physunit].unitno=romunit ;  /* assign the unit number */
  408.   return (0) ;
  409.   }
  410.  
  411. mvstruct (ots, ins, size)   /* move whole structure */
  412.   unsigned char (*ots)[], (*ins)[];
  413.   int size ;
  414.   {
  415.   int i;
  416.   for (i=0; i<size; i++) (*ots)[i]=(*ins)[i] ;
  417.   return (0);
  418.   }
  419.