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