home *** CD-ROM | disk | FTP | other *** search
- /*-
- * 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 "dkbad.h"
- #include "i386/isa/disk.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
- #define NUMTYPES 4
-
- 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[NUMTYPES] = {
- { 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 */
- { 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 */
- };
-
-
- /* state needed for current transfer */
- 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;
- if ((blknum + iosize > nblocks) || blknum < 0) {
- #ifndef SMALL
- 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) {
- if (fdio(func, unit, blknum, address))
- return(-1);
- iosize--;
- blknum++;
- address += FDBLK;
- }
- return(io->i_cc);
- }
-
- int
- fdio(func, unit, blknum, address)
- int func,unit,blknum;
- char *address;
- {
- int i,j,cyl,sectrac,sec,head,numretry;
- struct fd_type *ft;
-
- ft = &fd_types[fd_type];
- #ifdef FDDEBUG
- printf("fdio ");
- #endif
-
- sectrac = ft->sectrac;
- cyl = blknum / (2 * sectrac);
- numretry = NUMRETRY;
-
- if (func == F_WRITE) bcopy(address,bounce,FDBLK);
-
- retry:
- 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--;
- if (numretry) goto retry;
- #ifndef SMALL
- 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);
- #endif
- return -1;
- }
-
- /* set up transfer */
- fd_dma(func == F_READ, bounce, FDBLK);
- sec = blknum % (sectrac * 2);
- 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 XXX +1? */
- 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 (numretry) goto retry;
- #ifndef SMALL
- 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] );
- #endif
- 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;
-
- 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[type];
- 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();
- return(0);
- }
-
-
- /****************************************************************************/
- /* 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);
- }
-
-