|
|
1.1 root 1: /* (-lgl
2: * COHERENT Device Driver Kit version 2.0.1.b
3: * Copyright (c) 1982, 1991, 1992 by Mark Williams Company.
4: * All rights reserved. May not be copied without permission.
5: -lgl) */
6: /*
7: * This is a driver for the IBM AT and "above"
8: * floppy drives, using interrupts and DMA on
9: * the NEC 756 floppy chip. Ugh.
10: * Handles single, double and quad
11: * density drives, 8, 9, 15 or 18 sectors per track.
12: * It wil NOT run on an XT; it requires the CMOS setup memory.
13: *
14: * Minor device assignments: xxuuhkkk
15: * uu - unit = 0/1/2/3
16: * kkk - kind, struct fdata infra.
17: * h - alternating head rather than side by side
18: *
19: */
20:
21: #include <sys/coherent.h>
22: #ifdef _I386
23: #include <sys/reg.h>
24: #else
25: #include <sys/i8086.h>
26: #endif
27: #include <sys/buf.h>
28: #include <sys/con.h>
29: #include <sys/stat.h>
30: #include <errno.h>
31: #include <sys/uproc.h>
32: #include <sys/proc.h>
33: #include <sys/fdioctl.h>
34: /*
35: * Additional internal commands not available
36: * to outside users:
37: */
38: #include <sys/sched.h>
39: #include <sys/dmac.h>
40: #include <sys/devices.h>
41: #include <sys/seg.h>
42: #include <sys/inode.h>
43:
44: #define BIT(n) (1 << (n))
45:
46: #define MAXDRVS 2 /* Maximum number of drives that we will support */
47: #define MAXSCTRS 21 /* Maximum acceptable sectors per track. It is */
48: /* possible to put as many as 10 sectors/track */
49: /* on low density diskettes, 18 sectors/track on */
50: /* 5 1/4" high-density diskettes, and 21 sectors */
51: /* per track on 3 1/2" high density diskettes. */
52: /* the maximum on "2.88" meg diskettes is not */
53: /* known as of this writing, but may be as high */
54: /* as 42. */
55: #define MAXTYPE 4 /* Maximum "type" value as set in the CMOS RAM. */
56: /* The current value of this is 4, the type for */
57: /* 1.44 meg diskettes. */
58:
59: #ifdef FL_XTRA
60: /* This is conditioned out for now due to end-of-volume problems. */
61: #define FL_CYL_2STEP 42
62: #define FL_CYL_HDLO 82
63: #define FL_CYL_HDHI 83
64: #else
65: #define FL_CYL_2STEP 40
66: #define FL_CYL_HDLO 80
67: #define FL_CYL_HDHI 80
68: #endif
69:
70: /*
71: * Patchable parameters.
72: */
73:
74: int fl_srt = 0xD; /* Floppy seek step rate, in unit -2 millisec */
75: /* NOT DIRECTLY ENCODED */
76: /* All drives HAVE to work at 5 msec/step, so */
77: /* they HAVE to work at 6 msec/step! (The use of */
78: /* 8 msec/step in the old PCs was just IBM being */
79: /* excessively conservative. MS/PC-DOS, starting with */
80: /* version 2.0, changes it to 6 msec/step. There */
81: /* are, in fact, lots of drives that will step at */
82: /* 4 msec/step, but there's no sense in pushing it.) */
83: int fl_hlt = 1; /* Floppy head load time, in unit 4 millisec */
84: int fl_hut = 0xF; /* Floppy head unload time, in unit 32 millisec */
85: int fl_disp = 0; /* If nonzero, print drive parameters on screen */
86:
87: /*
88: * Patchable variables for compatibility with IBM products:
89: *
90: * FL_DSK_CH_PROB - some machines always have the disk changed line turned on.
91: * Currently some PS/1's (Consultant, Professional - possibly most of them)
92: * have this problem, so the default value of zero assumes normal disk change
93: * line operation.
94: *
95: * FL_AUTO_PARM - Only try to autosense floppy parameters if this variable
96: * is nonzero. The PS/2-L40 floppy controller apparently has trouble changing
97: * from low density to high density. Missing address marks when reading
98: * a HD floppy are the symptom if FL_AUTO_PARM is set when it shouldn't be.
99: */
100: int FL_DSK_CH_PROB = 0;
101: int FL_AUTO_PARM = 0;
102:
103: static int jopen;
104:
105: /*
106: Here's the problem. We need to be able to tell if the disk has been changed.
107: There is an i/o port we can read, but on some systems, we can get constant
108: false positives. This causes massive floppy slowdown as the disk is constantly
109: recalibrating. The solution is not completely satisfactory, but it's the best
110: one I could come up with. Basically, what I said was since we can't tell when
111: the disk has changed, we will act as if it has changed every time we do an
112: open or a reset. The code
113:
114: if (FL_DSK_CH_PROB)
115: jopen = 2;
116:
117: indicates the need to pretend that the disk has changed. It is set to 2 since
118: there are two parts to the change procedure. Additional code dependent on
119: the value of FL_DSK_CH_PROB says that if we have not just down an open, then
120: we should skip the recal. Otherwise, decrement the counter, and do the
121: recal. - mlk */
122:
123: int flload();
124: int flunload();
125: void flopen();
126: int flclose();
127: int flblock();
128: int flread();
129: int flwrite();
130: int flioctl();
131: int fldelay();
132: int flintr();
133: int fltimeout();
134: int nulldev();
135:
136: void fldrvstatus();
137: CON flcon = {
138: DFBLK | DFCHR, /* Flags */
139: FL_MAJOR, /* Major index */
140: flopen, /* Open */
141: flclose, /* Close */
142: flblock, /* Block */
143: flread, /* Read */
144: flwrite, /* Write */
145: flioctl, /* Ioctl */
146: nulldev, /* Powerfail */
147: fltimeout, /* Timeout */
148: flload, /* Load */
149: flunload /* Unload */
150: };
151:
152: #define MTIMER 2 /* Motor timeout */
153: #define FDCDOR 0x3F2 /* Digital output */
154: #define FDCDAT 0x3F5 /* Data register */
155: #define FDCMSR 0x3F4 /* Main status register */
156: #define FDCRATE 0x3F7 /* Transfer rate (500,300,250 Kbps) */
157: #define FDCCHGL 0x3F7 /* Port where we read the disk */
158: /* changed line */
159: #define DSKCHGD 0x80 /* Diskette changed line bit. */
160:
161: #define DORDS 0x03 /* Drive select bits */
162: #define DORNMR 0x04 /* Not master reset */
163: #define DORIEN 0x08 /* Interrupt, DMA enable */
164: #define DORMS 0xF0 /* Motor enables */
165:
166: #define MSRDB 0x0F /* Drive busy */
167: #define MSRCB 0x10 /* Control busy */
168: #define MSRNDMA 0x20 /* Not DMA */
169: #define MSRDIO 0x40 /* Data direction */
170: #define MSRRQM 0x80 /* Request for master */
171:
172: /*
173: * Status Register 0 - Bit Definitions.
174: */
175: #define ST0_US0 0x01 /* Unit Select 0 */
176: #define ST0_US1 0x02 /* Unit Select 1 */
177: #define ST0_HD 0x04 /* Head Address */
178: #define ST0_NR 0x08 /* Not Ready */
179: #define ST0_EC 0x10 /* Equipment Check */
180: #define ST0_SE 0x20 /* Seek End */
181: #define ST0_IC 0xC0 /* Interrupt code */
182: #define ST0_NT 0x00 /* Normal Termination */
183:
184: /*
185: * Status Register 1 - Bit Definitions.
186: */
187: #define ST1_MA 0x01 /* Missing Address Mark */
188: #define ST1_NW 0x02 /* Not writeable */
189: #define ST1_ND 0x04 /* No Data */
190: /* 0x08 */ /* Not used - always 0 */
191: #define ST1_OR 0x10 /* Overrun */
192: #define ST1_DE 0x20 /* Data Error */
193: /* 0x40 */ /* Not used - always 0 */
194: #define ST1_EN 0x80 /* End of Cylinder */
195:
196: /*
197: * Status Register 2 - Bit Definitions.
198: */
199: #define ST2_MD 0x01 /* Missing Address Mark in Data Field */
200: #define ST2_BC 0x02 /* Bad Cylinder */
201: #define ST2_SN 0x04 /* Scan Not Satisfied */
202: #define ST2_SH 0x08 /* Scan Equal Hit */
203: #define ST2_WC 0x10 /* Wrong Cylinder */
204: #define ST2_DD 0x20 /* Data Error in Data Field */
205: #define ST2_CM 0x40 /* Control Mark */
206: /* 0x80 */ /* Not used - always 0 */
207:
208: /*
209: * Status Register 3 - Bit Definitions.
210: */
211: #define ST3_US0 0x01 /* Unit Select 0 */
212: #define ST3_US1 0x02 /* Unit Select 1 */
213: #define ST3_HD 0x04 /* Head Address */
214: #define ST3_TS 0x08 /* Two Sides */
215: #define ST3_T0 0x10 /* Track 0 */
216: #define ST3_RDY 0x20 /* Ready */
217: #define ST3_WP 0x40 /* Write Protected */
218: #define ST3_FT 0x80 /* Fault */
219:
220: /*
221: * Controller Commands.
222: */
223: #define CMDSPEC 0x03 /* Specify */
224: #define CMDRCAL 0x07 /* Recal */
225: #define CMDSEEK 0x0F /* Seek */
226: #define CMDRDAT 0x66 /* Read data */
227: #define CMDWDAT 0x45 /* Write data */
228: #define CMDSINT 0x08 /* Sense interrupt status */
229: #define CMDSDRV 0x04 /* Sense drive status */
230: #define CMDRDID 0x4A /* Read ID */
231: #define CMDFMT 0x4D /* Format track */
232:
233: /*
234: * Driver States.
235: */
236: #define SIDLE 0 /* Idle */
237: #define SSEEK 1 /* Need seek */
238: #define SRDWR 2 /* Need read/write command */
239: #define SENDIO 3 /* Need end I/O processing */
240: #define SDELAY 4 /* Delay before next disk operation */
241: #define SHDLY 5 /* Head settling delay before r/w */
242: #define SLOCK 6 /* Got DMA controller lock */
243: #define SRECAL1 7 /* First recalibrate attempt */
244: #define SRECAL2 8 /* Try seeking to track 2 */
245: #define SRECAL3 9 /* Second recalibrate, if necessary */
246: #define SGOTO2 10 /* After seek to cylinder 2 */
247: #define SRDID 11 /* Get sector ID from FDC */
248: #define SSIDTST 12 /* Testing # of sides */
249:
250: #define funit(x) (minor(x) >> 4) /* Unit/drive number */
251: #define fkind(x) (minor(x) & 0x7) /* Kind of format */
252: #define fhbyh(x) (minor(x) & 0x8) /* 0=Side by side, 1=Head by head */
253:
254: static /* Parameters for each kind of format */
255: struct FDATA {
256: int fd_size; /* Blocks per diskette */
257: int fd_nhds; /* Heads per drive */
258: int fd_trks; /* Tracks per side */
259: int fd_offs; /* Sector base */
260: int fd_nspt; /* Sectors per track */
261: char fd_GPL[4]; /* Controller gap param (indexed by rate) */
262: char fd_N; /* Controller size param */
263: char fd_FGPL; /* Format gap length */
264: } fdata[] = {
265: /* 8 sectors per track, surface by surface seek. */
266: { 320,1,40,0, 8, { 0x00,0x20,0x20 }, 2,0x58 }, /* Single sided */
267: { 640,2,40,0, 8, { 0x00,0x20,0x20 }, 2,0x58 }, /* Double sided */
268: { 1280,2,80,0, 8, { 0x00,0x20,0x20 }, 2,0x58 }, /* Quad density */
269: /* 9 sectors per track, surface by surface seek. */
270: { 360,1,40,0, 9, { 0x00,0x20,0x20 }, 2,0x50 }, /* Single sided */
271: { 720,2,40,0, 9, { 0x00,0x20,0x20 }, 2,0x50 }, /* Double sided */
272: { 1440,2,80,0, 9, { 0x00,0x20,0x20 }, 2,0x50 }, /* Quad density */
273: /* 15 sectors per track, surface by surface seek. */
274: { 2400,2,80,0,15, { 0x1B,0x00,0x00 }, 2,0x54 }, /* High capacity */
275: /* 18 sectors per track, surface by surface seek. */
276: { 2880,2,80,0,18, { 0x1B,0x00,0x00 }, 2,0x6C } /* 1.44 3.5" */
277: };
278:
279: static /* Parameters for each device type */
280: struct FRATES {
281: char fl_hi_kind; /* "fdata" initial try for hi dens. */
282: char fl_hi_rate; /* -1 here for lo-dens. */
283: char fl_lo_kind; /* Lo-dens "fdata" entry to try 1st.*/
284: char fl_lo_rate; /* Proper lo-density rate for type. */
285: char dflt_kind; /* Default parameters. */
286: char dflt_rate; /* Default data rate. */
287: } frates[] = {
288: { 4,-1, 4,-1, 4, 2 }, /* Type 0 = no drive */
289: { 4,-1, 4, 2, 4, 2 }, /* Type 1 = 360K */
290: { 6, 0, 4, 1, 6, 0 }, /* Type 2 = 1.2M */
291: { 4,-1, 5, 2, 5, 2 }, /* Type 3 = 720K */
292: { 7, 0, 5, 2, 7, 0 } /* Type 4 = 1.44M */
293: };
294:
295: static
296: struct FL {
297: BUF *fl_actf; /* Queue, forward */
298: BUF *fl_actl; /* Queue, backward */
299: paddr_t fl_addr; /* Address */
300: int fl_nsec; /* # of sectors */
301: int fl_secn; /* Current sector */
302: struct FDATA fl_fd[MAXDRVS]; /* Disk kind data */
303: int fl_fcyl; /* Floppy cylinder # */
304: int fl_2step[MAXDRVS]; /* =1 for double-stepping */
305: char fl_incal[MAXDRVS]; /* Disk in cal flags and current cyl */
306: char fl_dsk_chngd[MAXDRVS]; /* Diskette changed flags */
307: char fl_ndsk; /* # of drives */
308: char fl_unit; /* Current unit # */
309: char fl_selected_unit; /* Last unit selected */
310: char fl_mask; /* Handy unit mask */
311: char fl_hbyh; /* 0/1 = Side by side/Head by head */
312: char fl_nerr; /* Error count */
313: int fl_ncmdstat; /* Number of cmd status bytes recvd */
314: char fl_cmdstat[8]; /* Command Status buffer */
315: int fl_nintstat; /* Number of intr status bytes recvd */
316: char fl_intstat[4]; /* Interrupt Status buffer */
317: int fl_ndrvstat; /* Number of drv status bytes read */
318: char fl_drvstat[2]; /* Drive Status buffer */
319: int fl_fsec; /* Floppy sector # */
320: int fl_head; /* Floppy head */
321: char fl_state; /* Processing state */
322: char fl_mstatus; /* Motor status */
323: char fl_time[MAXDRVS]; /* Motor timeout */
324: char fl_rate[MAXDRVS]; /* Data rate: 500,300,250,?? kbps */
325: char fl_type[MAXDRVS]; /* Type of drive: 2 = HiCap */
326: char fl_rate_set; /* Currently set data rate */
327: int fl_wflag; /* Write operation */
328: int fl_recov; /* Recovery initiated */
329: int fl_opct[MAXDRVS]; /* open count for each unit */
330: int fl_we[MAXDRVS]; /* write enable for each unit */
331: } fl;
332:
333: /*
334: * We need some areas in global RAM to use as BUF structures
335: * and as data areas for special functions such as formatting,
336: * reading the drive status and reading sector IDs. There is
337: * one set for each drive. When the blocks for a drive are in
338: * use, the "drv_locked" char is set to non-zero, and is
339: * cleared otherwise. While this scheme doesn't provide
340: * complete reentrancy, it does allow both drives to be used
341: * "at once" by separate tasks.
342: */
343: static char drv_locked[MAXDRVS]; /* One for each possible drive */
344: static char sw3[MAXDRVS];
345: static BUF flbuf[MAXDRVS];
346: /*
347: * These next items are related to the floppy disk system
348: * in general, so we only need one of each.
349: */
350: static TIM fltim;
351: static TIM fldmalck; /* DMA lock deferred function structure. */
352: static char scratch_buffer[BSIZE];
353: static char fl_clrng_cd;
354: static char fl_intlv_ct, /* Counts sectors to find interleave. */
355: fl_get_intlv, /* =1 to start search for interleave. */
356: fl_lk4_id, /* Sector ID to look for for interleave. */
357: fl_alt_kind, /* Alternate disk parameter index and */
358: fl_alt_rate, /* data rate to use if not first value. */
359: fl_1st_ID, /* Detects when all track sectors scanned*/
360: fl_hi_ID; /* Highest sector ID read so far. */
361:
362: /*-------- DEBUG START ---------*/
363: #define FL_DEBUG 1
364: #if FL_DEBUG
365: #define PUSH3(a,b,c) push3(a,b,c)
366: #define POP3() pop3()
367:
368: #define XX 75
369:
370: static int A[XX], B[XX], C[XX];
371: static int xxp = 0; /* next avail index */
372:
373: static push3(a,b,c)
374: int a,b,c;
375: {
376: if (xxp < XX) {
377: A[xxp] = a;
378: B[xxp] = b;
379: C[xxp] = c;
380: xxp++;
381: }
382: }
383:
384: static pop3()
385: {
386: int i;
387:
388: printf("pop3: ");
389: for (i = 0; i < xxp; i++) {
390: printf("c5=%d 1st=%d hi=%d ", A[i], B[i], C[i]);
391: }
392: xxp = 0;
393: printf(":done ");
394: }
395: #else
396: #define PUSH3(a,b,c)
397: #define POP3()
398: #endif
399: /*-------- DEBUG END ---------*/
400:
401: /*
402: * The load routine asks the
403: * switches how many drives are present
404: * in the machine, and sets up the field
405: * in the floppy database. It also grabs
406: * the level 6 interrupt vector.
407: */
408: static
409: flload()
410: {
411: register int eflag;
412: register int s, t;
413:
414: fl_clrng_cd = 0;
415:
416: /*
417: * Ensure DMA channel 2 is turned off.
418: * The Computerland ROM does not disable DMA channel after autoboot
419: * from hard disk. The Western Digital controller board appears to
420: * send a dma burst when the floppy controller chip is reset.
421: */
422: dmaoff(2);
423:
424: /*
425: * Read floppy equipment byte from CMOS ram
426: * drive 0 is in high nibble, drive 1 is in low nibble.
427: */
428: outb(0x70, 0x10);
429: /* delay */
430: eflag = inb(0x71);
431:
432: /*
433: * Reinitialize patchable parameters for IBM AT.
434: */
435: fl_srt = 0xD; /* Floppy seek step rate, in unit -2 ms */
436: /* NOT DIRECTLY ENCODED */
437: fl_hlt = 25; /* Floppy head load time, in unit 4 ms */
438:
439: /*
440: * Define AT drive information.
441: */
442: fl.fl_type[0] = eflag >> 4;
443: fl.fl_type[1] = eflag & 15;
444: fl.fl_ndsk = 0;
445: for (s = 0; s < MAXDRVS; s++) {
446: drv_locked[s] = 0;
447: fl.fl_dsk_chngd[s] = 1;
448: fl.fl_incal[s] = -1;
449: t = fl.fl_type[s];
450: if (t > MAXTYPE) /* --in case we get, like, */
451: fl.fl_type[s] = t = MAXTYPE; /* a 2.88 meg drive. */
452: fl.fl_rate[s] = frates[t].dflt_rate;
453: fl.fl_fd[s] = fdata[frates[t].dflt_kind];
454: if (t) fl.fl_ndsk = s + 1; /* Type 0 = no drive. */
455:
456: if (FL_DSK_CH_PROB)
457: jopen = 2;
458: }
459:
460: fl.fl_rate_set = 0;
461:
462: /*
463: * Initialize the floppy disk controller (if we
464: * have any floppy drives).
465: */
466: if (fl.fl_ndsk) {
467:
468: s = sphi();
469:
470: outb(FDCDOR, 0);
471: setivec(6, &flintr);
472: /* "Not Reset FDC" must remain low for at least 14 clocks */
473: outb(FDCDOR, 0);
474: fl.fl_state = SIDLE;
475: outb(FDCDOR, DORNMR | DORIEN);
476:
477: fl.fl_mstatus = 0; /* No motors on */
478: fl.fl_selected_unit = -1; /* No unit selected */
479:
480: flspecify();
481: outb(FDCRATE, fl.fl_rate_set);
482:
483: spl(s);
484: }
485: }
486:
487: /*
488: * Release resources.
489: */
490: flunload()
491: {
492: /*
493: * Cancel timed function.
494: */
495: timeout(&fltim, 0, NULL, NULL);
496:
497: /*
498: * Cancel periodic (1 second) invocation.
499: */
500: drvl[FL_MAJOR].d_time = 0;
501:
502: /*
503: * Turn motors off.
504: */
505: outb(FDCDOR, DORNMR); /* Leave interrupts disabled. */
506:
507: /*
508: * Clear interrupt vector.
509: */
510: if (fl.fl_ndsk)
511: clrivec(6);
512: }
513:
514: /*
515: * The open routine screens out
516: * opens of illegal minor devices and
517: * performs the NEC specify command if
518: * this is the very first floppy disk
519: * open call.
520: */
521: static void
522: flopen(dev, mode)
523: dev_t dev;
524: int mode;
525: {
526: register int unit_number = funit(dev);
527: register int s;
528:
529: /*
530: * Validate existence and data rate (Gap length != 0).
531: */
532: if ((unit_number >= fl.fl_ndsk)
533: || (fl.fl_type[unit_number] == 0)
534: || (fdata[fkind(dev)].fd_GPL[flrate(dev)] == 0)) {
535: u.u_error = ENXIO;
536: goto badFlopen; /* status. */
537: }
538:
539: if (FL_DSK_CH_PROB)
540: jopen = 2;
541:
542: /*
543: * May need to write - see if diskette is write proteced.
544: * We do this with a "Sense Drive Status" command. Since
545: * this requires the use of the FDC, we have to schedule it
546: * like data transfer I/O or FORMAT even though it doesn't
547: * use the DMA.
548: */
549: if (fl.fl_opct[unit_number] == 0) { /* first open for this floppy */
550: if (drv_locked[unit_number]) { /* Work areas avail? */
551: u.u_error = EBUSY; /* No. */
552: goto badFlopen; /* status. */
553: } else {
554: drv_locked[unit_number] = 1; /* Grab work areas. */
555: flbuf[unit_number].b_dev = dev;
556: flbuf[unit_number].b_req = BFLSTAT;
557: sw3[unit_number] = 0;
558: /* Get drive status. */
559: s = flQhang(&flbuf[unit_number]);
560:
561: for (;;) {
562: s = sphi();
563: if (fl.fl_state == SIDLE)
564: flfsm();
565: spl(s);
566: if (sw3[unit_number])
567: break;
568: if (fl.fl_state != SIDLE)
569: #ifdef _I386
570: x_sleep(&fl.fl_state,
571: pridisk, slpriSigCatch, "flopen");
572: #else
573: v_sleep(&fl.fl_state,
574: CVBLKIO, IVBLKIO, SVBLKIO,
575: "flopen");
576: #endif
577: if (SELF->p_ssig && nondsig()) { /* signal? */
578: u.u_error = EINTR;
579: goto badFlopen;
580: }
581: }
582:
583: if (flbuf[unit_number].b_resid != 0) {
584: u.u_error = EDATTN; /* Couldn't get drive */
585: goto badFlopen; /* status. */
586: }
587:
588: /* The payoff - set write enable status. */
589: fl.fl_we[unit_number] =
590: ((sw3[unit_number] & ST3_WP)==0);
591: drv_locked[unit_number] = 0; /* Release work areas */
592: }
593:
594: /*
595: * If the drive is low density (no change line) we should
596: * flag the need to verify the disk format and density.
597: * High density drives (which are also dual density) have
598: * change lines that we can check each time we want to read
599: * the drive.
600: */
601: if (frates[fl.fl_type[unit_number]].fl_hi_rate == -1) {
602: fl.fl_incal[unit_number] = -1;
603: fl.fl_dsk_chngd[unit_number] = 1;
604:
605: if (FL_DSK_CH_PROB)
606: jopen = 2;
607: }
608: } /* end of first open stuff */
609:
610: /* If opening for write, volume must be write enabled. */
611: if ((mode & IPW) && !fl.fl_we[unit_number]) {
612: printf("fd%d: <Write Protected>\n", fl.fl_unit);
613: u.u_error = EROFS; /* Diskette write */
614: goto badFlopen; /* protected. */
615: }
616:
617: fl.fl_opct[unit_number]++;
618: badFlopen:
619: return;
620: }
621:
622: /*
623: * flclose()
624: */
625: static
626: flclose(dev, mode)
627: dev_t dev;
628: int mode;
629: {
630: register int unit_number = funit(dev);
631:
632: fl.fl_opct[unit_number]--;
633: }
634:
635: /*
636: * The read routine just calls
637: * off to the common raw I/O processing
638: * code, using a static buffer header in
639: * the driver.
640: */
641:
642: static
643: flread(dev, iop)
644:
645: dev_t dev;
646: IO *iop;
647:
648: {
649: dmareq(&flbuf[funit(dev)], iop, dev, BREAD);
650: }
651:
652: /*
653: * The write routine is just like the
654: * read routine, except that the function code
655: * is write instead of read.
656: */
657:
658: static
659: flwrite(dev, iop)
660:
661: dev_t dev;
662: IO *iop;
663:
664: {
665: dmareq(&flbuf[funit(dev)], iop, dev, BWRITE);
666: }
667:
668: /*
669: * The ioctl routine simply queues a format request
670: * using the flbuf for the specified drive.
671: * The only valid command is to format a track.
672: * The parameter block contains the header records supplied to the controller.
673: */
674:
675: static
676: flioctl(dev, com, par)
677: dev_t dev;
678: int com;
679: char *par;
680: {
681: register unsigned s;
682: register struct fdata *fdp;
683: unsigned hd, cyl;
684:
685: if (com != FDFORMAT) {
686: u.u_error = EINVAL;
687: return;
688: }
689:
690: fdp = &fdata[fkind(dev)]; /* Locate formatting */
691: cyl = getubd(par); /* parameters. */
692: hd = getubd(par+1);
693:
694: if (hd > 1 || cyl >= fdp->fd_trks) {
695: u.u_error = EINVAL;
696: return;
697: }
698:
699: /*
700: * The following may need some explanation.
701: * dmareq will:
702: * claim the buffer,
703: * bounds check the parameter buffer,
704: * lock the parameter buffer in memory,
705: * convert io_seek to b_bno,
706: * dispatch the request,
707: * wait for completion,
708: * and unlock the parameter buffer.
709: * The b_bno is reconverted to hd, cyl in flfsm.
710: */
711:
712: s = fhbyh(dev) ? (cyl * fdp->fd_nhds + hd) : (hd * fdp->fd_trks + cyl);
713: s *= fdp->fd_nspt;
714: u.u_io.io_seek = ((long)s) * BSIZE;
715: #ifdef _I386
716: u.u_io.io.vbase = par;
717: #else
718: u.u_io.io_base = par;
719: #endif
720: u.u_io.io_ioc = fdp->fd_nspt * 4;
721: dmareq(&flbuf[funit(dev)], &u.u_io, dev, BFLFMT);
722: return 0;
723: }
724:
725: /*
726: * Start up block I/O on a
727: * buffer. Check that the block number
728: * is not out of range, given the style of
729: * the disk. Put the buffer header into the
730: * device queue. Start up the disk if the
731: * device is idle.
732: */
733: static
734: flblock(bp)
735: register BUF *bp;
736: {
737: register int s;
738: register unsigned bno;
739:
740: /* Nasty implicit dependency on BSIZE == 2**9 */
741: bno = bp->b_bno + (bp->b_count >> 9) - 1;
742:
743: { /*DEBUG*/
744: int first = bp->b_bno, last = bno;
745: int fdatasz = fdata[fkind(bp->b_dev)].fd_size;
746: int fl_fdsz = fl.fl_fd[funit(bp->b_dev)].fd_size;
747: /*DEBUG*/
748:
749: if ((bp->b_req == BFLFMT)
750: && ((unsigned)bp->b_bno >= fdata[fkind(bp->b_dev)].fd_size)) {
751: bp->b_flag |= BFERR;
752: bdone(bp);
753: return;
754: }
755:
756: if (bp->b_req != BFLFMT) {
757: if ((unsigned)bp->b_bno >=
758: fl.fl_fd[funit(bp->b_dev)].fd_size) {
759: bp->b_flag |= BFERR;
760: bdone(bp);
761: return;
762: }
763: if (bno >= fl.fl_fd[funit(bp->b_dev)].fd_size) {
764: if (bp->b_flag & BFRAW) {
765: bp->b_flag |= BFERR;
766: }
767: bp->b_resid = bp->b_count;
768: bdone(bp); /* return w/ b_resid != 0 */
769: return;
770: }
771: if ((bp->b_count & 0x1FF) != 0) {
772: bp->b_flag |= BFERR;
773: bdone(bp);
774: return;
775: }
776: }
777: } /*DEBUG*/
778:
779: flQhang(bp); /* Put the block in the queue. */
780:
781: s = sphi();
782: if (fl.fl_state == SIDLE) /* --if necessary, to */
783: flfsm(); /* get things moving. */
784: spl(s);
785: }
786:
787: /*
788: * This routine hangs a BUF in the processing queue
789: */
790:
791: static
792: flQhang(bp)
793: register BUF *bp;
794: {
795: register int s = sphi(); /* No interrupts during chaining, please */
796:
797: bp->b_actf = NULL;
798:
799: if (fl.fl_actf == NULL)
800: fl.fl_actf = bp;
801: else
802: fl.fl_actl->b_actf = bp;
803:
804: fl.fl_actl = bp;
805:
806: spl(s);
807: }
808:
809: /*
810: * This finite state machine is
811: * responsible for all sequencing on the disk.
812: * It builds the commands, does the seeks, spins up
813: * the drive motor for 1 second on the first call,
814: * and so on.
815: * Note that the format command is rather obscurely shoehorned into this.
816: */
817: static
818: flfsm()
819: {
820: register BUF *bp;
821: register int flcmd;
822: register int i;
823: int dods; /* for PS/1, do disk swap */
824:
825: again:
826: bp = fl.fl_actf;
827:
828: switch (fl.fl_state) {
829:
830: case SIDLE:
831: T_HAL(0x40000, printf("SIDLE "));
832: drvl[FL_MAJOR].d_time = 1;
833:
834: if (bp == NULL)
835: break;
836:
837: fl.fl_unit = funit(bp->b_dev);
838: fl.fl_mask = 0x10 << fl.fl_unit;
839:
840: #if 0
841: printf("drv%d: cmd=%d (%s), position=%d, count=%d\n",
842: fl.fl_unit,
843: bp->b_req,
844: (bp->b_req == BREAD) ? "BREAD"
845: : (bp->b_req == BWRITE) ? "BWRITE"
846: : (bp->b_req == BFLSTAT) ? "BFLSTAT"
847: : (bp->b_req == BFLFMT) ? "BFLFMT" : "?????",
848: bp->b_bno,
849: bp->b_count);
850: #endif
851: /*
852: * We do an entire check for drive status here
853: */
854: if (bp->b_req == BFLSTAT) {
855: fl.fl_drvstat[0] = 0;
856: fldrvstatus();
857: sw3[fl.fl_unit] = fl.fl_drvstat[0] | 3;
858: bp->b_resid = (fl.fl_ndrvstat == 1) ? 0 : 1;
859: fl.fl_actf = bp->b_actf;
860: fl.fl_state = SIDLE;
861: goto again;
862: }
863:
864: fl.fl_hbyh = fhbyh(bp->b_dev);
865:
866: fl.fl_addr = bp->b_paddr;
867: fl.fl_secn = bp->b_bno;
868: fl.fl_time[fl.fl_unit] = 0;
869:
870: if ((fl.fl_nsec = bp->b_count>>9) == 0)
871: fl.fl_nsec = 1;
872:
873: fl.fl_nerr = 0;
874:
875: /*
876: * Motor is turned off - turn it on, wait 1 second
877: * (for write operations only)
878: */
879: if (((fl.fl_mstatus & fl.fl_mask) == 0)
880: || (fl.fl_unit != fl.fl_selected_unit)) {
881: fldrvselect();
882: if ((bp->b_req == BWRITE)
883: || (bp->b_req == BFLFMT)) {
884: timeout(&fltim, HZ, fldelay, SSEEK);
885: fl.fl_state = SDELAY;
886: break;
887: }
888: }
889:
890: /* no break */
891:
892: case SSEEK:
893: T_HAL(0x40000, printf("SSEEK "));
894: fldrvselect(); /* Keep drive turned on */
895:
896: /*
897: * Test dual-density drive's disk changed line. We must
898: * test now before we (possibly) recalibrate the drive
899: * which would lose us the disk changed indication.
900: */
901:
902: if ((frates[fl.fl_type[fl.fl_unit]].fl_hi_rate != -1)
903: && (inb(FDCCHGL) & DSKCHGD)
904: && (fl_clrng_cd == 0)) {
905: /* See note at def of FL_DSK_CH_PROB above */
906: if (FL_DSK_CH_PROB) {
907: if (jopen) {
908: jopen--;
909: fl.fl_dsk_chngd[fl.fl_unit] = 1;
910: fl.fl_incal[fl.fl_unit] = -1;
911: }
912: } else {
913: fl.fl_dsk_chngd[fl.fl_unit] = 1;
914: fl.fl_incal[fl.fl_unit] = -1;
915: }
916: }
917:
918: fl_clrng_cd = 0;
919:
920: /*
921: * If we have a format command on cylinder zero, head
922: * zero, we must recalibrate the drive first, and set
923: * up the transfer speed and FDC stuff. We ignore
924: * a disk changed condition since the current format
925: * (it may, remember, be unformatted!) is of no
926: * consequence.
927: */
928: if (bp->b_req == BFLFMT) {
929: fl.fl_dsk_chngd[fl.fl_unit] = 0;
930: fl.fl_fd[fl.fl_unit] = fdata[fkind(bp->b_dev)];
931: fl.fl_rate[fl.fl_unit] =
932: fl.fl_rate_set = flrate(bp->b_dev);
933: if ((fl.fl_fd[fl.fl_unit].fd_trks < 45)
934: && (fl.fl_type[fl.fl_unit] != 1))
935: fl.fl_2step[fl.fl_unit] = 1;
936: outb(FDCRATE, fl.fl_rate_set);
937: if (fl.fl_secn == 0)
938: fl.fl_incal[fl.fl_unit] = -1;
939: }
940: /*
941: * Drive is not calibrated - seek to track 0.
942: */
943: if (fl.fl_incal[fl.fl_unit] == -1) {
944: flput(CMDRCAL);
945: flput(fl.fl_unit);
946: fl.fl_state = SRECAL1;
947: break;
948: } else goto Recalibrated;
949:
950: case SRECAL1:
951: T_HAL(0x40000, printf("SRECAL1 "));
952: /*
953: * If the recalibrate had to step more than 77 cylinders
954: * it will fail. We must check for this condition and
955: * try once more. With some controllers we will also get
956: * an error if the head STARTS over cylinder 0. In either
957: * event we will force a seek to track 2, then recalibrate
958: * again. If this fails, we can't recalibrate the drive.
959: */
960: if ((fl.fl_nintstat != 2)
961: || ((fl.fl_intstat[0] & (ST0_IC | ST0_SE)) != ST0_SE)) {
962: flput(CMDSEEK);
963: flput(fl.fl_unit);
964: flput(2);
965: fl.fl_state = SRECAL2;
966: break;
967: } else goto RecalibrateOK;
968: case SRECAL2:
969: T_HAL(0x40000, printf("SRECAL2 "));
970: flput(CMDRCAL);
971: flput(fl.fl_unit);
972: fl.fl_state = SRECAL3;
973: break;
974: case SRECAL3:
975: T_HAL(0x40000, printf("SRECAL3 "));
976: if ((fl.fl_nintstat != 2)
977: || ((fl.fl_intstat[0] & (ST0_IC | ST0_SE)) != ST0_SE)) {
978: RecalFailed:
979: printf("fd%d: <Can't Recalibrate>\n", fl.fl_unit);
980: clrQ(bp->b_dev);
981: goto again;
982: }
983: RecalibrateOK:
984: flput(CMDSEEK); /* We now get off of cyl 0 */
985: flput(fl.fl_unit); /* to try to clear the disk */
986: flput(2); /* changed line, which acts */
987: fl.fl_state = SGOTO2; /* differently on different */
988: break; /* controllers. <sigh> We */
989: /* use cyl 2 since all for- */
990: case SGOTO2: /* matted disks will have a */
991: T_HAL(0x40000, printf("SGOTO2 "));
992: if ((fl.fl_nintstat != 2) /* track here. */
993: || ((fl.fl_intstat[0] & (ST0_IC | ST0_SE)) != ST0_SE))
994: goto RecalFailed;
995:
996: fl.fl_incal[fl.fl_unit] = 2; /* Heads now on cylinder 2. */
997:
998: Recalibrated:
999: /*
1000: * Now, if we don't have to check the interleave factor,
1001: * we can continue with the seek!
1002: */
1003: if (fl.fl_dsk_chngd[fl.fl_unit] == 0) goto RateKnown;
1004:
1005: /*
1006: * <sigh>. Okay, first we'll try the requested density.
1007: */
1008:
1009: /* First we'll make sure */
1010: /* we're sitting on cyl 2. */
1011: if (fl.fl_incal[fl.fl_unit] != 2) goto RecalibrateOK;
1012:
1013: /*
1014: * We start by trying the requested density:
1015: */
1016:
1017: /* Get requested rate.*/
1018: i = fl.fl_rate[fl.fl_unit] = flrate(bp->b_dev);
1019: /* This next mess gets*/
1020: /* the disk parameters*/
1021: /* and the alternate */
1022: /* values. */
1023: if (i == frates[fl.fl_type[fl.fl_unit]].fl_hi_rate){
1024:
1025: fl.fl_fd[fl.fl_unit] =
1026: fdata[frates[fl.fl_type[fl.fl_unit]].fl_hi_kind];
1027: if (FL_AUTO_PARM) {
1028: fl_alt_kind =
1029: frates[fl.fl_type[fl.fl_unit]].fl_lo_kind;
1030: fl_alt_rate =
1031: frates[fl.fl_type[fl.fl_unit]].fl_lo_rate;
1032: }
1033: else {
1034: fl_alt_kind =
1035: frates[fl.fl_type[fl.fl_unit]].fl_hi_kind;
1036: fl_alt_rate =
1037: frates[fl.fl_type[fl.fl_unit]].fl_hi_rate;
1038: }
1039: } else {
1040: fl.fl_fd[fl.fl_unit] =
1041: fdata[frates[fl.fl_type[fl.fl_unit]].fl_lo_kind];
1042: if (FL_AUTO_PARM) {
1043: fl_alt_kind =
1044: frates[fl.fl_type[fl.fl_unit]].fl_hi_kind;
1045: fl_alt_rate =
1046: frates[fl.fl_type[fl.fl_unit]].fl_hi_rate;
1047: } else {
1048: fl_alt_kind =
1049: frates[fl.fl_type[fl.fl_unit]].fl_lo_kind;
1050: fl_alt_rate =
1051: frates[fl.fl_type[fl.fl_unit]].fl_lo_rate;
1052: }
1053: }
1054:
1055: fl.fl_state = SRDID; /* Set up to read sector IDs. */
1056: fl_get_intlv = 1;
1057: fl_intlv_ct =
1058: fl_lk4_id =
1059: fl_1st_ID =
1060: fl_hi_ID = 0;
1061:
1062: /*
1063: * Now we try the rate to see if we can read sector IDs
1064: */
1065: TryRate:
1066: if (fl.fl_rate_set != i)
1067: outb(FDCRATE, fl.fl_rate_set = i);
1068: GetNextID:
1069: flput(CMDRDID);
1070: flput(fl.fl_unit); /* Always read side 0. */
1071:
1072: break; /* Wait for ID to arrive. */
1073:
1074: case SRDID:
1075: T_HAL(0x40000, printf("SRDID "));
1076:
1077: if ((fl.fl_ncmdstat < 7) /* Did we get an ID? */
1078: || ((fl.fl_cmdstat[0] & ST0_IC) != ST0_NT) ) {
1079: if (fl_alt_rate == -1) { /* No, is there an alternate?*/
1080: flstatus(); /* No, we can't go on. */
1081: clrQ(bp->b_dev);
1082: PUSH3(-1,0,1);
1083: goto again;
1084: } else {
1085: fl.fl_fd[fl.fl_unit] = fdata[fl_alt_kind];
1086: i = fl.fl_rate[fl.fl_unit] = fl_alt_rate;
1087: fl_alt_rate = -1; /* Flag tried alternate. */
1088: PUSH3(-1,0,2);
1089: goto TryRate; /* Try alternate density. */
1090: }
1091: }
1092:
1093: /*
1094: * Test interleave
1095: */
1096:
1097: if (fl_get_intlv) /* Looking for interleave? */
1098: if (fl_lk4_id) { /* Yes; started yet? */
1099: if (fl_lk4_id == fl.fl_cmdstat[5]) /* Yes. */
1100: fl_get_intlv = 0; /* We have a hit.*/
1101: else /* No hit yet, */
1102: fl_intlv_ct++; /* count sector. */
1103: } else if (fl.fl_cmdstat[5] < 5) {/* Can we start yet?*/
1104: fl_intlv_ct = 1; /* Yes; count, */
1105: fl_lk4_id = fl.fl_cmdstat[5] + 1;/* set ID */
1106: } /* to find.*/
1107:
1108: /*
1109: * Look for highest ID on track
1110: */
1111:
1112: PUSH3(fl.fl_cmdstat[5], fl_1st_ID, fl_hi_ID);
1113: if (fl.fl_cmdstat[5] != fl_1st_ID) {
1114: if (fl_1st_ID == 0)
1115: fl_1st_ID = fl.fl_cmdstat[5];
1116: if (fl.fl_cmdstat[5] > fl_hi_ID)
1117: fl_hi_ID = fl.fl_cmdstat[5];
1118: goto GetNextID;
1119: }
1120:
1121: /*
1122: * Be sure we have the interleave
1123: */
1124:
1125: if (fl_get_intlv) goto GetNextID;
1126:
1127: /*
1128: * So now we know the density and sectors/track
1129: */
1130:
1131: fl.fl_dsk_chngd[fl.fl_unit] = 0;
1132: fl.fl_fd[fl.fl_unit].fd_nspt = fl_hi_ID;
1133:
1134: /*
1135: * There is a problem with the approach used here -
1136: * it assumes that once scan of a track starts, all
1137: * sectors appear in physical order without any misses.
1138: * Unfortunately, this is not always the case, especially
1139: * with 1.44 M 3-1/2" drives.
1140: *
1141: * A workaround which fixes incorrect nspt reading appears
1142: * below.
1143: */
1144: if (fl.fl_fd[fl.fl_unit].fd_nspt > 15
1145: && fl.fl_fd[fl.fl_unit].fd_nspt < 18)
1146: fl.fl_fd[fl.fl_unit].fd_nspt = 18;
1147:
1148: /*
1149: * We're (supposedly) sitting on track 2. We'll
1150: * look at the last sector ID we've read. If it's 1,
1151: * we need to do double-stepping.
1152: */
1153:
1154: if (fl.fl_2step[fl.fl_unit] = (fl.fl_cmdstat[3] == 1)) {
1155: fl.fl_fd[fl.fl_unit].fd_trks = FL_CYL_2STEP;
1156: fl.fl_incal[fl.fl_unit] = 1;
1157: } else /* Most 1.2M drives */
1158: fl.fl_fd[fl.fl_unit].fd_trks = /* have 83 cyls! */
1159: (fl.fl_type[fl.fl_unit] == 2)
1160: ? FL_CYL_HDHI : FL_CYL_HDLO;
1161:
1162: /*
1163: * We next test for one or two sides:
1164: */
1165:
1166: if (fl.fl_rate[fl.fl_unit] == 0) { /* If diskette is */
1167: fl.fl_fd[fl.fl_unit].fd_nhds = 2; /* high-density it*/
1168: PUSH3(-1,0,4);
1169: goto DiskEstablished; /* will have two */
1170: } /* sides. */
1171:
1172: /*
1173: * If the diskette is requested by caller as low density
1174: * we use the specified number of sides------
1175: */
1176:
1177: if (fdata[fkind(bp->b_dev)].fd_nspt < 12) {
1178: fl.fl_fd[fl.fl_unit].fd_nhds =
1179: fdata[fkind(bp->b_dev)].fd_nhds;
1180: PUSH3(-1,0,5);
1181: goto DiskEstablished;
1182: }
1183:
1184: /*
1185: * --otherwise we check to see:
1186: */
1187:
1188: flput(CMDRDID); /* Just try to read ANY sector*/
1189: flput(fl.fl_unit | 0x04); /* ID from side two. */
1190: fl.fl_state = SSIDTST;
1191: PUSH3(-1,0,6);
1192: break;
1193:
1194: case SSIDTST: /* If we succeeded, we have */
1195: T_HAL(0x40000, printf("SSIDTST "));
1196: /* 2 sides, else we have 1. */
1197: fl.fl_fd[fl.fl_unit].fd_nhds = ((fl.fl_ncmdstat < 7)
1198: || ((fl.fl_cmdstat[0] & ST0_IC) != ST0_NT) ) ? 1 : 2;
1199:
1200: /*
1201: * So now we now know all about the diskette!
1202: */
1203: DiskEstablished:
1204: fl.fl_fd[fl.fl_unit].fd_size = fl.fl_fd[fl.fl_unit].fd_nhds
1205: * fl.fl_fd[fl.fl_unit].fd_trks
1206: * fl.fl_fd[fl.fl_unit].fd_nspt;
1207:
1208: if (fl_disp) {
1209: printf("fl%d: rate=%d, sctrs/trk=%d, hds=%d, cyls=%d,"
1210: " size=%d, intlv=%d, stp=%d\n",
1211: fl.fl_unit,
1212: fl.fl_rate[fl.fl_unit],
1213: fl.fl_fd[fl.fl_unit].fd_nspt,
1214: fl.fl_fd[fl.fl_unit].fd_nhds,
1215: fl.fl_fd[fl.fl_unit].fd_trks,
1216: fl.fl_fd[fl.fl_unit].fd_size,
1217: fl_intlv_ct,
1218: fl.fl_2step[fl.fl_unit]+1);
1219: POP3();
1220: }
1221:
1222: /*
1223: * Finally, if the diskette drive has a change line
1224: * we'll force it off by reading a sector on cylinder 2.
1225: * Usually the testing for rate, the seek to cylinder 2
1226: * and the soon-to-follow read or write would clear this,
1227: * but there are some controllers that don't always clear
1228: * it. The machine I've been testing on clears it sometimes
1229: * and not other times. I hope there aren't machines even
1230: * flakier than this!
1231: */
1232:
1233: if ((frates[fl.fl_type[fl.fl_unit]].fl_hi_rate != -1)
1234: && (inb(FDCCHGL) & DSKCHGD)) {
1235: dods = 1;
1236:
1237: /* See note at def of FL_DSK_CH_PROB above */
1238: if (FL_DSK_CH_PROB) {
1239: if (jopen) {
1240: jopen--;
1241: } else
1242: dods = 0;
1243: }
1244: if (dods) {
1245: fl.fl_fcyl = fl.fl_incal[fl.fl_unit];
1246: fl.fl_head = 0;
1247: fl.fl_fsec = 1;
1248: #ifdef _I386
1249: fl.fl_addr = MAPIO(allocp.sr_segp->s_vmem,
1250: ((int)scratch_buffer - (int)allocp.sr_base));
1251: #else
1252: fl.fl_addr = vtop(scratch_buffer, sds);
1253: #endif
1254: fl_clrng_cd = 1;
1255: goto Sought;
1256: }
1257: }
1258:
1259: RateKnown:
1260: /*
1261: * Set data rate if changed.
1262: */
1263: if (fl.fl_rate_set != (i = fl.fl_rate[fl.fl_unit]))
1264: outb(FDCRATE, fl.fl_rate_set = i);
1265:
1266: /*
1267: * Next we must convert the ordinal block number to
1268: * cylinder/head/sector form.
1269: */
1270: fl.fl_fsec = (fl.fl_secn % fl.fl_fd[fl.fl_unit].fd_nspt) + 1;
1271:
1272: /*
1273: * Seek cylinder by cylinder (XENIX/DOS compatible).
1274: */
1275: if (fl.fl_hbyh) {
1276: fl.fl_head = fl.fl_secn / fl.fl_fd[fl.fl_unit].fd_nspt;
1277: fl.fl_fcyl = fl.fl_head / fl.fl_fd[fl.fl_unit].fd_nhds;
1278: fl.fl_head = fl.fl_head % fl.fl_fd[fl.fl_unit].fd_nhds;
1279: }
1280:
1281: /*
1282: * Seek surface by surface.
1283: */
1284: else {
1285: fl.fl_fcyl = fl.fl_secn / fl.fl_fd[fl.fl_unit].fd_nspt;
1286: fl.fl_head = fl.fl_fcyl / fl.fl_fd[fl.fl_unit].fd_trks;
1287: fl.fl_fcyl = fl.fl_fcyl % fl.fl_fd[fl.fl_unit].fd_trks;
1288: }
1289: /* Don't seek unless we have to. */
1290: if (fl.fl_fcyl == fl.fl_incal[fl.fl_unit])
1291: goto Sought; /* Past tense of seek. */
1292:
1293: fl.fl_incal[fl.fl_unit] = fl.fl_fcyl; /* Save new cylinder. */
1294:
1295: flput(CMDSEEK);
1296: flput((fl.fl_head<<2) | fl.fl_unit);
1297: /* If disk is around 40 tracks*/
1298: /* and drive is not 40 track- */
1299: if ((fl.fl_fd[fl.fl_unit].fd_trks < 45)
1300: && (fl.fl_type[fl.fl_unit] != 1))
1301: flput(fl.fl_fcyl << 1); /* -use double step. */
1302: else
1303: flput(fl.fl_fcyl); /* Single step. */
1304:
1305: fl.fl_state = SHDLY;
1306: break;
1307:
1308: case SHDLY:
1309: T_HAL(0x40000, printf("SHDLY "));
1310: /*
1311: * Delay for minimum 15 milliseconds after seek before w/fmt.
1312: * 2 clock ticks would give 10-20 millisecond (100 Hz clock).
1313: * 3 clock ticks gives 20-30 millisecond (100 Hz clock).
1314: */
1315: if (bp->b_req != BREAD) {
1316: timeout(&fltim, 3, fldelay, SRDWR);
1317: fl.fl_state = SDELAY;
1318: break;
1319: }
1320: /* no break */
1321:
1322: case SRDWR:
1323: T_HAL(0x40000, printf("SRDWR "));
1324: Sought:
1325: /*
1326: * Disable watchdog timer while waiting to lock DMA controller.
1327: */
1328: fl.fl_time[fl.fl_unit] = -1;
1329:
1330: /*
1331: * Next state will be DMA locked state.
1332: */
1333: fl.fl_state = SLOCK;
1334:
1335: /*
1336: * If DMA controller locked by someone else, exit for now.
1337: */
1338: if (dmalock(&fldmalck, flfsm, 0) != 0)
1339: return;
1340:
1341: case SLOCK:
1342: T_HAL(0x40000, printf("SLOCK "));
1343: /*
1344: * Reset watchdog timer to restart timeout sequence.
1345: */
1346:
1347: fl.fl_time[fl.fl_unit] = 0;
1348:
1349: flcmd = CMDRDAT;
1350: fl.fl_wflag = 0;
1351:
1352: if (fl_clrng_cd == 0)
1353: if (bp->b_req == BWRITE) {
1354: fl.fl_wflag = 1;
1355: flcmd = CMDWDAT;
1356: }
1357:
1358: else if (bp->b_req == BFLFMT) {
1359: fl.fl_wflag = 1;
1360: flcmd = CMDFMT;
1361:
1362: #ifdef _I386
1363: if(!dmaon(2, P2P(fl.fl_addr),bp->b_count,
1364: fl.fl_wflag))
1365: #else
1366: if(dmaon(2, fl.fl_addr, bp->b_count,
1367: fl.fl_wflag) == 0)
1368: #endif
1369: goto straddle;
1370:
1371: else
1372: goto command;
1373: }
1374:
1375: #ifdef _I386
1376: if (dmaon(2, P2P(fl.fl_addr), 512, fl.fl_wflag) == 0)
1377: #else
1378: if (dmaon(2, fl.fl_addr, 512, fl.fl_wflag) == 0)
1379: #endif
1380: {
1381: straddle:
1382: devmsg(bp->b_dev, "fd: DMA page straddle at %x:%x",
1383: fl.fl_addr);
1384: dmaunlock(&fldmalck);
1385: bp->b_flag |= BFERR;
1386: fldone(bp);
1387: goto again;
1388: }
1389: command:
1390: dmago(2);
1391: flput(flcmd);
1392: flput((fl.fl_head<<2) | fl.fl_unit);
1393:
1394: if (bp->b_req == BFLFMT) {
1395: flput(fl.fl_fd[fl.fl_unit].fd_N); /* N */
1396: flput(fl.fl_fd[fl.fl_unit].fd_nspt); /* SC */
1397: flput(fl.fl_fd[fl.fl_unit].fd_FGPL); /* GPL */
1398: flput(0xF6); /* D */
1399: }
1400:
1401: else {
1402: flput(fl.fl_fcyl);
1403: flput(fl.fl_head);
1404: flput(fl.fl_fsec);
1405: flput(fl.fl_fd[fl.fl_unit].fd_N); /* N */
1406: flput(fl.fl_fd[fl.fl_unit].fd_nspt); /* EOT */
1407: flput(fl.fl_fd[fl.fl_unit].fd_GPL[fl.fl_rate_set]);
1408: /* GPL */
1409: flput(0xFF); /* DTL */
1410: }
1411:
1412: fl.fl_state = SENDIO;
1413: break;
1414:
1415: case SENDIO:
1416: T_HAL(0x40000, printf("SENDIO "));
1417: fl.fl_time[fl.fl_unit] = 0;
1418: dmaoff(2);
1419: dmaunlock(&fldmalck);
1420:
1421: if (fl_clrng_cd) {
1422: fl.fl_state = SIDLE;
1423: wakeup(&fl.fl_state);
1424: goto again;
1425: }
1426:
1427: /*
1428: * We now check for errors. If the error is a data
1429: * CRC error, we KNOW we're on the correct track, and
1430: * we just retry the read once before recalibrating.
1431: * We recalibrate for all other errors.
1432: */
1433: if ((fl.fl_cmdstat[0] & ST0_IC) != ST0_NT) {
1434: if (++fl.fl_nerr < 5) {
1435: if (fl.fl_cmdstat[2] & ST2_DD) {
1436: if (fl.fl_nerr & 1)
1437: goto SetSEEKState;
1438: else
1439: goto Ask4Recal;
1440: } else {
1441: Ask4Recal:
1442: fl.fl_incal[fl.fl_unit] = -1;
1443: SetSEEKState:
1444: fl.fl_state = SSEEK;
1445: }
1446: } else {
1447: flstatus(); /* Total failure; */
1448: bp->b_flag |= BFERR; /* we give up. */
1449: fldone(bp);
1450: }
1451: }
1452:
1453: else if (--fl.fl_nsec == 0) {
1454: bp->b_resid = 0;
1455: fldone(bp);
1456: }
1457:
1458: else {
1459: ++fl.fl_secn;
1460: fl.fl_addr += 512; /* 512 == fl.fl_fd.fd_nbps */
1461: fl.fl_state = SSEEK;
1462: }
1463:
1464: /*
1465: * Delay for minimum 1.5 msecs after writing before seek.
1466: */
1467: if (fl.fl_wflag) {
1468: timeout(&fltim, 2, fldelay, fl.fl_state);
1469: fl.fl_state = SDELAY;
1470: break;
1471: }
1472:
1473: goto again;
1474:
1475: case SDELAY:
1476: T_HAL(0x40000, printf("SDELAY "));
1477: /*
1478: * Ignore interrupts until timeout occurs.
1479: */
1480: break;
1481:
1482: default:
1483: panic("fds");
1484: }
1485: }
1486:
1487: /*
1488: * Delay before initiating next operation.
1489: * This allows the floppy motor to turn on,
1490: * the head to settle before writing,
1491: * the erase head to turn off after writing, etc.
1492: */
1493: static
1494: fldelay(state)
1495: int state;
1496: {
1497: int s;
1498:
1499: s = sphi();
1500: if (fl.fl_state == SDELAY) {
1501: fl.fl_state = state;
1502: flfsm();
1503: }
1504: spl(s);
1505: }
1506:
1507: /*
1508: * The flrate function returns the data rate for the flopen and flfsm routines.
1509: */
1510: static int
1511: flrate(dev)
1512: register dev_t dev;
1513: {
1514: register int unit = funit(dev);
1515: register int rate = frates[fl.fl_type[unit]].fl_hi_rate;
1516:
1517: if ((rate == -1) || (fdata[fkind(dev)].fd_nspt < 15))
1518: rate = frates[fl.fl_type[unit]].fl_lo_rate;
1519:
1520: return(rate);
1521: }
1522:
1523: /*
1524: * This routine is called by the
1525: * clock handler every second. If the drive
1526: * has been idle for a long time it turns off
1527: * the motor and shuts off the timeouts.
1528: */
1529:
1530: static
1531: fltimeout()
1532: {
1533: register int unit;
1534: register int mask;
1535: register int s;
1536:
1537: s = sphi();
1538:
1539: /*
1540: * Scan all drives, looking for motor timeouts.
1541: */
1542: for (unit=0, mask=0x10; unit < MAXDRVS; unit++, mask <<= 1) {
1543:
1544: /*
1545: * Ignore drives which aren't spinning.
1546: */
1547: if ((fl.fl_mstatus & mask) == 0)
1548: continue;
1549:
1550: /*
1551: * If timer is disabled (i.e. we are waiting for the DMA
1552: * controller), go on to the next drive.
1553: */
1554: if (fl.fl_time[unit] < 0)
1555: continue;
1556:
1557: /*
1558: * Leave recently accessed (in last 4 seconds) drives spinning.
1559: */
1560: if (++fl.fl_time[unit] < MTIMER)
1561: continue;
1562:
1563: /*
1564: * Timeout drives which have been inactive for 5 seconds.
1565: */
1566: fl.fl_mstatus &= ~mask;
1567: if (unit == fl.fl_selected_unit)
1568: fl.fl_selected_unit = -1;
1569:
1570: /*
1571: * Not selected drive, or selected drive is idle.
1572: */
1573: if ((unit != fl.fl_unit) || (fl.fl_state == SIDLE))
1574: continue;
1575:
1576: /*
1577: * Active drive did not complete operation within 5 seconds.
1578: * Attempt recovery.
1579: */
1580: flrecov();
1581:
1582: /*
1583: * Initiate next block request.
1584: */
1585: if (fl.fl_state == SIDLE)
1586: flfsm();
1587: }
1588:
1589: /*
1590: * Physically turn off drives which timed out.
1591: */
1592: outb(FDCDOR, DORNMR | DORIEN | fl.fl_mstatus | fl.fl_unit);
1593:
1594: /*
1595: * Stop checking once all drives have been stopped.
1596: */
1597: if (fl.fl_mstatus == 0)
1598: drvl[FL_MAJOR].d_time = 0;
1599:
1600: spl(s);
1601: }
1602:
1603: /*
1604: * Remove all pending requests for a device from the queue
1605: * (used after errors).
1606: */
1607: static
1608: clrQ(dev)
1609: register int dev;
1610: {
1611: register BUF *bp, *bp2;
1612: int s;
1613:
1614: s = sphi();
1615:
1616: while ((bp = fl.fl_actf) && (bp->b_dev == dev)) {
1617: bp->b_flag |= BFERR; /* Strip BUFs from front */
1618: fl.fl_actf = bp->b_actf; /* of queue. */
1619: bdone(bp);
1620: }
1621: while (bp) {
1622: fl.fl_actl = bp;
1623: if ((bp2 = bp->b_actf) && (bp2->b_dev == dev)) {
1624: bp2->b_flag |= BFERR; /* Strip BUFs from rest */
1625: bp->b_actf = bp2->b_actf; /* rest of queue. */
1626: bdone(bp2);
1627: } else
1628: bp = bp2;
1629: }
1630: fl.fl_state = SIDLE;
1631: wakeup(&fl.fl_state);
1632: spl(s);
1633: }
1634:
1635: /*
1636: * The recovery routine resets and reprograms the floppy controller,
1637: * and discards any queued requests on the current drive.
1638: * This is required if the floppy door is open, or diskette is missing.
1639: */
1640: static
1641: flrecov()
1642: {
1643: register int x;
1644:
1645: if (FL_DSK_CH_PROB)
1646: jopen = 2;
1647:
1648: /*
1649: * Disable DMA transfer.
1650: * Reset floppy controller.
1651: */
1652: dmaoff(2);
1653:
1654: /*
1655: * Unlock the controller if locked by us.
1656: */
1657:
1658: outb(FDCDOR, 0);
1659: fl.fl_state = SIDLE;
1660: wakeup(&fl.fl_state);
1661: dmaunlock(&fldmalck); /* Ensures 14 clock cycles */
1662: outb(FDCDOR, DORNMR | DORIEN);
1663:
1664: fl.fl_mstatus = 0; /* No motors on */
1665: fl.fl_selected_unit = -1; /* No unit selected */
1666:
1667: /*
1668: * Program floppy controller.
1669: */
1670: flspecify(); /* Forces wait */
1671:
1672: /*
1673: * Program transfer bps.
1674: */
1675: outb(FDCRATE, fl.fl_rate_set);
1676:
1677: /*
1678: * Drives are no longer in calibration.
1679: */
1680: for (x = 0; x < MAXDRVS; x++)
1681: fl.fl_incal[1] = -1;
1682:
1683: /*
1684: * Abort all block requests on current drive after 1st recov attempt.
1685: */
1686: if (fl.fl_actf) {
1687: printf("fd%d: <Door Open>\n", fl.fl_unit); /* Message */
1688: clrQ(fl.fl_actf->b_dev); /* Dump pending reqs. */
1689: fl.fl_dsk_chngd[fl.fl_unit] = 1; /* Make disk changed. */
1690: }
1691:
1692: /*
1693: * Delay before setting controller state to idle.
1694: * This gives time for spurious floppy interrupts to occur.
1695: * NOTE: Can't call flfsm(), since it may call us (future revision).
1696: */
1697: timeout(&fltim, HZ/4, fldelay, SIDLE);
1698: fl.fl_state = SDELAY;
1699: }
1700:
1701: /*
1702: * The interrupt routine gets all
1703: * the status bytes the controller chip
1704: * will give it, then issues a sense interrupt
1705: * status command (which is necessary for a seek
1706: * to complete!) and throws all of the status
1707: * bytes away.
1708: */
1709:
1710: static
1711: flintr()
1712: {
1713: register int s;
1714:
1715: s = sphi();
1716: flsense();
1717:
1718: if (fl.fl_state != SIDLE)
1719: flfsm();
1720:
1721: spl(s);
1722: }
1723:
1724: /*
1725: * Fldone() returns current request to operating system.
1726: */
1727: fldone(bp)
1728: register BUF * bp;
1729: {
1730: fl.fl_actf = bp->b_actf;
1731: fl.fl_state = SIDLE;
1732: bdone(bp);
1733: wakeup(&fl.fl_state);
1734: }
1735:
1736: /*
1737: * Send Specify command and data bytes to FDC
1738: */
1739:
1740: static
1741: flspecify()
1742: {
1743: flput(CMDSPEC);
1744: flput((fl_srt << 4) | fl_hut);
1745: flput(fl_hlt << 1);
1746: }
1747:
1748: /*
1749: * Flsense() issues a sense interrupt status command
1750: * to restore the controller to a quiescent state.
1751: */
1752:
1753: static
1754: flsense()
1755: {
1756: flcmdstatus(); /* Get command status. */
1757: flintstatus(); /* Get int status, just in case. */
1758: }
1759:
1760: /*
1761: * Get status (if any) from last command
1762: */
1763: static
1764: flcmdstatus()
1765: {
1766: register int b;
1767: register int n = 0; /* # of status bytes read */
1768: register int i = 0; /* Timeout count */
1769: register int s;
1770:
1771: s = sphi();
1772:
1773: /*
1774: * Read all the status bytes the controller will give us.
1775: */
1776:
1777: for (;;) {
1778: while (((b=inb(FDCMSR)) & MSRRQM) == 0) {
1779: if (--i == 0) {
1780: printf("flintr: timeout\n");
1781: break;
1782: }
1783: }
1784:
1785: if ((b & MSRDIO) == 0)
1786: break;
1787:
1788: b = inb(FDCDAT);
1789: if (n < sizeof(fl.fl_cmdstat))
1790: fl.fl_cmdstat[n++] = b;
1791: }
1792:
1793: fl.fl_ncmdstat = n;
1794: spl(s);
1795: }
1796:
1797: /*
1798: * Get Inteerupt status
1799: */
1800: static
1801: flintstatus()
1802: {
1803: register int b;
1804: register int n = 0; /* # of status bytes read */
1805: register int i = 0; /* Timeout count */
1806: register int s;
1807:
1808: s = sphi();
1809:
1810: /*
1811: * Issue a sense interrupt command and stash result.
1812: */
1813: flput(CMDSINT);
1814:
1815: n = 0;
1816: for (;;) {
1817: while (((b=inb(FDCMSR)) & MSRRQM) == 0)
1818: if (--i == 0) {
1819: printf("flintsense: timeout\n");
1820: break;
1821: }
1822:
1823: if ((b & MSRDIO) == 0)
1824: break;
1825:
1826: b = inb(FDCDAT);
1827: if (n < sizeof(fl.fl_intstat))
1828: fl.fl_intstat[n++] = b;
1829: }
1830: fl.fl_nintstat = n;
1831: spl(s);
1832: }
1833:
1834: /*
1835: * Get the drive status
1836: */
1837: static void
1838: fldrvstatus()
1839: {
1840: register int b;
1841: register int n = 0; /* # of status bytes read */
1842: register int i = 0; /* Timeout count */
1843: register int s;
1844:
1845: s = sphi();
1846:
1847: fldrvselect(); /* Be sure drive is selected */
1848:
1849: /*
1850: * Issue a sense drive status command and stash result.
1851: */
1852: flput(CMDSDRV);
1853: flput(fl.fl_unit);
1854:
1855: for (;;) {
1856: spl(s);
1857: if (SELF->p_ssig && nondsig()) { /* signal? */
1858: u.u_error = EINTR;
1859: break;
1860: }
1861: s = sphi();
1862: while (((b=inb(FDCMSR)) & MSRRQM) == 0)
1863: if (--i == 0) {
1864: printf("fldrvsense: timeout\n");
1865: break;
1866: }
1867:
1868: if ((b & MSRDIO) == 0)
1869: break;
1870:
1871: b = inb(FDCDAT);
1872: if (n < sizeof(fl.fl_drvstat))
1873: fl.fl_drvstat[n++] = b;
1874: }
1875: fl.fl_ndrvstat = n;
1876: spl(s);
1877: }
1878:
1879: /*
1880: * fldrvselect() selects the drive and turns its motor on
1881: */
1882: static
1883: fldrvselect()
1884: {
1885: fl.fl_time[fl.fl_unit] = 0; /* Start motor-on timeout. */
1886: fl.fl_mstatus |= fl.fl_mask;
1887: outb(FDCDOR, DORNMR | DORIEN | fl.fl_mstatus | fl.fl_unit);
1888: fl.fl_selected_unit = fl.fl_unit; /* This unit is running. */
1889: flsense(); /* Just in case --- */
1890: }
1891:
1892: /*
1893: * Send a command byte to the
1894: * NEC chip, first waiting until the chip
1895: * says that it is ready. No timeout is
1896: * performed; if the chip dies, we do too!
1897: */
1898:
1899: static
1900: flput(b)
1901:
1902: int b;
1903:
1904: {
1905: register int i = 0;
1906:
1907: while ((inb(FDCMSR) & (MSRRQM | MSRDIO)) != MSRRQM) {
1908: if (--i == 0) {
1909: printf("flput(%x): timeout\n",b);
1910: return;
1911: }
1912: }
1913:
1914: outb(FDCDAT, b);
1915: }
1916:
1917: /*
1918: * Dissassemble the floppy error status for user reference.
1919: */
1920:
1921: static
1922: flstatus()
1923: {
1924: printf("fd%d: head=%u cyl=%u",
1925: fl.fl_cmdstat[0] & 3,
1926: fl.fl_head, fl.fl_fcyl);
1927:
1928: /*
1929: * Report on ST0 bits.
1930: */
1931: if (fl.fl_ncmdstat >= 1) {
1932: if (fl.fl_cmdstat[0] & ST0_NR)
1933: printf(" <Not Ready>");
1934:
1935: if (fl.fl_cmdstat[0] & ST0_EC)
1936: printf(" <Equipment Check>");
1937: }
1938:
1939: /*
1940: * Report on ST1 bits.
1941: */
1942: if (fl.fl_ncmdstat >= 2) {
1943: if (fl.fl_cmdstat[1] & ST1_MA)
1944: printf(" <Missing Address Mark>");
1945:
1946: if (fl.fl_cmdstat[1] & ST1_NW)
1947: printf(" <Write Protected>");
1948:
1949: if (fl.fl_cmdstat[1] & ST1_ND)
1950: printf(" <No Data>");
1951:
1952: if (fl.fl_cmdstat[1] & ST1_OR)
1953: printf(" <Overrun>");
1954:
1955: if (fl.fl_cmdstat[1] & ST1_DE)
1956: printf(" <Data Error>");
1957:
1958: if (fl.fl_cmdstat[1] & ST1_EN)
1959: printf(" <End of Cyl>");
1960: }
1961:
1962: /*
1963: * Report on ST2 bits.
1964: */
1965: if (fl.fl_ncmdstat >= 3) {
1966: if (fl.fl_cmdstat[2] & ST2_MD)
1967: printf(" <Missing Data Address Mark>");
1968:
1969: if (fl.fl_cmdstat[2] & ST2_BC)
1970: printf(" <Bad Cylinder>");
1971:
1972: if (fl.fl_cmdstat[2] & ST2_WC)
1973: printf(" <Wrong Cylinder>");
1974:
1975: if (fl.fl_cmdstat[2] & ST2_DD)
1976: printf(" <Bad Data CRC>");
1977:
1978: if (fl.fl_cmdstat[2] & ST2_CM)
1979: printf(" <Data Deleted>");
1980: }
1981:
1982: printf("\n");
1983: }
1984: /* * * * * End of FL.C * * * * */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.