|
|
1.1 ! root 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.