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