FreeBSD/Linux Kernel Cross Reference
sys/i386ps2/fd.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * Copyright (c) 1991 IBM Corporation
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation,
12 * and that the name IBM not be used in advertising or publicity
13 * pertaining to distribution of the software without specific, written
14 * prior permission.
15 *
16 * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie Mellon
28 * the rights to redistribute these changes.
29 */
30
31 /*
32 * HISTORY
33 * $Log: fd.c,v $
34 * Revision 2.3 93/03/11 14:08:53 danner
35 * u_long -> u_int
36 * [93/03/09 danner]
37 *
38 * Revision 2.2 93/02/04 07:59:23 danner
39 * Disable media-change detection for the floppy to allow booting
40 * from them in the microkernel world.
41 * [93/01/18 zon]
42 *
43 * Integrate PS2 code from IBM.
44 * [93/01/18 prithvi]
45 *
46 */
47
48 /*
49 * COMPONENT_NAME: (FLOPPY) Mach 3.0 PS/2 Floppy Driver
50 *
51 * FUNCTIONS:
52 *
53 * ORIGINS: 27
54 */
55
56 /* OSF/1 PS/2 ABIOS diskette driver. Driver lineage: AIX v3 R2 -> AIX v3 PS/2
57 * -> OSF/1 PS/2.
58 */
59
60
61 /* Changed for the 3.0 port */
62
63 #include <fd.h>
64
65 #ifdef MACH_KERNEL
66 #include <sys/types.h>
67 #include <device/io_req.h>
68 #include <device/buf.h>
69 #include <device/errno.h>
70 #include <i386/pmap.h>
71 #include <sys/ioctl.h>
72 #include <sys/syslog.h>
73 #include <i386ps2/abios.h>
74 #include <i386/ipl.h>
75 #include <i386ps2/bus.h>
76 #include <i386ps2/debugf.h>
77 #include <i386ps2/fd_abios.h>
78 #include <i386ps2/fdreg.h>
79 #define PRIBIO 20 /* taken from i386at/m765.h */
80 #else MACH_KERNEL
81 #include <sys/types.h>
82 #include <sys/buf.h>
83 #include <sys/errno.h>
84 #ifdef OSF
85 #include <sys/fcntl.h>
86 #else
87 #include <sys/file.h>
88 #endif OSF
89 #include <i386/pmap.h>
90 #include <sys/ioctl.h>
91 #include <sys/param.h>
92 #include <sys/proc.h>
93 #include <sys/syslog.h>
94 #include <sys/uio.h>
95 #include <sys/user.h>
96 #include <i386ps2/abios.h>
97 #include <i386/ipl.h>
98 #include <kern/assert.h>
99 #include <kern/task.h>
100 #ifdef OSF
101 #include <i386/handler.h>
102 #endif OSF
103 #include <i386ps2/bus.h>
104 #include "debugf.h"
105 #include "fd_abios.h"
106 #include "fdreg.h"
107 #include "fd.h"
108 #endif MACH_KERNEL
109
110 extern int hz;
111
112 extern hd_delay(int);
113
114 #define HZ hz
115
116 #if defined(FDDEBUG) && !defined(DEBUG)
117 #define DEBUG 1
118 #endif
119
120 #ifdef DEBUG
121 int fddebug = 0;
122 #define FDDEBUG(cond,args) if (cond) (args)
123 #define FDINIT (fddebug & DEBUG_CONFIG)
124 #define FDOPEN (fddebug & DEBUG_OPEN)
125 #define FDCLOSE (fddebug & DEBUG_CLOSE)
126 #define FDREAD (fddebug & DEBUG_READ)
127 #define FDWRITE (fddebug & DEBUG_WRITE)
128 #define FDSTRAT (fddebug & DEBUG_STRATEGY)
129 #define FDINTR (fddebug & DEBUG_INTR)
130 #define FDIOCTL (fddebug & DEBUG_IOCTL)
131 #define FDCMD (fddebug & BIT16)
132 #define FDSTAT (fddebug & BIT9)
133 #define FDABIOS (fddebug & DEBUG_ABIOS)
134 #define FDSTUB (fddebug & BIT17)
135 #define FDDETAIL (fddebug & DEBUG_ERR_COND)
136 #else
137 #define FDDEBUG(cond,args)
138 #endif
139
140 struct buf *geteblk(); /* Added for Mach 3.0 */
141
142 /* Changed for the 3.0 port */
143
144 #ifdef MACH_KERNEL
145 int fdopen(), fdclose(), fdread(), fdwrite(), fdstrategy(), fdintr();
146 #else MACH_KERNEL
147 int fdopen(), fdclose(), fdread(), fdwrite(), fdstrategy(), fdioctl();
148 int fdintr();
149 #endif MACH_KERNEL
150
151 /* Additional internal device driver routines.
152 */
153 int fd_iocformat(dev_t, long, struct floppy *);
154 int fd_iocsinfo(struct floppy *, long);
155 static void fd_sched(struct floppy *);
156 void fd_stot();
157 static int fdcall_abios(int, struct Fd_request *);
158 static int fdcall_abios_poll(int, struct Fd_request *, int);
159 int fdcheck_sequence(struct floppy *);
160 static void fdcleanup(struct floppy *);
161 static int fdcommon_intr(struct Fd_request *);
162 int fddisk_changed(struct floppy *);
163 int fddoor_check(struct floppy *,int);
164 int fderror(struct floppy *);
165 static int fdexecute_command(struct floppy *, int);
166 static void fdget_adapter();
167 static void fdio(struct buf *);
168 static void fdiodone(struct buf *, struct Fd_request *, struct floppy *, int);
169 static int fdissue_command(struct floppy *, int);
170 static int fdload_floppy(struct floppy *, int);
171 int fdmincnt(struct buf *);
172 int fdsettle_test(struct floppy *, int);
173 static int fdsetup_transfer(struct floppy *);
174 int fdspeed_test(struct floppy *);
175 int fdstage1_config(dev_t);
176 void fdtimer(struct fdwatchdog *);
177 static void fdlog_error();
178 static int d_max_page();
179
180 /* Macros:
181 */
182 #define fdtype(fdp) fdload_floppy(fdp,FDRMEDIA_PARMS)
183 #define fdstartio(fdp) fdexecute_command(fdp,\
184 (fdp->headptr->b_flags&B_READ) ? FDREAD_DATA : FDWRITE_DATA);
185
186 #define fd_no_retry(fdp) (fdp)->retry_count = FDMAXRETRIES;
187 #define fd_clear_retry(fdp) (fdp)->retry_count = \
188 ((fdp)->retry_flag == TRUE) ? 0 : FDMAXRETRIES;
189
190 /* Changed for the 3.0 Port */
191
192 #ifdef MACH_KERNEL
193 #define get_pmap(bp) (kernel_pmap)
194 #else MACH_KERNEL
195 #define get_pmap(bp) ( ((bp)->b_proc) ?\
196 (bp)->b_proc->task->map->pmap :\
197 kernel_pmap )
198 #endif MACH_KERNEL
199
200
201 #define NS_PER_TICK (1000000000/HZ)
202 #define NS_TO_TICKS(x) ((x + (NS_PER_TICK - 1)) / NS_PER_TICK)
203 #define us2tics(us) NS_TO_TICKS( ((us) * 1000) ) /* us -> ticks */
204
205 /* Global vars:
206 */
207 static struct adapter_structure fdadapter;
208 static struct floppy floppies[FDMAXDRIVES];
209 static struct buf fdbp[FDMAXDRIVES];
210
211 #ifdef OSF
212 static ihandler_t fd_handler;
213 static ihandler_id_t *fd_handler_id;
214 #endif OSF
215
216 static struct fd_data fd_data[] = {
217 { 18, 80, 2, 27, 108, 255 }, /* FDLOAD_144 */
218 { 9, 80, 2, 42, 80, 255 }, /* FDLOAD_720 */
219 { 9, 40, 2, 42, 80, 255 } /* FDLOAD_360 */
220 };
221
222 static int fddrive_val[FDMAXDRIVES] = {
223 FDDRIVE0,
224 FDDRIVE1
225 };
226
227 static char *fd_tmp_errors[] = {
228 "unsupported drive type", /* FD_UNSUP_DRIVE */
229 "unknown bytes/sector", /* FD_UNSUP_SECT */
230 "unsupported minor", /* FD_UNSUP_MINOR */
231 "lost interrupt", /* FD_ERR_LOSTINT */
232 "media not present", /* FD_ERR_NOMEDIA */
233 "media bad", /* FD_ERR_RETRY */
234 "media changed" /* FD_ERR_CHMEDIA */
235 };
236
237 int fdprobe(), fdslave(), fdattach();
238
239 int (*fdcintrs[])() = { fdintr, 0};
240
241 struct i386_dev *fdinfo[NFD];
242 struct i386_ctlr *fdcinfo[NFDC];
243
244 struct i386_driver fdcdriver = {
245 /* probe slave attach dname dinfo mname minfo */
246 fdprobe, fdslave, fdattach, "fd", fdinfo, "fdc", fdcinfo };
247
248 #ifdef DEBUG
249 #define MAX_ABIOS_FUNCTION_NAMES (sizeof abios_function_names/ sizeof abios_function_names[0])
250 static char *abios_function_names[] = {
251 "def_int", "ret_log_id_param", /* 0 - 1 */
252 "reserved", "read_dev_param", /* 2 - 3 */
253 "set_dev_param", "reset", /* 4 - 5 */
254 "enable", "disable", /* 6 - 7 */
255 "read", "write", /* 8 - 9 */
256 "write-verify", "verify", /* a - b */
257 "read-media-type", "set-media-type", /* c - d */
258 "change-signal-status", "motor-off" /* e - f */
259 "int-status" /* 10 */
260 };
261
262 #define ABIOS_FUNCTION_NAME(fn) ((unsigned) (fn) < MAX_ABIOS_FUNCTION_NAMES ? abios_function_names[fn] : "unknown")
263 #endif DEBUG
264
265 /*
266 * TODO:
267 * call fdinit here so that we can set up interrupts properly before
268 * open is called. Can't do it now because fdexecute_command currently
269 * will sleep which appears to be a no-no at this stage.
270 */
271
272 fdprobe(addr,ctlr)
273 struct i386_ctlr *ctlr;
274 {
275 return(fdinit(ctlr) == FDSUCCESS);
276 }
277
278 /*
279 * determine if the given slave (unit) is present
280 */
281 fdslave(iod)
282 struct i386_dev *iod;
283 {
284 if (iod->dev_slave >= fdadapter.fd_numd)
285 return(0); /* no such drive */
286 return(1);
287 }
288
289 fdattach(iod)
290 struct i386_dev *iod;
291 {
292 }
293
294
295 int
296 fdinit(ctlr)
297 struct i386_ctlr *ctlr;
298 {
299 struct floppy *fdp = &floppies[0];
300 int i, rc;
301
302 FDDEBUG(FDINIT,printf("fdinit: start\n"));
303
304 printf("IBM ABIOS Floppy Disk Driver Ver : 1.1\n");
305
306
307 /* Initialize the adapter struture
308 */
309 fdadapter.fdintr_status = FDFREE;
310 fdadapter.need_controller = FALSE;
311 fdadapter.int_wd.func = NULL;
312 fdadapter.mot_wd.func = NULL;
313 fdadapter.need_sleep = 0; /* NEEDS WORK -- needed ? */
314
315
316 /* Initialize each floppy structure
317 */
318 for (i = 0; i < FDMAXDRIVES; i++) {
319 floppies[i].drive_state = FDSTAT_CLOS;
320 floppies[i].headptr = NULL;
321 floppies[i].tailptr = NULL;
322 floppies[i].close_sleep = 0; /* NEEDS WORK -- sleep on? */
323 floppies[i].timeout_flag = FALSE;
324 floppies[i].retry_flag = TRUE;
325 floppies[i].read_count_bytes = 0;
326 floppies[i].read_count_megabytes = 0;
327 floppies[i].write_count_bytes = 0;
328 floppies[i].write_count_megabytes = 0;
329 floppies[i].open_check = FALSE;
330 floppies[i].motor_off_time = 10;
331
332 /* NEEDS WORK: THE FOLLOWING CAN PROBABLY GO AWAY! */
333 floppies[i].drive_type = D_135H;
334 floppies[i].head_settle_time = 0;
335 floppies[i].motor_start = 0;
336 }
337
338 fdadapter.int_wd.time = 5 * HZ; /* 5 second interrupt watchdog */
339 fdadapter.int_wd.func = fdtimer;
340 fdadapter.int_wd.type = FDINT_WD;
341
342 /* 10 second motor off watchdog
343 */
344 fdadapter.mot_wd.time = fdp->motor_off_time * HZ;
345 fdadapter.mot_wd.func = fdtimer;
346 fdadapter.mot_wd.type = FDMOT_WD;
347
348 /* Do initialization of ABIOS structures. This must
349 * be done before int_enable() and ABIOS_RESET.
350 *
351 * Note: we can set FDBUSY because we are resetting
352 * the adapter and there can't be any other
353 * activity on the floppy.
354 */
355 fdadapter.fdintr_status = FDBUSY;
356
357
358 #ifdef MACH_KERNEL
359 rc = fdabios_init(fdp);
360 #else MACH_KERNEL
361 rc = fdexecute_command(fdp,FDABIOS_INIT);
362 #endif MACH_KERNEL
363
364
365 if (rc != FDSUCCESS) {
366 FDDEBUG(FDOPEN,printf("FDOPEN: FDABIOS_INIT failed\n"));
367 fdcleanup(NULL);
368 return(EIO);
369 }
370
371 if (fdadapter.fd_numd == 0) /* ABIOS sanity check */
372 {
373 #ifdef MACH_KERNEL
374 return D_NO_SUCH_DEVICE;
375 #else /* MACH_KERNEL */
376 return(ENODEV);
377 #endif /* MACH_KERNEL */
378 }
379
380 if (fdadapter.fd_numd > FDMAXDRIVES) {
381 log(LOG_WARNING,"fd: %d drives present. Only %d are supported\n",
382 fdadapter.fd_numd, FDMAXDRIVES);
383 fdadapter.fd_numd = FDMAXDRIVES;
384 }
385
386 #ifdef OSF
387 /* init interrupts */
388 fd_handler.ih_level = fdadapter.fd_intl;
389 fd_handler.ih_handler = fdintr;
390 fd_handler.ih_resolver = (int (*)()) NULL;
391 fd_handler.ih_stats.intr_type = INTR_DEVICE;
392 fd_handler.ih_stats.intr_cnt = 0;
393 fd_handler.ih_priority = SPLFD;
394 fd_handler.ih_flags = IH_FLAG_NOSHARE;
395 if ((fd_handler_id = handler_add( &fd_handler )) != NULL)
396 handler_enable( fd_handler_id );
397 else
398 return(ENXIO);
399 #else
400 ctlr->ctlr_pic = fdadapter.fd_intl;
401 ctlr->ctlr_spl = SPLFD;
402 take_ctlr_irq(ctlr);
403 #endif /* OSF */
404 return(FDSUCCESS);
405 }
406
407 /*
408 * reset the adapter, since this causes an interrupt and hence
409 * a sleep we are called from open not from probe/slave/attach
410 */
411 fdreset()
412 {
413 struct floppy *fdp = &floppies[0];
414 int rc;
415
416 /* Reset the ABIOS "diskette system". This does
417 * stuff for the adapter, not a particular diskette
418 * drive.
419 */
420 fdadapter.fdintr_status = FDBUSY;
421 rc = fdexecute_command(fdp,FDABIOS_RESET);
422 if (rc != FDSUCCESS) {
423 FDDEBUG(FDOPEN, printf( "FDOPEN: FDABIOS_RESET failed\n"));
424 fdcleanup(fdp);
425 return(EIO);
426 }
427
428 return(FDSUCCESS);
429 }
430
431 /* NOTES: The 'devno' parameter always indicates which drive to open, and may
432 * indicate the diskette characteristics to use. The 'minor' macro is used
433 * to extract the minor number from 'devno'. If the minor number portion of
434 * 'devno' is a 0 or a 1, then the fdopen() routine will attempt to
435 * determine the drive type and diskette type by reading from the drive with
436 * different drive characteristics. This is done by calling the fdtype()
437 * routine. If the minor number is 4 or greater, then the diskette
438 * characteristics implied by that format specific special file are used.
439 * The determination of the drive type can be suppressed by ORing the O_NDELAY
440 * flag into the 'devflag' parameter. This is mainly used by the format
441 * command since the open will otherwise fail for an unformatted diskette.
442 */
443 int
444 fdopen(dev, flags)
445 dev_t dev;
446 int flags;
447 {
448 register struct floppy *fdp;
449 int drive;
450 int rc;
451 int firstopen = 1; /* For MULTIPLE_OPENS */
452 static int fdinited = 0;
453
454 FDDEBUG(FDOPEN,printf("fdopen(%x,%x)\n",dev,flags));
455
456 /* This needs to be done early so we can use the values it
457 * initializes.
458 */
459 if (!fdinited) {
460 fdinited = 1;
461 if ( (rc = fdreset()) != FDSUCCESS )
462 return(rc);
463 }
464
465 drive = fd_drive(dev); /* get the drive # */
466 if (drive < 0 || drive >= fdadapter.fd_numd) {
467 FDDEBUG(FDOPEN, printf("FDOPEN: bad drive number %d\n",drive));
468 return (EINVAL);
469 }
470
471 fdp = &floppies[drive];
472
473 /* This was commented out for MACH 3.0 because flags is not passed down */
474
475 #ifdef MACH_KERNEL
476 #else MACH_KERNEL
477
478 if (fdp->drive_state != FDSTAT_CLOS) {
479 /* Check to see if 2nd open has the same characteristics as the
480 * previous opens, as well as exclusive opens.
481 */
482 FDDEBUG(FDOPEN, printf("fdopen: drive already open\n"));
483
484 if ( (minor(fdp->device_number) != minor(dev)) ||
485 (flags & O_EXCL) || (fdp->drive_state & FDSTAT_EXOP) ) {
486 return(EBUSY);
487 }
488
489 goto fd_multopen; /* skip some 1st time stuff */
490 }
491 #endif MACH_KERNEL
492
493
494 /* Load the structure 'floppy' with the default values and the minor
495 * device number.
496 */
497 fdp->device_number = dev;
498 rc = fdload_floppy(fdp, FDREAD_PARMS); /* drive info */
499 if (rc != FDSUCCESS) {
500 fdcleanup(fdp);
501 FDDEBUG(FDOPEN,printf("FDOPEN: default load failed\n"));
502 return (rc);
503 }
504
505 /* This has to happen before fddoor_check() so that we get past
506 * the media changed signal successfully.
507 */
508 fdp->fd_change = FDCHANGE_NEW;
509
510 fd_multopen:
511
512 #ifdef MACH_KERNEL
513 if (!(flags & D_NODELAY)) {
514
515 /*
516 Commented out to allow working of floppy for Mach 3.0
517
518 rc = fddoor_check(fdp, (flags&D_WRITE));
519 */
520 if (rc != FDSUCCESS) {
521 fdcleanup(fdp);
522 return(rc);
523 }
524 }
525 #else MACH_KERNEL
526
527 if (flags & O_EXCL)
528 fdp->drive_state |= FDSTAT_EXOP;
529
530 /* Don't read the diskette if open with O_NDELAY
531 */
532 if (!(flags & O_NDELAY)) {
533 /* Check for diskette presence and write protection (if opening for
534 * write).
535 */
536 rc = fddoor_check(fdp, (flags&FWRITE));
537 if (rc != FDSUCCESS) {
538 fdcleanup(fdp);
539 return (rc);
540 }
541 }
542
543 #endif MACH_KERNEL
544
545 else {
546 /* If the O_NDELAY flag is set, the open is done. Set
547 * drive state to FDOPEN and return.
548 */
549 fdp->drive_state = FDSTAT_OPEN;
550 FDDEBUG(FDOPEN,printf("fdopen: opened O_NDELAY\n"));
551 return(0);
552 }
553
554 /* Some more stuff that needs to only be done on the first open.
555 */
556 if (firstopen) {
557 #ifdef NEEDS_WORK /* NEEDS WORK */
558 /* NEEDS WORK -- Need to do media sence and r/w the diskette before we
559 ** NEEDS WORK -- can determine it's soft type...someday.
560 */
561 /* Call fdtype() to load the floppy structure with the
562 * correct characteristics.
563 */
564 rc = fdtype(fdp);
565 if (rc != FDSUCCESS) {
566 FDDEBUG(FDOPEN, ("FDOPEN: fdtype failed\n"));
567 fdcleanup(fdp);
568 fdp->drive_state = FDSTAT_CLOS;
569 return (rc);
570 }
571 #endif
572
573 /* We're finally ready to set the open flag. Note that
574 * we don't want to set the open flag until the very end
575 * so that we can tell if the drive was on a multiple
576 * open or not.
577 */
578 fdp->drive_state = FDSTAT_OPEN;
579 fdp->close_waiting = FALSE;
580 }
581
582 FDDEBUG(FDOPEN,printf("fdopen: successful\n"));
583 return(0);
584 }
585
586 /* Close the diskette drive. Turn off the light if there is no other
587 * activity on the adapter. Make sure timers and stuff are off.
588 */
589 int
590 fdclose(devno)
591 dev_t devno;
592 {
593 register struct floppy *fdp;
594 int pri; /* for spl* calls */
595 int drive;
596
597 FDDEBUG(FDCLOSE, printf("fdclose: entering...\n"));
598
599 drive = fd_drive(devno);
600
601 FDDEBUG(FDCLOSE,printf("fdclose: drive %d\n", drive));
602
603 /* Is the drive given valid?
604 */
605 if (drive < 0 || drive >= fdadapter.fd_numd)
606 return (EINVAL);
607
608 fdp = &floppies[drive];
609
610 /* Check if see if finished with all i/o for this drive. If
611 * not, sleep until i/o is finished.
612 */
613 pri = splfd();
614 while (fdp->headptr != NULL) {
615 FDDEBUG(FDCLOSE, printf("fdclose: wait for i/o to finish\n"));
616
617 fdp->close_waiting = TRUE;
618 sleep(&fdp->close_sleep, PRIBIO); /* NEEDS WORK */
619 }
620 splx(pri);
621
622 /* Mark this drive as FDCLOSED, call fdcleanup() to do any
623 * cleanup that is possible (including turning off the
624 * light if need be).
625 */
626 fdp->drive_state = FDSTAT_CLOS;
627 fdcleanup(fdp);
628
629 FDDEBUG(FDCLOSE, printf("fdclose: done\n"));
630 return(0);
631 }
632
633 /* The block i/o entry point. Check parameters for validity and enqueue
634 * the request, starting i/o if the adapter is free.
635 */
636 int
637 fdstrategy(bp)
638 register struct buf *bp;
639 {
640 register struct floppy *fdp;
641 int pri;
642
643 FDDEBUG(FDSTRAT, printf("fdstrategy: entering...\n"));
644
645 fdp = &floppies[fd_drive(bp->b_dev)];
646 bp->b_resid = 0;
647 bp->b_error = 0;
648 bp->av_forw = NULL;
649
650 /* If the byte transfer length is not a multiple of 512
651 * bytes, return EINVAL and return.
652 */
653 if (bp->b_bcount % fdp->bytes_per_sector) {
654 FDDEBUG(FDSTRAT, printf("fdstrategy: n != x*512\n"));
655 bp->b_flags |= B_ERROR;
656 bp->b_error = EINVAL;
657
658 /* no data transferred */
659 bp->b_resid += bp->b_bcount;
660
661 iodone(bp);
662 goto fd_done;
663 }
664
665 /* Verify that i/o does not start past the end of the
666 * diskette. Also, verify that the starting block number is
667 * non-negative.
668 *
669 * Error codes:
670 * EINVAL - the blkno is negative, or is a read past
671 * the last block on the media
672 * ENOSPC - A write past the end of the media.
673 *
674 * Note that a read on the last block (actually 1st non-
675 * valid block) is not an error, but not data is transferred.
676 */
677 if ( (bp->b_blkno < 0) || (bp->b_blkno >= fdp->number_of_blocks) ) {
678 FDDEBUG(FDSTRAT, printf("fdstrategy: invalid blkno\n"));
679
680 if (!(bp->b_flags & B_READ)) { /* B_WRITE */
681 bp->b_flags |= B_ERROR;
682 if (bp->b_blkno < 0)
683 bp->b_error = EINVAL;
684 else
685 #ifdef MACH_KERNEL
686 bp->b_error = EIO; /* EIO is mapped D_IO_ERROR */
687 #else MACH_KERNEL
688 bp->b_error = ENOSPC;
689 #endif MACH_KERNEL
690 }
691 else if (bp->b_blkno == fdp->number_of_blocks) {
692 bp->b_error = 0;
693 }
694 else {
695 bp->b_flags |= B_ERROR;
696 bp->b_error = EINVAL;
697 }
698
699 /* all cases use the same b_resid */
700 bp->b_resid = bp->b_bcount;
701
702 iodone(bp);
703 goto fd_done;
704 }
705
706 /* See if there are any buffer headers in the queue.
707 * If there are, put the buffer header at the end of
708 * the queue. If the queue is empty, put the buffer
709 * header in the queue and call fdio().
710 */
711 pri = splfd();
712
713 if (fdp->headptr != NULL) { /* queue not empty */
714 FDDEBUG(FDSTRAT, printf("fdstrategy: buf appended to q\n"));
715
716 /* link it in the list:
717 * - old tail points at new element
718 * - new element becomes the new tail
719 */
720 fdp->tailptr->av_forw = bp;
721 fdp->tailptr = bp;
722
723 splx(pri);
724 }
725 else { /* q empty -> start i/o */
726 /* set up the queue of 1 buf struct
727 * - head and tail are the same.
728 */
729 fdp->headptr = fdp->tailptr = bp;
730
731 /* If the adapter is free (other diskettes also
732 * not busy) then start the io. If the adapter
733 * is busy, then the interrupt handler will find
734 * the request and start it up.
735 *
736 * To start the i/o, re-enable interrupts, make
737 * sure we can get the adapter (it will not sleep
738 * if we are at interrupt level), and then start
739 * the i/o.
740 */
741 if (fdadapter.fdintr_status == FDFREE) {
742 FDDEBUG(FDSTRAT, printf("fdstrategy: startio\n"));
743
744 splx(pri);
745 fdget_adapter();
746 fdio(bp);
747 }
748 else
749 splx(pri);
750 }
751
752 fd_done:
753 FDDEBUG(FDSTRAT, printf("fdstrategy: done\n"));
754 return (FDSUCCESS);
755 }
756
757 /* Raw read. Use physio() to do the transfer.
758 *
759 * NEEDS WORK - We should handle unaligned transfers for both read and
760 * NEEDS WORK - in a common routine around here somewhere.
761 */
762 int
763 fdread(devno, uiop)
764 dev_t devno;
765 struct uio *uiop;
766 {
767 register struct buf *bp = &fdbp[fd_drive(devno)];
768
769 #ifdef MACH_KERNEL
770 #else MACH_KERNEL
771 register struct iovec *iov;
772 register int cnt;
773 #endif MACH_KERNEL
774
775 FDDEBUG(FDREAD, printf("fdread: start\n"));
776
777
778 #ifdef MACH_KERNEL
779 #else MACH_KERNEL
780
781 /* Check for atleast 512 byte alignment on all io_vec's.
782 */
783 iov = uiop->uio_iov;
784 for(cnt = 0 ; cnt < uiop->uio_iovcnt; cnt++) {
785 if ( ((u_int)(iov++)->iov_base) & 0x1ff)
786 return(EIO);
787 }
788
789 #endif MACH_KERNEL
790
791 return(physio(fdstrategy,bp,devno,B_READ,fdmincnt,uiop));
792 }
793
794 /* Raw write. Use physio() to do the transfer.
795 */
796 int
797 fdwrite(devno, uiop)
798 dev_t devno;
799 struct uio *uiop;
800 {
801 register struct buf *bp = &fdbp[fd_drive(devno)];
802
803 #ifdef MACH_KERNEL
804 #else MACH_KERNEL
805 register struct iovec *iov;
806 register int cnt;
807 #endif MACH_KERNEL
808
809 FDDEBUG(FDWRITE, printf("fdwrite: start\n"));
810
811
812 #ifdef MACH_KERNEL
813 #else MACH_KERNEL
814 /* Check for atleast 512 byte alignment on all io_vec's.
815 */
816 iov = uiop->uio_iov;
817 for(cnt = 0 ; cnt < uiop->uio_iovcnt; cnt++) {
818 if ( ((u_int)(iov++)->iov_base) & 0x1ff)
819 return(EIO);
820 }
821 #endif MACH_KERNEL
822
823 return(physio(fdstrategy,bp,devno,B_WRITE,fdmincnt,uiop));
824 }
825
826 /* Changed for the 3.0 port */
827
828 #ifdef MACH_KERNEL
829 #else MACH_KERNEL
830
831 /* ioctl entry point. Lots of status, plus things like format.
832 *
833 * NEEDS WORK -- no ioctl's are currently implemented.
834 */
835 int
836 fdioctl(devno, op, arg, devflag)
837 dev_t devno;
838 int op;
839 register long arg;
840 u_int devflag;
841 {
842 #ifdef NEEDS_WORK /* NEEDS WORK: LOOK AT IOCTLs LATER */
843 register struct floppy *fdp;
844 register struct devinfo *devinfop;
845 register struct fdinfo *fdinfop;
846 register struct fdparms *fdparmsp;
847 int tmp;
848 int rc = FDSUCCESS;
849
850 FDDEBUG(FDIOCTL, printf("fdioctl: start\n"));
851
852 fdp = &floppies[fd_drive(devno)];
853
854 switch (op) {
855
856 case IOCINFO:
857 /* The following ioctl operation is defined for every device
858 * that uses the ioctl interface.
859 *
860 * IOCINFO - returns some information about the diskette.
861 * This is a standard ioctl option that can be issued to find
862 * out information about any device that uses ioctls. A
863 * poiner to a structure of type devinfo should be passed in
864 * the 'arg' parameter. The information about the diskette
865 * will be loaded into the devinfo structure.
866 */
867 FDDEBUG(FDIOCTL, printf("fdioctl: IOCINFO\n"));
868
869 /* Allocate a devinfo structure. */
870 devinfop = (struct devinfo *) malloc(sizeof(struct devinfo));
871
872 if (devinfop == NULL)
873 rc = ENOMEM;
874 else {
875 devinfop->devtype = DD_DISK;
876 devinfop->flags = DF_RAND;
877 devinfop->un.dk.bytpsec = (short) fdp->bytes_per_sector;
878 devinfop->un.dk.secptrk = (short) fdp->sectors_per_track;
879 devinfop->un.dk.trkpcyl = (short) fdp->tracks_per_cylinder;
880 devinfop->un.dk.numblks = (long) fdp->number_of_blocks;
881
882 /* Copy the structure to the user's address space.
883 */
884 tmp = copyout( (char *)devinfop, (char *)arg,
885 sizeof(struct devinfo) );
886 if (tmp == -1)
887 rc = EINVAL;
888
889 free((caddr_t) devinfop);
890 }
891 break;
892
893 case FDIOCFORMAT:
894 /* See the header comment for fdiocformat()
895 */
896 FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCFORMAT\n"));
897
898 rc = fd_iocformat(devno,arg,fdp);
899
900 FDDEBUG(FDIOCTL, printf("fdioctl: done\n"));
901 break;
902
903 case FDIOCGINFO:
904 /* FDIOCGINFO - gets the current diskette characteristics. A
905 * pointer to a structure of type fdinfo must be passed in
906 * the 'arg' parameter. This operation will load the fdinfo
907 * structure with the current diskette parameters.
908 */
909 FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCGINFO\n"));
910
911 /* Allocate an fdinfo structure. */
912 fdinfop = (struct fdinfo *) malloc(sizeof(struct fdinfo));
913
914 if (fdinfop == NULL)
915 rc = ENOMEM;
916 else {
917 fdinfop->type = (short) (fdp->drive_type);
918 fdinfop->nsects = (int) (fdp->sectors_per_track);
919 fdinfop->sides = (int) (fdp->tracks_per_cylinder);
920 fdinfop->ncyls = (int) (fdp->cylinders_per_disk);
921
922 /* Call copyout to copy the fdinfo structure to the
923 * user.
924 */
925 tmp = copyout((char *) (fdinfop), (char *) (arg),
926 sizeof(struct fdinfo));
927 if (tmp == -1)
928 rc = EINVAL;
929
930 free((caddr_t) fdinfop);
931 }
932 break;
933
934 case FDIOCSINFO:
935 /* See the header comment for fd_iocsinfo()
936 */
937 FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCSINFO\n"));
938 rc = fd_iocsinfo(fdp,arg);
939 break;
940
941 case FDIOCRETRY:
942 case FDIOCNORETRY:
943 /* FDIOCRETRY - enables retries on errors.
944 * FDIOCNORETRY - disables retries on errors.
945 *
946 * These operations require RAS_CONFIG authority.
947 */
948 FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCNORETRY\n"));
949
950 if (priv_chk(RAS_CONFIG))
951 fdp->retry_flag = (op == FDIOCRETRY) ? TRUE : FALSE;
952 else
953 rc = EACCES;
954 break;
955
956 case FDIOCSTATUS:
957 /* See header comment for fd_iocstatus()
958 */
959 rc = fd_iocstatus(fdp,arg);
960 break;
961
962 case FDIOCGETPARMS:
963 /* FDIOCGETPARMS - gets various drive and diskette parameters
964 * and returns them to the caller.
965 *
966 * The following two ioctls are designed for use by the PC
967 * simulator.
968 */
969 FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCGETPARMS\n"));
970
971 /* Allocate an fdparms structure.
972 */
973 fdparmsp = (struct fdparms *) malloc(sizeof(struct fdparms));
974 if (fdparmsp == NULL) {
975 rc = ENOMEM;
976 break;
977 }
978
979 fdparmsp->diskette_type = fdp->diskette_type;
980 fdparmsp->sector_size = fdp->e_bytesps;
981 fdparmsp->sectors_per_track = fdp->sectors_per_track;
982 fdparmsp->sectors_per_cylinder = fdp->sectors_per_cylinder;
983 fdparmsp->tracks_per_cylinder = fdp->tracks_per_cylinder;
984 fdparmsp->cylinders_per_disk = fdp->cylinders_per_disk;
985 fdparmsp->data_rate = fdp->data_rate;
986 fdparmsp->head_settle_time = fdp->head_settle_time;
987 fdparmsp->head_load = 0;
988 fdparmsp->fill_byte = fdp->fill_byte;
989 fdparmsp->step_rate = 0;
990 fdparmsp->step_rate_time = 0;
991 fdparmsp->gap = fdp->gap;
992 fdparmsp->format_gap = fdp->format_gap;
993 fdparmsp->data_length = fdp->data_length;
994 fdparmsp->motor_off_time = fdp->motor_off_time;
995 fdparmsp->bytes_per_sector = fdp->bytes_per_sector;
996 fdparmsp->number_of_blocks = fdp->number_of_blocks;
997
998 /* Call copyout to copy the fdinfo structure to the user. */
999
1000 tmp = copyout((char *) (fdparmsp), (char *) (arg), sizeof(struct fdparms));
1001 if (tmp == -1)
1002 rc = EINVAL;
1003 free((caddr_t) fdparmsp);
1004 break;
1005
1006 case FDIOCSETPARMS:
1007 #define check(cnd,errno) if (!(cnd)) {
1008 free((caddr_t) fdparmsp);
1009 rc = (errno);
1010 break;
1011 }
1012 #define cond(member) (fdp->member == fdparmsp->member)
1013
1014 /* FDIOCGETPARMS - sets various drive and diskette parameters
1015 * from values passed in from the caller.
1016 */
1017 FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCSETPARMS\n"));
1018
1019 /* Allocate an fdparms structure. */
1020
1021 fdparmsp = (struct fdparms *) malloc(sizeof(struct fdparms));
1022 if (fdparmsp == NULL) {
1023 rc = ENOMEM;
1024 break;
1025 }
1026
1027 /* get the fdparms structure from the user
1028 */
1029 tmp = copyin((char *) (arg), (char *) (fdparmsp),
1030 sizeof(struct fdparms));
1031 check(tmp == 0,EINVAL);
1032
1033 /* There are certin fields we just can't let the user
1034 * change, because it will reek havoc on the driver, and
1035 * potentially the kernel. Here we check them, and return
1036 * EINVAL if they are bad. Note they are also not set, but
1037 * we want to return EINVAL, just to make sure someone
1038 * doesn't get the delusion that something has changed.
1039 */
1040 check(fdp->diskette_type == fdparmsp->diskette_type,EINVAL);
1041 check(fdparmsp->head_load == 0,EINVAL);
1042 check(fdparmsp->step_rate == 0,EINVAL);
1043 check(fdparmsp->step_rate_time == 0,EINVAL);
1044 check(cond(sectors_per_track),EINVAL);
1045 check(cond(sectors_per_cylinder),EINVAL);
1046 check(cond(tracks_per_cylinder),EINVAL);
1047 check(cond(cylinders_per_disk),EINVAL);
1048 check(cond(data_rate),EINVAL);
1049 check(cond(head_settle_time),EINVAL);
1050 check(cond(number_of_blocks),EINVAL);
1051 check(cond(bytes_per_sector),EINVAL);
1052
1053 /* Now the fields we can really change with a "Set Device
1054 * Parameters" ABIOS call. If the attribute has changed
1055 * then we save the original value, and call FD_SETDP_POLL
1056 * or FD_SETMT_POLL to attempt to change the value. If the
1057 * call fails, we back out the change, and fail the ioctl
1058 * with EINVAL.
1059 */
1060 if (fdp->e_bytesps != fdparmsp->sector_size) {
1061 check((fdparmsp->sector_size==FD_256_BYTE_PER_SECTOR)||
1062 (fdparmsp->sector_size==FD_512_BYTE_PER_SECTOR),
1063 EINVAL);
1064 tmp = fdp->e_bytesps;
1065 fdp->e_bytesps = fdparmsp->sector_size;
1066 fdget_adapter();
1067 if (fdexecute_command(fdp,FD_SETDP_POLL)!=FDSUCCESS) {
1068 fdp->e_bytesps = tmp;
1069 free(fdparmsp);
1070 rc = EINVAL;
1071 break;
1072 }
1073
1074 /* When changing the sector_size, bytes_per_sector
1075 * is implicitly changed, and we need to reflect
1076 * this back to the user so he can continue to make
1077 * fdiocsetparms ioctl's with the current fdparm
1078 * structure.
1079 */
1080 fdparmsp->bytes_per_sector = fdp->bytes_per_sector;
1081 tmp = copyout((char *) (fdparmsp), (char *) (arg),
1082 sizeof(struct fdparms));
1083 check(tmp == 0,EINVAL);
1084 }
1085
1086 if (fdp->gap != fdparmsp->gap) {
1087 tmp = fdp->gap;
1088 fdp->gap = fdparmsp->gap;
1089 fdget_adapter();
1090 if (fdexecute_command(fdp,FD_SETDP_POLL)!=FDSUCCESS) {
1091 fdp->gap = tmp;
1092 free(fdparmsp);
1093 rc = EINVAL;
1094 break;
1095 }
1096 }
1097
1098 if (fdp->data_length != fdparmsp->data_length) {
1099 tmp = fdp->data_length;
1100 fdp->data_length = fdparmsp->data_length;
1101 fdget_adapter();
1102 if (fdexecute_command(fdp,FD_SETDP_POLL)!=FDSUCCESS) {
1103 fdp->data_length = tmp;
1104 free(fdparmsp);
1105 rc = EINVAL;
1106 break;
1107 }
1108 }
1109
1110 if (fdp->fill_byte != fdparmsp->fill_byte) {
1111 tmp = fdp->fill_byte;
1112 fdp->fill_byte = fdparmsp->fill_byte;
1113 fdget_adapter();
1114 if (fdexecute_command(fdp,FD_SETMT_POLL)!=FDSUCCESS) {
1115 fdp->fill_byte = tmp;
1116 free(fdparmsp);
1117 rc = EINVAL;
1118 break;
1119 }
1120 }
1121
1122 if (fdp->format_gap != fdparmsp->format_gap) {
1123 tmp = fdp->format_gap;
1124 fdp->format_gap = fdparmsp->format_gap;
1125 fdget_adapter();
1126 if (fdexecute_command(fdp,FD_SETMT_POLL)!=FDSUCCESS) {
1127 fdp->format_gap = tmp;
1128 free(fdparmsp);
1129 rc = EINVAL;
1130 break;
1131 }
1132 }
1133
1134 /* Update the motor off time: If it is really changed, then
1135 * calculate the delta between the 2 times, making sure the
1136 * value is atleast 1 second so it won't possibly get missed.
1137 */
1138 /* NEEDS WORK -- this code changed a touch from version 3
1139 * NEEDS WORK -- since we use 1/HZ timers instead of watch-
1140 * NEEDS WORK -- dogish timers, and we have to untimeout()
1141 * NEEDS WORK -- them, and can't update on the fly...Don't
1142 * NEEDS WORK -- if we can get it to change the time, until
1143 * NEEDS WORK -- with the next time out...
1144 */
1145 if (fdp->motor_off_time != fdparmsp->motor_off_time) {
1146 #ifdef NEEDS_WORK /* NEEDS WORK */
1147 tmp = fdadapter.mot_wd.time -
1148 (fdp->motor_off_time -
1149 fdparmsp->motor_off_time);
1150 tmp = (tmp < 1) ? 1 : tmp;
1151 fdadapter.mot_wd.timer.count = tmp;
1152 #endif
1153 fdadapter.mot_wd.time = fdparmsp->motor_off_time;
1154 fdp->motor_off_time = fdparmsp->motor_off_time;
1155 }
1156
1157 free((caddr_t) fdparmsp);
1158 break;
1159
1160 default:
1161 FDDEBUG(FDIOCTL, printf("fdioctl: no such ioctl\n"));
1162 rc = EINVAL;
1163 break;
1164 }
1165
1166 FDDEBUG(FDIOCTL, printf("fdioctl: done\n"));
1167 return (rc);
1168 #else
1169 return(EINVAL);
1170 #endif
1171 }
1172 #endif MACH_KERNEL
1173
1174
1175 /* This routine calls fdcall_abios() and uses sleep() to wait until
1176 * the call is completed. The FD_RB_SYNC flag is set in the request
1177 * block so the interrupt handler knows to handle the request specially.
1178 *
1179 * The interrupt handler uses wakeup() to wake this process up, and does
1180 * not do an iodone() since a polled request will never come from the
1181 * buffer cache.
1182 *
1183 * The 3rd parameter to this function (sched) is a boolean that indicates
1184 * if we should call fd_sched() to look for more ABIOS requests to process.
1185 * This is useful when a particular function requires multiple ABIOS
1186 * requests or the caller needs to use values out of the request block,
1187 * and does not want to have these values trashed by subsequent ABIOS calls.
1188 *
1189 * NOTES: fdcall_abios_poll() should not be used for ABIOS calls that do
1190 * not stage on time, or stage on interrupt. Use fdcall_abios() for this
1191 * directly. If the poll functionality is used in this case, then the
1192 * error code cannot be returned properly.
1193 *
1194 * open_check gets set to FALSE when the polled request is done. See
1195 * fdtimer() for more info.
1196 */
1197 static int
1198 fdcall_abios_poll(abios_function, rb, sched)
1199 int abios_function;
1200 register struct Fd_request *rb;
1201 int sched;
1202 {
1203 register struct floppy *fdp;
1204 int rc;
1205 int pri; /* for i_ calls */
1206
1207 FDDEBUG(FDABIOS, printf("fdcall_abios_poll: function 0x%x (%s) rb=0x%x sched=%d\n",
1208 abios_function, ABIOS_FUNCTION_NAME(abios_function),rb,sched));
1209
1210 fdp = &floppies[rb->r_unit]; /* get floppy structure */
1211 fdp->timeout_flag = FALSE; /* clear timeout flag */
1212 rb->state |= FD_RB_SYNC; /* this is a synchronous request */
1213 rb->req_errno = 0; /* clear for non-intr calls */
1214
1215
1216 fdcall_abios(abios_function,rb);
1217
1218
1219
1220 /* Sleep until our request is finished.
1221 */
1222
1223 pri = splfd();
1224
1225 while (rb->r_return_code != ABIOS_DONE) {
1226 FDDEBUG(FDABIOS,printf("fdcall_abios_poll: calling sleep\n"));
1227 sleep(&rb->sleep_on_intr, PRIBIO); /* NEEDS WORK */
1228 FDDEBUG(FDABIOS, printf("fdcall_abios_poll: sleep done\n"));
1229 }
1230
1231
1232 splx(pri);
1233
1234
1235 /* Any errors will be found on interrupt level and passed
1236 * back to use through req_errno.
1237 */
1238
1239 rc = rb->req_errno;
1240
1241 pri = splfd();
1242 rb->state &= ~FD_RB_SYNC; /* done with sync reqest */
1243 fdp->open_check = FALSE; /* make sure this gets set off */
1244
1245 /* If the caller wants is to schedule more jobs, and the request
1246 * passed then try schedule a job. If the request failed then
1247 * fdexecute_command() will end up calling fd_sched() for us.
1248 */
1249
1250 if ( (sched == TRUE) && (rc == FDSUCCESS) )
1251 fd_sched(fdp); /* look for additional requests */
1252
1253 splx(pri);
1254
1255 FDDEBUG(FDABIOS, printf("fdcall_abios_poll: done\n"));
1256
1257 return (rc);
1258 }
1259
1260 /* Calls ABIOS (abios_common_start() is used). Sets up a watchdog
1261 * timer to watch for losing interrupts. Also sets up for the first
1262 * first stage on time by scheduling a stage on time "interrupt".
1263 */
1264 static int
1265 fdcall_abios(abios_function, rb)
1266 int abios_function;
1267 register struct Fd_request *rb;
1268 {
1269 FDDEBUG(FDABIOS, printf("fdcall_abios: function 0x%x (%s)\n", abios_function, ABIOS_FUNCTION_NAME(abios_function)));
1270
1271 rb->r_function = abios_function;
1272 rb->r_return_code = ABIOS_UNDEFINED;
1273 rb->state |= FD_RB_STARTED;
1274
1275 abios_common_start(rb, fdadapter.fd_flag);
1276
1277 FDDEBUG(FDABIOS, {
1278 printf("[start_rw] RET abios_common_start... status=%x [", rb->r_return_code);
1279 fd_error_decode(rb->r_return_code, "]\n");});
1280
1281 /* Schedule a pseudeo interrupt if ABIOS tells us to wait.
1282 */
1283
1284
1285 if (rb->r_return_code == ABIOS_STAGE_ON_TIME) {
1286 FDDEBUG(FDABIOS,printf("fdcall_abios: ABIOS_STAGE_ON_TIME(%d)\n",
1287 fd_wait_time(rb)));
1288
1289 timeout(fd_stot,(caddr_t)NULL,us2tics(fd_wait_time(rb)));
1290 }
1291
1292 /* If this operation does not return immediatly, it will set
1293 * r_time_out. Set a watchdog for the proper # of seconds
1294 * incase this operation does not complete.
1295 */
1296
1297 if (rb->r_time_out != 0) {
1298 fdadapter.int_wd.time = (rb->r_time_out >> 3) * HZ;
1299 fdadapter.int_wd.fdp = &floppies[fdadapter.fd_req.r_unit];
1300 TIMEOUT(fdadapter.int_wd);
1301 }
1302
1303 FDDEBUG(FDABIOS, printf("fdcall_abios: done\n"));
1304 return(FDSUCCESS);
1305 }
1306
1307 /* Does some front/back end processing for fdissue_command().
1308 *
1309 * Calls fdissue_command() and arranges for proper scheduling of further
1310 * jobs after that request is done.
1311 */
1312 static int
1313 fdexecute_command(fdp, arg)
1314 register struct floppy *fdp;
1315 int arg;
1316 {
1317 int sched_needed; /* schedule flag */
1318 int pri; /* for i_* */
1319 int rc;
1320
1321 /* This is a safty catch. It is assumed that the job calling
1322 * fdexecute_command() has gotten access to the controller.
1323 */
1324 assert(fdadapter.fdintr_status == FDBUSY);
1325
1326 rc = fdissue_command(fdp, arg);
1327
1328 if (rc == FDSUCCESS) {
1329 switch (arg) {
1330 case FDABIOS_INIT:
1331 case FDREAD_PARMS:
1332 case FDRMEDIA_PARMS:
1333 case FDLOAD_144:
1334 case FDLOAD_720:
1335 case FDLOAD_360:
1336 case FD_SETDP_POLL:
1337 /* For commands that poll and need to read data
1338 * out of the request block, we must schedule
1339 * the pending requests.
1340 */
1341 sched_needed = TRUE;
1342 break;
1343
1344 default:
1345 sched_needed = FALSE;
1346 break;
1347 }
1348 }
1349 else {
1350 /* A schedule is not on polled requests that fail. All
1351 * non-polled requests return FDSUCCESS always.
1352 */
1353 sched_needed = TRUE;
1354 }
1355
1356 /* If we have a status of free, check to see if there are any
1357 * requests to do, and if so, do start them up.
1358 */
1359 pri = splfd();
1360 if (sched_needed == TRUE)
1361 fd_sched(fdp);
1362 splx(pri);
1363
1364 return (rc);
1365 }
1366
1367 /* Sets up the floppy structure for i/o and calls fdstartio. This routine
1368 * translates the starting block of a read or write into the cylinder,
1369 * head, sector address required by the controller. It then computes
1370 * the total number of reads or writes needed and initializes the fields
1371 * in the floppy structure that are used to execute a read or write.
1372 *
1373 * NOTES: This routine is called once for each buf struct processed. It is
1374 * called by both fdstrategy() and fdintr() to initiate a new i/o sequence
1375 * for a given buf struct.
1376 */
1377 static void
1378 fdio(bp)
1379 register struct buf *bp;
1380 {
1381 register struct floppy *fdp;
1382 u_char drive;
1383 daddr_t last_block;
1384
1385 drive = fd_drive(bp->b_dev);
1386 fdp = &floppies[drive];
1387 FDDEBUG(FDCMD, printf("fdio: start io drive %d\n", drive));
1388
1389 /* See if a request goes past the end of the diskette.
1390 */
1391 last_block = bp->b_blkno + (bp->b_bcount / fdp->bytes_per_sector);
1392
1393 fdp->modified_bcount = bp->b_bcount; /* cnt for this transfer */
1394
1395 if (last_block > fdp->number_of_blocks) {
1396 /* Request starts before the end of the diskette but
1397 * runs over the end. Set up to do a partial data transfer
1398 * and return the number of bytes not transferred in the
1399 * b_resid field.
1400 */
1401 FDDEBUG(FDCMD, printf("fdio: truncated request\n"));
1402
1403 bp->b_resid = (last_block - fdp->number_of_blocks) *
1404 fdp->bytes_per_sector;
1405 fdp->modified_bcount -= bp->b_resid;
1406 }
1407
1408 /* initialize io counters */
1409 fdp->buf_offset = 0;
1410 fdp->sectors_done = 0;
1411 fd_clear_retry(fdp);
1412
1413 /* Set up the transfer with fdsetup_transfer, and if this
1414 * succeeds, then actually start the transfer.
1415 */
1416 if (fdsetup_transfer(fdp))
1417 fdstartio(fdp);
1418
1419 return;
1420 }
1421
1422 /* Takes an fdp, and sets the transfer in terms of what AIBOS understands.
1423 * Mainly this is converting an offset into a physical address on the
1424 * diskette.
1425 *
1426 * We also have to check for splitting transfers that would encompass
1427 * multiple heads. Another thing we do is set up the request block which
1428 * includes using pmap_extract() to get the physical address.
1429 */
1430 static int
1431 fdsetup_transfer(fdp)
1432 register struct floppy *fdp;
1433 {
1434 daddr_t blkno;
1435 u_char cyl;
1436 u_char head;
1437 u_char sect;
1438 u_short sectors_left;
1439 u_short temp;
1440 int msize; /* maximum size of transfer */
1441 u_int paddr;
1442 u_int vaddr;
1443
1444 /* Calculate blkno of transfer as where we were suppost to
1445 * start plus where we currently are.
1446 */
1447 blkno = (daddr_t) fdp->headptr->b_blkno + fdp->sectors_done;
1448
1449 /* Translate block number into physical address.
1450 */
1451 FDDEBUG(FDCMD, printf("fdio: start block is #%d\n", blkno));
1452 cyl = fdp->start.cylinder = blkno / fdp->sectors_per_cylinder;
1453 temp = blkno % fdp->sectors_per_cylinder;
1454 head = fdp->start.head = temp / fdp->sectors_per_track;
1455 sect = fdp->start.sector = (temp % fdp->sectors_per_track) + 1;
1456
1457 /* Set up the other fields in 'floppy' that are used for keeping
1458 * track of reads and writes.
1459 */
1460 fdp->start_block = blkno;
1461 fdp->sector_count = fdp->modified_bcount / fdp->bytes_per_sector;
1462
1463 /* compute number of sectors to r/w from starting cylinder
1464 */
1465 sectors_left = fdp->sectors_per_cylinder - head *
1466 fdp->sectors_per_track - sect + 1;
1467
1468 /* If a read requires of multiple sectors goes onto another cylinder
1469 * then we have to split it into multiple requests.
1470 */
1471 if (sectors_left < fdp->sector_count) {
1472 FDDEBUG(FDCMD, printf("fdsetup_transfer: multiple requests!!\n"));
1473
1474 fdp->transfer_split = TRUE;
1475 fdp->start.transfer_length = sectors_left * fdp->bytes_per_sector;
1476 }
1477 else {
1478 fdp->start.transfer_length = fdp->modified_bcount;
1479 fdp->transfer_split = FALSE;
1480 }
1481
1482 /* Check to see if transfer crosses a page boundry. If so we
1483 * need to split it into multiple transfers. Also set up both
1484 * the virtual and physical pointers for the ABIOS call.
1485 */
1486 vaddr = (u_int) fdp->headptr->b_un.b_addr + fdp->buf_offset;
1487 msize = d_max_page(fdp->headptr, vaddr, &paddr, fdp->start.transfer_length);
1488 fd_data_ptr_1(&fdadapter.fd_req) = vaddr;
1489 fd_data_ptr_2(&fdadapter.fd_req) = paddr;
1490
1491 if (msize < fdp->start.transfer_length) {
1492 FDDEBUG(FDCMD,printf("fdsetup_transfer: split for page!\n"));
1493
1494 if (!msize) {
1495 fdiodone(fdp->headptr,&fdadapter.fd_req,fdp,EIO);
1496 return(0);
1497 }
1498
1499 fdp->transfer_split = TRUE;
1500 fdp->start.transfer_length = msize;
1501 }
1502
1503 return(1);
1504 }
1505
1506 /* Builds a command for ABIOS, and then calls the ABIOS interface routines.
1507 *
1508 * This should only be called when you have the FDBUSY flag set for you
1509 * job. Currently only fdexecute_command() and fdcommon_intr() call this.
1510 */
1511 static int
1512 fdissue_command(fdp, arg)
1513 register struct floppy *fdp;
1514 int arg;
1515 {
1516 int rc = FDSUCCESS;
1517 register struct Fd_request *fdreq;
1518 u_char drive_number;
1519 int poll = arg & FDABIOS_POLL; /* save poll status */
1520
1521 arg &= ~FDABIOS_POLL; /* make it transparent to switch */
1522
1523 /* Set up:
1524 * - reset timeout flag.
1525 * - stop previous motor watchdog timer.
1526 * - get local copies of the adapter pointer and the driveno
1527 */
1528 fdp->timeout_flag = FALSE;
1529 UNTIMEOUT(fdadapter.mot_wd);
1530 fdreq = &fdadapter.fd_req;
1531 drive_number = fd_drive(fdp->device_number);
1532
1533 switch (arg) {
1534 case FDABIOS_INIT:
1535 /* Does the first few ABIOS calls to initialize the
1536 * request block, and find a little bit of info about
1537 * the adapter. This is the first thing that should
1538 * be called for ABIOS, and before i_init() is done.
1539 *
1540 * ie fdintr() must not be called till after this
1541 * done. Nothing here will cause an interrupt.
1542 */
1543 FDDEBUG(FDCMD, printf("FDABIOS_INIT: entering...\n"));
1544
1545 fdadapter.fd_flag = 0;
1546 fdreq->state = FD_RB_IDLE;
1547 fdreq->sleep_on_intr = 0; /* NEEDS WORK -- sleep on? */
1548
1549 /* First we have to set up the initial request block,
1550 * and call "Return Logical ID parameters" in order
1551 * to get info for future ABIOS calls.
1552 */
1553
1554 FD_SET_RESERVED_ABIOS_LOGICAL_PARAMETER(fdreq);
1555
1556 fdreq->r_current_req_blck_len = sizeof(struct Fd_request);
1557 fdreq->r_logical_id = abios_next_LID(FD_ID,2);
1558 fdreq->r_unit = 0;
1559 fdreq->request_header.Request_Block_Flags = 0; /* ABIOS32 */
1560 fdreq->request_header.ELA_Offset = 0;
1561 fd_no_retry(fdp);
1562
1563 rc = fdcall_abios_poll(ABIOS_LOGICAL_PARAMETER, fdreq, FALSE);
1564
1565 if (rc != FDSUCCESS)
1566 break;
1567
1568 /* Note: We don't have to do an fdget_adapter() here
1569 * because the above call will not reschedule the floppy
1570 * adapter, and the FDBUSY flag will not get turned off.
1571 */
1572
1573 /* update certain fields based on what abios just told us
1574 * 1) use the real block length
1575 * 2) logical .vs. physical ptr
1576 * 3) hardware interrupt level
1577 * 4) # of drives on the adapter
1578 */
1579 fdreq->r_current_req_blck_len = fdreq->r_request_block_length;
1580 fdadapter.fd_flag = fdreq->r_logical_id_flags;
1581 fdadapter.fd_intl = fdreq->r_hardware_intr;
1582 fdadapter.fd_numd = fdreq->r_number_units;
1583
1584 /* We need to make this call before ABIOS_RESET inorder
1585 * to get the motor_off_delay
1586 */
1587
1588 FD_SET_RESERVED_ABIOS_READ_PARAMETER(fdreq);
1589 fdreq->r_unit = 0;
1590 fd_no_retry(fdp);
1591
1592 rc = fdcall_abios_poll(ABIOS_READ_PARAMETER, fdreq, FALSE);
1593
1594 fdadapter.motor_off_delay = fd_motor_off_delay_time(fdreq);
1595 /* rc falls through */
1596 break;
1597
1598 case FDABIOS_RESET:
1599 /* This does an ABIOS_RESET on the diskette system which
1600 * basically gets the adapter set up. This should
1601 * be the 2nd thing called when initializing the adapter.
1602 * First FDABIOS_INIT should be called.
1603 */
1604 FDDEBUG(FDCMD, printf("FDABIOS_RESET: entering...\n"));
1605
1606 FD_SET_RESERVED_ABIOS_RESET(fdreq);
1607 fdreq->r_unit = fd_drive(fdp->device_number);
1608 fd_no_retry(fdp);
1609
1610 rc = fdcall_abios_poll(ABIOS_RESET, fdreq, TRUE);
1611 /* rc falls through */
1612 break;
1613
1614 case FDREAD_PARMS:
1615 /* This does a "Read Device Parameters" ABIOS call
1616 * inorder to populate the floppy structure with what
1617 * ABIOS thinks the values should be.
1618 */
1619 FDDEBUG(FDCMD, printf("FDREAD_PARMS: entering...\n"));
1620
1621 FD_SET_RESERVED_ABIOS_READ_PARAMETER(fdreq);
1622 fdreq->r_unit = fd_drive(fdp->device_number);
1623 fd_no_retry(fdp);
1624
1625 rc = fdcall_abios_poll(ABIOS_READ_PARAMETER, fdreq, FALSE);
1626 if (rc != FDSUCCESS)
1627 break;
1628
1629 switch(fd_drive_type(fdreq)) {
1630 case FD_NO_DRIVE:
1631 rc = EIO;
1632 break;
1633 case FD_360_KB_DRIVE:
1634 fdp->drive_type = D_48;
1635 break;
1636 case FD_1440_KB_DRIVE:
1637 fdp->drive_type = D_135H;
1638 break;
1639 default:
1640 fdlog_error(fdp,FD_UNSUP_DRIVE);
1641 rc = EIO;
1642 break;
1643 }
1644
1645 switch (fdp->e_bytesps = fd_bytes_per_sector(fdreq)) {
1646 case FD_256_BYTE_PER_SECTOR:
1647 fdp->bytes_per_sector = 256;
1648 break;
1649 case FD_512_BYTE_PER_SECTOR:
1650 fdp->bytes_per_sector = 512;
1651 break;
1652 default:
1653 fdlog_error(fdp,FD_UNSUP_SECT);
1654 rc = EIO;
1655 }
1656
1657 /* Move info from request block to the fdp
1658 */
1659 fdp->sectors_per_track = fd_sectors_per_track(fdreq);
1660 fdp->abios_flags = fd_dev_ctrl_flag(fdreq);
1661 fdp->motor_start = fd_motor_start_delay_time(fdreq);
1662 fdp->cylinders_per_disk = fd_num_of_cylinders(fdreq);
1663 fdp->tracks_per_cylinder = fd_num_of_heads(fdreq);
1664 fdp->fill_byte = fd_format_fill_byte(fdreq);
1665 fdp->head_settle_time = fd_head_settle_time(fdreq);
1666 fdp->gap = fd_rwv_gap_len(fdreq);
1667 fdp->format_gap = fd_format_gap_len(fdreq);
1668 fdp->data_length = fd_data_len(fdreq);
1669
1670
1671 /* Calculate the rest of the fdp values:
1672 */
1673 fdp->number_of_blocks = fdp->sectors_per_track *
1674 fdp->cylinders_per_disk * fdp->tracks_per_cylinder;
1675 fdp->sectors_per_cylinder = fdp->sectors_per_track *
1676 fdp->tracks_per_cylinder;
1677 break;
1678
1679 case FDRMEDIA_PARMS:
1680 /* This will report the media parameters used for the
1681 * the last r/w/format.
1682 */
1683 FDDEBUG(FDCMD, printf("FDRMEDIA_PARMS: entering...\n"));
1684
1685 FD_SET_RESERVED_ABIOS_FD_READ_MEDIA_TYPE(fdreq);
1686 fdreq->r_unit = fd_drive(fdp->device_number);
1687 fd_no_retry(fdp);
1688
1689 rc = fdcall_abios_poll(ABIOS_FD_READ_MEDIA_TYPE, fdreq, FALSE);
1690 if (rc != FDSUCCESS)
1691 break;
1692
1693 /* Convert ABIOS return to a real value
1694 */
1695 switch (fdp->e_bytesps = fd_bytes_per_sector(fdreq)) {
1696 case FD_256_BYTE_PER_SECTOR:
1697 fdp->bytes_per_sector = 256;
1698 break;
1699 case FD_512_BYTE_PER_SECTOR:
1700 fdp->bytes_per_sector = 512;
1701 break;
1702 default:
1703 fdlog_error(fdp,FD_UNSUP_SECT);
1704 rc = EIO;
1705 }
1706
1707 /* On the PS/2 the 5 1/4" adapter is 250 KBPS. all the
1708 * other adapters are 500 KBPS.
1709 */
1710 fdp->data_rate = (minor(fdp->device_number) & FD_5)
1711 ? FD250KBPS : FD500KBPS;
1712
1713 /* Move data from request block into fdp
1714 */
1715 fdp->sectors_per_track = fd_sectors_per_track(fdreq);
1716 fdp->cylinders_per_disk = fd_num_of_cylinders(fdreq);
1717 fdp->tracks_per_cylinder = fd_num_of_heads(fdreq);
1718 fdp->gap = fd_rwv_gap_len(fdreq);
1719 fdp->format_gap = fd_format_gap_len(fdreq);
1720 fdp->data_length = fd_data_len(fdreq);
1721
1722 fdp->number_of_blocks = fdp->sectors_per_track *
1723 fdp->cylinders_per_disk * fdp->tracks_per_cylinder;
1724 fdp->sectors_per_cylinder = fdp->sectors_per_track *
1725 fdp->tracks_per_cylinder;
1726
1727 /* Now see if the values returned by the read media type
1728 * agree with the minor we're opened under. If they do,
1729 * then everything is fine, otherwise return an appropriate
1730 * errno.
1731 */
1732 switch (minor(fdp->device_number) & ~FDDRIVEMASK) {
1733 case FD_GENERIC | FD_3:
1734 case FD_GENERIC | FD_5:
1735 /* We don't have to check because by giving the
1736 * generic minor, we agree to use what the drive
1737 * tells us.
1738 */
1739 break;
1740 case FD_3H:
1741 if (fdp->number_of_blocks != 2880)
1742 rc = EIO;
1743 break;
1744 case FD_3L:
1745 if (fdp->number_of_blocks != 1440)
1746 rc = EIO;
1747 break;
1748 case FD_5L:
1749 if (fdp->number_of_blocks != 720)
1750 rc = EIO;
1751 break;
1752 case FD_5H:
1753 default:
1754 fdlog_error(fdp,FD_UNSUP_MINOR);
1755 rc = EINVAL;
1756 break;
1757 }
1758
1759 /* Lastly we want to set the diskette_type field. We
1760 * already know the disk_type. This will tell us how
1761 * the media in the diskette is formatted.
1762 */
1763 switch (fdp->number_of_blocks) {
1764 case 720: /* 360K 5 1/4" */
1765 fdp->diskette_type = FD360_5;
1766 break;
1767 case 1440: /* 720K 3 1/2" */
1768 fdp->diskette_type = FD720_3;
1769 break;
1770 case 2880: /* 144M 3 1/2" */
1771 fdp->diskette_type = FD1440_3;
1772 break;
1773 default:
1774 fdlog_error(fdp,FD_UNSUP_DRIVE);
1775 rc = EINVAL;
1776 }
1777
1778 break;
1779
1780 case FDLOAD_144:
1781 case FDLOAD_720:
1782 case FDLOAD_360:
1783 /* These are dummy commands that do not use ABIOS, but
1784 * make the setting of drive parameters easier because
1785 * we can use a consistant interface.
1786 */
1787 {
1788 int off = arg & ~0x100;
1789
1790 /* Copy the data from the array to the fdp
1791 */
1792 fdp->sectors_per_track = fd_data[off].sectors;
1793 fdp->cylinders_per_disk = fd_data[off].cylinders;
1794 fdp->tracks_per_cylinder = fd_data[off].heads;
1795 fdp->gap = fd_data[off].gap;
1796 fdp->format_gap = fd_data[off].format_gap;
1797 fdp->data_length = fd_data[off].data_len;
1798
1799 fdp->number_of_blocks = fdp->sectors_per_track *
1800 fdp->cylinders_per_disk * fdp->tracks_per_cylinder;
1801 fdp->sectors_per_cylinder = fdp->sectors_per_track *
1802 fdp->tracks_per_cylinder;
1803 }
1804 break;
1805
1806 case FDREAD_DATA:
1807 /* This reads data off the diskette. It finishes setting
1808 * up the the request block and then calls the ABIOS
1809 * proper ABIOS interface (polled, or non-polled).
1810 *
1811 * The data pointers should be set up before this is
1812 * called.
1813 *
1814 * NOTE: the retry count is controlled by fdio().
1815 */
1816 FDDEBUG(FDCMD, printf("fdissue_command: READ_DATA\n"));
1817
1818 FD_SET_RESERVED_ABIOS_READ(fdreq);
1819 fdreq->r_unit = fd_drive(fdp->device_number);
1820
1821 fd_num_sector_rw(fdreq) = fdp->start.transfer_length /
1822 fdp->bytes_per_sector;
1823 fd_cylinder_num(fdreq) = fdp->start.cylinder;
1824 fd_head_num(fdreq) = fdp->start.head;
1825 fd_sector_num(fdreq) = fdp->start.sector;
1826
1827 FDDEBUG(FDCMD, printf("vaddr: %x\n",fd_data_ptr_1(fdreq)));
1828 FDDEBUG(FDCMD, printf("paddr: %x\n",fd_data_ptr_2(fdreq)));
1829 FDDEBUG(FDCMD, printf("# sectors: %d\n",
1830 fdp->start.transfer_length / fdp->bytes_per_sector));
1831 FDDEBUG(FDCMD, printf("cylinder: %d\n",fdp->start.cylinder));
1832 FDDEBUG(FDCMD, printf("head: %d\n",fdp->start.head));
1833 FDDEBUG(FDCMD, printf("sector: %d\n",fdp->start.sector));
1834
1835 rc = (poll) ? fdcall_abios_poll(ABIOS_READ,fdreq, TRUE)
1836 : fdcall_abios(ABIOS_READ, fdreq);
1837 break;
1838
1839 case FDWRITE_DATA:
1840 /* This writes data to the diskette. It finishes setting
1841 * up the the request block and then calls the ABIOS
1842 * proper ABIOS interface (polled, or non-polled).
1843 *
1844 * The data pointers should be set up before this is
1845 * called.
1846 *
1847 * NOTE: the retry count is controlled by fdio().
1848 */
1849 FDDEBUG(FDCMD, printf("fdissue_command: WRITE_DATA\n"));
1850
1851 FD_SET_RESERVED_ABIOS_READ(fdreq);
1852 fdreq->r_unit = fd_drive(fdp->device_number);
1853 fd_num_sector_rw(fdreq) = fdp->start.transfer_length /
1854 fdp->bytes_per_sector;
1855 fd_cylinder_num(fdreq) = fdp->start.cylinder;
1856 fd_head_num(fdreq) = fdp->start.head;
1857 fd_sector_num(fdreq) = fdp->start.sector;
1858
1859 FDDEBUG(FDCMD, printf("vaddr: %x\n",fd_data_ptr_1(fdreq)));
1860 FDDEBUG(FDCMD, printf("paddr: %x\n",fd_data_ptr_2(fdreq)));
1861 FDDEBUG(FDCMD, printf("# sectors: %d\n",
1862 fdp->start.transfer_length / fdp->bytes_per_sector));
1863 FDDEBUG(FDCMD, printf("cylinder: %d\n",fdp->start.cylinder));
1864 FDDEBUG(FDCMD, printf("head: %d\n",fdp->start.head));
1865 FDDEBUG(FDCMD, printf("sector: %d\n",fdp->start.sector));
1866
1867 rc = (poll) ? fdcall_abios_poll(ABIOS_WRITE, fdreq, TRUE)
1868 : fdcall_abios(ABIOS_WRITE, fdreq);
1869 break;
1870
1871 case FDMOTOR_OFF:
1872 /* This does an ABIOS request to turn the motor (and
1873 * the light) for the drive off.
1874 */
1875 FD_SET_RESERVED_ABIOS_FD_TURN_OFF_MOTOR(fdreq);
1876 fdreq->r_unit = fd_drive(fdp->device_number);
1877 fd_no_retry(fdp);
1878
1879 rc = fdcall_abios_poll(ABIOS_FD_TURN_OFF_MOTOR, fdreq, TRUE);
1880 /* RC Falls through to break */
1881
1882 /* fdcall_abios_poll() will call fdsched() {like it shoud}
1883 * and restart the motor watchdog.
1884 */
1885 UNTIMEOUT(fdadapter.mot_wd);
1886 break;
1887
1888 case FDFORMAT_TRACK:
1889 /* This does and ABIOS request to format a track. It
1890 * has to create an xmem descriptor and get the physical
1891 * address of the format information.
1892 *
1893 * It fills in the request block and does the format
1894 * to how the drive was set up (high or low, etc).
1895 */
1896 FDDEBUG(FDCMD,"fdissue_command: FDFORMAT_TRACK\n");
1897
1898 FD_SET_RESERVED_ABIOS_FD_SET_MEDIA_TYPE(fdreq);
1899 fdreq->r_unit = fd_drive(fdp->device_number);
1900
1901 fd_sectors_per_track(fdreq) = fdp->sectors_per_track;
1902 fd_bytes_per_sector(fdreq) = fdp->e_bytesps;
1903 fd_num_of_cylinders(fdreq) = fdp->cylinders_per_disk;
1904 fd_format_fill_byte(fdreq) = fdp->fill_byte;
1905 fd_format_gap_len(fdreq) = fdp->format_gap;
1906
1907 fd_no_retry(fdp); /* don't try again */
1908
1909 rc = fdcall_abios_poll(ABIOS_FD_SET_MEDIA_TYPE, fdreq, FALSE);
1910 if (rc != FDSUCCESS) {
1911 break;
1912 }
1913
1914 fd_xfer_sub_function(fdreq) = FD_XFER_SUB_FORMAT;
1915 fd_cylinder_num(fdreq) = fdp->cylinder_id;
1916 fd_head_num(fdreq) = fdp->head_id;
1917
1918 fd_clear_retry(fdp); /* retry this request */
1919
1920 rc = (poll) ? fdcall_abios_poll(ABIOS_ADDITIONAL_XFER, fdreq, TRUE)
1921 : fdcall_abios(ABIOS_ADDITIONAL_XFER, fdreq);
1922
1923 break;
1924
1925 case FDDISK_SAME:
1926 /* Check to see if the Change signal is high. In order
1927 * to return a value w/o using the fdp structure, we use
1928 * two return codes that are > 0, and will look like
1929 * errors. fdexecute_command() will see the error and
1930 * try to schedule more work for the diskette adapter
1931 * to do.
1932 *
1933 * Note that we first check to see if the change signal
1934 * is supported. If it is not supported with the current
1935 * drive, then we just say the diskette is the same.
1936 */
1937 if (!(fdp->abios_flags & FD_CHANGE_SIGNAL_AVAIL)) {
1938 rc = DISK_SAME;
1939 break;
1940 }
1941
1942 FD_SET_RESERVED_ABIOS_FD_CHANGE_SIGNAL_STATUS(fdreq);
1943 fdreq->r_unit = fd_drive(fdp->device_number);
1944
1945 fdcall_abios_poll(ABIOS_FD_CHANGE_SIGNAL_STATUS,fdreq,FALSE);
1946
1947 /* If the diskette changed signal is high report it. If
1948 * no say the diskette is the same, even though this drive
1949 * may not support it.
1950 */
1951 if (fd_change_signal_status(fdreq) == FD_CHANGE_SIGNAL_ACTIVE)
1952 rc = DISK_CHANGED;
1953 else
1954 rc = DISK_SAME;
1955 break;
1956
1957 case FD_SETDP:
1958 /* This call does a "Set Device Parameters" ABIOS call
1959 * and is used by the one of the ioctl()'s.
1960 */
1961 FD_SET_RESERVED_ABIOS_WRITE_PARAMETER(fdreq);
1962 fd_bytes_per_sector(fdreq) = fdp->e_bytesps;
1963 fd_rwv_gap_len(fdreq) = fdp->gap;
1964 fd_data_len(fdreq) = fdp->data_length;
1965
1966 fdreq->r_unit = fd_drive(fdp->device_number);
1967
1968 rc = fdcall_abios_poll(ABIOS_WRITE_PARAMETER, fdreq, FALSE);
1969
1970 if (rc == FDSUCCESS) {
1971 switch(fdp->e_bytesps) {
1972 case FD_256_BYTE_PER_SECTOR:
1973 fdp->bytes_per_sector = 256;
1974 break;
1975 case FD_512_BYTE_PER_SECTOR:
1976 fdp->bytes_per_sector = 512;
1977 break;
1978 default:
1979 fdlog_error(fdp,FD_UNSUP_SECT);
1980 rc = EIO;
1981 }
1982 }
1983 break;
1984
1985 case FD_SETMT:
1986 /* This call does a "Set Media Type for Format" ABIOS call
1987 * and is used by one of the ioctl's. It is done at this
1988 * time instead of waiting till a format occurs to make
1989 * sure the data given is valid.
1990 */
1991 FD_SET_RESERVED_ABIOS_FD_SET_MEDIA_TYPE(fdreq);
1992 fd_sectors_per_track(fdreq) = fdp->sectors_per_track;
1993 fd_bytes_per_sector(fdreq) = fdp->e_bytesps;
1994 fd_num_of_cylinders(fdreq) = fdp->cylinders_per_disk;
1995 fd_format_fill_byte(fdreq) = fdp->fill_byte;
1996 fd_format_gap_len(fdreq) = fdp->format_gap;
1997
1998 fdreq->r_unit = fd_drive(fdp->device_number);
1999
2000 rc = (poll) ? fdcall_abios_poll(ABIOS_FD_SET_MEDIA_TYPE,fdreq,TRUE)
2001 : fdcall_abios(ABIOS_FD_SET_MEDIA_TYPE, fdreq);
2002 break;
2003
2004 default:
2005 FDDEBUG(FDCMD, printf("fdissue_command: unknown command\n"));
2006 rc = EINVAL;
2007 break;
2008 }
2009 return (rc);
2010 }
2011
2012 /* Handles the diskette timer exceptions. This routine is called when
2013 * when a watchdog timer pops. It then determines the proper actions to
2014 * take and does them.
2015 *
2016 * There are 2 types of watchdogs. There is one to turn the motor off,
2017 * and one for lost interrupts. The motor timer is easy, but the interrupt
2018 * timer is harder because it can mean different things depending on the
2019 * state of the drive, and the type of drive.
2020 *
2021 * NEEDS WORK: IS THE FOLLOWING STILL NEEDED, AND/OR TRUE WITH OSF?
2022 * NOTES: It is assumed that the interrupt level when the timer pops will
2023 * splfd().
2024 */
2025 void
2026 fdtimer(timer)
2027 register struct fdwatchdog *timer;
2028 {
2029 register struct floppy *fdp;
2030 int rc;
2031
2032 switch (timer->type) {
2033 case FDINT_WD:
2034 /* In this case an ABIOS request that should have finished
2035 * did not within the recommended timeout. We log the
2036 * error, and then try to keep going...
2037 */
2038 FDDEBUG(FDCMD,printf("interrupt watchdog!\n"));
2039 fdp = fdadapter.int_wd.fdp;
2040
2041 /* We need to finish up with the request block early
2042 * incase we have to do any ABIOS calls later.
2043 */
2044 rc = fdadapter.fd_req.r_return_code;
2045 abios_common_timeout(&fdadapter.fd_req, fdadapter.fd_flag);
2046 fdadapter.fd_req.r_return_code = rc;
2047
2048 /* If the watchdog timeout came on the 5 1/4" drive
2049 * then it could be that the media is not present,
2050 * because this drive cannot sense the diskette is not
2051 * there. Unfortunatly there is no good way to test
2052 * this.
2053 *
2054 * The best we can do is in fddoor_check() is to set
2055 * a flag in the fdp structure, and if we get a watchdog
2056 * on a 5 1/4" drive and the flag is set, then we return
2057 * EIO.
2058 *
2059 * The other problem encountered on the 5 1/4 is when
2060 * doing a format, without the diskette in the drive.
2061 * It looks like ABIOS doesn't do the reset so we do
2062 * it ourselves. This only happens when opening NDELAY
2063 * since the drive isn't checked with a read.
2064 */
2065 if ((minor(fdp->device_number) & FD_5) && ((fdp->open_check == TRUE) ||
2066 (fdadapter.fd_req.r_function == ABIOS_ADDITIONAL_XFER) ) ) {
2067 fdlog_error(fdp,FD_ERR_NOMEDIA);
2068 rc = EIO;
2069 }
2070 else {
2071 /* Log timeout error.
2072 */
2073 fdlog_error(fdp, FD_ERR_LOSTINT);
2074 fdp->timeout_flag = TRUE;
2075 rc = EIO;
2076 }
2077
2078 /* If we need to recalibrate (5 1/4" disk) then set up and
2079 * do the reset (note that this will do the fdiodone() for
2080 * us. Otherwise call fdiodone().
2081 */
2082 if (fdp->abios_flags & FD_RECALIBRATE_REQUIRED) {
2083 register struct Fd_request *rb;
2084
2085 rb = &fdadapter.fd_req;
2086 rb->state |= FD_RB_RESET;
2087 rb->req_errno = rc;
2088 fdcall_abios(ABIOS_RESET, rb);
2089 }
2090 else
2091 fdiodone(fdp->headptr, &fdadapter.fd_req, fdp, rc);
2092
2093 break;
2094
2095 case FDMOT_WD:
2096 /* Note: In this case the light is on. All care has
2097 * been taken not to let the watchdog continue if this
2098 * drive is busy. Hence we don't (and can't sleep())
2099 * call fdget_adapter(), and can just turn off the light.
2100 */
2101 FDDEBUG(FDCMD,printf("fdtimer: motor watchdog!\n"));
2102 fdadapter.fdintr_status = FDBUSY;
2103 fdexecute_command(fdadapter.mot_wd.fdp,FDMOTOR_OFF);
2104 break;
2105 }
2106 }
2107
2108 #ifdef DEBUG
2109 #undef DEBUG_RB
2110 #ifdef DEBUG_RB
2111
2112 /* This can be compiled in for printing out AIBOS request blocks for driver
2113 * debugging.
2114 */
2115 static void
2116 fd_dump_rb(rb)
2117 struct Fd_request *rb;
2118 {
2119 register int i,j;
2120
2121 printf("RB: len %d, lid %d, unit %d, func %\n",
2122 rb->r_current_req_blck_len,
2123 rb->r_logical_id,
2124 rb->r_unit,
2125 rb->r_function);
2126 printf("flags %d, ELA %d, rc %d, timeout %d\n",
2127 rb->request_header.Request_Block_Flags,
2128 rb->request_header.ELA_Offset,
2129 rb->r_return_code,
2130 rb->r_time_out);
2131
2132 for (i=0 ; i < 128 ; i += 24) {
2133 for (j = 0 ; j < 24 ; j += 4)
2134 printf("%02x%02x%02x%02x ",
2135 rb->un.uc[i+j],
2136 rb->un.uc[i+j+1],
2137 rb->un.uc[i+j+2],
2138 rb->un.uc[i+j+3]);
2139 printf("\n");
2140 }
2141
2142 printf("state %x, sleep %x, req_errno %d\n",
2143 rb->state, rb->sleep_on_intr, rb->req_errno);
2144 }
2145 #endif
2146 #endif
2147
2148
2149 /* If DEBUG is on we also want to leave some hooks in to test the
2150 * watchdog timers for losing interrupts. To test losing an interrupt,
2151 * have fd_inttest set to a non-zero value.
2152 *
2153 * The best way to do this is to set a breakpoint in fdintr() and then
2154 * set the flag to 1 on the interrupt you want to simulate the loss of.
2155 *
2156 * WARNING -- Don't forget to set this flag back to 0, or nothing works!
2157 */
2158 #ifdef DEBUG
2159 #define WATCHTEST
2160 #endif
2161 #ifdef WATCHTEST
2162 int fd_inttest = 0;
2163 #endif
2164
2165 /* This is the front end to the common interrupt handler for ABIOS
2166 * stage on time (stot) events. When ABIOS tells us to stage on
2167 * time we call timeout() which will set a timer to call fd_stot()
2168 * after the period has expired.
2169 *
2170 * We call fdcommon_intr() which will query ABIOS with what to do next.
2171 * The one parameter to this routine is a pointer to the ABIOS request
2172 * block.
2173 */
2174 void
2175 fd_stot()
2176 {
2177 int pri;
2178
2179 FDDEBUG(FDINTR, printf("fd_stot: entering...\n"));
2180 pri = splfd();
2181 fdcommon_intr(&fdadapter.fd_req);
2182 splx(pri);
2183 }
2184
2185 /* This is the interrupt handler for the diskette controller. It calls
2186 * fdcommon_intr with the current ABIOS request block to do most of the
2187 * work. If this call corresponds to our interrupt, then we i_reset()
2188 * it, and in either case we return the return value from fdcommon_intr().
2189 *
2190 * NOTES: Turn off the interrupt watchdog.
2191 */
2192 fdintr(fdtmp)
2193 register struct intr *fdtmp;
2194 {
2195 /* We have gotten our interrupt so turn off the timer ASAP.
2196 */
2197 UNTIMEOUT(fdadapter.int_wd);
2198
2199 FDDEBUG(FDINTR, printf("\nfdintr: entering...\n"));
2200
2201 fdcommon_intr(&fdadapter.fd_req);
2202
2203 return(1); /* return to FLIH */
2204 }
2205
2206 /* Handles an interrupt for the floppy driver. First we check
2207 * to make sure we are expecting an interrupt. If so we call
2208 * abios_common_interrupt() to process the interrupt. Next we
2209 * do what abios_common_interrupt() told us to do.
2210 *
2211 * When we have an ABIOS_DONE condition we call fdiodone() to terminate
2212 * the i/o for us.
2213 */
2214 static int
2215 fdcommon_intr(fdreq)
2216 register struct Fd_request *fdreq;
2217 {
2218 register struct buf *bp;
2219 register struct floppy *fdp;
2220
2221 FDDEBUG(FDINTR, printf("\nfdcommon_intr: entering...\n"));
2222
2223 /* Get data structures pointing at the right place. Note that
2224 * the bp may be NULL if FD_RB_SYNC bit is set in the request
2225 * block. In anycase if FD_RB_SYNC is set the bp should not
2226 * be used.
2227 */
2228 fdp = &floppies[fdreq->r_unit];
2229 bp = fdp->headptr;
2230
2231 /* Make sure we are expecting an interuupt
2232 */
2233 if ( (fdreq->state==FD_RB_IDLE) || (fdreq->r_return_code==ABIOS_UNDEFINED))
2234 return(0); /* not me! */
2235
2236 abios_common_interrupt(fdreq, fdadapter.fd_flag);
2237 FDDEBUG(FDINTR, {
2238 printf("fdcommon_intr: after abios_common_interrupt rc=0x%x [",
2239 fdreq->r_return_code);
2240 fd_error_decode(fdreq->r_return_code, "]\n"); });
2241
2242 #ifdef WATCHTEST
2243 /* For more info about watchdog testing, see above comment.
2244 */
2245 if (fd_inttest) { /* if true loose interrupt */
2246 return(0);
2247 }
2248 #endif
2249
2250 /* If ABIOS_NOT_MY_INT and ABIOS_STAGE_ON_INT are both set in the
2251 * return code from abios_common_start(), then the interrupt
2252 * is not ours. Return and let the slih go through the list
2253 * of devices on this interrupt level.
2254 */
2255 if ( fdreq->r_return_code & (ABIOS_NOT_MY_INT & ABIOS_STAGE_ON_INT) ) {
2256 FDDEBUG(FDINTR, printf("fdcommon_intr: ABIOS_NOT_MY_INTR\n"));
2257 return(0); /* not me either! */
2258 }
2259
2260 /* Now check the various cases of the return code and do the
2261 * appropriate action.
2262 */
2263 switch (fdreq->r_return_code) {
2264 case ABIOS_DONE:
2265 /* The request has completed successfully. For read
2266 * and write we have to update some counters, but for
2267 * all other cases we're done.
2268 */
2269 FDDEBUG(FDINTR,printf("fdcommon_intr: ABIOS_DONE\n"));
2270
2271 if ((fdreq->r_function == ABIOS_READ) ||
2272 (fdreq->r_function == ABIOS_WRITE)) {
2273
2274 /* Keep track of the number of sectors moved,
2275 * as well as updating the modified_bcount (used
2276 * for counting the i/o on strategy requests).
2277 */
2278 fdp->sectors_done += fd_sectors_moved(fdreq);
2279 fdp->modified_bcount -= fd_sectors_moved(fdreq) * fdp->bytes_per_sector;
2280
2281 /* check if all sectors were moved
2282 */
2283 if ( fd_sectors_moved(fdreq) <
2284 fd_num_sector_rw(fdreq) ) {
2285 fdiodone(bp,fdreq,fdp,EIO);
2286 }
2287 /* Check for a split request.
2288 *
2289 * A request is split if it goes from sector that
2290 * is one head and is continued on the next head.
2291 *
2292 * The other case is when the place to dma to/from
2293 * crosses a page boundry that is not contiguous
2294 * in physical memory.
2295 *
2296 * See fdsetup_transfer()
2297 *
2298 * Note that the convention for polled r/w calls
2299 * is that they will not set up split transfers,
2300 * hence it is legal for us to call fdstartio and
2301 * then indirect through the buf struct pointer.
2302 */
2303 else if (fdp->transfer_split != 0) {
2304 FDDEBUG(FDINTR,printf("split request\n"));
2305
2306 /* Update the offset so the address to
2307 * move to can be determined correctly
2308 */
2309 fdp->buf_offset += fd_sectors_moved(fdreq) * fdp->bytes_per_sector;
2310
2311 /* If we have more of this transfer to do,
2312 * then start the i/o for it.
2313 */
2314 if (fdsetup_transfer(fdp))
2315 fdstartio(fdp);
2316 break; /* don't do fdiodone()! */
2317 }
2318 }
2319
2320 /* If the RESET flag is set, that means we have just
2321 * completed a special RESET for an error condition
2322 * (probably on the 5 1/4" drive). Flip the RESET bit
2323 * off and call fdiodone with the set errno.
2324 */
2325 if (fdreq->state & FD_RB_RESET) {
2326 fdreq->state &= ~FD_RB_RESET;
2327 fdiodone(bp,fdreq,fdp,fdreq->req_errno);
2328 }
2329 else
2330 fdiodone(bp,fdreq,fdp,FDSUCCESS);
2331 break;
2332
2333 case ABIOS_STAGE_ON_INT:
2334 /* Discrete multi stages, just continue. Eventualy
2335 * we will get a done or some sort of errors.
2336 */
2337 FDDEBUG(FDINTR, printf("fdcommon_intr: ABIOS_STAGE_ON_INT\n"));
2338 fdreq->state |= FD_RB_STAGING;
2339 break;
2340
2341 case ABIOS_STAGE_ON_TIME:
2342 /* In this case we want to call fd_stot in fd_wait_time()
2343 * micro seconds.
2344 */
2345 FDDEBUG(FDINTR, printf("fdcommon_intr: ABIOS_STAGE_ON_TIME\n"));
2346 timeout(fd_stot,(caddr_t)NULL,us2tics(fd_wait_time(fdreq)));
2347 break;
2348
2349 case FDABIOS_MEDIACHANGED:
2350 /* If this is our first request to the drive, this
2351 * this is a retryable error (and the only way to
2352 * clear the signal).
2353 *
2354 * However, if this is not the first request for this open
2355 * it is an error to have changed media.
2356 */
2357 FDDEBUG(FDINTR, printf("fdcommon_intr: FDABIOS_MEDIACHANGED\n"));
2358
2359 /* to boot from floppy, have to allow media to change... */
2360 fdissue_command(fdp,fdreq->r_function);
2361 break;
2362 if (fdp->fd_change == FDCHANGE_NEW) {
2363 fdp->fd_change = FDCHANGE_INIT;
2364 fdissue_command(fdp,fdreq->r_function);
2365 }
2366 else {
2367 /* return media changed error
2368 */
2369 fdlog_error(fdp,FD_ERR_CHMEDIA);
2370 fdiodone(bp,fdreq,fdp,EIO);
2371 }
2372 break;
2373
2374 case FDABIOS_MEDIANOTPRESENT:
2375 /* This is an obvious error condition.
2376 */
2377 fdlog_error(fdp,FD_ERR_NOMEDIA);
2378 fdiodone(bp,fdreq,fdp,EIO);
2379 break;
2380
2381 case FDABIOS_WRITEPROTECTED:
2382 /* The diskette was write protected and we attempted to
2383 * do a write to it. Return EIO (no write protected errno).
2384 */
2385 FDDEBUG(FDINTR,printf("fdcommon_intr: WRITE PROTECTED\n"));
2386 fdiodone(bp,fdreq,fdp,EIO);
2387 break;
2388
2389 default:
2390 /* All the errors get handled here. Retry the error.
2391 * up to FDMAXRETRIES, and if all is still lost, return
2392 * EIO.
2393 */
2394 FDDEBUG(FDINTR, printf("fdcommon_intr: error (rc=%x)\n",
2395 fdreq->r_return_code));
2396
2397 if (fdp->retry_count < FDMAXRETRIES) {
2398 fdp->retry_count++;
2399 fdissue_command(fdp,fdreq->r_function);
2400 }
2401 else {
2402 /* We're out of retries, so log the error. If
2403 * the error is on the 5 1/4" drive reset the
2404 * drive. Note that resetting the drive will
2405 * call fdiodone for us.
2406 */
2407 fdlog_error(fdp,FD_ERR_RETRY);
2408
2409 if (fdp->abios_flags & FD_RECALIBRATE_REQUIRED) {
2410 fdreq->state |= FD_RB_RESET;
2411 fdreq->req_errno = EIO;
2412 fdcall_abios(ABIOS_RESET,fdreq);
2413 }
2414 else
2415 fdiodone(bp,fdreq,fdp,EIO);
2416 }
2417 break;
2418
2419 }
2420
2421 FDDEBUG(FDINTR, printf("fdcommon_intr: done\n"));
2422 return(1);
2423 }
2424
2425 /* NEEDS WORK - are polled interrupt abios requests still done now
2426 * NEEDS WORK - that we call strategy to sense the media?
2427 */
2428 /* Completes the i/o for the specified request. Handles two different
2429 * cases. One for polled requests, and one for non-polled (from strategy)
2430 * requests.
2431 *
2432 * NOTES: This should only be used after i/o has been attemped on the
2433 * buf struct in question. Before that time just call iodone() directly.
2434 */
2435 static void
2436 fdiodone(buf,fdreq,fdp,errno)
2437 register struct buf *buf;
2438 register struct Fd_request *fdreq;
2439 register struct floppy *fdp;
2440 int errno;
2441 {
2442 if ( (fdreq->state & FD_RB_SYNC) || (buf == NULL) ) {
2443 /* Polled request:
2444 *
2445 * The error code is returned to the caller in req_errno.
2446 *
2447 * We need to set ABIOS_DONE, so that polled requests
2448 * will wake up even if we have an error. req_errno is
2449 * used to handle the error conditions.
2450 *
2451 * Also note that any outstanding requests will be started
2452 * up after the request is woken up. It would be better to
2453 * be able to check the queues here, and then start the
2454 * requests, but we have to wait for the data to get back
2455 * to the caller of the polled request.
2456 */
2457 FDDEBUG(FDINTR, printf("fdiodone: entering...polled\n"));
2458 fdreq->req_errno = errno;
2459 fdreq->r_return_code = ABIOS_DONE;
2460 wakeup(&fdreq->sleep_on_intr);
2461 }
2462 else {
2463 /* Strategy request:
2464 *
2465 * This is a little more complicated than the polled
2466 * request. We check for errors, and for people to
2467 * wake up, play with the queue's and then look for
2468 * more work to do.
2469 *
2470 * Note that we can use the buf struct in this case.
2471 */
2472 FDDEBUG(FDINTR, printf("fdiodone: entering...intr\n"));
2473
2474 /* If this request resulted in an error, then set
2475 * the flags in the buf struct to indicate the error.
2476 */
2477 if (errno) {
2478 buf->b_resid += fdp->modified_bcount;
2479 buf->b_flags |= B_ERROR;
2480 buf->b_error = errno;
2481 }
2482 else {
2483 /* we have had a succesful non-polled call, so
2484 * note that the diskette is in ok.
2485 */
2486 fdp->fd_change = FDCHANGE_INIT;
2487 }
2488
2489 /* Tally i/o counts:
2490 * - read_count_bytes is the number of bytes less
2491 * than a megabyte read. read_count_megabytes is
2492 * the number of megabytes read. By using both of
2493 * them together, you get an accurate #.
2494 *
2495 * - write_count* is the same, but for write operations.
2496 */
2497 if (buf->b_flags & B_READ) {
2498 fdp->read_count_bytes += buf->b_bcount - buf->b_resid;
2499 if (fdp->read_count_bytes >= 0x100000) {
2500 fdp->read_count_megabytes += fdp->read_count_bytes / 0x100000;
2501 fdp->read_count_bytes %= 0x100000;
2502 }
2503 }
2504 else { /* B_WRITE */
2505 fdp->write_count_bytes += buf->b_bcount - buf->b_resid;
2506 if (fdp->write_count_bytes >= 1000000) {
2507 fdp->write_count_megabytes += fdp->write_count_bytes / 1000000;
2508 fdp->write_count_bytes %= 1000000;
2509 }
2510 }
2511
2512 /* if this is the last buffer, dq everything, else
2513 * get the next one...
2514 */
2515 if (fdp->headptr == fdp->tailptr) {
2516 fdp->headptr = fdp->tailptr = NULL;
2517
2518 /* If fd_close() has been called with outstanding
2519 * i/o on this drive the the close_waiting flag
2520 * will be set. We have to wake up the process
2521 * that is waiting on the close and indicate that
2522 * it's i/o is done.
2523 *
2524 * Note that we only do this when the request
2525 * queue is empty, and there is no more
2526 * outstanding i/o for this drive.
2527 */
2528 if (fdp->close_waiting == TRUE) {
2529 fdp->close_waiting = FALSE;
2530 wakeup(&fdp->close_sleep);
2531 }
2532 }
2533 else
2534 fdp->headptr = fdp->headptr->av_forw;
2535
2536 FDDEBUG(FDINTR,printf("fdiodone: fdp->headptr is %x\n", fdp->headptr));
2537
2538 fd_sched(fdp); /* look for more requests */
2539 iodone(buf); /* done with this buffer */
2540 }
2541 }
2542
2543 /* Looks for more work for the diskette adapter to work on.
2544 */
2545 static void
2546 fd_sched(fdp)
2547 register struct floppy *fdp;
2548 {
2549 register struct floppy *tfdp, *lfdp;
2550 int unit, pri;
2551
2552 /* Handle watchdog timers:
2553 * - Make sure the interrupt loss watchdog is off. If we
2554 * are finishing a request via an interrupt it will be
2555 * off, but if we are doing a non interrupting ABIOS call
2556 * it may not. It is low enough overhead, so we just
2557 * do it again.
2558 *
2559 * - Start the motor off timer. If we start another request this
2560 * timer will be turned off.
2561 */
2562 UNTIMEOUT(fdadapter.int_wd);
2563 fdadapter.mot_wd.fdp = fdp;
2564 TIMEOUT(fdadapter.mot_wd);
2565
2566 /* If we need the controller to process an open, give
2567 * that presedence over other q'ed requests. Otherwise
2568 * go and look for other requests to do.
2569 */
2570 pri = splfd();
2571 if (fdadapter.need_controller == TRUE) {
2572 fdadapter.fdintr_status = FDFREE;
2573 wakeup(&fdadapter.need_sleep);
2574 }
2575 else {
2576 /* Look for another request to start. To be fair try
2577 * the other drives first.
2578 */
2579 tfdp = &floppies[unit=next_unit(fdadapter.fd_req.r_unit)];
2580 lfdp = (struct floppy *)NULL;
2581 while (lfdp != fdp) {
2582 if (tfdp->headptr != NULL) {
2583 /* Do the request, and then
2584 * don't loop looking for more
2585 */
2586 fdio(tfdp->headptr);
2587 break;
2588 }
2589 lfdp = tfdp;
2590 tfdp = &floppies[next_unit(unit)];
2591 }
2592
2593 /* If we didn't run anything new, then set the intr
2594 * status to free and wake up any polled requests that
2595 * want to access the adapter.
2596 */
2597 if (lfdp == fdp)
2598 fdadapter.fdintr_status = FDFREE;
2599 }
2600 splx(pri);
2601 }
2602
2603 /*
2604 * This does the work of an FDIOCFORMAT ioctl call.
2605 *
2606 * The following ioctl operations are provided for the format
2607 * command.
2608 *
2609 * FDIOCFORMAT - formats a diskette track. A track is
2610 * formatted using values passed in an array of bytes
2611 * pointed to by the 'arg' parameter. The buffer should be
2612 * 4 times the number of sectors per track long. Four bytes
2613 * of data are needed for each sector on the track. The
2614 * following shows the structure of the data buffer:
2615 * _________________
2616 * | |
2617 * | cylinder number | - byte 0
2618 * S |_________________|
2619 * E | |
2620 * C | side number | - byte 1
2621 * T |_________________|
2622 * O | |
2623 * R | sector number | - byte 2
2624 * |_________________|
2625 * 0 | |
2626 * | # bytes/sector | - byte 3
2627 * |_________________|
2628 *
2629 * .
2630 * .
2631 * .
2632 * _________________
2633 * | |
2634 * | cylinder number | - byte (n * 4) - 4
2635 * S |_________________|
2636 * E | |
2637 * C | side number | - byte (n * 4) - 3
2638 * T |_________________|
2639 * O | |
2640 * R | sector number | - byte (n * 4) - 2
2641 * |_________________|
2642 * n | |
2643 * | # bytes/sector | - byte (n * 4) - 1
2644 * |_________________|
2645 *
2646 * where n is the number of sectors per track. In general,
2647 * the cylinder number, side number, and number of bytes per
2648 * sector should not change from sector to sector. The sector
2649 * number should be different for each sector. Usually the
2650 * sector numbers will correspond to the physical sector
2651 * numbers, but they can be different if some special copy
2652 * protection scheme is being used.
2653 */
2654 #ifdef NEEDS_WORK /* NEEDS WORK -- more ioctls..later */
2655 static int
2656 fd_iocformat(devno,arg,fdp)
2657 dev_t devno;
2658 register long arg;
2659 register struct floppy *fdp;
2660 {
2661 int rc = FDSUCCESS;
2662 caddr_t paddr;
2663 struct Fd_request *fdreq = &fdadpter.fd_req;
2664
2665 fdp->format_size = fdp->sectors_per_track * 4;
2666
2667 /* allocate a page for the format info.
2668 */
2669 fdp->format_buffer = (char *)
2670 xmalloc(fdp->format_size, PGSHIFT, pinned_heap);
2671 if (fdp->format_buffer == NULL)
2672 return(ENOMEM);
2673
2674 /* pin the buffer.
2675 */
2676 rc = pin((caddr_t) fdp->format_buffer, (int) fdp->format_size);
2677 if (rc != 0) {
2678 xmfree((caddr_t) fdp->format_buffer, (caddr_t) pinned_heap);
2679 return(rc); /* return pin's errno */
2680 }
2681
2682 /* copy the buffer in our address space.
2683 */
2684 rc = copyin((char *) (arg), (char *) (fdp->format_buffer),
2685 fdp->format_size);
2686 if (rc == -1) {
2687 unpin((caddr_t) fdp->format_buffer, (int) fdp->format_size);
2688 xmfree((caddr_t) fdp->format_buffer, (caddr_t) pinned_heap);
2689 return(EINVAL);
2690 }
2691
2692 fdp->cylinder_id = *(fdp->format_buffer); /* byte 0 */
2693 fdp->head_id = *((char *)(fdp->format_buffer)+1); /* byte 1 */
2694
2695 fdget_adapter();
2696
2697 if ((paddr = pmap_extract(kernel_pmap,fdp->format_buffer)) == 0) {
2698 free(fdp->format_buffer);
2699 return(EIO);
2700 }
2701 fd_data_ptr_1(fdreq) = (u_int) fdp->format_buffer;
2702 fd_data_ptr_2(fdreq) = (u_int) paddr;
2703
2704 rc = fdexecute_command(fdp,FDFORMAT_TRACK_POLL);
2705
2706 unpin((caddr_t) fdp->format_buffer, (int) fdp->format_size);
2707 xmfree((caddr_t) fdp->format_buffer, (caddr_t) pinned_heap);
2708
2709 return(rc);
2710 }
2711 #endif
2712
2713 /* Does the work for a FDIOCSINFO ioctl.
2714 *
2715 * FDIOCSINFO - sets the current diskette characteristics.
2716 * A structure of type fdinfo is loaded with the desired
2717 * values and a pointer to this structure must be passed
2718 * to the device driver in the 'arg' parameter.
2719 *
2720 * NOTES: This routine is fairly hardcoded with values for the various
2721 * formats of the 2 drives and will have to be updated when new drives
2722 * or formats are added.
2723 */
2724 #ifdef NEEDS_WORK /* NEEDS WORK -- ioctl stuff...later */
2725 static int
2726 fd_iocsinfo(fdp,arg)
2727 register struct floppy *fdp;
2728 register long arg;
2729 {
2730 register struct fdinfo *fdinfop;
2731 int tmp;
2732 int rc = FDSUCCESS;
2733
2734 /* Allocate an fdinfo structure. */
2735 fdinfop = (struct fdinfo *) malloc(sizeof(struct fdinfo));
2736
2737 if (fdinfop == NULL)
2738 return(ENOMEM);
2739
2740 /* Call copyin to get the fdinfo structure from the user.
2741 */
2742 tmp = copyin((char *) (arg), (char *) (fdinfop), sizeof(struct fdinfo));
2743 if (tmp == -1) {
2744 free(fdinfop);
2745 return(EINVAL);
2746 }
2747
2748 /* Make sure the request has the correct drive type. If not there
2749 * must be a user error.
2750 */
2751 if (fdp->drive_type != fdinfop->type) {
2752 free(fdinfop);
2753 return(EINVAL);
2754 }
2755
2756 switch (fdinfop->type) {
2757 case D_48: /* 360K, 5.25" drive */
2758 switch (fdinfop->ncyls) {
2759 case 40: /* 360K diskette */
2760 if ( (fdinfop->sides == 2) && (fdinfop->nsects == 9) )
2761 rc = fdload_floppy(fdp,FDLOAD_360);
2762 else
2763 rc = EINVAL;
2764 break;
2765 /* The 1.2M diskette is not currently supported, but this
2766 * will be handy if one does come up.
2767 */
2768 case 80: /* 1.2M diskette -- not supported */
2769 if ( (fdinfop->nsects != 15) || (fdinfop->sides != 2) )
2770 rc = EINVAL;
2771 else
2772 rc = EINVAL;
2773 break;
2774 default:
2775 rc = EINVAL;
2776 break;
2777 }
2778 break;
2779
2780 case D_135H: /* 1.44M, 3.5" drive */
2781 if ((fdinfop->sides != 2) || (fdinfop->ncyls != 80))
2782 rc = EINVAL;
2783 else {
2784 switch (fdinfop->nsects) {
2785 case 9: /* 720K diskette */
2786 rc = fdload_floppy(fdp, FDLOAD_720);
2787 break;
2788 case 18: /* 1.44M diskette */
2789 rc = fdload_floppy(fdp,FDLOAD_144);
2790 break;
2791 default:
2792 rc = EINVAL;
2793 break;
2794 }
2795 }
2796 break;
2797 default:
2798 rc = EINVAL;
2799 break;
2800 }
2801
2802 if (rc == FDSUCCESS)
2803 fdp->drive_type = (u_char) fdinfop->type;
2804
2805 free((caddr_t) fdinfop);
2806
2807 return(rc);
2808 }
2809 #endif
2810
2811 /* Does a FDIOCSTATUS ioctl.
2812 *
2813 * FDIOCSTATUS - returns the status of the diskette drive and
2814 * device driver. A pointer to a structure of type fd_status
2815 * should be be passed in the 'arg' parameter. The driver
2816 * status will be loaded into the fd_status structure
2817 * The result phase portion of the status is only
2818 * valid if the device driver was opened in raw mode.
2819 * otherwise, there is no way of knowing to which i/o
2820 * operation the result phase corresponds.
2821 *
2822 * NEEDS WORK - In our ABIOS implementation there are fields in the fd_status
2823 * struct that are not used. Let's see about cleaning them up.
2824 */
2825 #ifdef NEEDS_WORK /* NEEDS WORK -- ioctl's */
2826 static int
2827 fd_iocstatus(fdp,arg)
2828 register struct floppy *fdp;
2829 long arg;
2830 {
2831 register struct fd_status *fdstatusp;
2832 int rc = FDSUCCESS;
2833 int tmp;
2834
2835 FDDEBUG(FDIOCTL, printf("fdioctl: FDIOCSTATUS\n"));
2836
2837 /* Allocate an fd_status structure. */
2838
2839 fdstatusp = (struct fd_status *) malloc(sizeof(struct fd_status));
2840
2841 if (fdstatusp == NULL)
2842 return(ENOMEM);
2843
2844 /* Start building the status1 bitmask with the drive number.
2845 */
2846 tmp = fddrive_val[fd_drive(fdp->device_number)];
2847
2848 fdstatusp->status1 = (u_char) fdp->data_rate;
2849
2850 /* Start building the status2 bitmask with the retry flag.
2851 */
2852 if (fdp->retry_flag)
2853 tmp = FDRETRY;
2854 else
2855 tmp = 0;
2856
2857 if (fdp->timeout_flag == TRUE)
2858 tmp |= FDTIMEOUT;
2859
2860 switch (fdp->drive_type) {
2861 case D_48:
2862 tmp |= FD5INCHLOW;
2863 break;
2864 case D_135H:
2865 tmp |= FD3INCHHIGH;
2866 break;
2867 default:
2868 break;
2869 }
2870
2871 fdstatusp->status2 = (u_char) tmp;
2872 fdstatusp->status3 = fdp->diskette_type;
2873
2874 fdstatusp->head_settle_time = fdp->head_settle_time;
2875 fdstatusp->motor_speed = 300; /* On R2 1.44 its 300 */
2876 fdstatusp->Mbytes_read = fdp->read_count_megabytes;
2877 fdstatusp->Mbytes_written = fdp->write_count_megabytes;
2878
2879 fdstatusp->cylinder_num = fdp->start.cylinder;
2880 fdstatusp->head_num = fdp->start.head;
2881 fdstatusp->sector_num = fdp->start.sector;
2882
2883 fdstatusp->bytes_num = fdp->sector_count * fdp->bytes_per_sector;
2884 fdstatusp->bytes_num = fdp->e_bytesps;
2885
2886 fdget_adapter();
2887 tmp = fdexecute_command(fdp,FDDISK_SAME);
2888
2889 switch(tmp) {
2890 case DISK_CHANGED:
2891 fdstatusp->dsktchng = TRUE;
2892 break;
2893 case DISK_SAME:
2894 fdstatusp->dsktchng = FALSE;
2895 break;
2896 default:
2897 /* Unknown rc from command, so return an error.
2898 */
2899 free((caddr_t) fdstatusp);
2900 return(EIO);
2901 }
2902
2903 /* Call copyout to copy the fd_status structure to the user
2904 */
2905 tmp = copyout((char *) (fdstatusp), (char *) (arg),
2906 sizeof(struct fd_status));
2907 if (tmp == -1) {
2908 rc = EINVAL;
2909 }
2910
2911 free((caddr_t) fdstatusp);
2912 return(rc);
2913 }
2914 #endif
2915
2916
2917 /* Cleans up initialization stuff prior to exiting. This routine is
2918 * called just before exiting in fd_open and fd_close.
2919 */
2920 static void
2921 fdcleanup(fdp)
2922 struct floppy *fdp;
2923 {
2924 register int unit;
2925 int pri;
2926
2927 /* If our drive is still open, we're done otherwise turn off
2928 * the light. If the other drives are also closed then reclaim
2929 * some system resources.
2930 */
2931 if (fdp != NULL) {
2932 if (fdp->drive_state & FDSTAT_OPEN)
2933 return;
2934
2935 /* If the adapter is free, get it, and turn off the
2936 * motor. If the adapter is not free, something else
2937 * is going on, and hence we won't have to turn off
2938 * the light.
2939 */
2940 pri = splfd();
2941 if (fdadapter.fdintr_status == FDFREE) {
2942 fdget_adapter();
2943 splx(pri);
2944 fdexecute_command(fdp,FDMOTOR_OFF);
2945 }
2946 else
2947 splx(pri);
2948
2949 for (unit=0 ; unit < FDMAXDRIVES ; unit++)
2950 if (floppies[unit].drive_state & FDSTAT_OPEN)
2951 return;
2952 }
2953
2954 /* Reclaim some of the resources we were using. If there is
2955 * activity on the diskette adapter we will not get this far.
2956 */
2957 /* NEEDS WORK -- do we really want to untimeout() on the
2958 * NEEDS WORK -- watchdog timers here?? This might cause
2959 * NEEDS WORK -- problems with they system if they arn't
2960 * NEEDS WORK -- on, but probably not....
2961 */
2962 UNTIMEOUT(fdadapter.mot_wd);
2963 UNTIMEOUT(fdadapter.int_wd);
2964
2965 return;
2966 }
2967
2968 /*
2969 * Checks to see if the drive door is open. To do this with
2970 * an ABIOS interface we read the first sector into memory. This sector
2971 * is written back if we need to check for write protect.
2972 *
2973 * NOTES: We set fdp->open_check to TRUE to know when the 5 1/4" drive
2974 * does not have a diskette in it. fdcall_abios_poll() will turn this
2975 * flag off. See fdtimer() for further explination.
2976 */
2977 #if NEEDS_WORK
2978 static
2979 #endif
2980 int
2981 fddoor_check(fdp, wrck)
2982 register struct floppy *fdp;
2983 int wrck;
2984 {
2985 struct buf *bp;
2986 int rc;
2987
2988 FDDEBUG(FDCMD, printf("fddoor_check: entering...\n"));
2989
2990 bp = geteblk(512);
2991 #ifdef OSF
2992 event_clear(&bp->b_iocomplete);
2993 #endif OSF
2994 if (!bp) return(ENOMEM);
2995 bp->b_dev = fdp->device_number;
2996 bp->b_bcount = 512;
2997 bp->b_flags = B_READ;
2998 bp->b_blkno = 0;
2999 fdstrategy(bp);
3000 rc = biowait(bp);
3001
3002 if (rc) goto dcdone;
3003
3004 if (wrck) {
3005 bp->b_bcount = 512;
3006 bp->b_error = 0;
3007 bp->b_resid = 0;
3008 /* Added to fix B_INVAL for Mach 3.0 */
3009
3010 #ifdef MACH_KERNEL
3011 bp->b_flags = B_WRITE;
3012 #else MACH_KERNEL
3013 bp->b_flags = B_WRITE|B_INVAL;
3014 #endif MACH_KERNEL
3015 bp->b_blkno = 0;
3016 #ifdef OSF
3017 event_clear(&bp->b_iocomplete);
3018 #endif OSF
3019 fdstrategy(bp);
3020 rc = biowait(bp);
3021 }
3022
3023 dcdone:
3024 brelse(bp);
3025 return(rc);
3026 }
3027
3028 /* Loads the proper diskette characteristics. The 2nd parameter is a
3029 * function for fdexecute_command(), which will do the actual loading.
3030 *
3031 * There are actually 2 different ways that the fdp structure can be
3032 * populated. After fdexecute_command() is done we do some sanity
3033 * checks.
3034 */
3035 static int
3036 fdload_floppy(fdp,cmd)
3037 register struct floppy *fdp;
3038 int cmd;
3039 {
3040 int rc = FDSUCCESS;
3041 u_char drive_type;
3042
3043 drive_type = fdp->drive_type;
3044
3045 fdget_adapter();
3046
3047 if ( (rc = fdexecute_command(fdp,cmd)) != FDSUCCESS )
3048 return(rc);
3049
3050 #ifdef NEEDS_WORK /* NEEDS WORK */
3051 /* NEEDS WORK -- ok. We probably won't check drive_type anymore to
3052 * NEEDS WORK -- compare what it was configured for. This routine
3053 * NEEDS WORK -- can probably drop to a macro like fdtype(), and we
3054 * NEEDS WORK -- should also make sure both fdtype and load_floppy
3055 * NEEDS WORK -- are really infact needed.
3056 */
3057 /* Is the drive type what it was configured for?
3058 */
3059 if (drive_type != fdp->drive_type)
3060 return(EINVAL);
3061
3062 /* NEEDS WORK -- since drive_type is no longer configed,
3063 * NEEDS WORK -- this will have to change eventually.
3064 */
3065 switch(fdp->drive_type) {
3066 case D_135H:
3067 /* If they wanted a 5 1/4 inch drive explicitly, then
3068 * we have an error because this is a 3 1/2 inch drive.
3069 */
3070 if (minor(fdp->device_number) & FD_5)
3071 rc = EINVAL;
3072 break;
3073 case D_48:
3074 /* If they wanted a 3 1/2 inch drive explicitly, then
3075 * we have an error because this is a 5 1/4 inch drive.
3076 */
3077 if ((minor(fdp->device_number) & FD_5) == 0)
3078 rc = EINVAL;
3079 break;
3080 }
3081 #endif
3082
3083 return (rc);
3084 }
3085
3086 /* Currently this is a no-op.
3087 */
3088 int
3089 fdmincnt(bp)
3090 struct buf *bp;
3091 {
3092 return (0);
3093 }
3094
3095 /*
3096 * Logs a hard diskette error. It is called when we get an error that
3097 * should be reported to the user by more than an errno.
3098 *
3099 * Usually it will occur after all the retries are done, and the error
3100 * still exists.
3101 *
3102 */
3103 static void
3104 fdlog_error(fdp, value)
3105 register struct floppy *fdp;
3106 u_char value;
3107 {
3108 char *msg;
3109
3110 FDDEBUG(FDSTAT, printf("fdlog_error: entering...\n"));
3111
3112 /* NEEDS WORK -- this should be syslog or whatever the heck
3113 * NEEDS WORK -- OSF/1 uses. Took out the errsave() stuff.
3114 */
3115
3116 /* Differentiate between some hardware and internal errors.
3117 */
3118 switch(fdadapter.fd_req.r_return_code) {
3119 case 0x8000: /* Device Busy, Operation Fefused */
3120 case 0x800f: /* Invalid Value in NVRAM */
3121 case 0x9009: /* Controller Failure on Reset */
3122 case 0x9108: /* DMA Overrun on Operation */
3123 case 0x9120: /* Controller Failure */
3124 case 0x9140: /* Seek Operation Failed */
3125 case 0x9180: /* General Error */
3126 case 0xa120: /* Controller Failure */
3127 case 0xb020: /* Controller Failure */
3128 msg = "hardware error";
3129 break;
3130 case 0xc000: /* Invalid Logical ID */
3131 case 0xc001: /* Invalid Function */
3132 case 0xc003: /* Invalid Unit Number */
3133 case 0xc004: /* Invalid Request Block Length */
3134 case 0xc005: /* Invalid Diskette Parameter */
3135 msg = "internal driver error";
3136 break;
3137 default:
3138 msg = fd_tmp_errors[value];
3139 break;
3140 }
3141 printf("***fd%d: %s (%x)!***\n",fdadapter.fd_req.r_unit, msg,
3142 fdadapter.fd_req.r_return_code);
3143 }
3144
3145 /* Gains access of the diskette adapter for the caller, sleeping if
3146 * necessary. This can be called from interrupt level, because FDBUSY
3147 * is set in this case.
3148 */
3149 static void
3150 fdget_adapter()
3151 {
3152 register int pri;
3153
3154 pri = splfd();
3155
3156 while (fdadapter.fdintr_status != FDFREE) {
3157 FDDEBUG(FDCMD,printf("fdget_adapter: adapter not free!\n"));
3158
3159 fdadapter.need_controller = TRUE;
3160 sleep(&fdadapter.need_sleep,PRIBIO); /* NEEDS WORK */
3161 }
3162
3163 fdadapter.fdintr_status = FDBUSY;
3164 fdadapter.need_controller = FALSE;
3165
3166 splx(pri);
3167 }
3168
3169 /* Checks for non-contiguous physical pages. We can't dma across a virtual
3170 * page boundry that are not physically contiguous.
3171 */
3172 static int
3173 d_max_page(bp,baddr,paddr,max)
3174 struct buf *bp;
3175 u_int baddr;
3176 u_int *paddr;
3177 unsigned long max;
3178 {
3179 unsigned long count = ((unsigned long) baddr) & (I386_PGBYTES-1);
3180 unsigned long old_addr;
3181 unsigned long new_addr;
3182
3183 /* if count is aligned, we can transfer a whole page */
3184 if (count==0) count = I386_PGBYTES;
3185
3186 if ( (*paddr = pmap_extract(get_pmap(bp),baddr)) == 0)
3187 return(0);
3188
3189 /* Now loop through and get the real address of each of the
3190 ** following pages. Break on the first non-contiguous page,
3191 ** or when we exceed count.
3192 */
3193 baddr += I386_PGBYTES;
3194 old_addr = *paddr + I386_PGBYTES;
3195 while ( (count < max) &&
3196 ((new_addr = pmap_extract(get_pmap(bp),baddr)) != 0) &&
3197 (new_addr == old_addr) ) {
3198 count += I386_PGBYTES;
3199 baddr += I386_PGBYTES;
3200 old_addr += I386_PGBYTES;
3201 }
3202 return(count > max ? max : count);
3203 }
3204
3205 fddump(){} /* NEEDS WORK */
3206 fdsize(){} /* NEEDS WORK */
3207
3208 struct fd_errors {
3209 int code;
3210 char *msg;
3211 } fd_err_codes [] = {
3212 {0x00, "timeout"},
3213 {0x01, "bad-command"},
3214 {0x02, "address-mark-not-found"},
3215 {0x04, "record-not-found"},
3216 {0x05, "reset-failed"},
3217 {0x07, "activity-failed"},
3218 {0x0a, "defective-sector"},
3219 {0x0b, "bad-track"},
3220 {0x0d, "invalid-sector"},
3221 {0x0e, "CAM-detected"},
3222 {0x0f, "DMA-arb-level-bad"},
3223 {0x10, "bad-ecc-error"},
3224 {0x11, "ecc-corrected"},
3225 {0x20, "bad-controller"},
3226 {0x21, "equipment-check"},
3227 {0x40, "bad-seek"},
3228 {0x80, "device-didn't-respond"},
3229 {0xaa, "drive-not-ready"},
3230 {0xbb, "undefined-error"},
3231 {0xcc, "write-fault"},
3232 {0xff, "incomplete-sense"},
3233 {0xc000,"invalid LID"},
3234 {0xc001,"invalid function"},
3235 {0xc003,"invalid unit number"},
3236 {0xc004,"invalid request block length"},
3237 {0xc005,"invalid parameter"}
3238
3239 };
3240
3241 fd_error_decode(code,msg)
3242 char *msg;
3243 {
3244 int i;
3245 int n = code&0x00ff;
3246
3247 if ((code&0x8000) == 0) {
3248 char *p;
3249 switch(code)
3250 {
3251 case 0:
3252 p = "completed ok";
3253 break;
3254 case 1:
3255 p = "stage on int";
3256 break;
3257 case 2:
3258 p = "stage on time";
3259 break;
3260 case 5:
3261 p = "not my int";
3262 break;
3263 default:
3264 printf("unknown[0x%x]%s", code, msg);
3265 return;
3266 }
3267 printf("%s%s", p, msg);
3268 return;
3269 }
3270 if (code&0x4000) {
3271 printf("PARAMETER ");
3272 n = code;
3273 }
3274 if (code&0x2000)
3275 printf("TIME-OUT ");
3276 if (code&0x1000)
3277 printf("DEVICE ");
3278 if (code&0x100)
3279 printf("RETRYABLE ");
3280 printf("ERROR ");
3281 for (i=0; i<(sizeof fd_err_codes)/(sizeof fd_err_codes[0]); ++i)
3282 if (fd_err_codes[i].code == n)
3283 {
3284 printf("%s%s", fd_err_codes[i].msg, msg);
3285 return;
3286 }
3287 printf("unknown[0x%x]%s", code, msg);
3288 }
3289
3290
3291 #ifdef MACH_KERNEL
3292
3293
3294
3295 /*
3296 * NAME: fdgetstat(dev, flavour, data, count)
3297 *
3298 * FUNCTION: This function implements one half of the functions implemented
3299 * by the IOCTL routine in the MACH 2.5 version of this floppy
3300 * driver.
3301 *
3302 * EXECUTION ENVIRONMENT:
3303 *
3304 * RETURNS:
3305 */
3306
3307
3308
3309 io_return_t fdgetstat(dev, flavor, data, count)
3310 dev_t dev; /* device */
3311 int flavor; /* command */
3312 int * data; /* pointer to OUT array */
3313 unsigned int *count; /* OUT */
3314 {
3315
3316 register struct floppy *fdp;
3317 register struct fdparms *fdparmsp;
3318 io_return_t errcode = D_SUCCESS;
3319
3320 fdp = &floppies[fd_drive(dev)];
3321
3322 switch(flavor){
3323
3324 case FDIOCGETPARMS:
3325
3326 /* Check to see if out buffer is large enough */
3327
3328 if (*count < sizeof(struct fdparms)/sizeof(int))
3329 return(D_INVALID_OPERATION);
3330
3331 /* In mach 2.5 space for fdparmsp was allocated here */
3332 /* initialized, then a copyout would be done to the */
3333 /* user supplied buffer space. and then a copyout */
3334 /* would be done to user space. But here the pointer */
3335 /* to data is in kernel space and so it need not be */
3336 /* done. */
3337
3338
3339 fdparmsp = (struct fdparms *)data;
3340
3341 fdparmsp->diskette_type = fdp->diskette_type;
3342 fdparmsp->sector_size = fdp->e_bytesps;
3343 fdparmsp->sectors_per_track = fdp->sectors_per_track;
3344 fdparmsp->sectors_per_cylinder = fdp->sectors_per_cylinder;
3345 fdparmsp->tracks_per_cylinder = fdp->tracks_per_cylinder;
3346 fdparmsp->cylinders_per_disk = fdp->cylinders_per_disk;
3347 fdparmsp->data_rate = fdp->data_rate;
3348 fdparmsp->head_settle_time = fdp->head_settle_time;
3349 fdparmsp->head_load = 0;
3350 fdparmsp->fill_byte = fdp->fill_byte;
3351 fdparmsp->step_rate = 0;
3352 fdparmsp->step_rate_time = 0;
3353 fdparmsp->gap = fdp->gap;
3354 fdparmsp->format_gap = fdp->format_gap;
3355 fdparmsp->data_length = fdp->data_length;
3356 fdparmsp->motor_off_time = fdp->motor_off_time;
3357 fdparmsp->bytes_per_sector = fdp->bytes_per_sector;
3358 fdparmsp->number_of_blocks = fdp->number_of_blocks;
3359
3360 /* force the out buffer to be word alligned */
3361
3362 *count = sizeof(struct fdparms)/sizeof(int);
3363
3364 errcode = D_SUCCESS;
3365 break;
3366
3367 default:
3368
3369 errcode = D_INVALID_OPERATION;
3370
3371 } /* End of case flavor statement */
3372
3373 return(errcode);
3374
3375 }
3376
3377
3378
3379 /*
3380 * NAME: fdsetstat(dev, flavour, data, count)
3381 *
3382 * FUNCTION: This function implements a set of the functions that were
3383 * being performed in the IOCT routine of the MACH 2.5 version
3384 * of this floppy driver
3385 *
3386 * EXECUTION ENVIRONMENT:
3387 *
3388 * RETURNS:
3389 */
3390
3391
3392 io_return_t fdsetstat(dev, flavor, data, count)
3393 dev_t dev;
3394 int flavor;
3395 int * data;
3396 unsigned int count;
3397 {
3398
3399 register struct floppy *fdp;
3400 register struct devinfo *devinfop;
3401 register struct fdinfo *fdinfop;
3402 register struct fdparms *fdparmsp;
3403 int temp;
3404 io_return_t errcode = D_SUCCESS;
3405
3406
3407 fdp = &floppies[fd_drive(dev)];
3408
3409 #define check(cnd, err) if (!(cnd)) { \
3410 errcode = (err);\
3411 break; \
3412 }
3413
3414 #define cond(member) (fdp->member == fdparmsp->member)
3415
3416
3417
3418 switch(flavor){
3419
3420 case FDIOCSETPARMS:
3421
3422 /* define two macros that will be used to screen */
3423 /* requests to set protected parameters of the */
3424 /* floppy drive that ABIOS doesnt support changes */
3425 /* to by the user */
3426
3427 /*
3428
3429 #define check(cnd, err) if (!(cnd)) { \
3430 errcode = (err); \
3431 break; \
3432 }
3433
3434 #define cond(member) (fdp->member == fdparmsp->member)
3435
3436 */
3437
3438 /* base the the fdparmsp on the user supplied data */
3439
3440 fdparmsp = (struct fdparms *)data;
3441
3442 if (fdparmsp == NULL)
3443 {
3444 errcode = ENOMEM;
3445 break;
3446 }
3447
3448 /* Check to see if ABIOS protected fields are being */
3449 /* requested to be changed, if so retuen Error */
3450
3451
3452 check(fdp->diskette_type == fdparmsp->diskette_type,
3453 D_INVALID_OPERATION);
3454 check(fdparmsp->head_load == 0, D_INVALID_OPERATION);
3455 check(fdparmsp->step_rate == 0, D_INVALID_OPERATION);
3456 check(fdparmsp->step_rate_time == 0, D_INVALID_OPERATION);
3457 check(cond(sectors_per_track), D_INVALID_OPERATION);
3458 check(cond(sectors_per_cylinder), D_INVALID_OPERATION);
3459 check(cond(tracks_per_cylinder), D_INVALID_OPERATION);
3460 check(cond(cylinders_per_disk), D_INVALID_OPERATION);
3461 check(cond(data_rate), D_INVALID_OPERATION);
3462 check(cond(head_settle_time), D_INVALID_OPERATION);
3463 check(cond(number_of_blocks), D_INVALID_OPERATION);
3464 check(cond(bytes_per_sector), D_INVALID_OPERATION);
3465
3466 /* If we are here it means that the request is a legal */
3467 /* ABIOS supported request. So we check to see which of */
3468 /* the legal parameters are being requested to be changed */
3469 /* save the original value, attempt a change, if the ABIOS */
3470 /* request fails then we reset the value to the original */
3471 /* legal value and return a FAILURE */
3472
3473
3474 /* Check to see if bytes_per_sector changed */
3475
3476
3477 if (fdp->e_bytesps != fdparmsp->sector_size)
3478 {
3479
3480 /* 256 and 512 Bytes per sector are legal values */
3481
3482 check((fdparmsp->sector_size==FD_256_BYTE_PER_SECTOR) ||
3483 (fdparmsp->sector_size==FD_512_BYTE_PER_SECTOR),
3484 D_INVALID_OPERATION);
3485
3486 temp = fdp->e_bytesps; /* save original */
3487
3488 fdp->e_bytesps = fdparmsp->sector_size;
3489
3490 fdget_adapter();
3491
3492 if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
3493 {
3494
3495 fdp->e_bytesps = temp;
3496 errcode = D_INVALID_OPERATION;
3497 break;
3498
3499 }
3500
3501 /* When changing sector_size, bytes_per_sector will be */
3502 /* implicitly changed, so update the users view of */
3503 /* bytes_per_sector accordingly */
3504
3505 fdparmsp->bytes_per_sector = fdp->bytes_per_sector;
3506
3507
3508 check(temp == 0, D_INVALID_OPERATION); /* Magic */
3509
3510 }
3511
3512 /* Check to see if gap has changed */
3513
3514 if (fdp->gap != fdparmsp->gap)
3515 {
3516 temp = fdp->gap; /* save original value */
3517 fdp->gap = fdparmsp->gap;
3518 fdget_adapter();
3519 if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
3520 {
3521 fdp->gap = temp;
3522 errcode = D_INVALID_OPERATION;
3523 break;
3524
3525 }
3526 }
3527
3528
3529 /* Check to see if data_length has changed */
3530
3531
3532 if (fdp->data_length != fdparmsp->data_length)
3533 {
3534 temp = fdp->data_length; /* save original */
3535 fdp->data_length = fdparmsp->data_length;
3536 fdget_adapter();
3537 if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
3538 {
3539 fdp->data_length = temp;
3540 errcode = D_INVALID_OPERATION;
3541 break;
3542 }
3543 }
3544
3545 /* Check to see fill_byte has changed */
3546
3547
3548 if (fdp->fill_byte != fdparmsp->fill_byte)
3549 {
3550 temp = fdp->fill_byte; /* save original */
3551 fdp->fill_byte = fdparmsp->fill_byte;
3552 fdget_adapter();
3553 if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
3554 {
3555 fdp->fill_byte = temp;
3556 errcode = D_INVALID_OPERATION;
3557 break;
3558 }
3559 }
3560
3561
3562 /* Check to see if format_gap has changed */
3563
3564 if (fdp->format_gap != fdparmsp->format_gap)
3565 {
3566 temp = fdp->format_gap; /* save original */
3567 fdp->format_gap = fdparmsp->format_gap;
3568 fdget_adapter();
3569 if (fdexecute_command(fdp,FD_SETDP_POLL) != FDSUCCESS)
3570 {
3571 fdp->format_gap = temp;
3572 errcode = D_INVALID_OPERATION;
3573 break;
3574 }
3575 }
3576
3577 /* Check if motor_off_time has changed */
3578
3579 if (fdp->motor_off_time != fdparmsp->motor_off_time)
3580 {
3581 fdadapter.mot_wd.time = fdparmsp->motor_off_time;
3582 fdp->motor_off_time = fdparmsp->motor_off_time;
3583 break;
3584 }
3585
3586
3587 case FDIOCFORMAT:
3588
3589 default:
3590
3591 errcode = D_INVALID_OPERATION;
3592 break;
3593
3594
3595 } /* End of switch statement for flavor */
3596
3597
3598 return(errcode);
3599 }
3600
3601 /*
3602 * NAME: fdabios_init
3603 *
3604 * FUNCTION: This function initializes the floppy driver data structures
3605 * by calling ABIOS to querry for the parameters of the floppy
3606 * drive and controller in the system.
3607 *
3608 * EXECUTION ENVIRONMENT:
3609 *
3610 * This is called by fdinit() at system initialization time. *
3611 * RETURNS: NONE
3612 */
3613
3614 fdabios_init(fdp)
3615 register struct floppy *fdp;
3616 {
3617
3618 register struct Fd_request *fdreq;
3619 u_char drive_number;
3620 int rc = FDSUCCESS;
3621
3622 fdadapter.fdintr_status = FDBUSY;
3623
3624 fdp->timeout_flag = FALSE;
3625 UNTIMEOUT(fdadapter.mot_wd);
3626
3627 fdreq = &fdadapter.fd_req;
3628 drive_number = fd_drive(fdp->device_number);
3629 fdadapter.fd_flag = 0;
3630 fdreq->state = FD_RB_IDLE; /* may not be needed */
3631 fdreq->sleep_on_intr = 0; /* may not be needed */
3632
3633 FD_SET_RESERVED_ABIOS_LOGICAL_PARAMETER(fdreq);
3634
3635 fdreq->r_current_req_blck_len = sizeof(struct Fd_request);
3636 fdreq->r_logical_id = abios_next_LID(FD_ID, 2);
3637 fdreq->r_unit = 0;
3638 fdreq->request_header.Request_Block_Flags = 0;
3639 fdreq->request_header.ELA_Offset = 0;
3640 fd_no_retry(fdp);
3641
3642
3643 fdp->timeout_flag = FALSE;
3644 fdreq->state |= FD_RB_SYNC;
3645 fdreq->req_errno = 0;
3646
3647
3648 fdreq->r_function = FDABIOS_INIT;
3649 fdreq->r_return_code = ABIOS_UNDEFINED;
3650 fdreq->state |= FD_RB_STARTED;
3651
3652 abios_common_start(fdreq, fdadapter.fd_flag);
3653
3654 /* wait for ABIOS to get done */
3655
3656 while (fdreq->r_return_code == ABIOS_UNDEFINED)
3657 {
3658 assert_wait(0, FALSE);
3659 thread_set_timeout(10);
3660 thread_block((continuation_t) 0);
3661 }
3662
3663 /* Look for synchronous errors from ABIOS */
3664
3665 if (fdreq->r_return_code & 0x8000)
3666 {
3667 if (fdreq->r_return_code == 0xc000)
3668 printf("Req 1: Invalid Logical ID\n\n");
3669 if (fdreq->r_return_code == 0xc001)
3670 printf("Req 1: Invalid Function\n\n");
3671 if (fdreq->r_return_code == 0xc003)
3672 printf("Req 1: Invalid Unit Number\n\n");
3673 if (fdreq->r_return_code == 0xc004)
3674 printf("Req 1: Invalid Request Block Length\n\n");
3675 else
3676 printf("Req 1: Unkown Error\n\n");
3677
3678 return(EIO);
3679 }
3680
3681 while (fdreq->r_return_code != ABIOS_DONE)
3682 {
3683 assert_wait(0, FALSE);
3684 thread_set_timeout(10);
3685 thread_block((continuation_t) 0);
3686 }
3687
3688 rc = fdreq->req_errno;
3689
3690 if (rc != FDSUCCESS)
3691 return(rc);
3692
3693 fdreq->r_current_req_blck_len = fdreq->r_request_block_length;
3694 fdadapter.fd_flag = fdreq->r_logical_id_flags;
3695 fdadapter.fd_intl = fdreq->r_hardware_intr;
3696 fdadapter.fd_numd = fdreq->r_number_units;
3697
3698
3699 if (fdadapter.fd_numd == 0)
3700 #ifdef MACH_KERNEL
3701 return D_NO_SUCH_DEVICE;
3702 #else /* MACH_KERNEL */
3703 return(ENODEV);
3704 #endif /* MACH_KERNEL */
3705
3706 if (fdadapter.fd_numd > FDMAXDRIVES)
3707 fdadapter.fd_numd = FDMAXDRIVES;
3708
3709
3710 FD_SET_RESERVED_ABIOS_READ_PARAMETER(fdreq);
3711
3712 fd_no_retry(fdp);
3713
3714 fdp->timeout_flag = FALSE;
3715 fdreq->state |= FD_RB_SYNC;
3716 fdreq->req_errno = 0;
3717
3718 fdreq->r_function = ABIOS_READ_PARAMETER;
3719 fdreq->r_return_code = ABIOS_UNDEFINED;
3720 fdreq->state |= FD_RB_STARTED;
3721
3722
3723 abios_common_start(fdreq, fdadapter.fd_flag);
3724
3725 /* wait for ABIOS to get done */
3726
3727 while(fdreq->r_return_code == ABIOS_UNDEFINED)
3728 {
3729 assert_wait(0, FALSE);
3730 thread_set_timeout(10);
3731 thread_block((continuation_t) 0);
3732 }
3733
3734
3735 /* Look for synchronous errors from ABIOS */
3736
3737 if (fdreq->r_return_code & 0x8000)
3738 {
3739
3740 if (fdreq->r_return_code == 0x8000)
3741 printf("Req 2: Device Busy Error\n\n");
3742 if (fdreq->r_return_code == 0x8001)
3743 printf("Req 2: Diskette Not Started\n\n");
3744 if (fdreq->r_return_code == 0xc000)
3745 printf("Req 2: Invalid Logical ID\n\n");
3746 if (fdreq->r_return_code == 0xc001)
3747 printf("Req 2: Invalid Function\n\n");
3748 if (fdreq->r_return_code == 0xc003)
3749 printf("Req 2: Invalid Unit Number\n\n");
3750 if (fdreq->r_return_code == 0xc004)
3751 printf("Req 2: Invalid Request Block Length\n\n");
3752 else
3753 printf("Req 2: Sync Error reported by ABIOS \n\n");
3754
3755 return(EIO);
3756 }
3757
3758 while (fdreq->r_return_code != ABIOS_DONE)
3759 {
3760 assert_wait(0, FALSE);
3761 thread_set_timeout(10);
3762 thread_block((continuation_t)0);
3763 }
3764
3765
3766 rc = fdreq->req_errno;
3767
3768 if (rc != FDSUCCESS)
3769 return(rc);
3770
3771 fdadapter.motor_off_delay = fd_motor_off_delay_time(fdreq);
3772
3773 fdadapter.fdintr_status = FDFREE;
3774
3775 return(rc);
3776
3777 }
3778
3779 #endif MACH_KERNEL
3780
3781
3782
Cache object: 642651b0a0c6681e13845a67712e9f2b
|