|
|
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: *
1.1.1.4 ! root 36: * from: @(#)fd.c 7.3 (Berkeley) 5/25/91
! 37: * fd.c,v 1.2 1993/05/22 08:02:14 cgd Exp
1.1 root 38: */
39:
40: /****************************************************************************/
41: /* standalone fd driver */
42: /****************************************************************************/
43: #include "param.h"
1.1.1.2 root 44: #include "disklabel.h"
1.1 root 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:
1.1.1.2 root 55: extern struct disklabel disklabel;
56:
1.1 root 57: struct fd_type {
58: int sectrac; /* sectors per track */
59: int secsize; /* size code for sectors */
60: int datalen; /* data len when secsize = 0 */
61: int gap; /* gap len between sectors */
62: int tracks; /* total num of tracks */
63: int size; /* size of disk in sectors */
64: int steptrac; /* steps per cylinder */
65: int trans; /* transfer speed code */
66: };
67:
1.1.1.3 root 68: struct fd_type fd_types[] = {
1.1 root 69: { 18,2,0xFF,0x1B,80,2880,1,0 }, /* 1.44 meg HD 3.5in floppy */
70: { 15,2,0xFF,0x1B,80,2400,1,0 }, /* 1.2 meg HD floppy */
1.1.1.3 root 71: /* need 720K 3.5in here as well */
72: #ifdef noway
1.1 root 73: { 9,2,0xFF,0x23,40,720,2,1 }, /* 360k floppy in 1.2meg drive */
74: { 9,2,0xFF,0x2A,40,720,1,1 }, /* 360k floppy in DD drive */
1.1.1.3 root 75: #endif
1.1 root 76: };
77:
78:
79: /* state needed for current transfer */
1.1.1.3 root 80: static int probetype;
1.1 root 81: static int fd_type;
82: static int fd_motor;
83: static int fd_retry;
84: static int fd_drive;
85: static int fd_status[7];
86:
87: static int fdc = IO_FD1; /* floppy disk base */
88:
89: /* Make sure DMA buffer doesn't cross 64k boundary */
90: char bounce[FDBLK];
91:
92:
93: /****************************************************************************/
94: /* fdstrategy */
95: /****************************************************************************/
96: int
97: fdstrategy(io,func)
98: register struct iob *io;
99: int func;
100: {
101: char *address;
102: long nblocks,blknum;
103: int unit, iosize;
104:
105: #ifdef FDDEBUG
106: printf("fdstrat ");
107: #endif
108: unit = io->i_unit;
1.1.1.3 root 109: /*fd_type = io->i_part;*/
1.1 root 110:
111: /*
112: * Set up block calculations.
113: */
114: iosize = io->i_cc / FDBLK;
115: blknum = (unsigned long) io->i_bn * DEV_BSIZE / FDBLK;
1.1.1.3 root 116: nblocks = fd_types[fd_type].size /* disklabel.d_secperunit */;
1.1 root 117: if ((blknum + iosize > nblocks) || blknum < 0) {
1.1.1.3 root 118: #ifdef nope
1.1 root 119: printf("bn = %d; sectors = %d; type = %d; fssize = %d ",
120: blknum, iosize, fd_type, nblocks);
121: printf("fdstrategy - I/O out of filesystem boundaries\n");
122: #endif
123: return(-1);
124: }
125:
126: address = io->i_ma;
127: while (iosize > 0) {
1.1.1.2 root 128: /*printf("iosize %d ", iosize);*/
1.1 root 129: if (fdio(func, unit, blknum, address))
130: return(-1);
131: iosize--;
132: blknum++;
133: address += FDBLK;
134: }
135: return(io->i_cc);
136: }
137:
1.1.1.3 root 138: int ccyl = -1;
139:
1.1 root 140: int
141: fdio(func, unit, blknum, address)
142: int func,unit,blknum;
143: char *address;
144: {
1.1.1.3 root 145: int i,j, cyl, sectrac,sec,head,numretry;
1.1 root 146: struct fd_type *ft;
147:
1.1.1.2 root 148: /*printf("fdio ");*/
1.1 root 149: ft = &fd_types[fd_type];
150:
1.1.1.3 root 151: sectrac = ft->sectrac;
152: cyl = blknum / (sectrac*2);
1.1 root 153: numretry = NUMRETRY;
154:
1.1.1.3 root 155: if (func == F_WRITE)
156: bcopy(address,bounce,FDBLK);
1.1 root 157:
158: retry:
1.1.1.3 root 159: if (ccyl != cyl) {
1.1 root 160: out_fdc(15); /* Seek function */
161: out_fdc(unit); /* Drive number */
162: out_fdc(cyl);
163:
164: waitio();
1.1.1.3 root 165: }
1.1 root 166:
167: out_fdc(0x8);
168: i = in_fdc(); j = in_fdc();
169: if (!(i&0x20) || (cyl != j)) {
170: numretry--;
1.1.1.3 root 171: ccyl = j;
1.1 root 172: if (numretry) goto retry;
1.1.1.3 root 173:
1.1 root 174: printf("Seek error %d, req = %d, at = %d\n",i,cyl,j);
175: printf("unit %d, type %d, sectrac %d, blknum %d\n",
176: unit,fd_type,sectrac,blknum);
1.1.1.3 root 177:
1.1 root 178: return -1;
179: }
1.1.1.3 root 180: ccyl = cyl;
1.1 root 181:
182: /* set up transfer */
183: fd_dma(func == F_READ, bounce, FDBLK);
1.1.1.3 root 184: sec = blknum % (sectrac * 2) /*disklabel.d_secpercyl*/;
1.1 root 185: head = sec / sectrac;
186: sec = sec % sectrac + 1;
187: #ifdef FDDEBUG
188: printf("sec %d hd %d cyl %d ", sec, head, cyl);
189: #endif
190:
191: if (func == F_READ) out_fdc(0xE6);/* READ */
192: else out_fdc(0xC5); /* WRITE */
193: out_fdc(head << 2 | fd_drive); /* head & unit */
194: out_fdc(cyl); /* track */
195: out_fdc(head);
1.1.1.3 root 196: out_fdc(sec); /* sector */
1.1 root 197: out_fdc(ft->secsize); /* sector size */
198: out_fdc(sectrac); /* sectors/track */
199: out_fdc(ft->gap); /* gap size */
200: out_fdc(ft->datalen); /* data length */
201:
202: waitio();
203:
204: for(i=0;i<7;i++) {
205: fd_status[i] = in_fdc();
206: }
207: if (fd_status[0]&0xF8) {
208: numretry--;
1.1.1.3 root 209:
210: if (!probetype)
211: printf("FD err %lx %lx %lx %lx %lx %lx %lx\n",
212: fd_status[0], fd_status[1], fd_status[2], fd_status[3],
213: fd_status[4], fd_status[5], fd_status[6] );
1.1.1.2 root 214: if (numretry) goto retry;
1.1 root 215: return -1;
216: }
1.1.1.3 root 217: if (func == F_READ)
218: bcopy(bounce,address,FDBLK);
1.1 root 219: return 0;
220: }
221:
222: /****************************************************************************/
223: /* fdc in/out */
224: /****************************************************************************/
225: int
226: in_fdc()
227: {
228: int i;
229: while ((i = inb(fdc+fdsts) & 192) != 192) if (i == 128) return -1;
230: return inb(0x3f5);
231: }
232:
233: dump_stat()
234: {
235: int i;
236: for(i=0;i<7;i++) {
237: fd_status[i] = in_fdc();
238: if (fd_status[i] < 0) break;
239: }
240: #ifdef FDDEBUGx
241: printf("FD bad status :%lx %lx %lx %lx %lx %lx %lx\n",
242: fd_status[0], fd_status[1], fd_status[2], fd_status[3],
243: fd_status[4], fd_status[5], fd_status[6] );
244: #endif
245: }
246:
247: set_intr()
248: {
249: /* initialize 8259's */
250: outb(0x20,0x11);
251: outb(0x21,32);
252: outb(0x21,4);
253: outb(0x21,1);
254: outb(0x21,0x0f); /* turn on int 6 */
255:
256: /*
257: outb(0xa0,0x11);
258: outb(0xa1,40);
259: outb(0xa1,2);
260: outb(0xa1,1);
261: outb(0xa1,0xff); */
262:
263: }
264:
265:
266:
267: waitio()
268: {
269: char c;
270: int n;
271:
272: do
273: outb(0x20,0xc); /* read polled interrupt */
274: while ((c=inb(0x20))&0x7f != 6); /* wait for int */
275: outb(0x20,0x20);
276: }
277:
278: out_fdc(x)
279: int x;
280: {
281: int r;
282: do {
283: r = (inb(fdc+fdsts) & 192);
284: if (r==128) break;
285: if (r==192) {
286: dump_stat(); /* error: direction. eat up output */
287: }
288: } while (1);
289: outb(0x3f5,x&0xFF);
290: }
291:
292:
293: /****************************************************************************/
294: /* fdopen/fdclose */
295: /****************************************************************************/
296: fdopen(io)
297: register struct iob *io;
298: {
299: int unit, type, i;
300: struct fd_type *ft;
1.1.1.3 root 301: char buf[512];
1.1 root 302:
303: unit = io->i_unit;
1.1.1.3 root 304: /* type = io->i_part; */
1.1 root 305: io->i_boff = 0; /* no disklabels -- tar/dump wont work */
306: #ifdef FDDEBUG
307: printf("fdopen %d %d ", unit, type);
308: #endif
1.1.1.3 root 309: ft = &fd_types[0];
1.1 root 310: fd_drive = unit;
311:
312: set_intr(); /* init intr cont */
313:
314: /* Try a reset, keep motor on */
315: outb(0x3f2,0);
316: for(i=0; i < 100000; i++);
317: outb(0x3f2,unit | (unit ? 32 : 16) );
318: for(i=0; i < 100000; i++);
319: outb(0x3f2,unit | 0xC | (unit ? 32 : 16) );
320: outb(0x3f7,ft->trans);
321: fd_motor = 1;
322:
323: waitio();
324:
325: out_fdc(3); /* specify command */
326: out_fdc(0xDF);
327: out_fdc(2);
328:
329: out_fdc(7); /* Recalibrate Function */
330: out_fdc(unit);
331:
332: waitio();
1.1.1.3 root 333: probetype = 1;
334: for (fd_type = 0; fd_type < sizeof(fd_types)/sizeof(fd_types[0]);
335: fd_type++, ft++) {
336: /*for(i=0; i < 100000; i++);
337: outb(0x3f7,ft->trans);
338: for(i=0; i < 100000; i++);*/
339: if (fdio(F_READ, unit, ft->sectrac-1, buf) >= 0){
340: probetype = 0;
341: return(0);
342: }
343: }
344: printf("failed fdopen");
345: return(-1);
1.1 root 346: }
347:
348:
349: /****************************************************************************/
350: /* fd_dma */
351: /* set up DMA read/write operation and virtual address addr for nbytes */
352: /****************************************************************************/
353: fd_dma(read,addr,nbytes)
354: int read;
355: unsigned long addr;
356: int nbytes;
357: {
358: /* Set read/write bytes */
359: if (read) {
360: outb(0xC,0x46); outb(0xB,0x46);
361: } else {
362: outb(0xC,0x4A); outb(0xB,0x4A);
363: }
364: /* Send start address */
365: outb(0x4,addr & 0xFF);
366: outb(0x4,(addr>>8) & 0xFF);
367: outb(0x81,(addr>>16) & 0xFF);
368: /* Send count */
369: nbytes--;
370: outb(0x5,nbytes & 0xFF);
371: outb(0x5,(nbytes>>8) & 0xFF);
372: /* set channel 2 */
373: outb(0x0A,2);
374: }
375:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.