1 /* This file contains the device dependent part of the driver for the Floppy
2 * Disk Controller (FDC) using the NEC PD765 chip.
3 *
4 * The file contains two entry points:
5 *
6 * floppy_task: main entry when system is brought up
7 *
8 * Changes:
9 * Sep 11, 2005 code cleanup (Andy Tanenbaum)
10 * Dec 01, 2004 floppy driver moved to user-space (Jorrit N. Herder)
11 * Sep 15, 2004 sync alarms/ local timer management (Jorrit N. Herder)
12 * Aug 12, 2003 null seek no interrupt fix (Mike Haertel)
13 * May 14, 2000 d-d/i rewrite (Kees J. Bot)
14 * Apr 04, 1992 device dependent/independent split (Kees J. Bot)
15 * Mar 27, 1992 last details on density checking (Kees J. Bot)
16 * Feb 14, 1992 check drive density on opens only (Andy Tanenbaum)
17 * 1991 len[] / motors / reset / step rate / ... (Bruce Evans)
18 * May 13, 1991 renovated the errors loop (Don Chapman)
19 * 1989 I/O vector to keep up with 1-1 interleave (Bruce Evans)
20 * Jan 06, 1988 allow 1.44 MB diskettes (Al Crew)
21 * Nov 28, 1986 better resetting for 386 (Peter Kay)
22 * Oct 27, 1986 fdc_results fixed for 8 MHz (Jakob Schripsema)
23 */
24
25 #include "floppy.h"
26 #include <timers.h>
27 #include <ibm/diskparm.h>
28 #include <minix/sysutil.h>
29 #include <minix/syslib.h>
30
31 /* I/O Ports used by floppy disk task. */
32 #define DOR 0x3F2 /* motor drive control bits */
33 #define FDC_STATUS 0x3F4 /* floppy disk controller status register */
34 #define FDC_DATA 0x3F5 /* floppy disk controller data register */
35 #define FDC_RATE 0x3F7 /* transfer rate register */
36 #define DMA_ADDR 0x004 /* port for low 16 bits of DMA address */
37 #define DMA_TOP 0x081 /* port for top 8 bits of 24-bit DMA addr */
38 #define DMA_COUNT 0x005 /* port for DMA count (count = bytes - 1) */
39 #define DMA_FLIPFLOP 0x00C /* DMA byte pointer flip-flop */
40 #define DMA_MODE 0x00B /* DMA mode port */
41 #define DMA_INIT 0x00A /* DMA init port */
42 #define DMA_RESET_VAL 0x006
43
44 #define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */
45
46 /* Status registers returned as result of operation. */
47 #define ST0 0x00 /* status register 0 */
48 #define ST1 0x01 /* status register 1 */
49 #define ST2 0x02 /* status register 2 */
50 #define ST3 0x00 /* status register 3 (return by DRIVE_SENSE) */
51 #define ST_CYL 0x03 /* slot where controller reports cylinder */
52 #define ST_HEAD 0x04 /* slot where controller reports head */
53 #define ST_SEC 0x05 /* slot where controller reports sector */
54 #define ST_PCN 0x01 /* slot where controller reports present cyl */
55
56 /* Fields within the I/O ports. */
57 /* Main status register. */
58 #define CTL_BUSY 0x10 /* bit is set when read or write in progress */
59 #define DIRECTION 0x40 /* bit is set when reading data reg is valid */
60 #define MASTER 0x80 /* bit is set when data reg can be accessed */
61
62 /* Digital output port (DOR). */
63 #define MOTOR_SHIFT 4 /* high 4 bits control the motors in DOR */
64 #define ENABLE_INT 0x0C /* used for setting DOR port */
65
66 /* ST0. */
67 #define ST0_BITS_TRANS 0xD8 /* check 4 bits of status */
68 #define TRANS_ST0 0x00 /* 4 bits of ST0 for READ/WRITE */
69 #define ST0_BITS_SEEK 0xF8 /* check top 5 bits of seek status */
70 #define SEEK_ST0 0x20 /* top 5 bits of ST0 for SEEK */
71
72 /* ST1. */
73 #define BAD_SECTOR 0x05 /* if these bits are set in ST1, recalibrate */
74 #define WRITE_PROTECT 0x02 /* bit is set if diskette is write protected */
75
76 /* ST2. */
77 #define BAD_CYL 0x1F /* if any of these bits are set, recalibrate */
78
79 /* ST3 (not used). */
80 #define ST3_FAULT 0x80 /* if this bit is set, drive is sick */
81 #define ST3_WR_PROTECT 0x40 /* set when diskette is write protected */
82 #define ST3_READY 0x20 /* set when drive is ready */
83
84 /* Floppy disk controller command bytes. */
85 #define FDC_SEEK 0x0F /* command the drive to seek */
86 #define FDC_READ 0xE6 /* command the drive to read */
87 #define FDC_WRITE 0xC5 /* command the drive to write */
88 #define FDC_SENSE 0x08 /* command the controller to tell its status */
89 #define FDC_RECALIBRATE 0x07 /* command the drive to go to cyl 0 */
90 #define FDC_SPECIFY 0x03 /* command the drive to accept params */
91 #define FDC_READ_ID 0x4A /* command the drive to read sector identity */
92 #define FDC_FORMAT 0x4D /* command the drive to format a track */
93
94 /* DMA channel commands. */
95 #define DMA_READ 0x46 /* DMA read opcode */
96 #define DMA_WRITE 0x4A /* DMA write opcode */
97
98 /* Parameters for the disk drive. */
99 #define HC_SIZE 2880 /* # sectors on largest legal disk (1.44MB) */
100 #define NR_HEADS 0x02 /* two heads (i.e., two tracks/cylinder) */
101 #define MAX_SECTORS 18 /* largest # sectors per track */
102 #define DTL 0xFF /* determines data length (sector size) */
103 #define SPEC2 0x02 /* second parameter to SPECIFY */
104 #define MOTOR_OFF (3*HZ) /* how long to wait before stopping motor */
105 #define WAKEUP (2*HZ) /* timeout on I/O, FDC won't quit. */
106
107 /* Error codes */
108 #define ERR_SEEK (-1) /* bad seek */
109 #define ERR_TRANSFER (-2) /* bad transfer */
110 #define ERR_STATUS (-3) /* something wrong when getting status */
111 #define ERR_READ_ID (-4) /* bad read id */
112 #define ERR_RECALIBRATE (-5) /* recalibrate didn't work properly */
113 #define ERR_DRIVE (-6) /* something wrong with a drive */
114 #define ERR_WR_PROTECT (-7) /* diskette is write protected */
115 #define ERR_TIMEOUT (-8) /* interrupt timeout */
116
117 /* No retries on some errors. */
118 #define err_no_retry(err) ((err) <= ERR_WR_PROTECT)
119
120 /* Encoding of drive type in minor device number. */
121 #define DEV_TYPE_BITS 0x7C /* drive type + 1, if nonzero */
122 #define DEV_TYPE_SHIFT 2 /* right shift to normalize type bits */
123 #define FORMAT_DEV_BIT 0x80 /* bit in minor to turn write into format */
124
125 /* Miscellaneous. */
126 #define MAX_ERRORS 6 /* how often to try rd/wt before quitting */
127 #define MAX_RESULTS 7 /* max number of bytes controller returns */
128 #define NR_DRIVES 2 /* maximum number of drives */
129 #define DIVISOR 128 /* used for sector size encoding */
130 #define SECTOR_SIZE_CODE 2 /* code to say "512" to the controller */
131 #define TIMEOUT_MICROS 500000L /* microseconds waiting for FDC */
132 #define TIMEOUT_TICKS 30 /* ticks waiting for FDC */
133 #define NT 7 /* number of diskette/drive combinations */
134 #define UNCALIBRATED 0 /* drive needs to be calibrated at next use */
135 #define CALIBRATED 1 /* no calibration needed */
136 #define BASE_SECTOR 1 /* sectors are numbered starting at 1 */
137 #define NO_SECTOR (-1) /* current sector unknown */
138 #define NO_CYL (-1) /* current cylinder unknown, must seek */
139 #define NO_DENS 100 /* current media unknown */
140 #define BSY_IDLE 0 /* busy doing nothing */
141 #define BSY_IO 1 /* busy doing I/O */
142 #define BSY_WAKEN 2 /* got a wakeup call */
143
144 /* Seven combinations of diskette/drive are supported.
145 *
146 * # Diskette Drive Sectors Tracks Rotation Data-rate Comment
147 * 0 360K 360K 9 40 300 RPM 250 kbps Standard PC DSDD
148 * 1 1.2M 1.2M 15 80 360 RPM 500 kbps AT disk in AT drive
149 * 2 360K 720K 9 40 300 RPM 250 kbps Quad density PC
150 * 3 720K 720K 9 80 300 RPM 250 kbps Toshiba, et al.
151 * 4 360K 1.2M 9 40 360 RPM 300 kbps PC disk in AT drive
152 * 5 720K 1.2M 9 80 360 RPM 300 kbps Toshiba in AT drive
153 * 6 1.44M 1.44M 18 80 300 RPM 500 kbps PS/2, et al.
154 *
155 * In addition, 720K diskettes can be read in 1.44MB drives, but that does
156 * not need a different set of parameters. This combination uses
157 *
158 * 3 720K 1.44M 9 80 300 RPM 250 kbps PS/2, et al.
159 */
160 PRIVATE struct density {
161 u8_t secpt; /* sectors per track */
162 u8_t cyls; /* tracks per side */
163 u8_t steps; /* steps per cylinder (2 = double step) */
164 u8_t test; /* sector to try for density test */
165 u8_t rate; /* data rate (2=250, 1=300, 0=500 kbps) */
166 u8_t start; /* motor start (clock ticks) */
167 u8_t gap; /* gap size */
168 u8_t spec1; /* first specify byte (SRT/HUT) */
169 } fdensity[NT] = {
170 { 9, 40, 1, 4*9, 2, 4*HZ/8, 0x2A, 0xDF }, /* 360K / 360K */
171 { 15, 80, 1, 14, 0, 4*HZ/8, 0x1B, 0xDF }, /* 1.2M / 1.2M */
172 { 9, 40, 2, 2*9, 2, 4*HZ/8, 0x2A, 0xDF }, /* 360K / 720K */
173 { 9, 80, 1, 4*9, 2, 6*HZ/8, 0x2A, 0xDF }, /* 720K / 720K */
174 { 9, 40, 2, 2*9, 1, 4*HZ/8, 0x23, 0xDF }, /* 360K / 1.2M */
175 { 9, 80, 1, 4*9, 1, 4*HZ/8, 0x23, 0xDF }, /* 720K / 1.2M */
176 { 18, 80, 1, 17, 0, 6*HZ/8, 0x1B, 0xCF }, /* 1.44M / 1.44M */
177 };
178
179 /* The following table is used with the test_sector array to recognize a
180 * drive/floppy combination. The sector to test has been determined by
181 * looking at the differences in gap size, sectors/track, and double stepping.
182 * This means that types 0 and 3 can't be told apart, only the motor start
183 * time differs. If a read test succeeds then the drive is limited to the
184 * set of densities it can support to avoid unnecessary tests in the future.
185 */
186
187 #define b(d) (1 << (d)) /* bit for density d. */
188
189 PRIVATE struct test_order {
190 u8_t t_density; /* floppy/drive type */
191 u8_t t_class; /* limit drive to this class of densities */
192 } test_order[NT-1] = {
193 { 6, b(3) | b(6) }, /* 1.44M {720K, 1.44M} */
194 { 1, b(1) | b(4) | b(5) }, /* 1.2M {1.2M, 360K, 720K} */
195 { 3, b(2) | b(3) | b(6) }, /* 720K {360K, 720K, 1.44M} */
196 { 4, b(1) | b(4) | b(5) }, /* 360K {1.2M, 360K, 720K} */
197 { 5, b(1) | b(4) | b(5) }, /* 720K {1.2M, 360K, 720K} */
198 { 2, b(2) | b(3) }, /* 360K {360K, 720K} */
199 /* Note that type 0 is missing, type 3 can read/write it too, which is
200 * why the type 3 parameters have been pessimized to be like type 0.
201 */
202 };
203
204 /* Variables. */
205 PRIVATE struct floppy { /* main drive struct, one entry per drive */
206 unsigned fl_curcyl; /* current cylinder */
207 unsigned fl_hardcyl; /* hardware cylinder, as opposed to: */
208 unsigned fl_cylinder; /* cylinder number addressed */
209 unsigned fl_sector; /* sector addressed */
210 unsigned fl_head; /* head number addressed */
211 char fl_calibration; /* CALIBRATED or UNCALIBRATED */
212 u8_t fl_density; /* NO_DENS = ?, 0 = 360K; 1 = 360K/1.2M; etc.*/
213 u8_t fl_class; /* bitmap for possible densities */
214 timer_t fl_tmr_stop; /* timer to stop motor */
215 struct device fl_geom; /* Geometry of the drive */
216 struct device fl_part[NR_PARTITIONS]; /* partition's base & size */
217 } floppy[NR_DRIVES];
218
219 PRIVATE int irq_hook_id; /* id of irq hook at the kernel */
220 PRIVATE int motor_status; /* bitmap of current motor status */
221 PRIVATE int need_reset; /* set to 1 when controller must be reset */
222 PRIVATE unsigned f_drive; /* selected drive */
223 PRIVATE unsigned f_device; /* selected minor device */
224 PRIVATE struct floppy *f_fp; /* current drive */
225 PRIVATE struct density *f_dp; /* current density parameters */
226 PRIVATE struct density *prev_dp;/* previous density parameters */
227 PRIVATE unsigned f_sectors; /* equal to f_dp->secpt (needed a lot) */
228 PRIVATE u16_t f_busy; /* BSY_IDLE, BSY_IO, BSY_WAKEN */
229 PRIVATE struct device *f_dv; /* device's base and size */
230 PRIVATE struct disk_parameter_s fmt_param; /* parameters for format */
231 PRIVATE u8_t f_results[MAX_RESULTS];/* the controller can give lots of output */
232
233 /* The floppy uses various timers. These are managed by the floppy driver
234 * itself, because only a single synchronous alarm is available per process.
235 * Besides the 'f_tmr_timeout' timer below, the floppy structure for each
236 * floppy disk drive contains a 'fl_tmr_stop' timer.
237 */
238 PRIVATE timer_t f_tmr_timeout; /* timer for various timeouts */
239 PRIVATE timer_t *f_timers; /* queue of floppy timers */
240 PRIVATE clock_t f_next_timeout; /* the next timeout time */
241 FORWARD _PROTOTYPE( void f_expire_tmrs, (struct driver *dp, message *m_ptr) );
242 FORWARD _PROTOTYPE( void f_set_timer, (timer_t *tp, clock_t delta,
243 tmr_func_t watchdog) );
244 FORWARD _PROTOTYPE( void stop_motor, (timer_t *tp) );
245 FORWARD _PROTOTYPE( void f_timeout, (timer_t *tp) );
246
247 FORWARD _PROTOTYPE( struct device *f_prepare, (int device) );
248 FORWARD _PROTOTYPE( char *f_name, (void) );
249 FORWARD _PROTOTYPE( void f_cleanup, (void) );
250 FORWARD _PROTOTYPE( int f_transfer, (int proc_nr, int opcode, off_t position,
251 iovec_t *iov, unsigned nr_req) );
252 FORWARD _PROTOTYPE( int dma_setup, (int opcode) );
253 FORWARD _PROTOTYPE( void start_motor, (void) );
254 FORWARD _PROTOTYPE( int seek, (void) );
255 FORWARD _PROTOTYPE( int fdc_transfer, (int opcode) );
256 FORWARD _PROTOTYPE( int fdc_results, (void) );
257 FORWARD _PROTOTYPE( int fdc_command, (u8_t *cmd, int len) );
258 FORWARD _PROTOTYPE( void fdc_out, (int val) );
259 FORWARD _PROTOTYPE( int recalibrate, (void) );
260 FORWARD _PROTOTYPE( void f_reset, (void) );
261 FORWARD _PROTOTYPE( int f_intr_wait, (void) );
262 FORWARD _PROTOTYPE( int read_id, (void) );
263 FORWARD _PROTOTYPE( int f_do_open, (struct driver *dp, message *m_ptr) );
264 FORWARD _PROTOTYPE( void floppy_stop, (struct driver *dp, message *m_ptr));
265 FORWARD _PROTOTYPE( int test_read, (int density) );
266 FORWARD _PROTOTYPE( void f_geometry, (struct partition *entry) );
267
268 /* Entry points to this driver. */
269 PRIVATE struct driver f_dtab = {
270 f_name, /* current device's name */
271 f_do_open, /* open or mount request, sense type of diskette */
272 do_nop, /* nothing on a close */
273 do_diocntl, /* get or set a partitions geometry */
274 f_prepare, /* prepare for I/O on a given minor device */
275 f_transfer, /* do the I/O */
276 f_cleanup, /* cleanup before sending reply to user process */
277 f_geometry, /* tell the geometry of the diskette */
278 floppy_stop, /* floppy cleanup on shutdown */
279 f_expire_tmrs,/* expire all alarm timers */
280 nop_cancel,
281 nop_select,
282 NULL,
283 NULL
284 };
285
286 /*===========================================================================*
287 * floppy_task *
288 *===========================================================================*/
289 PUBLIC void main()
290 {
291 /* Initialize the floppy structure and the timers. */
292
293 struct floppy *fp;
294 int s;
295 struct sigaction sa;
296
297 sa.sa_handler = SIG_MESS;
298 sigemptyset(&sa.sa_mask);
299 sa.sa_flags = 0;
300 if (sigaction(SIGTERM,&sa,NULL)<0) panic("floppy","sigaction failed", errno);
301 signal(SIGTERM, SIG_IGN);
302
303 f_next_timeout = TMR_NEVER;
304 tmr_inittimer(&f_tmr_timeout);
305
306 for (fp = &floppy[0]; fp < &floppy[NR_DRIVES]; fp++) {
307 fp->fl_curcyl = NO_CYL;
308 fp->fl_density = NO_DENS;
309 fp->fl_class = ~0;
310 tmr_inittimer(&fp->fl_tmr_stop);
311 }
312
313 /* Set IRQ policy, only request notifications, do not automatically
314 * reenable interrupts. ID return on interrupt is the IRQ line number.
315 */
316 irq_hook_id = FLOPPY_IRQ;
317 if ((s=sys_irqsetpolicy(FLOPPY_IRQ, 0, &irq_hook_id )) != OK)
318 panic("FLOPPY", "Couldn't set IRQ policy", s);
319 if ((s=sys_irqenable(&irq_hook_id)) != OK)
320 panic("FLOPPY", "Couldn't enable IRQs", s);
321
322 driver_task(&f_dtab);
323 }
324
325 /*===========================================================================*
326 * f_expire_tmrs *
327 *===========================================================================*/
328 PRIVATE void f_expire_tmrs(struct driver *dp, message *m_ptr)
329 {
330 /* A synchronous alarm message was received. Check if there are any expired
331 * timers. Possibly reschedule the next alarm.
332 */
333 clock_t now; /* current time */
334 timer_t *tp;
335 int s;
336
337 /* Get the current time to compare the timers against. */
338 if ((s=getuptime(&now)) != OK)
339 panic("FLOPPY","Couldn't get uptime from clock.", s);
340
341 /* Scan the timers queue for expired timers. Dispatch the watchdog function
342 * for each expired timers. FLOPPY watchdog functions are f_tmr_timeout()
343 * and stop_motor(). Possibly a new alarm call must be scheduled.
344 */
345 tmrs_exptimers(&f_timers, now, NULL);
346 if (f_timers == NULL) {
347 f_next_timeout = TMR_NEVER;
348 } else { /* set new sync alarm */
349 f_next_timeout = f_timers->tmr_exp_time;
350 if ((s=sys_setalarm(f_next_timeout, 1)) != OK)
351 panic("FLOPPY","Couldn't set synchronous alarm.", s);
352 }
353 }
354
355 /*===========================================================================*
356 * f_set_timer *
357 *===========================================================================*/
358 PRIVATE void f_set_timer(tp, delta, watchdog)
359 timer_t *tp; /* timer to be set */
360 clock_t delta; /* in how many ticks */
361 tmr_func_t watchdog; /* watchdog function to be called */
362 {
363 clock_t now; /* current time */
364 int s;
365
366 /* Get the current time. */
367 if ((s=getuptime(&now)) != OK)
368 panic("FLOPPY","Couldn't get uptime from clock.", s);
369
370 /* Add the timer to the local timer queue. */
371 tmrs_settimer(&f_timers, tp, now + delta, watchdog, NULL);
372
373 /* Possibly reschedule an alarm call. This happens when the front of the
374 * timers queue was reinserted at another position, i.e., when a timer was
375 * reset, or when a new timer was added in front.
376 */
377 if (f_timers->tmr_exp_time != f_next_timeout) {
378 f_next_timeout = f_timers->tmr_exp_time;
379 if ((s=sys_setalarm(f_next_timeout, 1)) != OK)
380 panic("FLOPPY","Couldn't set synchronous alarm.", s);
381 }
382 }
383
384 /*===========================================================================*
385 * f_prepare *
386 *===========================================================================*/
387 PRIVATE struct device *f_prepare(device)
388 int device;
389 {
390 /* Prepare for I/O on a device. */
391
392 f_device = device;
393 f_drive = device & ~(DEV_TYPE_BITS | FORMAT_DEV_BIT);
394 if (f_drive < 0 || f_drive >= NR_DRIVES) return(NIL_DEV);
395
396 f_fp = &floppy[f_drive];
397 f_dv = &f_fp->fl_geom;
398 if (f_fp->fl_density < NT) {
399 f_dp = &fdensity[f_fp->fl_density];
400 f_sectors = f_dp->secpt;
401 f_fp->fl_geom.dv_size = mul64u((long) (NR_HEADS * f_sectors
402 * f_dp->cyls), SECTOR_SIZE);
403 }
404
405 /* A partition? */
406 if ((device &= DEV_TYPE_BITS) >= MINOR_fd0p0)
407 f_dv = &f_fp->fl_part[(device - MINOR_fd0p0) >> DEV_TYPE_SHIFT];
408
409 return f_dv;
410 }
411
412 /*===========================================================================*
413 * f_name *
414 *===========================================================================*/
415 PRIVATE char *f_name()
416 {
417 /* Return a name for the current device. */
418 static char name[] = "fd0";
419
420 name[2] = '' + f_drive;
421 return name;
422 }
423
424 /*===========================================================================*
425 * f_cleanup *
426 *===========================================================================*/
427 PRIVATE void f_cleanup()
428 {
429 /* Start a timer to turn the motor off in a few seconds. */
430 tmr_arg(&f_fp->fl_tmr_stop)->ta_int = f_drive;
431 f_set_timer(&f_fp->fl_tmr_stop, MOTOR_OFF, stop_motor);
432
433 /* Exiting the floppy driver, so forget where we are. */
434 f_fp->fl_sector = NO_SECTOR;
435 }
436
437 /*===========================================================================*
438 * f_transfer *
439 *===========================================================================*/
440 PRIVATE int f_transfer(proc_nr, opcode, position, iov, nr_req)
441 int proc_nr; /* process doing the request */
442 int opcode; /* DEV_GATHER or DEV_SCATTER */
443 off_t position; /* offset on device to read or write */
444 iovec_t *iov; /* pointer to read or write request vector */
445 unsigned nr_req; /* length of request vector */
446 {
447 struct floppy *fp = f_fp;
448 iovec_t *iop, *iov_end = iov + nr_req;
449 int s, r, errors;
450 unsigned block; /* Seen any 32M floppies lately? */
451 unsigned nbytes, count, chunk, sector;
452 unsigned long dv_size = cv64ul(f_dv->dv_size);
453 vir_bytes user_addr;
454 vir_bytes uaddrs[MAX_SECTORS], *up;
455 u8_t cmd[3];
456
457 /* Check disk address. */
458 if ((position & SECTOR_MASK) != 0) return(EINVAL);
459
460 errors = 0;
461 while (nr_req > 0) {
462 /* How many bytes to transfer? */
463 nbytes = 0;
464 for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size;
465
466 /* Which block on disk and how close to EOF? */
467 if (position >= dv_size) return(OK); /* At EOF */
468 if (position + nbytes > dv_size) nbytes = dv_size - position;
469 block = div64u(add64ul(f_dv->dv_base, position), SECTOR_SIZE);
470
471 if ((nbytes & SECTOR_MASK) != 0) return(EINVAL);
472
473 /* Using a formatting device? */
474 if (f_device & FORMAT_DEV_BIT) {
475 if (opcode != DEV_SCATTER) return(EIO);
476 if (iov->iov_size < SECTOR_SIZE + sizeof(fmt_param))
477 return(EINVAL);
478
479 if ((s=sys_datacopy(proc_nr, iov->iov_addr + SECTOR_SIZE,
480 SELF, (vir_bytes) &fmt_param,
481 (phys_bytes) sizeof(fmt_param))) != OK)
482 panic("FLOPPY", "Sys_vircopy failed", s);
483
484 /* Check that the number of sectors in the data is reasonable,
485 * to avoid division by 0. Leave checking of other data to
486 * the FDC.
487 */
488 if (fmt_param.sectors_per_cylinder == 0) return(EIO);
489
490 /* Only the first sector of the parameters now needed. */
491 iov->iov_size = nbytes = SECTOR_SIZE;
492 }
493
494 /* Only try one sector if there were errors. */
495 if (errors > 0) nbytes = SECTOR_SIZE;
496
497 /* Compute cylinder and head of the track to access. */
498 fp->fl_cylinder = block / (NR_HEADS * f_sectors);
499 fp->fl_hardcyl = fp->fl_cylinder * f_dp->steps;
500 fp->fl_head = (block % (NR_HEADS * f_sectors)) / f_sectors;
501
502 /* For each sector on this track compute the user address it is to
503 * go or to come from.
504 */
505 for (up = uaddrs; up < uaddrs + MAX_SECTORS; up++) *up = 0;
506 count = 0;
507 iop = iov;
508 sector = block % f_sectors;
509 for (;;) {
510 user_addr = iop->iov_addr;
511 chunk = iop->iov_size;
512 if ((chunk & SECTOR_MASK) != 0) return(EINVAL);
513
514 while (chunk > 0) {
515 uaddrs[sector++] = user_addr;
516 chunk -= SECTOR_SIZE;
517 user_addr += SECTOR_SIZE;
518 count += SECTOR_SIZE;
519 if (sector == f_sectors || count == nbytes)
520 goto track_set_up;
521 }
522 iop++;
523 }
524 track_set_up:
525
526 /* First check to see if a reset is needed. */
527 if (need_reset) f_reset();
528
529 /* See if motor is running; if not, turn it on and wait. */
530 start_motor();
531
532 /* Set the stepping rate and data rate */
533 if (f_dp != prev_dp) {
534 cmd[0] = FDC_SPECIFY;
535 cmd[1] = f_dp->spec1;
536 cmd[2] = SPEC2;
537 (void) fdc_command(cmd, 3);
538 if ((s=sys_outb(FDC_RATE, f_dp->rate)) != OK)
539 panic("FLOPPY","Sys_outb failed", s);
540 prev_dp = f_dp;
541 }
542
543 /* If we are going to a new cylinder, perform a seek. */
544 r = seek();
545
546 /* Avoid read_id() if we don't plan to read much. */
547 if (fp->fl_sector == NO_SECTOR && count < (6 * SECTOR_SIZE))
548 fp->fl_sector = 0;
549
550 for (nbytes = 0; nbytes < count; nbytes += SECTOR_SIZE) {
551 if (fp->fl_sector == NO_SECTOR) {
552 /* Find out what the current sector is. This often
553 * fails right after a seek, so try it twice.
554 */
555 if (r == OK && read_id() != OK) r = read_id();
556 }
557
558 /* Look for the next job in uaddrs[] */
559 if (r == OK) {
560 for (;;) {
561 if (fp->fl_sector >= f_sectors)
562 fp->fl_sector = 0;
563
564 up = &uaddrs[fp->fl_sector];
565 if (*up != 0) break;
566 fp->fl_sector++;
567 }
568 }
569
570 if (r == OK && opcode == DEV_SCATTER) {
571 /* Copy the user bytes to the DMA buffer. */
572 if ((s=sys_datacopy(proc_nr, *up, SELF,
573 (vir_bytes) tmp_buf,
574 (phys_bytes) SECTOR_SIZE)) != OK)
575 panic("FLOPPY", "Sys_vircopy failed", s);
576 }
577
578 /* Set up the DMA chip and perform the transfer. */
579 if (r == OK) {
580 if (dma_setup(opcode) != OK) {
581 /* This can only fail for addresses above 16MB
582 * that cannot be handled by the controller,
583 * because it uses 24-bit addressing.
584 */
585 return(EIO);
586 }
587 r = fdc_transfer(opcode);
588 }
589
590 if (r == OK && opcode == DEV_GATHER) {
591 /* Copy the DMA buffer to user space. */
592 if ((s=sys_datacopy(SELF, (vir_bytes) tmp_buf,
593 proc_nr, *up,
594 (phys_bytes) SECTOR_SIZE)) != OK)
595 panic("FLOPPY", "Sys_vircopy failed", s);
596 }
597
598 if (r != OK) {
599 /* Don't retry if write protected or too many errors. */
600 if (err_no_retry(r) || ++errors == MAX_ERRORS) {
601 return(EIO);
602 }
603
604 /* Recalibrate if halfway. */
605 if (errors == MAX_ERRORS / 2)
606 fp->fl_calibration = UNCALIBRATED;
607
608 nbytes = 0;
609 break; /* retry */
610 }
611 }
612
613 /* Book the bytes successfully transferred. */
614 position += nbytes;
615 for (;;) {
616 if (nbytes < iov->iov_size) {
617 /* Not done with this one yet. */
618 iov->iov_addr += nbytes;
619 iov->iov_size -= nbytes;
620 break;
621 }
622 nbytes -= iov->iov_size;
623 iov->iov_addr += iov->iov_size;
624 iov->iov_size = 0;
625 if (nbytes == 0) {
626 /* The rest is optional, so we return to give FS a
627 * chance to think it over.
628 */
629 return(OK);
630 }
631 iov++;
632 nr_req--;
633 }
634 }
635 return(OK);
636 }
637
638 /*===========================================================================*
639 * dma_setup *
640 *===========================================================================*/
641 PRIVATE int dma_setup(opcode)
642 int opcode; /* DEV_GATHER or DEV_SCATTER */
643 {
644 /* The IBM PC can perform DMA operations by using the DMA chip. To use it,
645 * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
646 * to be read from or written to, the byte count minus 1, and a read or write
647 * opcode. This routine sets up the DMA chip. Note that the chip is not
648 * capable of doing a DMA across a 64K boundary (e.g., you can't read a
649 * 512-byte block starting at physical address 65520).
650 *
651 * Warning! Also note that it's not possible to do DMA above 16 MB because
652 * the ISA bus uses 24-bit addresses. Addresses above 16 MB therefore will
653 * be interpreted modulo 16 MB, dangerously overwriting arbitrary memory.
654 * A check here denies the I/O if the address is out of range.
655 */
656 pvb_pair_t byte_out[9];
657 int s;
658
659 /* First check the DMA memory address not to exceed maximum. */
660 if (tmp_phys != (tmp_phys & DMA_ADDR_MASK)) {
661 report("FLOPPY", "DMA denied because address out of range", NO_NUM);
662 return(EIO);
663 }
664
665 /* Set up the DMA registers. (The comment on the reset is a bit strong,
666 * it probably only resets the floppy channel.)
667 */
668 pv_set(byte_out[0], DMA_INIT, DMA_RESET_VAL); /* reset the dma controller */
669 pv_set(byte_out[1], DMA_FLIPFLOP, 0); /* write anything to reset it */
670 pv_set(byte_out[2], DMA_MODE, opcode == DEV_SCATTER ? DMA_WRITE : DMA_READ);
671 pv_set(byte_out[3], DMA_ADDR, (unsigned) tmp_phys >> 0);
672 pv_set(byte_out[4], DMA_ADDR, (unsigned) tmp_phys >> 8);
673 pv_set(byte_out[5], DMA_TOP, (unsigned) (tmp_phys >> 16));
674 pv_set(byte_out[6], DMA_COUNT, (((SECTOR_SIZE - 1) >> 0) & 0xff));
675 pv_set(byte_out[7], DMA_COUNT, (SECTOR_SIZE - 1) >> 8);
676 pv_set(byte_out[8], DMA_INIT, 2); /* some sort of enable */
677
678 if ((s=sys_voutb(byte_out, 9)) != OK)
679 panic("FLOPPY","Sys_voutb in dma_setup() failed", s);
680 return(OK);
681 }
682
683 /*===========================================================================*
684 * start_motor *
685 *===========================================================================*/
686 PRIVATE void start_motor()
687 {
688 /* Control of the floppy disk motors is a big pain. If a motor is off, you
689 * have to turn it on first, which takes 1/2 second. You can't leave it on
690 * all the time, since that would wear out the diskette. However, if you turn
691 * the motor off after each operation, the system performance will be awful.
692 * The compromise used here is to leave it on for a few seconds after each
693 * operation. If a new operation is started in that interval, it need not be
694 * turned on again. If no new operation is started, a timer goes off and the
695 * motor is turned off. I/O port DOR has bits to control each of 4 drives.
696 */
697
698 int s, motor_bit, running;
699 message mess;
700
701 motor_bit = 1 << f_drive; /* bit mask for this drive */
702 running = motor_status & motor_bit; /* nonzero if this motor is running */
703 motor_status |= motor_bit; /* want this drive running too */
704
705 if ((s=sys_outb(DOR,
706 (motor_status << MOTOR_SHIFT) | ENABLE_INT | f_drive)) != OK)
707 panic("FLOPPY","Sys_outb in start_motor() failed", s);
708
709 /* If the motor was already running, we don't have to wait for it. */
710 if (running) return; /* motor was already running */
711
712 /* Set an alarm timer to force a timeout if the hardware does not interrupt
713 * in time. Expect HARD_INT message, but check for SYN_ALARM timeout.
714 */
715 f_set_timer(&f_tmr_timeout, f_dp->start, f_timeout);
716 f_busy = BSY_IO;
717 do {
718 receive(ANY, &mess);
719 if (mess.m_type == SYN_ALARM) {
720 f_expire_tmrs(NULL, NULL);
721 } else if(mess.m_type == DEV_PING) {
722 notify(mess.m_source);
723 } else {
724 f_busy = BSY_IDLE;
725 }
726 } while (f_busy == BSY_IO);
727 f_fp->fl_sector = NO_SECTOR;
728 }
729
730 /*===========================================================================*
731 * stop_motor *
732 *===========================================================================*/
733 PRIVATE void stop_motor(tp)
734 timer_t *tp;
735 {
736 /* This routine is called from an alarm timer after several seconds have
737 * elapsed with no floppy disk activity. It turns the drive motor off.
738 */
739 int s;
740 motor_status &= ~(1 << tmr_arg(tp)->ta_int);
741 if ((s=sys_outb(DOR, (motor_status << MOTOR_SHIFT) | ENABLE_INT)) != OK)
742 panic("FLOPPY","Sys_outb in stop_motor() failed", s);
743 }
744
745 /*===========================================================================*
746 * floppy_stop *
747 *===========================================================================*/
748 PRIVATE void floppy_stop(struct driver *dp, message *m_ptr)
749 {
750 /* Stop all activity and cleanly exit with the system. */
751 int s;
752 sigset_t sigset = m_ptr->NOTIFY_ARG;
753 if (sigismember(&sigset, SIGTERM) || sigismember(&sigset, SIGKSTOP)) {
754 if ((s=sys_outb(DOR, ENABLE_INT)) != OK)
755 panic("FLOPPY","Sys_outb in floppy_stop() failed", s);
756 exit(0);
757 }
758 }
759
760 /*===========================================================================*
761 * seek *
762 *===========================================================================*/
763 PRIVATE int seek()
764 {
765 /* Issue a SEEK command on the indicated drive unless the arm is already
766 * positioned on the correct cylinder.
767 */
768
769 struct floppy *fp = f_fp;
770 int r;
771 message mess;
772 u8_t cmd[3];
773
774 /* Are we already on the correct cylinder? */
775 if (fp->fl_calibration == UNCALIBRATED)
776 if (recalibrate() != OK) return(ERR_SEEK);
777 if (fp->fl_curcyl == fp->fl_hardcyl) return(OK);
778
779 /* No. Wrong cylinder. Issue a SEEK and wait for interrupt. */
780 cmd[0] = FDC_SEEK;
781 cmd[1] = (fp->fl_head << 2) | f_drive;
782 cmd[2] = fp->fl_hardcyl;
783 if (fdc_command(cmd, 3) != OK) return(ERR_SEEK);
784 if (f_intr_wait() != OK) return(ERR_TIMEOUT);
785
786 /* Interrupt has been received. Check drive status. */
787 fdc_out(FDC_SENSE); /* probe FDC to make it return status */
788 r = fdc_results(); /* get controller status bytes */
789 if (r != OK || (f_results[ST0] & ST0_BITS_SEEK) != SEEK_ST0
790 || f_results[ST1] != fp->fl_hardcyl) {
791 /* seek failed, may need a recalibrate */
792 return(ERR_SEEK);
793 }
794 /* Give head time to settle on a format, no retrying here! */
795 if (f_device & FORMAT_DEV_BIT) {
796 /* Set a synchronous alarm to force a timeout if the hardware does
797 * not interrupt. Expect HARD_INT, but check for SYN_ALARM timeout.
798 */
799 f_set_timer(&f_tmr_timeout, HZ/30, f_timeout);
800 f_busy = BSY_IO;
801 do {
802 receive(ANY, &mess);
803 if (mess.m_type == SYN_ALARM) {
804 f_expire_tmrs(NULL, NULL);
805 } else if(mess.m_type == DEV_PING) {
806 notify(mess.m_source);
807 } else {
808 f_busy = BSY_IDLE;
809 }
810 } while (f_busy == BSY_IO);
811 }
812 fp->fl_curcyl = fp->fl_hardcyl;
813 fp->fl_sector = NO_SECTOR;
814 return(OK);
815 }
816
817 /*===========================================================================*
818 * fdc_transfer *
819 *===========================================================================*/
820 PRIVATE int fdc_transfer(opcode)
821 int opcode; /* DEV_GATHER or DEV_SCATTER */
822 {
823 /* The drive is now on the proper cylinder. Read, write or format 1 block. */
824
825 struct floppy *fp = f_fp;
826 int r, s;
827 u8_t cmd[9];
828
829 /* Never attempt a transfer if the drive is uncalibrated or motor is off. */
830 if (fp->fl_calibration == UNCALIBRATED) return(ERR_TRANSFER);
831 if ((motor_status & (1 << f_drive)) == 0) return(ERR_TRANSFER);
832
833 /* The command is issued by outputting several bytes to the controller chip.
834 */
835 if (f_device & FORMAT_DEV_BIT) {
836 cmd[0] = FDC_FORMAT;
837 cmd[1] = (fp->fl_head << 2) | f_drive;
838 cmd[2] = fmt_param.sector_size_code;
839 cmd[3] = fmt_param.sectors_per_cylinder;
840 cmd[4] = fmt_param.gap_length_for_format;
841 cmd[5] = fmt_param.fill_byte_for_format;
842 if (fdc_command(cmd, 6) != OK) return(ERR_TRANSFER);
843 } else {
844 cmd[0] = opcode == DEV_SCATTER ? FDC_WRITE : FDC_READ;
845 cmd[1] = (fp->fl_head << 2) | f_drive;
846 cmd[2] = fp->fl_cylinder;
847 cmd[3] = fp->fl_head;
848 cmd[4] = BASE_SECTOR + fp->fl_sector;
849 cmd[5] = SECTOR_SIZE_CODE;
850 cmd[6] = f_sectors;
851 cmd[7] = f_dp->gap; /* sector gap */
852 cmd[8] = DTL; /* data length */
853 if (fdc_command(cmd, 9) != OK) return(ERR_TRANSFER);
854 }
855
856 /* Block, waiting for disk interrupt. */
857 if (f_intr_wait() != OK) {
858 printf("%s: disk interrupt timed out.\n", f_name());
859 return(ERR_TIMEOUT);
860 }
861
862 /* Get controller status and check for errors. */
863 r = fdc_results();
864 if (r != OK) return(r);
865
866 if (f_results[ST1] & WRITE_PROTECT) {
867 printf("%s: diskette is write protected.\n", f_name());
868 return(ERR_WR_PROTECT);
869 }
870
871 if ((f_results[ST0] & ST0_BITS_TRANS) != TRANS_ST0) return(ERR_TRANSFER);
872 if (f_results[ST1] | f_results[ST2]) return(ERR_TRANSFER);
873
874 if (f_device & FORMAT_DEV_BIT) return(OK);
875
876 /* Compare actual numbers of sectors transferred with expected number. */
877 s = (f_results[ST_CYL] - fp->fl_cylinder) * NR_HEADS * f_sectors;
878 s += (f_results[ST_HEAD] - fp->fl_head) * f_sectors;
879 s += (f_results[ST_SEC] - BASE_SECTOR - fp->fl_sector);
880 if (s != 1) return(ERR_TRANSFER);
881
882 /* This sector is next for I/O: */
883 fp->fl_sector = f_results[ST_SEC] - BASE_SECTOR;
884 #if 0
885 if (processor < 386) fp->fl_sector++; /* Old CPU can't keep up. */
886 #endif
887 return(OK);
888 }
889
890 /*===========================================================================*
891 * fdc_results *
892 *===========================================================================*/
893 PRIVATE int fdc_results()
894 {
895 /* Extract results from the controller after an operation, then allow floppy
896 * interrupts again.
897 */
898
899 int s, result_nr, status;
900 clock_t t0,t1;
901
902 /* Extract bytes from FDC until it says it has no more. The loop is
903 * really an outer loop on result_nr and an inner loop on status.
904 * A timeout flag alarm is set.
905 */
906 result_nr = 0;
907 getuptime(&t0);
908 do {
909 /* Reading one byte is almost a mirror of fdc_out() - the DIRECTION
910 * bit must be set instead of clear, but the CTL_BUSY bit destroys
911 * the perfection of the mirror.
912 */
913 if ((s=sys_inb(FDC_STATUS, &status)) != OK)
914 panic("FLOPPY","Sys_inb in fdc_results() failed", s);
915 status &= (MASTER | DIRECTION | CTL_BUSY);
916 if (status == (MASTER | DIRECTION | CTL_BUSY)) {
917 if (result_nr >= MAX_RESULTS) break; /* too many results */
918 if ((s=sys_inb(FDC_DATA, &f_results[result_nr])) != OK)
919 panic("FLOPPY","Sys_inb in fdc_results() failed", s);
920 result_nr ++;
921 continue;
922 }
923 if (status == MASTER) { /* all read */
924 if ((s=sys_irqenable(&irq_hook_id)) != OK)
925 panic("FLOPPY", "Couldn't enable IRQs", s);
926
927 return(OK); /* only good exit */
928 }
929 } while ( (s=getuptime(&t1))==OK && (t1-t0) < TIMEOUT_TICKS );
930 if (OK!=s) printf("FLOPPY: warning, getuptime failed: %d\n", s);
931 need_reset = TRUE; /* controller chip must be reset */
932
933 if ((s=sys_irqenable(&irq_hook_id)) != OK)
934 panic("FLOPPY", "Couldn't enable IRQs", s);
935 return(ERR_STATUS);
936 }
937
938 /*===========================================================================*
939 * fdc_command *
940 *===========================================================================*/
941 PRIVATE int fdc_command(cmd, len)
942 u8_t *cmd; /* command bytes */
943 int len; /* command length */
944 {
945 /* Output a command to the controller. */
946
947 /* Set a synchronous alarm to force a timeout if the hardware does
948 * not interrupt. Expect HARD_INT, but check for SYN_ALARM timeout.
949 * Note that the actual check is done by the code that issued the
950 * fdc_command() call.
951 */
952 f_set_timer(&f_tmr_timeout, WAKEUP, f_timeout);
953
954 f_busy = BSY_IO;
955 while (len > 0) {
956 fdc_out(*cmd++);
957 len--;
958 }
959 return(need_reset ? ERR_DRIVE : OK);
960 }
961
962 /*===========================================================================*
963 * fdc_out *
964 *===========================================================================*/
965 PRIVATE void fdc_out(val)
966 int val; /* write this byte to floppy disk controller */
967 {
968 /* Output a byte to the controller. This is not entirely trivial, since you
969 * can only write to it when it is listening, and it decides when to listen.
970 * If the controller refuses to listen, the FDC chip is given a hard reset.
971 */
972 clock_t t0, t1;
973 int s, status;
974
975 if (need_reset) return; /* if controller is not listening, return */
976
977 /* It may take several tries to get the FDC to accept a command. */
978 getuptime(&t0);
979 do {
980 if ( (s=getuptime(&t1))==OK && (t1-t0) > TIMEOUT_TICKS ) {
981 if (OK!=s) printf("FLOPPY: warning, getuptime failed: %d\n", s);
982 need_reset = TRUE; /* hit it over the head */
983 return;
984 }
985 if ((s=sys_inb(FDC_STATUS, &status)) != OK)
986 panic("FLOPPY","Sys_inb in fdc_out() failed", s);
987 }
988 while ((status & (MASTER | DIRECTION)) != (MASTER | 0));
989
990 if ((s=sys_outb(FDC_DATA, val)) != OK)
991 panic("FLOPPY","Sys_outb in fdc_out() failed", s);
992 }
993
994 /*===========================================================================*
995 * recalibrate *
996 *===========================================================================*/
997 PRIVATE int recalibrate()
998 {
999 /* The floppy disk controller has no way of determining its absolute arm
1000 * position (cylinder). Instead, it steps the arm a cylinder at a time and
1001 * keeps track of where it thinks it is (in software). However, after a
1002 * SEEK, the hardware reads information from the diskette telling where the
1003 * arm actually is. If the arm is in the wrong place, a recalibration is done,
1004 * which forces the arm to cylinder 0. This way the controller can get back
1005 * into sync with reality.
1006 */
1007
1008 struct floppy *fp = f_fp;
1009 int r;
1010 u8_t cmd[2];
1011
1012 /* Issue the RECALIBRATE command and wait for the interrupt. */
1013 cmd[0] = FDC_RECALIBRATE; /* tell drive to recalibrate itself */
1014 cmd[1] = f_drive; /* specify drive */
1015 if (fdc_command(cmd, 2) != OK) return(ERR_SEEK);
1016 if (f_intr_wait() != OK) return(ERR_TIMEOUT);
1017
1018 /* Determine if the recalibration succeeded. */
1019 fdc_out(FDC_SENSE); /* issue SENSE command to request results */
1020 r = fdc_results(); /* get results of the FDC_RECALIBRATE command*/
1021 fp->fl_curcyl = NO_CYL; /* force a SEEK next time */
1022 fp->fl_sector = NO_SECTOR;
1023 if (r != OK || /* controller would not respond */
1024 (f_results[ST0] & ST0_BITS_SEEK) != SEEK_ST0 || f_results[ST_PCN] != 0) {
1025 /* Recalibration failed. FDC must be reset. */
1026 need_reset = TRUE;
1027 return(ERR_RECALIBRATE);
1028 } else {
1029 /* Recalibration succeeded. */
1030 fp->fl_calibration = CALIBRATED;
1031 fp->fl_curcyl = f_results[ST_PCN];
1032 return(OK);
1033 }
1034 }
1035
1036 /*===========================================================================*
1037 * f_reset *
1038 *===========================================================================*/
1039 PRIVATE void f_reset()
1040 {
1041 /* Issue a reset to the controller. This is done after any catastrophe,
1042 * like the controller refusing to respond.
1043 */
1044 pvb_pair_t byte_out[2];
1045 int s,i;
1046 message mess;
1047
1048 /* Disable interrupts and strobe reset bit low. */
1049 need_reset = FALSE;
1050
1051 /* It is not clear why the next lock is needed. Writing 0 to DOR causes
1052 * interrupt, while the PC documentation says turning bit 8 off disables
1053 * interrupts. Without the lock:
1054 * 1) the interrupt handler sets the floppy mask bit in the 8259.
1055 * 2) writing ENABLE_INT to DOR causes the FDC to assert the interrupt
1056 * line again, but the mask stops the cpu being interrupted.
1057 * 3) the sense interrupt clears the interrupt (not clear which one).
1058 * and for some reason the reset does not work.
1059 */
1060 (void) fdc_command((u8_t *) 0, 0); /* need only the timer */
1061 motor_status = 0;
1062 pv_set(byte_out[0], DOR, 0); /* strobe reset bit low */
1063 pv_set(byte_out[1], DOR, ENABLE_INT); /* strobe it high again */
1064 if ((s=sys_voutb(byte_out, 2)) != OK)
1065 panic("FLOPPY", "Sys_voutb in f_reset() failed", s);
1066
1067 /* A synchronous alarm timer was set in fdc_command. Expect a HARD_INT
1068 * message to collect the reset interrupt, but be prepared to handle the
1069 * SYN_ALARM message on a timeout.
1070 */
1071 do {
1072 receive(ANY, &mess);
1073 if (mess.m_type == SYN_ALARM) {
1074 f_expire_tmrs(NULL, NULL);
1075 } else if(mess.m_type == DEV_PING) {
1076 notify(mess.m_source);
1077 } else { /* expect HARD_INT */
1078 f_busy = BSY_IDLE;
1079 }
1080 } while (f_busy == BSY_IO);
1081
1082 /* The controller supports 4 drives and returns a result for each of them.
1083 * Collect all the results now. The old version only collected the first
1084 * result. This happens to work for 2 drives, but it doesn't work for 3
1085 * or more drives, at least with only drives 0 and 2 actually connected
1086 * (the controller generates an extra interrupt for the middle drive when
1087 * drive 2 is accessed and the driver panics).
1088 *
1089 * It would be better to keep collecting results until there are no more.
1090 * For this, fdc_results needs to return the number of results (instead
1091 * of OK) when it succeeds.
1092 */
1093 for (i = 0; i < 4; i++) {
1094 fdc_out(FDC_SENSE); /* probe FDC to make it return status */
1095 (void) fdc_results(); /* flush controller */
1096 }
1097 for (i = 0; i < NR_DRIVES; i++) /* clear each drive */
1098 floppy[i].fl_calibration = UNCALIBRATED;
1099
1100 /* The current timing parameters must be specified again. */
1101 prev_dp = NULL;
1102 }
1103
1104 /*===========================================================================*
1105 * f_intr_wait *
1106 *===========================================================================*/
1107 PRIVATE int f_intr_wait()
1108 {
1109 /* Wait for an interrupt, but not forever. The FDC may have all the time of
1110 * the world, but we humans do not.
1111 */
1112 message mess;
1113
1114 /* We expect a HARD_INT message from the interrupt handler, but if there is
1115 * a timeout, a SYN_ALARM notification is received instead. If a timeout
1116 * occurs, report an error.
1117 */
1118 do {
1119 receive(ANY, &mess);
1120 if (mess.m_type == SYN_ALARM) {
1121 f_expire_tmrs(NULL, NULL);
1122 } else if(mess.m_type == DEV_PING) {
1123 notify(mess.m_source);
1124 } else {
1125 f_busy = BSY_IDLE;
1126 }
1127 } while (f_busy == BSY_IO);
1128
1129 if (f_busy == BSY_WAKEN) {
1130
1131 /* No interrupt from the FDC, this means that there is probably no
1132 * floppy in the drive. Get the FDC down to earth and return error.
1133 */
1134 need_reset = TRUE;
1135 return(ERR_TIMEOUT);
1136 }
1137 return(OK);
1138 }
1139
1140 /*===========================================================================*
1141 * f_timeout *
1142 *===========================================================================*/
1143 PRIVATE void f_timeout(tp)
1144 timer_t *tp;
1145 {
1146 /* This routine is called when a timer expires. Usually to tell that a
1147 * motor has spun up, but also to forge an interrupt when it takes too long
1148 * for the FDC to interrupt (no floppy in the drive). It sets a flag to tell
1149 * what has happened.
1150 */
1151 if (f_busy == BSY_IO) {
1152 f_busy = BSY_WAKEN;
1153 }
1154 }
1155
1156 /*===========================================================================*
1157 * read_id *
1158 *===========================================================================*/
1159 PRIVATE int read_id()
1160 {
1161 /* Determine current cylinder and sector. */
1162
1163 struct floppy *fp = f_fp;
1164 int result;
1165 u8_t cmd[2];
1166
1167 /* Never attempt a read id if the drive is uncalibrated or motor is off. */
1168 if (fp->fl_calibration == UNCALIBRATED) return(ERR_READ_ID);
1169 if ((motor_status & (1 << f_drive)) == 0) return(ERR_READ_ID);
1170
1171 /* The command is issued by outputting 2 bytes to the controller chip. */
1172 cmd[0] = FDC_READ_ID; /* issue the read id command */
1173 cmd[1] = (fp->fl_head << 2) | f_drive;
1174 if (fdc_command(cmd, 2) != OK) return(ERR_READ_ID);
1175 if (f_intr_wait() != OK) return(ERR_TIMEOUT);
1176
1177 /* Get controller status and check for errors. */
1178 result = fdc_results();
1179 if (result != OK) return(result);
1180
1181 if ((f_results[ST0] & ST0_BITS_TRANS) != TRANS_ST0) return(ERR_READ_ID);
1182 if (f_results[ST1] | f_results[ST2]) return(ERR_READ_ID);
1183
1184 /* The next sector is next for I/O: */
1185 fp->fl_sector = f_results[ST_SEC] - BASE_SECTOR + 1;
1186 return(OK);
1187 }
1188
1189 /*===========================================================================*
1190 * f_do_open *
1191 *===========================================================================*/
1192 PRIVATE int f_do_open(dp, m_ptr)
1193 struct driver *dp;
1194 message *m_ptr; /* pointer to open message */
1195 {
1196 /* Handle an open on a floppy. Determine diskette type if need be. */
1197
1198 int dtype;
1199 struct test_order *top;
1200
1201 /* Decode the message parameters. */
1202 if (f_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
1203
1204 dtype = f_device & DEV_TYPE_BITS; /* get density from minor dev */
1205 if (dtype >= MINOR_fd0p0) dtype = 0;
1206
1207 if (dtype != 0) {
1208 /* All types except 0 indicate a specific drive/medium combination.*/
1209 dtype = (dtype >> DEV_TYPE_SHIFT) - 1;
1210 if (dtype >= NT) return(ENXIO);
1211 f_fp->fl_density = dtype;
1212 (void) f_prepare(f_device); /* Recompute parameters. */
1213 return(OK);
1214 }
1215 if (f_device & FORMAT_DEV_BIT) return(EIO); /* Can't format /dev/fdN */
1216
1217 /* The device opened is /dev/fdN. Experimentally determine drive/medium.
1218 * First check fl_density. If it is not NO_DENS, the drive has been used
1219 * before and the value of fl_density tells what was found last time. Try
1220 * that first. If the motor is still running then assume nothing changed.
1221 */
1222 if (f_fp->fl_density != NO_DENS) {
1223 if (motor_status & (1 << f_drive)) return(OK);
1224 if (test_read(f_fp->fl_density) == OK) return(OK);
1225 }
1226
1227 /* Either drive type is unknown or a different diskette is now present.
1228 * Use test_order to try them one by one.
1229 */
1230 for (top = &test_order[0]; top < &test_order[NT-1]; top++) {
1231 dtype = top->t_density;
1232
1233 /* Skip densities that have been proven to be impossible */
1234 if (!(f_fp->fl_class & (1 << dtype))) continue;
1235
1236 if (test_read(dtype) == OK) {
1237 /* The test succeeded, use this knowledge to limit the
1238 * drive class to match the density just read.
1239 */
1240 f_fp->fl_class &= top->t_class;
1241 return(OK);
1242 }
1243 /* Test failed, wrong density or did it time out? */
1244 if (f_busy == BSY_WAKEN) break;
1245 }
1246 f_fp->fl_density = NO_DENS;
1247 return(EIO); /* nothing worked */
1248 }
1249
1250 /*===========================================================================*
1251 * test_read *
1252 *===========================================================================*/
1253 PRIVATE int test_read(density)
1254 int density;
1255 {
1256 /* Try to read the highest numbered sector on cylinder 2. Not all floppy
1257 * types have as many sectors per track, and trying cylinder 2 finds the
1258 * ones that need double stepping.
1259 */
1260 int device;
1261 off_t position;
1262 iovec_t iovec1;
1263 int result;
1264
1265 f_fp->fl_density = density;
1266 device = ((density + 1) << DEV_TYPE_SHIFT) + f_drive;
1267
1268 (void) f_prepare(device);
1269 position = (off_t) f_dp->test << SECTOR_SHIFT;
1270 iovec1.iov_addr = (vir_bytes) tmp_buf;
1271 iovec1.iov_size = SECTOR_SIZE;
1272 result = f_transfer(SELF, DEV_GATHER, position, &iovec1, 1);
1273
1274 if (iovec1.iov_size != 0) return(EIO);
1275
1276 partition(&f_dtab, f_drive, P_FLOPPY, 0);
1277 return(OK);
1278 }
1279
1280 /*===========================================================================*
1281 * f_geometry *
1282 *===========================================================================*/
1283 PRIVATE void f_geometry(entry)
1284 struct partition *entry;
1285 {
1286 entry->cylinders = f_dp->cyls;
1287 entry->heads = NR_HEADS;
1288 entry->sectors = f_sectors;
1289 }
1290
Cache object: d310e5fcf0edf9a144fbf361ac43da40
|