home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / i386 / stand / fd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-25  |  8.9 KB  |  351 lines

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Don Ahn.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  *    @(#)fd.c    7.3 (Berkeley) 5/25/91
  37.  */
  38.  
  39. /****************************************************************************/
  40. /*                        standalone fd driver                               */
  41. /****************************************************************************/
  42. #include "param.h"
  43. #include "dkbad.h"
  44. #include "i386/isa/disk.h"
  45. #include "i386/isa/fdreg.h"
  46. #include "i386/isa/isa.h"
  47. #include "saio.h"
  48.  
  49. #define NUMRETRY 10
  50. /*#define FDDEBUG*/
  51.  
  52. #define NFD 2
  53. #define FDBLK 512
  54. #define NUMTYPES 4
  55.  
  56. struct fd_type {
  57.     int    sectrac;        /* sectors per track         */
  58.     int    secsize;        /* size code for sectors     */
  59.     int    datalen;        /* data len when secsize = 0 */
  60.     int    gap;            /* gap len between sectors   */
  61.     int    tracks;            /* total num of tracks       */
  62.     int    size;            /* size of disk in sectors   */
  63.     int    steptrac;        /* steps per cylinder        */
  64.     int    trans;            /* transfer speed code       */
  65. };
  66.  
  67. struct fd_type fd_types[NUMTYPES] = {
  68.      { 18,2,0xFF,0x1B,80,2880,1,0 },    /* 1.44 meg HD 3.5in floppy    */
  69.     { 15,2,0xFF,0x1B,80,2400,1,0 },    /* 1.2 meg HD floppy           */
  70.     { 9,2,0xFF,0x23,40,720,2,1 },    /* 360k floppy in 1.2meg drive */
  71.     { 9,2,0xFF,0x2A,40,720,1,1 },    /* 360k floppy in DD drive     */
  72. };
  73.  
  74.  
  75. /* state needed for current transfer */
  76. static int fd_type;
  77. static int fd_motor;
  78. static int fd_retry;
  79. static int fd_drive;
  80. static int fd_status[7];
  81.  
  82. static int fdc = IO_FD1;    /* floppy disk base */
  83.  
  84. /* Make sure DMA buffer doesn't cross 64k boundary */
  85. char bounce[FDBLK];
  86.  
  87.  
  88. /****************************************************************************/
  89. /*                               fdstrategy                                 */
  90. /****************************************************************************/
  91. int
  92. fdstrategy(io,func)
  93. register struct iob *io;
  94. int func;
  95. {
  96.     char *address;
  97.     long nblocks,blknum;
  98.      int unit, iosize;
  99.  
  100. #ifdef FDDEBUG
  101. printf("fdstrat ");
  102. #endif
  103.     unit = io->i_unit;
  104.     fd_type = io->i_part;
  105.  
  106.     /*
  107.      * Set up block calculations.
  108.      */
  109.         iosize = io->i_cc / FDBLK;
  110.     blknum = (unsigned long) io->i_bn * DEV_BSIZE / FDBLK;
  111.      nblocks = fd_types[fd_type].size;
  112.     if ((blknum + iosize > nblocks) || blknum < 0) {
  113. #ifndef SMALL
  114.         printf("bn = %d; sectors = %d; type = %d; fssize = %d ",
  115.             blknum, iosize, fd_type, nblocks);
  116.                 printf("fdstrategy - I/O out of filesystem boundaries\n");
  117. #endif
  118.         return(-1);
  119.     }
  120.  
  121.     address = io->i_ma;
  122.         while (iosize > 0) {
  123.                 if (fdio(func, unit, blknum, address))
  124.                         return(-1);
  125.         iosize--;
  126.         blknum++;
  127.                 address += FDBLK;
  128.         }
  129.         return(io->i_cc);
  130. }
  131.  
  132. int
  133. fdio(func, unit, blknum, address)
  134. int func,unit,blknum;
  135. char *address;
  136. {
  137.     int i,j,cyl,sectrac,sec,head,numretry;
  138.     struct fd_type *ft;
  139.  
  140.      ft = &fd_types[fd_type];
  141. #ifdef FDDEBUG
  142. printf("fdio ");
  143. #endif
  144.  
  145.      sectrac = ft->sectrac;
  146.     cyl = blknum / (2 * sectrac);
  147.     numretry = NUMRETRY;
  148.  
  149.     if (func == F_WRITE) bcopy(address,bounce,FDBLK);
  150.  
  151. retry:
  152.     out_fdc(15);    /* Seek function */
  153.     out_fdc(unit);    /* Drive number */
  154.     out_fdc(cyl);
  155.  
  156.     waitio();
  157.  
  158.     out_fdc(0x8);
  159.     i = in_fdc(); j = in_fdc();
  160.     if (!(i&0x20) || (cyl != j)) {
  161.         numretry--;
  162.         if (numretry) goto retry;
  163. #ifndef SMALL
  164.         printf("Seek error %d, req = %d, at = %d\n",i,cyl,j);
  165.         printf("unit %d, type %d, sectrac %d, blknum %d\n",
  166.             unit,fd_type,sectrac,blknum);
  167. #endif
  168.         return -1;
  169.     }
  170.  
  171.     /* set up transfer */
  172.     fd_dma(func == F_READ, bounce, FDBLK);
  173.     sec = blknum %  (sectrac * 2);
  174.     head = sec / sectrac;
  175.     sec = sec % sectrac + 1;
  176. #ifdef FDDEBUG
  177.     printf("sec %d hd %d cyl %d ", sec, head, cyl);
  178. #endif
  179.  
  180.     if (func == F_READ)  out_fdc(0xE6);/* READ */
  181.     else out_fdc(0xC5);        /* WRITE */
  182.     out_fdc(head << 2 | fd_drive);    /* head & unit */
  183.     out_fdc(cyl);            /* track */
  184.     out_fdc(head);
  185.     out_fdc(sec);            /* sector XXX +1? */
  186.     out_fdc(ft->secsize);        /* sector size */
  187.     out_fdc(sectrac);        /* sectors/track */
  188.     out_fdc(ft->gap);        /* gap size */
  189.     out_fdc(ft->datalen);        /* data length */
  190.  
  191.     waitio();
  192.  
  193.     for(i=0;i<7;i++) {
  194.         fd_status[i] = in_fdc();
  195.     }
  196.     if (fd_status[0]&0xF8) {
  197.         numretry--;
  198.         if (numretry) goto retry;
  199. #ifndef SMALL
  200.         printf("FD err %lx %lx %lx %lx %lx %lx %lx\n",
  201.         fd_status[0], fd_status[1], fd_status[2], fd_status[3],
  202.         fd_status[4], fd_status[5], fd_status[6] );
  203. #endif
  204.         return -1;
  205.     }
  206.     if (func == F_READ) bcopy(bounce,address,FDBLK);
  207.     return 0;
  208. }
  209.  
  210. /****************************************************************************/
  211. /*                             fdc in/out                                   */
  212. /****************************************************************************/
  213. int
  214. in_fdc()
  215. {
  216.     int i;
  217.     while ((i = inb(fdc+fdsts) & 192) != 192) if (i == 128) return -1;
  218.     return inb(0x3f5);
  219. }
  220.  
  221. dump_stat()
  222. {
  223.     int i;
  224.     for(i=0;i<7;i++) {
  225.         fd_status[i] = in_fdc();
  226.         if (fd_status[i] < 0) break;
  227.     }
  228. #ifdef FDDEBUGx
  229. printf("FD bad status :%lx %lx %lx %lx %lx %lx %lx\n",
  230.     fd_status[0], fd_status[1], fd_status[2], fd_status[3],
  231.     fd_status[4], fd_status[5], fd_status[6] );
  232. #endif
  233. }
  234.  
  235. set_intr()
  236. {
  237.     /* initialize 8259's */
  238.     outb(0x20,0x11);
  239.     outb(0x21,32);
  240.     outb(0x21,4);
  241.     outb(0x21,1);
  242.     outb(0x21,0x0f); /* turn on int 6 */
  243.  
  244. /*
  245.     outb(0xa0,0x11);
  246.     outb(0xa1,40);
  247.     outb(0xa1,2);
  248.     outb(0xa1,1);
  249.     outb(0xa1,0xff); */
  250.  
  251. }
  252.  
  253.  
  254.  
  255. waitio()
  256. {
  257. char c;
  258. int n;
  259.  
  260.     do
  261.         outb(0x20,0xc); /* read polled interrupt */
  262.     while ((c=inb(0x20))&0x7f != 6); /* wait for int */
  263.     outb(0x20,0x20);
  264. }
  265.  
  266. out_fdc(x)
  267. int x;
  268. {
  269.     int r;
  270.     do {
  271.         r = (inb(fdc+fdsts) & 192);
  272.         if (r==128) break;
  273.         if (r==192) {
  274.             dump_stat(); /* error: direction. eat up output */
  275.         }
  276.     } while (1);
  277.     outb(0x3f5,x&0xFF);
  278. }
  279.  
  280.  
  281. /****************************************************************************/
  282. /*                           fdopen/fdclose                                 */
  283. /****************************************************************************/
  284. fdopen(io)
  285.     register struct iob *io;
  286. {
  287.     int unit, type, i;
  288.     struct fd_type *ft;
  289.  
  290.     unit = io->i_unit;
  291.     type = io->i_part;
  292.     io->i_boff = 0;        /* no disklabels -- tar/dump wont work */
  293. #ifdef FDDEBUG
  294.     printf("fdopen %d %d ", unit, type);
  295. #endif
  296.      ft = &fd_types[type];
  297.     fd_drive = unit;
  298.  
  299.     set_intr(); /* init intr cont */
  300.  
  301.     /* Try a reset, keep motor on */
  302.     outb(0x3f2,0);
  303.     for(i=0; i < 100000; i++);
  304.     outb(0x3f2,unit | (unit  ? 32 : 16) );
  305.     for(i=0; i < 100000; i++);
  306.     outb(0x3f2,unit | 0xC | (unit  ? 32 : 16) );
  307.     outb(0x3f7,ft->trans);
  308.     fd_motor = 1;
  309.  
  310.     waitio();
  311.  
  312.     out_fdc(3); /* specify command */
  313.     out_fdc(0xDF);
  314.     out_fdc(2);
  315.  
  316.     out_fdc(7);    /* Recalibrate Function */
  317.     out_fdc(unit);
  318.  
  319.     waitio();
  320.     return(0);
  321. }
  322.  
  323.  
  324. /****************************************************************************/
  325. /*                                 fd_dma                                   */
  326. /* set up DMA read/write operation and virtual address addr for nbytes      */
  327. /****************************************************************************/
  328. fd_dma(read,addr,nbytes)
  329. int read;
  330. unsigned long addr;
  331. int nbytes;
  332. {
  333.     /* Set read/write bytes */
  334.     if (read) {
  335.         outb(0xC,0x46); outb(0xB,0x46);
  336.     } else {
  337.         outb(0xC,0x4A); outb(0xB,0x4A);
  338.     }
  339.     /* Send start address */
  340.     outb(0x4,addr & 0xFF);
  341.     outb(0x4,(addr>>8) & 0xFF);
  342.     outb(0x81,(addr>>16) & 0xFF);
  343.     /* Send count */
  344.     nbytes--;
  345.     outb(0x5,nbytes & 0xFF);
  346.     outb(0x5,(nbytes>>8) & 0xFF);
  347.     /* set channel 2 */
  348.     outb(0x0A,2);
  349. }
  350.  
  351.