386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Sun, 28 Jun 1992 21:39:07 +0000 (13:39 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Sun, 28 Jun 1992 21:39:07 +0000 (13:39 -0800)
Work on file usr/src/sys.386bsd/i386/stand/fd.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/src/sys.386bsd/i386/stand/fd.c [new file with mode: 0644]

diff --git a/usr/src/sys.386bsd/i386/stand/fd.c b/usr/src/sys.386bsd/i386/stand/fd.c
new file mode 100644 (file)
index 0000000..f933b6b
--- /dev/null
@@ -0,0 +1,374 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Don Ahn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)fd.c        7.3 (Berkeley) 5/25/91
+ */
+
+/****************************************************************************/
+/*                        standalone fd driver                               */
+/****************************************************************************/
+#include "param.h"
+#include "disklabel.h"
+#include "i386/isa/fdreg.h"
+#include "i386/isa/isa.h"
+#include "saio.h"
+
+#define NUMRETRY 10
+/*#define FDDEBUG*/
+
+#define NFD 2
+#define FDBLK 512
+
+extern struct disklabel disklabel;
+
+struct fd_type {
+       int     sectrac;                /* sectors per track         */
+       int     secsize;                /* size code for sectors     */
+       int     datalen;                /* data len when secsize = 0 */
+       int     gap;                    /* gap len between sectors   */
+       int     tracks;                 /* total num of tracks       */
+       int     size;                   /* size of disk in sectors   */
+       int     steptrac;               /* steps per cylinder        */
+       int     trans;                  /* transfer speed code       */
+};
+
+struct fd_type fd_types[] = {
+       { 18,2,0xFF,0x1B,80,2880,1,0 }, /* 1.44 meg HD 3.5in floppy    */
+       { 15,2,0xFF,0x1B,80,2400,1,0 }, /* 1.2 meg HD floppy           */
+       /* need 720K 3.5in here as well */
+#ifdef noway
+       { 9,2,0xFF,0x23,40,720,2,1 },   /* 360k floppy in 1.2meg drive */
+       { 9,2,0xFF,0x2A,40,720,1,1 },   /* 360k floppy in DD drive     */
+#endif
+};
+
+
+/* state needed for current transfer */
+static int probetype;
+static int fd_type;
+static int fd_motor;
+static int fd_retry;
+static int fd_drive;
+static int fd_status[7];
+
+static int fdc = IO_FD1;       /* floppy disk base */
+
+/* Make sure DMA buffer doesn't cross 64k boundary */
+char bounce[FDBLK];
+
+
+/****************************************************************************/
+/*                               fdstrategy                                 */
+/****************************************************************************/
+int
+fdstrategy(io,func)
+register struct iob *io;
+int func;
+{
+       char *address;
+       long nblocks,blknum;
+       int unit, iosize;
+
+#ifdef FDDEBUG
+printf("fdstrat ");
+#endif
+       unit = io->i_unit;
+       /*fd_type = io->i_part;*/
+
+       /*
+        * Set up block calculations.
+        */
+        iosize = io->i_cc / FDBLK;
+       blknum = (unsigned long) io->i_bn * DEV_BSIZE / FDBLK;
+       nblocks = fd_types[fd_type].size /*  disklabel.d_secperunit */;
+       if ((blknum + iosize > nblocks) || blknum < 0) {
+#ifdef nope
+               printf("bn = %d; sectors = %d; type = %d; fssize = %d ",
+                       blknum, iosize, fd_type, nblocks);
+                printf("fdstrategy - I/O out of filesystem boundaries\n");
+#endif
+               return(-1);
+       }
+
+       address = io->i_ma;
+        while (iosize > 0) {
+/*printf("iosize %d ", iosize);*/
+                if (fdio(func, unit, blknum, address))
+                        return(-1);
+               iosize--;
+               blknum++;
+                address += FDBLK;
+        }
+        return(io->i_cc);
+}
+
+int ccyl = -1;
+
+int
+fdio(func, unit, blknum, address)
+int func,unit,blknum;
+char *address;
+{
+       int i,j, cyl, sectrac,sec,head,numretry;
+       struct fd_type *ft;
+
+/*printf("fdio ");*/
+       ft = &fd_types[fd_type];
+
+       sectrac = ft->sectrac;
+       cyl = blknum / (sectrac*2);
+       numretry = NUMRETRY;
+
+       if (func == F_WRITE)
+               bcopy(address,bounce,FDBLK);
+
+retry:
+       if (ccyl != cyl) {
+       out_fdc(15);    /* Seek function */
+       out_fdc(unit);  /* Drive number */
+       out_fdc(cyl);
+
+       waitio();
+       }
+
+       out_fdc(0x8);
+       i = in_fdc(); j = in_fdc();
+       if (!(i&0x20) || (cyl != j)) {
+               numretry--;
+               ccyl = j;
+               if (numretry) goto retry;
+
+               printf("Seek error %d, req = %d, at = %d\n",i,cyl,j);
+               printf("unit %d, type %d, sectrac %d, blknum %d\n",
+                       unit,fd_type,sectrac,blknum);
+
+               return -1;
+       }
+       ccyl = cyl;
+
+       /* set up transfer */
+       fd_dma(func == F_READ, bounce, FDBLK);
+       sec = blknum %  (sectrac * 2) /*disklabel.d_secpercyl*/;
+       head = sec / sectrac;
+       sec = sec % sectrac + 1;
+#ifdef FDDEBUG
+       printf("sec %d hd %d cyl %d ", sec, head, cyl);
+#endif
+
+       if (func == F_READ)  out_fdc(0xE6);/* READ */
+       else out_fdc(0xC5);             /* WRITE */
+       out_fdc(head << 2 | fd_drive);  /* head & unit */
+       out_fdc(cyl);                   /* track */
+       out_fdc(head);
+       out_fdc(sec);                   /* sector */
+       out_fdc(ft->secsize);           /* sector size */
+       out_fdc(sectrac);               /* sectors/track */
+       out_fdc(ft->gap);               /* gap size */
+       out_fdc(ft->datalen);           /* data length */
+
+       waitio();
+
+       for(i=0;i<7;i++) {
+               fd_status[i] = in_fdc();
+       }
+       if (fd_status[0]&0xF8) {
+               numretry--;
+
+               if (!probetype)
+                       printf("FD err %lx %lx %lx %lx %lx %lx %lx\n",
+                       fd_status[0], fd_status[1], fd_status[2], fd_status[3],
+                       fd_status[4], fd_status[5], fd_status[6] );
+               if (numretry) goto retry;
+               return -1;
+       }
+       if (func == F_READ)
+               bcopy(bounce,address,FDBLK);
+       return 0;
+}
+
+/****************************************************************************/
+/*                             fdc in/out                                   */
+/****************************************************************************/
+int
+in_fdc()
+{
+       int i;
+       while ((i = inb(fdc+fdsts) & 192) != 192) if (i == 128) return -1;
+       return inb(0x3f5);
+}
+
+dump_stat()
+{
+       int i;
+       for(i=0;i<7;i++) {
+               fd_status[i] = in_fdc();
+               if (fd_status[i] < 0) break;
+       }
+#ifdef FDDEBUGx
+printf("FD bad status :%lx %lx %lx %lx %lx %lx %lx\n",
+       fd_status[0], fd_status[1], fd_status[2], fd_status[3],
+       fd_status[4], fd_status[5], fd_status[6] );
+#endif
+}
+
+set_intr()
+{
+       /* initialize 8259's */
+       outb(0x20,0x11);
+       outb(0x21,32);
+       outb(0x21,4);
+       outb(0x21,1);
+       outb(0x21,0x0f); /* turn on int 6 */
+
+/*
+       outb(0xa0,0x11);
+       outb(0xa1,40);
+       outb(0xa1,2);
+       outb(0xa1,1);
+       outb(0xa1,0xff); */
+
+}
+
+
+
+waitio()
+{
+char c;
+int n;
+
+       do
+               outb(0x20,0xc); /* read polled interrupt */
+       while ((c=inb(0x20))&0x7f != 6); /* wait for int */
+       outb(0x20,0x20);
+}
+
+out_fdc(x)
+int x;
+{
+       int r;
+       do {
+               r = (inb(fdc+fdsts) & 192);
+               if (r==128) break;
+               if (r==192) {
+                       dump_stat(); /* error: direction. eat up output */
+               }
+       } while (1);
+       outb(0x3f5,x&0xFF);
+}
+
+
+/****************************************************************************/
+/*                           fdopen/fdclose                                 */
+/****************************************************************************/
+fdopen(io)
+       register struct iob *io;
+{
+       int unit, type, i;
+       struct fd_type *ft;
+       char buf[512];
+
+       unit = io->i_unit;
+       /* type = io->i_part; */
+       io->i_boff = 0;         /* no disklabels -- tar/dump wont work */
+#ifdef FDDEBUG
+       printf("fdopen %d %d ", unit, type);
+#endif
+       ft = &fd_types[0];
+       fd_drive = unit;
+
+       set_intr(); /* init intr cont */
+
+       /* Try a reset, keep motor on */
+       outb(0x3f2,0);
+       for(i=0; i < 100000; i++);
+       outb(0x3f2,unit | (unit  ? 32 : 16) );
+       for(i=0; i < 100000; i++);
+       outb(0x3f2,unit | 0xC | (unit  ? 32 : 16) );
+       outb(0x3f7,ft->trans);
+       fd_motor = 1;
+
+       waitio();
+
+       out_fdc(3); /* specify command */
+       out_fdc(0xDF);
+       out_fdc(2);
+
+       out_fdc(7);     /* Recalibrate Function */
+       out_fdc(unit);
+
+       waitio();
+       probetype = 1;
+       for (fd_type = 0; fd_type < sizeof(fd_types)/sizeof(fd_types[0]);
+               fd_type++, ft++) {
+               /*for(i=0; i < 100000; i++);
+               outb(0x3f7,ft->trans);
+               for(i=0; i < 100000; i++);*/
+               if (fdio(F_READ, unit, ft->sectrac-1, buf) >= 0){
+                       probetype = 0;
+                       return(0);
+               }
+       }
+       printf("failed fdopen");
+       return(-1);
+}
+
+
+/****************************************************************************/
+/*                                 fd_dma                                   */
+/* set up DMA read/write operation and virtual address addr for nbytes      */
+/****************************************************************************/
+fd_dma(read,addr,nbytes)
+int read;
+unsigned long addr;
+int nbytes;
+{
+       /* Set read/write bytes */
+       if (read) {
+               outb(0xC,0x46); outb(0xB,0x46);
+       } else {
+               outb(0xC,0x4A); outb(0xB,0x4A);
+       }
+       /* Send start address */
+       outb(0x4,addr & 0xFF);
+       outb(0x4,(addr>>8) & 0xFF);
+       outb(0x81,(addr>>16) & 0xFF);
+       /* Send count */
+       nbytes--;
+       outb(0x5,nbytes & 0xFF);
+       outb(0x5,(nbytes>>8) & 0xFF);
+       /* set channel 2 */
+       outb(0x0A,2);
+}
+