1 /* This file contains the device dependent part of the driver for the Floppy
2 * Disk Controller (FDC) using the NEC PD765 chip.
4 * The file contains two entry points:
6 * floppy_task: main entry when system is brought up
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)
27 #include <machine/diskparm.h>
28 #include <minix/sysutil.h>
29 #include <minix/syslib.h>
30 #include <minix/endpoint.h>
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
46 #define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */
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 */
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 */
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 */
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 */
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 */
79 #define BAD_CYL 0x1F /* if any of these bits are set, recalibrate */
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 */
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 */
96 /* DMA channel commands. */
97 #define DMA_READ 0x46 /* DMA read opcode */
98 #define DMA_WRITE 0x4A /* DMA write opcode */
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. */
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 */
119 /* No retries on some errors. */
120 #define err_no_retry(err) ((err) <= ERR_WR_PROTECT)
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 */
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 500000L /* microseconds waiting for FDC */
134 #define TIMEOUT_TICKS 30 /* ticks waiting for FDC */
135 #define NT 7 /* number of diskette/drive combinations */
136 #define UNCALIBRATED 0 /* drive needs to be calibrated at next use */
137 #define CALIBRATED 1 /* no calibration needed */
138 #define BASE_SECTOR 1 /* sectors are numbered starting at 1 */
139 #define NO_SECTOR (-1) /* current sector unknown */
140 #define NO_CYL (-1) /* current cylinder unknown, must seek */
141 #define NO_DENS 100 /* current media unknown */
142 #define BSY_IDLE 0 /* busy doing nothing */
143 #define BSY_IO 1 /* busy doing I/O */
144 #define BSY_WAKEN 2 /* got a wakeup call */
146 /* Seven combinations of diskette/drive are supported.
148 * # Diskette Drive Sectors Tracks Rotation Data-rate Comment
149 * 0 360K 360K 9 40 300 RPM 250 kbps Standard PC DSDD
150 * 1 1.2M 1.2M 15 80 360 RPM 500 kbps AT disk in AT drive
151 * 2 360K 720K 9 40 300 RPM 250 kbps Quad density PC
152 * 3 720K 720K 9 80 300 RPM 250 kbps Toshiba, et al.
153 * 4 360K 1.2M 9 40 360 RPM 300 kbps PC disk in AT drive
154 * 5 720K 1.2M 9 80 360 RPM 300 kbps Toshiba in AT drive
155 * 6 1.44M 1.44M 18 80 300 RPM 500 kbps PS/2, et al.
157 * In addition, 720K diskettes can be read in 1.44MB drives, but that does
158 * not need a different set of parameters. This combination uses
160 * 3 720K 1.44M 9 80 300 RPM 250 kbps PS/2, et al.
162 PRIVATE
struct density
{
163 u8_t secpt
; /* sectors per track */
164 u8_t cyls
; /* tracks per side */
165 u8_t steps
; /* steps per cylinder (2 = double step) */
166 u8_t test
; /* sector to try for density test */
167 u8_t rate
; /* data rate (2=250, 1=300, 0=500 kbps) */
168 clock_t start_ms
; /* motor start (milliseconds) */
169 u8_t gap
; /* gap size */
170 u8_t spec1
; /* first specify byte (SRT/HUT) */
172 { 9, 40, 1, 4*9, 2, 500, 0x2A, 0xDF }, /* 360K / 360K */
173 { 15, 80, 1, 14, 0, 500, 0x1B, 0xDF }, /* 1.2M / 1.2M */
174 { 9, 40, 2, 2*9, 2, 500, 0x2A, 0xDF }, /* 360K / 720K */
175 { 9, 80, 1, 4*9, 2, 750, 0x2A, 0xDF }, /* 720K / 720K */
176 { 9, 40, 2, 2*9, 1, 500, 0x23, 0xDF }, /* 360K / 1.2M */
177 { 9, 80, 1, 4*9, 1, 500, 0x23, 0xDF }, /* 720K / 1.2M */
178 { 18, 80, 1, 17, 0, 750, 0x1B, 0xCF }, /* 1.44M / 1.44M */
181 /* The following table is used with the test_sector array to recognize a
182 * drive/floppy combination. The sector to test has been determined by
183 * looking at the differences in gap size, sectors/track, and double stepping.
184 * This means that types 0 and 3 can't be told apart, only the motor start
185 * time differs. If a read test succeeds then the drive is limited to the
186 * set of densities it can support to avoid unnecessary tests in the future.
189 #define b(d) (1 << (d)) /* bit for density d. */
191 PRIVATE
struct test_order
{
192 u8_t t_density
; /* floppy/drive type */
193 u8_t t_class
; /* limit drive to this class of densities */
194 } test_order
[NT
-1] = {
195 { 6, b(3) | b(6) }, /* 1.44M {720K, 1.44M} */
196 { 1, b(1) | b(4) | b(5) }, /* 1.2M {1.2M, 360K, 720K} */
197 { 3, b(2) | b(3) | b(6) }, /* 720K {360K, 720K, 1.44M} */
198 { 4, b(1) | b(4) | b(5) }, /* 360K {1.2M, 360K, 720K} */
199 { 5, b(1) | b(4) | b(5) }, /* 720K {1.2M, 360K, 720K} */
200 { 2, b(2) | b(3) }, /* 360K {360K, 720K} */
201 /* Note that type 0 is missing, type 3 can read/write it too, which is
202 * why the type 3 parameters have been pessimized to be like type 0.
207 PRIVATE
struct floppy
{ /* main drive struct, one entry per drive */
208 unsigned fl_curcyl
; /* current cylinder */
209 unsigned fl_hardcyl
; /* hardware cylinder, as opposed to: */
210 unsigned fl_cylinder
; /* cylinder number addressed */
211 unsigned fl_sector
; /* sector addressed */
212 unsigned fl_head
; /* head number addressed */
213 char fl_calibration
; /* CALIBRATED or UNCALIBRATED */
214 u8_t fl_density
; /* NO_DENS = ?, 0 = 360K; 1 = 360K/1.2M; etc.*/
215 u8_t fl_class
; /* bitmap for possible densities */
216 timer_t fl_tmr_stop
; /* timer to stop motor */
217 struct device fl_geom
; /* Geometry of the drive */
218 struct device fl_part
[NR_PARTITIONS
]; /* partition's base & size */
221 PRIVATE
int irq_hook_id
; /* id of irq hook at the kernel */
222 PUBLIC
int motor_status
; /* bitmap of current motor status */
223 PRIVATE
int need_reset
; /* set to 1 when controller must be reset */
224 PUBLIC
unsigned f_drive
; /* selected drive */
225 PRIVATE
unsigned f_device
; /* selected minor device */
226 PRIVATE
struct floppy
*f_fp
; /* current drive */
227 PRIVATE
struct density
*f_dp
; /* current density parameters */
228 PRIVATE
struct density
*prev_dp
;/* previous density parameters */
229 PRIVATE
unsigned f_sectors
; /* equal to f_dp->secpt (needed a lot) */
230 PUBLIC u16_t f_busy
; /* BSY_IDLE, BSY_IO, BSY_WAKEN */
231 PRIVATE
struct device
*f_dv
; /* device's base and size */
232 PRIVATE
struct disk_parameter_s fmt_param
; /* parameters for format */
233 PRIVATE u8_t f_results
[MAX_RESULTS
];/* the controller can give lots of output */
235 /* The floppy uses various timers. These are managed by the floppy driver
236 * itself, because only a single synchronous alarm is available per process.
237 * Besides the 'f_tmr_timeout' timer below, the floppy structure for each
238 * floppy disk drive contains a 'fl_tmr_stop' timer.
240 PRIVATE timer_t f_tmr_timeout
; /* timer for various timeouts */
241 PRIVATE timer_t
*f_timers
; /* queue of floppy timers */
242 PRIVATE
clock_t f_next_timeout
; /* the next timeout time */
243 PRIVATE u32_t system_hz
; /* system clock frequency */
244 FORWARD
_PROTOTYPE( void f_expire_tmrs
, (struct driver
*dp
, message
*m_ptr
) );
245 FORWARD
_PROTOTYPE( void f_set_timer
, (timer_t
*tp
, clock_t delta
,
246 tmr_func_t watchdog
) );
247 FORWARD
_PROTOTYPE( void stop_motor
, (timer_t
*tp
) );
248 FORWARD
_PROTOTYPE( void f_timeout
, (timer_t
*tp
) );
250 FORWARD
_PROTOTYPE( struct device
*f_prepare
, (int device
) );
251 FORWARD
_PROTOTYPE( char *f_name
, (void) );
252 FORWARD
_PROTOTYPE( void f_cleanup
, (void) );
253 FORWARD
_PROTOTYPE( int f_transfer
, (int proc_nr
, int opcode
, u64_t position
,
254 iovec_t
*iov
, unsigned nr_req
) );
255 FORWARD
_PROTOTYPE( int dma_setup
, (int opcode
) );
256 FORWARD
_PROTOTYPE( void start_motor
, (void) );
257 FORWARD
_PROTOTYPE( int seek
, (void) );
258 FORWARD
_PROTOTYPE( int fdc_transfer
, (int opcode
) );
259 FORWARD
_PROTOTYPE( int fdc_results
, (void) );
260 FORWARD
_PROTOTYPE( int fdc_command
, (const u8_t
*cmd
, int len
) );
261 FORWARD
_PROTOTYPE( void fdc_out
, (int val
) );
262 FORWARD
_PROTOTYPE( int recalibrate
, (void) );
263 FORWARD
_PROTOTYPE( void f_reset
, (void) );
264 FORWARD
_PROTOTYPE( int f_intr_wait
, (void) );
265 FORWARD
_PROTOTYPE( int read_id
, (void) );
266 FORWARD
_PROTOTYPE( int f_do_open
, (struct driver
*dp
, message
*m_ptr
) );
267 FORWARD
_PROTOTYPE( int test_read
, (int density
) );
268 FORWARD
_PROTOTYPE( void f_geometry
, (struct partition
*entry
) );
270 /* Entry points to this driver. */
271 PRIVATE
struct driver f_dtab
= {
272 f_name
, /* current device's name */
273 f_do_open
, /* open or mount request, sense type of diskette */
274 do_nop
, /* nothing on a close */
275 do_diocntl
, /* get or set a partitions geometry */
276 f_prepare
, /* prepare for I/O on a given minor device */
277 f_transfer
, /* do the I/O */
278 f_cleanup
, /* cleanup before sending reply to user process */
279 f_geometry
, /* tell the geometry of the diskette */
280 f_expire_tmrs
,/* expire all alarm timers */
287 static char *floppy_buf
;
288 static phys_bytes floppy_buf_phys
;
290 /* SEF functions and variables. */
291 FORWARD
_PROTOTYPE( void sef_local_startup
, (void) );
292 FORWARD
_PROTOTYPE( int sef_cb_init_fresh
, (int type
, sef_init_info_t
*info
) );
293 FORWARD
_PROTOTYPE( void sef_cb_signal_handler
, (int signo
) );
294 EXTERN
_PROTOTYPE( int sef_cb_lu_prepare
, (int state
) );
295 EXTERN
_PROTOTYPE( int sef_cb_lu_state_isvalid
, (int state
) );
296 EXTERN
_PROTOTYPE( void sef_cb_lu_state_dump
, (int state
) );
297 PUBLIC
int last_transfer_opcode
;
299 /*===========================================================================*
301 *===========================================================================*/
302 PUBLIC
int main(void)
304 /* SEF local startup. */
307 /* Call the generic receive loop. */
308 driver_task(&f_dtab
, DRIVER_STD
);
313 /*===========================================================================*
314 * sef_local_startup *
315 *===========================================================================*/
316 PRIVATE
void sef_local_startup(void)
318 /* Register init callbacks. */
319 sef_setcb_init_fresh(sef_cb_init_fresh
);
320 sef_setcb_init_lu(sef_cb_init_fresh
);
321 sef_setcb_init_restart(sef_cb_init_fresh
);
323 /* Register live update callbacks. */
324 sef_setcb_lu_prepare(sef_cb_lu_prepare
);
325 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid
);
326 sef_setcb_lu_state_dump(sef_cb_lu_state_dump
);
328 /* Register signal callbacks. */
329 sef_setcb_signal_handler(sef_cb_signal_handler
);
331 /* Let SEF perform startup. */
335 /*===========================================================================*
336 * sef_cb_init_fresh *
337 *===========================================================================*/
338 PRIVATE
int sef_cb_init_fresh(int type
, sef_init_info_t
*info
)
340 /* Initialize the floppy driver. */
344 /* Initialize the floppy structure and the timers. */
345 system_hz
= sys_hz();
347 if(!(floppy_buf
= alloc_contig(2*DMA_BUF_SIZE
,
348 AC_LOWER16M
| AC_ALIGN4K
, &floppy_buf_phys
)))
349 panic("couldn't allocate dma buffer");
351 f_next_timeout
= TMR_NEVER
;
352 tmr_inittimer(&f_tmr_timeout
);
354 for (fp
= &floppy
[0]; fp
< &floppy
[NR_DRIVES
]; fp
++) {
355 fp
->fl_curcyl
= NO_CYL
;
356 fp
->fl_density
= NO_DENS
;
358 tmr_inittimer(&fp
->fl_tmr_stop
);
361 /* Set IRQ policy, only request notifications, do not automatically
362 * reenable interrupts. ID return on interrupt is the IRQ line number.
364 irq_hook_id
= FLOPPY_IRQ
;
365 if ((s
=sys_irqsetpolicy(FLOPPY_IRQ
, 0, &irq_hook_id
)) != OK
)
366 panic("Couldn't set IRQ policy: %d", s
);
367 if ((s
=sys_irqenable(&irq_hook_id
)) != OK
)
368 panic("Couldn't enable IRQs: %d", s
);
370 /* Announce we are up! */
376 /*===========================================================================*
377 * sef_cb_signal_handler *
378 *===========================================================================*/
379 PRIVATE
void sef_cb_signal_handler(int signo
)
383 /* Only check for termination signal, ignore anything else. */
384 if (signo
!= SIGTERM
) return;
386 /* Stop all activity and cleanly exit with the system. */
387 if ((s
=sys_outb(DOR
, ENABLE_INT
)) != OK
)
388 panic("Sys_outb failed: %d", s
);
392 /*===========================================================================*
394 *===========================================================================*/
395 PRIVATE
void f_expire_tmrs(struct driver
*dp
, message
*m_ptr
)
397 /* A synchronous alarm message was received. Check if there are any expired
398 * timers. Possibly reschedule the next alarm.
400 clock_t now
; /* current time */
403 /* Get the current time to compare the timers against. */
404 if ((s
=getuptime(&now
)) != OK
)
405 panic("Couldn't get uptime from clock: %d", s
);
407 /* Scan the timers queue for expired timers. Dispatch the watchdog function
408 * for each expired timers. FLOPPY watchdog functions are f_tmr_timeout()
409 * and stop_motor(). Possibly a new alarm call must be scheduled.
411 tmrs_exptimers(&f_timers
, now
, NULL
);
412 if (f_timers
== NULL
) {
413 f_next_timeout
= TMR_NEVER
;
414 } else { /* set new sync alarm */
415 f_next_timeout
= f_timers
->tmr_exp_time
;
416 if ((s
=sys_setalarm(f_next_timeout
, 1)) != OK
)
417 panic("Couldn't set synchronous alarm: %d", s
);
421 /*===========================================================================*
423 *===========================================================================*/
424 PRIVATE
void f_set_timer(tp
, delta
, watchdog
)
425 timer_t
*tp
; /* timer to be set */
426 clock_t delta
; /* in how many ticks */
427 tmr_func_t watchdog
; /* watchdog function to be called */
429 clock_t now
; /* current time */
432 /* Get the current time. */
433 if ((s
=getuptime(&now
)) != OK
)
434 panic("Couldn't get uptime from clock: %d", s
);
436 /* Add the timer to the local timer queue. */
437 tmrs_settimer(&f_timers
, tp
, now
+ delta
, watchdog
, NULL
);
439 /* Possibly reschedule an alarm call. This happens when the front of the
440 * timers queue was reinserted at another position, i.e., when a timer was
441 * reset, or when a new timer was added in front.
443 if (f_timers
->tmr_exp_time
!= f_next_timeout
) {
444 f_next_timeout
= f_timers
->tmr_exp_time
;
445 if ((s
=sys_setalarm(f_next_timeout
, 1)) != OK
)
446 panic("Couldn't set synchronous alarm: %d", s
);
450 /*===========================================================================*
452 *===========================================================================*/
453 PRIVATE
struct device
*f_prepare(int device
)
455 /* Prepare for I/O on a device. */
458 f_drive
= device
& ~(DEV_TYPE_BITS
| FORMAT_DEV_BIT
);
459 if (f_drive
< 0 || f_drive
>= NR_DRIVES
) return(NULL
);
461 f_fp
= &floppy
[f_drive
];
462 f_dv
= &f_fp
->fl_geom
;
463 if (f_fp
->fl_density
< NT
) {
464 f_dp
= &fdensity
[f_fp
->fl_density
];
465 f_sectors
= f_dp
->secpt
;
466 f_fp
->fl_geom
.dv_size
= mul64u((long) (NR_HEADS
* f_sectors
467 * f_dp
->cyls
), SECTOR_SIZE
);
471 if ((device
&= DEV_TYPE_BITS
) >= MINOR_fd0p0
)
472 f_dv
= &f_fp
->fl_part
[(device
- MINOR_fd0p0
) >> DEV_TYPE_SHIFT
];
477 /*===========================================================================*
479 *===========================================================================*/
480 PRIVATE
char *f_name(void)
482 /* Return a name for the current device. */
483 static char name
[] = "fd0";
485 name
[2] = '0' + f_drive
;
489 /*===========================================================================*
491 *===========================================================================*/
492 PRIVATE
void f_cleanup(void)
494 /* Start a timer to turn the motor off in a few seconds. */
495 tmr_arg(&f_fp
->fl_tmr_stop
)->ta_int
= f_drive
;
496 f_set_timer(&f_fp
->fl_tmr_stop
, MOTOR_OFF
, stop_motor
);
498 /* Exiting the floppy driver, so forget where we are. */
499 f_fp
->fl_sector
= NO_SECTOR
;
502 /*===========================================================================*
504 *===========================================================================*/
505 PRIVATE
int f_transfer(proc_nr
, opcode
, pos64
, iov
, nr_req
)
506 int proc_nr
; /* process doing the request */
507 int opcode
; /* DEV_GATHER_S or DEV_SCATTER_S */
508 u64_t pos64
; /* offset on device to read or write */
509 iovec_t
*iov
; /* pointer to read or write request vector */
510 unsigned nr_req
; /* length of request vector */
513 struct floppy
*fp
= f_fp
;
514 iovec_t
*iop
, *iov_end
= iov
+ nr_req
;
515 int s
, r
, errors
, nr
;
516 unsigned block
; /* Seen any 32M floppies lately? */
517 unsigned nbytes
, count
, chunk
, sector
;
518 unsigned long dv_size
= cv64ul(f_dv
->dv_size
);
519 vir_bytes user_offset
, iov_offset
= 0, iop_offset
;
521 signed long uoffsets
[MAX_SECTORS
], *up
;
522 cp_grant_id_t ugrants
[MAX_SECTORS
], *ug
;
525 if (ex64hi(pos64
) != 0)
526 return OK
; /* Way beyond EOF */
527 position
= cv64ul(pos64
);
529 /* Record the opcode of the last transfer performed. */
530 last_transfer_opcode
= opcode
;
532 /* Check disk address. */
533 if ((position
& SECTOR_MASK
) != 0) return(EINVAL
);
535 #if 0 /* XXX hack to create a disk driver that crashes */
536 { static int count
= 0; if (++count
> 10) {
537 printf("floppy: time to die\n"); *(int *)-1= 42;
543 /* How many bytes to transfer? */
545 for (iop
= iov
; iop
< iov_end
; iop
++) nbytes
+= iop
->iov_size
;
547 /* Which block on disk and how close to EOF? */
548 if (position
>= dv_size
) return(OK
); /* At EOF */
549 if (position
+ nbytes
> dv_size
) nbytes
= dv_size
- position
;
550 block
= div64u(add64ul(f_dv
->dv_base
, position
), SECTOR_SIZE
);
552 if ((nbytes
& SECTOR_MASK
) != 0) return(EINVAL
);
554 /* Using a formatting device? */
555 if (f_device
& FORMAT_DEV_BIT
) {
556 if (opcode
!= DEV_SCATTER_S
) return(EIO
);
557 if (iov
->iov_size
< SECTOR_SIZE
+ sizeof(fmt_param
))
560 if(proc_nr
!= SELF
) {
561 s
=sys_safecopyfrom(proc_nr
, iov
->iov_addr
,
562 SECTOR_SIZE
+ iov_offset
, (vir_bytes
) &fmt_param
,
563 (phys_bytes
) sizeof(fmt_param
), D
);
565 panic("sys_safecopyfrom failed: %d", s
);
567 memcpy(&fmt_param
, (void *) (iov
->iov_addr
+
568 SECTOR_SIZE
+ iov_offset
),
569 (phys_bytes
) sizeof(fmt_param
));
572 /* Check that the number of sectors in the data is reasonable,
573 * to avoid division by 0. Leave checking of other data to
576 if (fmt_param
.sectors_per_cylinder
== 0) return(EIO
);
578 /* Only the first sector of the parameters now needed. */
579 iov
->iov_size
= nbytes
= SECTOR_SIZE
;
582 /* Only try one sector if there were errors. */
583 if (errors
> 0) nbytes
= SECTOR_SIZE
;
585 /* Compute cylinder and head of the track to access. */
586 fp
->fl_cylinder
= block
/ (NR_HEADS
* f_sectors
);
587 fp
->fl_hardcyl
= fp
->fl_cylinder
* f_dp
->steps
;
588 fp
->fl_head
= (block
% (NR_HEADS
* f_sectors
)) / f_sectors
;
590 /* For each sector on this track compute the user address it is to
591 * go or to come from.
593 for (up
= uoffsets
; up
< uoffsets
+ MAX_SECTORS
; up
++) *up
= NO_OFFSET
;
596 sector
= block
% f_sectors
;
598 iop_offset
= iov_offset
;
601 user_offset
= iop_offset
;
602 chunk
= iop
->iov_size
;
603 if ((chunk
& SECTOR_MASK
) != 0) return(EINVAL
);
606 ugrants
[sector
] = iop
->iov_addr
;
607 uoffsets
[sector
++] = user_offset
;
608 chunk
-= SECTOR_SIZE
;
609 user_offset
+= SECTOR_SIZE
;
610 count
+= SECTOR_SIZE
;
611 if (sector
== f_sectors
|| count
== nbytes
)
619 /* First check to see if a reset is needed. */
620 if (need_reset
) f_reset();
622 /* See if motor is running; if not, turn it on and wait. */
625 /* Set the stepping rate and data rate */
626 if (f_dp
!= prev_dp
) {
627 cmd
[0] = FDC_SPECIFY
;
628 cmd
[1] = f_dp
->spec1
;
630 (void) fdc_command(cmd
, 3);
631 if ((s
=sys_outb(FDC_RATE
, f_dp
->rate
)) != OK
)
632 panic("Sys_outb failed: %d", s
);
636 /* If we are going to a new cylinder, perform a seek. */
639 /* Avoid read_id() if we don't plan to read much. */
640 if (fp
->fl_sector
== NO_SECTOR
&& count
< (6 * SECTOR_SIZE
))
643 for (nbytes
= 0; nbytes
< count
; nbytes
+= SECTOR_SIZE
) {
644 if (fp
->fl_sector
== NO_SECTOR
) {
645 /* Find out what the current sector is. This often
646 * fails right after a seek, so try it twice.
648 if (r
== OK
&& read_id() != OK
) r
= read_id();
651 /* Look for the next job in uoffsets[] */
654 if (fp
->fl_sector
>= f_sectors
)
657 up
= &uoffsets
[fp
->fl_sector
];
658 ug
= &ugrants
[fp
->fl_sector
];
659 if (*up
!= NO_OFFSET
) break;
663 if (opcode
== DEV_SCATTER_S
) {
664 /* Copy the user bytes to the DMA buffer. */
665 if(proc_nr
!= SELF
) {
666 s
=sys_safecopyfrom(proc_nr
, *ug
, *up
,
667 (vir_bytes
) floppy_buf
,
668 (phys_bytes
) SECTOR_SIZE
, D
);
670 panic("sys_safecopyfrom failed: %d", s
);
672 memcpy(floppy_buf
, (void *) (*ug
+ *up
), SECTOR_SIZE
);
677 /* Set up the DMA chip and perform the transfer. */
679 if (dma_setup(opcode
) != OK
) {
680 /* This can only fail for addresses above 16MB
681 * that cannot be handled by the controller,
682 * because it uses 24-bit addressing.
686 r
= fdc_transfer(opcode
);
689 if (r
== OK
&& opcode
== DEV_GATHER_S
) {
690 /* Copy the DMA buffer to user space. */
691 if(proc_nr
!= SELF
) {
692 s
=sys_safecopyto(proc_nr
, *ug
, *up
,
693 (vir_bytes
) floppy_buf
,
694 (phys_bytes
) SECTOR_SIZE
, D
);
696 panic("sys_safecopyto failed: %d", s
);
698 memcpy((void *) (*ug
+ *up
), floppy_buf
, SECTOR_SIZE
);
703 /* Don't retry if write protected or too many errors. */
704 if (err_no_retry(r
) || ++errors
== MAX_ERRORS
) {
708 /* Recalibrate if halfway. */
709 if (errors
== MAX_ERRORS
/ 2)
710 fp
->fl_calibration
= UNCALIBRATED
;
717 /* Book the bytes successfully transferred. */
720 if (nbytes
< iov
->iov_size
) {
721 /* Not done with this one yet. */
722 iov_offset
+= nbytes
;
723 iov
->iov_size
-= nbytes
;
727 nbytes
-= iov
->iov_size
;
730 /* The rest is optional, so we return to give FS a
731 * chance to think it over.
742 /*===========================================================================*
744 *===========================================================================*/
745 PRIVATE
int dma_setup(
746 int opcode
/* DEV_GATHER_S or DEV_SCATTER_S */
749 /* The IBM PC can perform DMA operations by using the DMA chip. To use it,
750 * the DMA (Direct Memory Access) chip is loaded with the 20-bit memory address
751 * to be read from or written to, the byte count minus 1, and a read or write
752 * opcode. This routine sets up the DMA chip. Note that the chip is not
753 * capable of doing a DMA across a 64K boundary (e.g., you can't read a
754 * 512-byte block starting at physical address 65520).
756 * Warning! Also note that it's not possible to do DMA above 16 MB because
757 * the ISA bus uses 24-bit addresses. Addresses above 16 MB therefore will
758 * be interpreted modulo 16 MB, dangerously overwriting arbitrary memory.
759 * A check here denies the I/O if the address is out of range.
761 pvb_pair_t byte_out
[9];
764 /* First check the DMA memory address not to exceed maximum. */
765 if (floppy_buf_phys
!= (floppy_buf_phys
& DMA_ADDR_MASK
)) {
766 printf("floppy: DMA denied because address out of range\n");
770 /* Set up the DMA registers. (The comment on the reset is a bit strong,
771 * it probably only resets the floppy channel.)
773 pv_set(byte_out
[0], DMA_INIT
, DMA_RESET_VAL
); /* reset the dma controller */
774 pv_set(byte_out
[1], DMA_FLIPFLOP
, 0); /* write anything to reset it */
775 pv_set(byte_out
[2], DMA_MODE
, opcode
== DEV_SCATTER_S
? DMA_WRITE
: DMA_READ
);
776 pv_set(byte_out
[3], DMA_ADDR
, (unsigned) (floppy_buf_phys
>> 0) & 0xff);
777 pv_set(byte_out
[4], DMA_ADDR
, (unsigned) (floppy_buf_phys
>> 8) & 0xff);
778 pv_set(byte_out
[5], DMA_TOP
, (unsigned) (floppy_buf_phys
>> 16) & 0xff);
779 pv_set(byte_out
[6], DMA_COUNT
, (((SECTOR_SIZE
- 1) >> 0)) & 0xff);
780 pv_set(byte_out
[7], DMA_COUNT
, (SECTOR_SIZE
- 1) >> 8);
781 pv_set(byte_out
[8], DMA_INIT
, 2); /* some sort of enable */
783 if ((s
=sys_voutb(byte_out
, 9)) != OK
)
784 panic("Sys_voutb in dma_setup() failed: %d", s
);
788 /*===========================================================================*
790 *===========================================================================*/
791 PRIVATE
void start_motor(void)
793 /* Control of the floppy disk motors is a big pain. If a motor is off, you
794 * have to turn it on first, which takes 1/2 second. You can't leave it on
795 * all the time, since that would wear out the diskette. However, if you turn
796 * the motor off after each operation, the system performance will be awful.
797 * The compromise used here is to leave it on for a few seconds after each
798 * operation. If a new operation is started in that interval, it need not be
799 * turned on again. If no new operation is started, a timer goes off and the
800 * motor is turned off. I/O port DOR has bits to control each of 4 drives.
803 int s
, motor_bit
, running
;
807 motor_bit
= 1 << f_drive
; /* bit mask for this drive */
808 running
= motor_status
& motor_bit
; /* nonzero if this motor is running */
809 motor_status
|= motor_bit
; /* want this drive running too */
812 (motor_status
<< MOTOR_SHIFT
) | ENABLE_INT
| f_drive
)) != OK
)
813 panic("Sys_outb in start_motor() failed: %d", s
);
815 /* If the motor was already running, we don't have to wait for it. */
816 if (running
) return; /* motor was already running */
818 /* Set an alarm timer to force a timeout if the hardware does not interrupt
819 * in time. Expect an interrupt, but check for a timeout.
821 f_set_timer(&f_tmr_timeout
, f_dp
->start_ms
* system_hz
/ 1000, f_timeout
);
824 driver_receive(ANY
, &mess
, &ipc_status
);
826 if (is_ipc_notify(ipc_status
)) {
827 switch (_ENDPOINT_P(mess
.m_source
)) {
829 f_expire_tmrs(NULL
, NULL
);
838 } while (f_busy
== BSY_IO
);
839 f_fp
->fl_sector
= NO_SECTOR
;
842 /*===========================================================================*
844 *===========================================================================*/
845 PRIVATE
void stop_motor(timer_t
*tp
)
847 /* This routine is called from an alarm timer after several seconds have
848 * elapsed with no floppy disk activity. It turns the drive motor off.
851 motor_status
&= ~(1 << tmr_arg(tp
)->ta_int
);
852 if ((s
=sys_outb(DOR
, (motor_status
<< MOTOR_SHIFT
) | ENABLE_INT
)) != OK
)
853 panic("Sys_outb in stop_motor() failed: %d", s
);
856 /*===========================================================================*
858 *===========================================================================*/
859 PRIVATE
int seek(void)
861 /* Issue a SEEK command on the indicated drive unless the arm is already
862 * positioned on the correct cylinder.
865 struct floppy
*fp
= f_fp
;
871 /* Are we already on the correct cylinder? */
872 if (fp
->fl_calibration
== UNCALIBRATED
)
873 if (recalibrate() != OK
) return(ERR_SEEK
);
874 if (fp
->fl_curcyl
== fp
->fl_hardcyl
) return(OK
);
876 /* No. Wrong cylinder. Issue a SEEK and wait for interrupt. */
878 cmd
[1] = (fp
->fl_head
<< 2) | f_drive
;
879 cmd
[2] = fp
->fl_hardcyl
;
880 if (fdc_command(cmd
, 3) != OK
) return(ERR_SEEK
);
881 if (f_intr_wait() != OK
) return(ERR_TIMEOUT
);
883 /* Interrupt has been received. Check drive status. */
884 fdc_out(FDC_SENSE
); /* probe FDC to make it return status */
885 r
= fdc_results(); /* get controller status bytes */
886 if (r
!= OK
|| (f_results
[ST0
] & ST0_BITS_SEEK
) != SEEK_ST0
887 || f_results
[ST1
] != fp
->fl_hardcyl
) {
888 /* seek failed, may need a recalibrate */
891 /* Give head time to settle on a format, no retrying here! */
892 if (f_device
& FORMAT_DEV_BIT
) {
893 /* Set a synchronous alarm to force a timeout if the hardware does
896 f_set_timer(&f_tmr_timeout
, system_hz
/30, f_timeout
);
899 driver_receive(ANY
, &mess
, &ipc_status
);
901 if (is_ipc_notify(ipc_status
)) {
902 switch (_ENDPOINT_P(mess
.m_source
)) {
904 f_expire_tmrs(NULL
, NULL
);
913 } while (f_busy
== BSY_IO
);
915 fp
->fl_curcyl
= fp
->fl_hardcyl
;
916 fp
->fl_sector
= NO_SECTOR
;
920 /*===========================================================================*
922 *===========================================================================*/
923 PRIVATE
int fdc_transfer(
924 int opcode
/* DEV_GATHER_S or DEV_SCATTER_S */
927 /* The drive is now on the proper cylinder. Read, write or format 1 block. */
929 struct floppy
*fp
= f_fp
;
933 /* Never attempt a transfer if the drive is uncalibrated or motor is off. */
934 if (fp
->fl_calibration
== UNCALIBRATED
) return(ERR_TRANSFER
);
935 if ((motor_status
& (1 << f_drive
)) == 0) return(ERR_TRANSFER
);
937 /* The command is issued by outputting several bytes to the controller chip.
939 if (f_device
& FORMAT_DEV_BIT
) {
941 cmd
[1] = (fp
->fl_head
<< 2) | f_drive
;
942 cmd
[2] = fmt_param
.sector_size_code
;
943 cmd
[3] = fmt_param
.sectors_per_cylinder
;
944 cmd
[4] = fmt_param
.gap_length_for_format
;
945 cmd
[5] = fmt_param
.fill_byte_for_format
;
946 if (fdc_command(cmd
, 6) != OK
) return(ERR_TRANSFER
);
948 cmd
[0] = opcode
== DEV_SCATTER_S
? FDC_WRITE
: FDC_READ
;
949 cmd
[1] = (fp
->fl_head
<< 2) | f_drive
;
950 cmd
[2] = fp
->fl_cylinder
;
951 cmd
[3] = fp
->fl_head
;
952 cmd
[4] = BASE_SECTOR
+ fp
->fl_sector
;
953 cmd
[5] = SECTOR_SIZE_CODE
;
955 cmd
[7] = f_dp
->gap
; /* sector gap */
956 cmd
[8] = DTL
; /* data length */
957 if (fdc_command(cmd
, 9) != OK
) return(ERR_TRANSFER
);
960 /* Block, waiting for disk interrupt. */
961 if (f_intr_wait() != OK
) {
962 printf("%s: disk interrupt timed out.\n", f_name());
966 /* Get controller status and check for errors. */
968 if (r
!= OK
) return(r
);
970 if (f_results
[ST1
] & WRITE_PROTECT
) {
971 printf("%s: diskette is write protected.\n", f_name());
972 return(ERR_WR_PROTECT
);
975 if ((f_results
[ST0
] & ST0_BITS_TRANS
) != TRANS_ST0
) return(ERR_TRANSFER
);
976 if (f_results
[ST1
] | f_results
[ST2
]) return(ERR_TRANSFER
);
978 if (f_device
& FORMAT_DEV_BIT
) return(OK
);
980 /* Compare actual numbers of sectors transferred with expected number. */
981 s
= (f_results
[ST_CYL
] - fp
->fl_cylinder
) * NR_HEADS
* f_sectors
;
982 s
+= (f_results
[ST_HEAD
] - fp
->fl_head
) * f_sectors
;
983 s
+= (f_results
[ST_SEC
] - BASE_SECTOR
- fp
->fl_sector
);
984 if (s
!= 1) return(ERR_TRANSFER
);
986 /* This sector is next for I/O: */
987 fp
->fl_sector
= f_results
[ST_SEC
] - BASE_SECTOR
;
989 if (processor
< 386) fp
->fl_sector
++; /* Old CPU can't keep up. */
994 /*===========================================================================*
996 *===========================================================================*/
997 PRIVATE
int fdc_results(void)
999 /* Extract results from the controller after an operation, then allow floppy
1004 unsigned long status
;
1007 /* Extract bytes from FDC until it says it has no more. The loop is
1008 * really an outer loop on result_nr and an inner loop on status.
1009 * A timeout flag alarm is set.
1014 /* Reading one byte is almost a mirror of fdc_out() - the DIRECTION
1015 * bit must be set instead of clear, but the CTL_BUSY bit destroys
1016 * the perfection of the mirror.
1018 if ((s
=sys_inb(FDC_STATUS
, &status
)) != OK
)
1019 panic("Sys_inb in fdc_results() failed: %d", s
);
1020 status
&= (MASTER
| DIRECTION
| CTL_BUSY
);
1021 if (status
== (MASTER
| DIRECTION
| CTL_BUSY
)) {
1022 unsigned long tmp_r
;
1023 if (result_nr
>= MAX_RESULTS
) break; /* too many results */
1024 if ((s
=sys_inb(FDC_DATA
, &tmp_r
)) != OK
)
1025 panic("Sys_inb in fdc_results() failed: %d", s
);
1026 f_results
[result_nr
] = tmp_r
;
1030 if (status
== MASTER
) { /* all read */
1031 if ((s
=sys_irqenable(&irq_hook_id
)) != OK
)
1032 panic("Couldn't enable IRQs: %d", s
);
1034 return(OK
); /* only good exit */
1036 } while ( (s
=getuptime(&t1
))==OK
&& (t1
-t0
) < TIMEOUT_TICKS
);
1037 if (OK
!=s
) printf("FLOPPY: warning, getuptime failed: %d\n", s
);
1038 need_reset
= TRUE
; /* controller chip must be reset */
1040 if ((s
=sys_irqenable(&irq_hook_id
)) != OK
)
1041 panic("Couldn't enable IRQs: %d", s
);
1045 /*===========================================================================*
1047 *===========================================================================*/
1048 PRIVATE
int fdc_command(
1049 const u8_t
*cmd
, /* command bytes */
1050 int len
/* command length */
1053 /* Output a command to the controller. */
1055 /* Set a synchronous alarm to force a timeout if the hardware does
1057 * Note that the actual check is done by the code that issued the
1058 * fdc_command() call.
1060 f_set_timer(&f_tmr_timeout
, WAKEUP
, f_timeout
);
1067 return(need_reset
? ERR_DRIVE
: OK
);
1070 /*===========================================================================*
1072 *===========================================================================*/
1073 PRIVATE
void fdc_out(
1074 int val
/* write this byte to floppy disk controller */
1077 /* Output a byte to the controller. This is not entirely trivial, since you
1078 * can only write to it when it is listening, and it decides when to listen.
1079 * If the controller refuses to listen, the FDC chip is given a hard reset.
1083 unsigned long status
;
1085 if (need_reset
) return; /* if controller is not listening, return */
1087 /* It may take several tries to get the FDC to accept a command. */
1090 if ( (s
=getuptime(&t1
))==OK
&& (t1
-t0
) > TIMEOUT_TICKS
) {
1091 if (OK
!=s
) printf("FLOPPY: warning, getuptime failed: %d\n", s
);
1092 need_reset
= TRUE
; /* hit it over the head */
1095 if ((s
=sys_inb(FDC_STATUS
, &status
)) != OK
)
1096 panic("Sys_inb in fdc_out() failed: %d", s
);
1098 while ((status
& (MASTER
| DIRECTION
)) != (MASTER
| 0));
1100 if ((s
=sys_outb(FDC_DATA
, val
)) != OK
)
1101 panic("Sys_outb in fdc_out() failed: %d", s
);
1104 /*===========================================================================*
1106 *===========================================================================*/
1107 PRIVATE
int recalibrate(void)
1109 /* The floppy disk controller has no way of determining its absolute arm
1110 * position (cylinder). Instead, it steps the arm a cylinder at a time and
1111 * keeps track of where it thinks it is (in software). However, after a
1112 * SEEK, the hardware reads information from the diskette telling where the
1113 * arm actually is. If the arm is in the wrong place, a recalibration is done,
1114 * which forces the arm to cylinder 0. This way the controller can get back
1115 * into sync with reality.
1118 struct floppy
*fp
= f_fp
;
1122 /* Issue the RECALIBRATE command and wait for the interrupt. */
1123 cmd
[0] = FDC_RECALIBRATE
; /* tell drive to recalibrate itself */
1124 cmd
[1] = f_drive
; /* specify drive */
1125 if (fdc_command(cmd
, 2) != OK
) return(ERR_SEEK
);
1126 if (f_intr_wait() != OK
) return(ERR_TIMEOUT
);
1128 /* Determine if the recalibration succeeded. */
1129 fdc_out(FDC_SENSE
); /* issue SENSE command to request results */
1130 r
= fdc_results(); /* get results of the FDC_RECALIBRATE command*/
1131 fp
->fl_curcyl
= NO_CYL
; /* force a SEEK next time */
1132 fp
->fl_sector
= NO_SECTOR
;
1133 if (r
!= OK
|| /* controller would not respond */
1134 (f_results
[ST0
] & ST0_BITS_SEEK
) != SEEK_ST0
|| f_results
[ST_PCN
] != 0) {
1135 /* Recalibration failed. FDC must be reset. */
1137 return(ERR_RECALIBRATE
);
1139 /* Recalibration succeeded. */
1140 fp
->fl_calibration
= CALIBRATED
;
1141 fp
->fl_curcyl
= f_results
[ST_PCN
];
1146 /*===========================================================================*
1148 *===========================================================================*/
1149 PRIVATE
void f_reset(void)
1151 /* Issue a reset to the controller. This is done after any catastrophe,
1152 * like the controller refusing to respond.
1154 pvb_pair_t byte_out
[2];
1159 /* Disable interrupts and strobe reset bit low. */
1162 /* It is not clear why the next lock is needed. Writing 0 to DOR causes
1163 * interrupt, while the PC documentation says turning bit 8 off disables
1164 * interrupts. Without the lock:
1165 * 1) the interrupt handler sets the floppy mask bit in the 8259.
1166 * 2) writing ENABLE_INT to DOR causes the FDC to assert the interrupt
1167 * line again, but the mask stops the cpu being interrupted.
1168 * 3) the sense interrupt clears the interrupt (not clear which one).
1169 * and for some reason the reset does not work.
1171 (void) fdc_command((u8_t
*) 0, 0); /* need only the timer */
1173 pv_set(byte_out
[0], DOR
, 0); /* strobe reset bit low */
1174 pv_set(byte_out
[1], DOR
, ENABLE_INT
); /* strobe it high again */
1175 if ((s
=sys_voutb(byte_out
, 2)) != OK
)
1176 panic("Sys_voutb in f_reset() failed: %d", s
);
1178 /* A synchronous alarm timer was set in fdc_command. Expect an interrupt,
1179 * but be prepared to handle a timeout.
1182 driver_receive(ANY
, &mess
, &ipc_status
);
1183 if (is_ipc_notify(ipc_status
)) {
1184 switch (_ENDPOINT_P(mess
.m_source
)) {
1186 f_expire_tmrs(NULL
, NULL
);
1192 } else { /* expect hw interrupt */
1195 } while (f_busy
== BSY_IO
);
1197 /* The controller supports 4 drives and returns a result for each of them.
1198 * Collect all the results now. The old version only collected the first
1199 * result. This happens to work for 2 drives, but it doesn't work for 3
1200 * or more drives, at least with only drives 0 and 2 actually connected
1201 * (the controller generates an extra interrupt for the middle drive when
1202 * drive 2 is accessed and the driver panics).
1204 * It would be better to keep collecting results until there are no more.
1205 * For this, fdc_results needs to return the number of results (instead
1206 * of OK) when it succeeds.
1208 for (i
= 0; i
< 4; i
++) {
1209 fdc_out(FDC_SENSE
); /* probe FDC to make it return status */
1210 (void) fdc_results(); /* flush controller */
1212 for (i
= 0; i
< NR_DRIVES
; i
++) /* clear each drive */
1213 floppy
[i
].fl_calibration
= UNCALIBRATED
;
1215 /* The current timing parameters must be specified again. */
1219 /*===========================================================================*
1221 *===========================================================================*/
1222 PRIVATE
int f_intr_wait(void)
1224 /* Wait for an interrupt, but not forever. The FDC may have all the time of
1225 * the world, but we humans do not.
1230 /* We expect an interrupt, but if a timeout, occurs, report an error. */
1232 driver_receive(ANY
, &mess
, &ipc_status
);
1233 if (is_ipc_notify(ipc_status
)) {
1234 switch (_ENDPOINT_P(mess
.m_source
)) {
1236 f_expire_tmrs(NULL
, NULL
);
1245 } while (f_busy
== BSY_IO
);
1247 if (f_busy
== BSY_WAKEN
) {
1249 /* No interrupt from the FDC, this means that there is probably no
1250 * floppy in the drive. Get the FDC down to earth and return error.
1253 return(ERR_TIMEOUT
);
1258 /*===========================================================================*
1260 *===========================================================================*/
1261 PRIVATE
void f_timeout(timer_t
*tp
)
1263 /* This routine is called when a timer expires. Usually to tell that a
1264 * motor has spun up, but also to forge an interrupt when it takes too long
1265 * for the FDC to interrupt (no floppy in the drive). It sets a flag to tell
1266 * what has happened.
1268 if (f_busy
== BSY_IO
) {
1273 /*===========================================================================*
1275 *===========================================================================*/
1276 PRIVATE
int read_id(void)
1278 /* Determine current cylinder and sector. */
1280 struct floppy
*fp
= f_fp
;
1284 /* Never attempt a read id if the drive is uncalibrated or motor is off. */
1285 if (fp
->fl_calibration
== UNCALIBRATED
) return(ERR_READ_ID
);
1286 if ((motor_status
& (1 << f_drive
)) == 0) return(ERR_READ_ID
);
1288 /* The command is issued by outputting 2 bytes to the controller chip. */
1289 cmd
[0] = FDC_READ_ID
; /* issue the read id command */
1290 cmd
[1] = (fp
->fl_head
<< 2) | f_drive
;
1291 if (fdc_command(cmd
, 2) != OK
) return(ERR_READ_ID
);
1292 if (f_intr_wait() != OK
) return(ERR_TIMEOUT
);
1294 /* Get controller status and check for errors. */
1295 result
= fdc_results();
1296 if (result
!= OK
) return(result
);
1298 if ((f_results
[ST0
] & ST0_BITS_TRANS
) != TRANS_ST0
) return(ERR_READ_ID
);
1299 if (f_results
[ST1
] | f_results
[ST2
]) return(ERR_READ_ID
);
1301 /* The next sector is next for I/O: */
1302 fp
->fl_sector
= f_results
[ST_SEC
] - BASE_SECTOR
+ 1;
1306 /*===========================================================================*
1308 *===========================================================================*/
1309 PRIVATE
int f_do_open(dp
, m_ptr
)
1311 message
*m_ptr
; /* pointer to open message */
1313 /* Handle an open on a floppy. Determine diskette type if need be. */
1316 struct test_order
*top
;
1318 /* Decode the message parameters. */
1319 if (f_prepare(m_ptr
->DEVICE
) == NULL
) return(ENXIO
);
1321 dtype
= f_device
& DEV_TYPE_BITS
; /* get density from minor dev */
1322 if (dtype
>= MINOR_fd0p0
) dtype
= 0;
1325 /* All types except 0 indicate a specific drive/medium combination.*/
1326 dtype
= (dtype
>> DEV_TYPE_SHIFT
) - 1;
1327 if (dtype
>= NT
) return(ENXIO
);
1328 f_fp
->fl_density
= dtype
;
1329 (void) f_prepare(f_device
); /* Recompute parameters. */
1332 if (f_device
& FORMAT_DEV_BIT
) return(EIO
); /* Can't format /dev/fdN */
1334 /* The device opened is /dev/fdN. Experimentally determine drive/medium.
1335 * First check fl_density. If it is not NO_DENS, the drive has been used
1336 * before and the value of fl_density tells what was found last time. Try
1337 * that first. If the motor is still running then assume nothing changed.
1339 if (f_fp
->fl_density
!= NO_DENS
) {
1340 if (motor_status
& (1 << f_drive
)) return(OK
);
1341 if (test_read(f_fp
->fl_density
) == OK
) return(OK
);
1344 /* Either drive type is unknown or a different diskette is now present.
1345 * Use test_order to try them one by one.
1347 for (top
= &test_order
[0]; top
< &test_order
[NT
-1]; top
++) {
1348 dtype
= top
->t_density
;
1350 /* Skip densities that have been proven to be impossible */
1351 if (!(f_fp
->fl_class
& (1 << dtype
))) continue;
1353 if (test_read(dtype
) == OK
) {
1354 /* The test succeeded, use this knowledge to limit the
1355 * drive class to match the density just read.
1357 f_fp
->fl_class
&= top
->t_class
;
1360 /* Test failed, wrong density or did it time out? */
1361 if (f_busy
== BSY_WAKEN
) break;
1363 f_fp
->fl_density
= NO_DENS
;
1364 return(EIO
); /* nothing worked */
1367 /*===========================================================================*
1369 *===========================================================================*/
1370 PRIVATE
int test_read(int density
)
1372 /* Try to read the highest numbered sector on cylinder 2. Not all floppy
1373 * types have as many sectors per track, and trying cylinder 2 finds the
1374 * ones that need double stepping.
1381 f_fp
->fl_density
= density
;
1382 device
= ((density
+ 1) << DEV_TYPE_SHIFT
) + f_drive
;
1384 (void) f_prepare(device
);
1385 position
= (off_t
) f_dp
->test
<< SECTOR_SHIFT
;
1386 iovec1
.iov_addr
= (vir_bytes
) floppy_buf
;
1387 iovec1
.iov_size
= SECTOR_SIZE
;
1388 result
= f_transfer(SELF
, DEV_GATHER_S
, cvul64(position
), &iovec1
, 1);
1390 if (iovec1
.iov_size
!= 0) return(EIO
);
1392 partition(&f_dtab
, f_drive
, P_FLOPPY
, 0);
1396 /*===========================================================================*
1398 *===========================================================================*/
1399 PRIVATE
void f_geometry(struct partition
*entry
)
1401 entry
->cylinders
= f_dp
->cyls
;
1402 entry
->heads
= NR_HEADS
;
1403 entry
->sectors
= f_sectors
;