FreeBSD/Linux Kernel Cross Reference
sys/i386at/fd.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: fd.c,v $
29 * Revision 2.15 93/08/02 21:43:43 mrt
30 * Put the free copyright on this file, again.
31 * [93/07/22 mrt]
32 *
33 * Revision 2.14 93/05/15 19:32:35 mrt
34 * machparam.h -> machspl.h
35 *
36 * Revision 2.13 93/05/10 21:19:02 rvb
37 * Lint.
38 * [93/05/08 11:19:03 af]
39 *
40 * Revision 2.12 93/01/24 13:15:28 danner
41 * [93/01/19 11:03:43 rvb]
42 *
43 * Test lower bound of media type; convert fd_addr to vm_offset_t.
44 *
45 * Revision 2.11 93/01/14 17:30:11 danner
46 * Proper spl typing.
47 * [92/11/30 af]
48 *
49 * Revision 2.10 92/07/09 22:53:34 rvb
50 * There is a problem with ADAPTEC boards, where scsi disk dma will
51 * lock out the floppy dma. An expedient fix seems to be to drop
52 * the DMA size for the floppy, in the retry code when/if this happens.
53 * [92/07/08 rvb]
54 *
55 * Revision 2.9 92/04/08 08:58:30 rpd
56 * Fixed fdprobe to loop longer. From rvb.
57 * [92/04/08 rpd]
58 *
59 * Revision 2.8 92/02/23 22:42:57 elf
60 * Added (mandatory) DEV_GET_SIZE flavor of get_status.
61 * [92/02/22 af]
62 *
63 * Revision 2.7 92/01/27 16:42:54 rpd
64 * Fixed fdgetstat and fdsetstat to return D_INVALID_OPERATION
65 * for unsupported flavors.
66 * [92/01/26 rpd]
67 *
68 * Revision 2.6 91/11/12 11:09:18 rvb
69 * Amazing how hard getting the probe to work for all machines is.
70 * [91/10/16 rvb]
71 *
72 * Revision 2.5 91/10/07 17:25:22 af
73 * Still better
74 * [91/10/07 16:29:57 rvb]
75 *
76 * From mg32: Better probe for multiple controllers now possible.
77 * [91/09/23 rvb]
78 * New chips/busses.[ch] nomenclature.
79 * [91/09/09 17:12:23 rvb]
80 *
81 * Added a reset in open to prevent "no such device" errors
82 * Added dlb's fddevinfo.
83 * Reworked to make 2.5/3.0 compatible
84 * [91/09/04 15:46:49 rvb]
85 *
86 * Major rewrite by mg32.
87 * [91/08/07 mg32]
88 *
89 * Revision 2.4 91/08/24 11:57:32 af
90 * New MI autoconf.
91 * [91/08/02 02:53:26 af]
92 *
93 * Revision 2.3 91/05/14 16:22:47 mrt
94 * Correcting copyright
95 *
96 * Revision 2.2 91/02/14 14:42:23 mrt
97 * This file is the logical contatenation of the previous c765.c,
98 * m765knl.c and m765drv.c, in that order.
99 * [91/01/15 rvb]
100 *
101 * Revision 2.5 91/01/08 17:33:32 rpd
102 * Add some 3.0 get/set stat stuff.
103 * [91/01/04 12:21:06 rvb]
104 *
105 * Revision 2.4 90/11/26 14:50:54 rvb
106 * jsb bet me to XMK34, sigh ...
107 * [90/11/26 rvb]
108 * Synched 2.5 & 3.0 at I386q (r1.6.1.6) & XMK35 (r2.4)
109 * [90/11/15 rvb]
110 *
111 * Revision 1.6.1.6 90/11/27 13:44:55 rvb
112 * Synched 2.5 & 3.0 at I386q (r1.6.1.6) & XMK35 (r2.4)
113 * [90/11/15 rvb]
114 *
115 * Revision 2.3 90/08/27 22:01:22 dbg
116 * Remove include of device/param.h (unnecessary). Flush ushort.
117 * [90/07/17 dbg]
118 *
119 * Revision 1.6.1.5 90/08/25 15:44:31 rvb
120 * Use take_<>_irq() vs direct manipulations of ivect and friends.
121 * [90/08/20 rvb]
122 *
123 * Revision 1.6.1.4 90/07/27 11:26:53 rvb
124 * Fix Intel Copyright as per B. Davies authorization.
125 * [90/07/27 rvb]
126 *
127 * Revision 1.6.1.3 90/07/10 11:45:11 rvb
128 * New style probe/attach.
129 * NOTE: the whole probe/slave/attach is a crock. Someone
130 * who spends the time to understand the driver should do
131 * it right.
132 * [90/06/15 rvb]
133 *
134 * Revision 2.2 90/05/03 15:45:37 dbg
135 * Convert for pure kernel.
136 * Optimized fd_disksort iff dp empty.
137 * [90/04/19 dbg]
138 *
139 * Revision 1.6.1.2 90/01/08 13:30:14 rvb
140 * Add Intel copyright.
141 * [90/01/08 rvb]
142 *
143 * Revision 1.6.1.1 89/10/22 11:34:51 rvb
144 * Received from Intel October 5, 1989.
145 * [89/10/13 rvb]
146 *
147 * Revision 1.6 89/09/25 12:27:05 rvb
148 * vtoc.h -> disk.h
149 * [89/09/23 rvb]
150 *
151 * Revision 1.5 89/09/09 15:23:15 rvb
152 * Have fd{read,write} use stragegy now that physio maps correctly.
153 * [89/09/06 rvb]
154 *
155 * Revision 1.4 89/03/09 20:07:26 rpd
156 * More cleanup.
157 *
158 * Revision 1.3 89/02/26 12:40:28 gm0w
159 * Changes for cleanup.
160 *
161 */
162
163 /*
164 Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
165
166 All Rights Reserved
167
168 Permission to use, copy, modify, and distribute this software and
169 its documentation for any purpose and without fee is hereby
170 granted, provided that the above copyright notice appears in all
171 copies and that both the copyright notice and this permission notice
172 appear in supporting documentation, and that the name of Intel
173 not be used in advertising or publicity pertaining to distribution
174 of the software without specific, written prior permission.
175
176 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
177 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
178 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
179 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
180 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
181 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
182 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
183 */
184
185 /* Copyright (c) 1987, 1988 TOSHIBA Corp. */
186 /* All Rights Reserved */
187
188 #include <fd.h>
189
190 #ifdef MACH_KERNEL
191 #include <sys/types.h>
192 #include <device/buf.h>
193 #include <device/errno.h>
194 #else MACH_KERNEL
195 #include <sys/buf.h>
196 #include <sys/errno.h>
197 #include <sys/user.h>
198 #endif MACH_KERNEL
199 #include <sys/ioctl.h>
200 #include <i386/pio.h>
201 #include <i386/machspl.h>
202 #include <chips/busses.h>
203 #include <i386at/fdreg.h>
204 #include <i386at/disk.h>
205
206 #ifdef DEBUG
207 #define D(x) x
208 #else /* DEBUG */
209 #define D(x)
210 #endif /* DEBUG */
211
212 /*
213 * Floppy Device-Table Definitions (drtabs)
214 *
215 * Cyls,Sec,spc,part,Mtype,RWFpl,FGpl
216 */
217 struct fddrtab m765f[] = { /* format table */
218 80, 18, 1440, 9, 0x88, 0x2a, 0x50, /* [0] 3.50" 720 Kb */
219 80, 36, 2880, 18, 0x08, 0x1b, 0x6c, /* [1] 3.50" 1.44 Meg */
220 40, 18, 720, 9, 0xa8, 0x2a, 0x50, /* [2] 5.25" 360 Kb */
221 80, 30, 2400, 15, 0x08, 0x1b, 0x54 /* [3] 5.25" 1.20 Meg */
222 };
223
224 /*
225 * The following are static initialization variables
226 * which are based on the configuration.
227 */
228 struct ctrl_info ctrl_info[MAXUNIT>>1] = { /* device data table */
229 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ,
230 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
231 };
232
233 struct unit_info unit_info[MAXUNIT]; /* unit buffer headers */
234
235 char *fderr = "FD Error on unit";
236 char *fdmsg[] = {
237 "?",
238 "Missing data address mark",
239 "Write protected",
240 "Sector not found",
241 "Data Overrun", /* Over run error */
242 "Uncorrectable data read error", /* CRC Error */
243 "FDC Error",
244 "Illegal format type",
245 "Drive not ready",
246 "diskette not present - please insert",
247 "Illegal interrupt type"
248 };
249
250 struct buf fdrbuf[MAXUNIT]; /* data transfer buffer structures */
251
252 int fdminphys();
253 int fdintr(), fdprobe(), fdslave();
254 void fdattach();
255 vm_offset_t fd_std[NFD] = { 0 };
256 struct bus_device *fd_dinfo[NFD*2];
257 struct bus_ctlr *fd_minfo[NFD];
258 struct bus_driver fddriver =
259 {fdprobe, fdslave, fdattach, 0, fd_std, "fd", fd_dinfo, "fdc", fd_minfo, 0};
260
261 int m765verify[MAXUNIT] = {1,1,1,1}; /* write after read flag */
262 /* 0 != verify mode */
263 /* 0 == not verify mode */
264 #ifdef MACH_KERNEL
265 extern struct buf *geteblk();
266 #endif MACH_KERNEL
267
268 #define trfrate(uip, type) outb(VFOREG(uip->addr),(((type)&RATEMASK)>>6))
269 #define rbskrate(uip, type) trfrate(uip,(type)&RAPID?RPSEEK:NMSEEK)
270 #define getparm(type) ((type<0||type>3)?(struct fddrtab *)ERROR:&m765f[type])
271 #define relative(s1,s2) ((s1)>(s2)?(s1)-(s2):(s2)-(s1))
272
273 fdprobe(port, ctlr)
274 struct bus_ctlr *ctlr;
275 {
276 int spot = STSREG((int) ctlr->address);
277 struct ctrl_info *cip = &ctrl_info[ctlr->unit];
278 int i, in;
279
280 outb(spot, DATAOK);
281 for (i = 1000; i--;) {
282 in = inb(spot);
283 if ((in&DATAOK) == DATAOK && !(in&0x0f)) {
284 take_ctlr_irq(ctlr);
285 cip->b_cmd.c_rbmtr = 0; /* recalibrate/moter flag */
286 cip->b_cmd.c_intr = CMDRST; /* interrupt flag */
287 cip->b_unitf = 0;
288 cip->b_uip = 0;
289 cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
290 printf("%s%d: port = %x, spl = %d, pic = %d.\n", ctlr->name,
291 ctlr->unit, ctlr->address, ctlr->sysdep, ctlr->sysdep1);
292 return(1);
293 }
294 }
295 return(0);
296 }
297
298 fdslave(dev, xxxx)
299 struct bus_device *dev;
300 {
301 return(1); /* gross hack */
302 }
303
304 void fdattach(dev)
305 struct bus_device *dev;
306 {
307 struct unit_info *uip = &unit_info[dev->unit];
308 struct ctrl_info *cip = &ctrl_info[dev->ctlr];
309
310 uip->dev = dev;
311 dev->address = dev->mi->address;
312 uip->addr = dev->address;
313 uip->b_cmd = &cip->b_cmd;
314 uip->b_seekaddr = 0;
315 uip->av_forw = 0;
316 uip->wakeme = 0;
317 if (cip->b_unitf) {
318 uip->b_unitf=cip->b_unitf->b_unitf;
319 cip->b_unitf->b_unitf=uip;
320 } else {
321 uip->b_unitf=uip;
322 cip->b_unitf=uip;
323 }
324 uip->d_drtab.dr_type &= ~OKTYPE;
325
326 printf(", port = %x, spl = %d, pic = %d.",
327 dev->address, dev->sysdep, dev->sysdep1);
328
329 rstout(uip);
330 specify(uip);
331 }
332 /*****************************************************************************
333 *
334 * TITLE: fdopen
335 *
336 * ABSTRACT: Open a unit.
337 *
338 ****************************************************************************/
339 fdopen(dev, flag, otyp)
340 dev_t dev;
341 int flag; /* not used */
342 int otyp; /* not used */
343 {
344 struct fddrtab *driv;
345 struct buf *wbp;
346 spl_t x = SPL();
347 int error = 0;
348 int unit = UNIT(dev);
349 struct unit_info *uip = &unit_info[unit];
350 int slave = uip->dev->slave;
351 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
352 struct fdcmd *cmdp = uip->b_cmd;
353 if (unit < MAXUNIT){
354 /* Since all functions that use this are called from open, we only
355 set this once, right here. */
356 rstout(uip);
357 cip->b_wup = uip;
358 openchk(cmdp);
359 cmdp->c_devflag |= FDMCHK;
360 chkbusy(cmdp);
361 cmdp->c_stsflag |= MTRFLAG;
362 mtr_on(uip);
363 if(inb(VFOREG(uip->addr))&OPENBIT ||
364 !(uip->d_drtab.dr_type&OKTYPE)){
365 uip->d_drtab.dr_type &= ~OKTYPE;
366 if(!rbrate(RAPID, uip))
367 fdseek(RAPID, uip, 2);
368 if(inb(VFOREG(uip->addr))&OPENBIT)
369 error = ENXIO;
370 }
371 cmdp->c_stsflag &= ~MTRFLAG;
372 mtr_on(uip);
373 openfre(cmdp);
374 if(!error && !(uip->d_drtab.dr_type & OKTYPE)) {
375 if (MEDIATYPE(dev)>3)
376 goto endopen;
377 driv = &m765f[MEDIATYPE(dev)];
378 wbp = geteblk(BLKSIZE);
379 m765sweep(uip, driv);
380 cmdp->c_rbmtr &= ~(1<<(RBSHIFT+(slave)));
381 ++cip->b_rwerr;
382 wbp->b_dev = dev; wbp->b_error = 0; wbp->b_resid = 0;
383 wbp->b_flags = (B_READ|B_VERIFY); wbp->b_bcount = 512;
384 wbp->b_pfcent = 2*driv->dr_spc + driv->dr_nsec - 1;
385 setqueue(wbp, uip);
386 biowait(wbp);
387 brelse(wbp);
388 error = 0;
389 uip->d_drtab.dr_type |= OKTYPE;
390 }
391 } else
392 error = ENXIO;
393 endopen:
394 splx(x);
395 return(error);
396 }
397 /*****************************************************************************
398 *
399 * TITLE: fdclose
400 *
401 * ABSTRACT: Close a unit.
402 *
403 * Called on last close. mark the unit closed and not-ready.
404 *
405 * Unix doesn't actually "open" an inode for rootdev, swapdev or pipedev.
406 * If UNIT(swapdev) != UNIT(rootdev), then must add code in init() to
407 * "open" swapdev. These devices should never be closed.
408 *
409 *****************************************************************************/
410 fdclose(dev, flag, otyp, offset)
411 dev_t dev; /* major, minor numbers */
412 int flag; /* not used */
413 int otyp; /* not used */
414 off_t offset; /* not used */
415 {
416 extern dev_t rootdev, swapdev;
417 struct unit_info *uip = &unit_info[UNIT(dev)];
418 spl_t s;
419
420 #ifdef MACH_KERNEL
421 #else MACH_KERNEL
422 if ((dev == rootdev) || (dev == swapdev)) /* never close these */
423 return(0);
424 #endif MACH_KERNEL
425
426 /* Clear the bit.
427 * If last close of drive insure drtab queue is empty before returning.
428 */
429 s = SPL();
430 while(uip->av_forw != 0) {
431 uip->wakeme = 1;
432 sleep(uip, PRIBIO);
433 }
434 splx(s);
435 #ifdef MACH_KERNEL
436 return(0);
437 #else MACH_KERNEL
438 close(0);
439 #endif MACH_KERNEL
440 }
441 /*****************************************************************************
442 *
443 * TITLE: fdstrategy
444 *
445 * ABSTRACT: Queue an I/O Request, and start it if not busy already.
446 *
447 * Reject request if unit is not-ready.
448 *
449 * Note: check for not-ready done here ==> could get requests
450 * queued prior to unit going not-ready.
451 * not-ready status to those requests that are attempted
452 * before a new volume is inserted. Once a new volume is
453 * inserted, would get good I/O's to wrong volume.
454 *
455 * CALLS: iodone(),setqueue()
456 *
457 * CALLING ROUTINES: fdread (indirectly, thru physio)
458 * fdwrite (indirectly, thru physio)
459 *
460 ****************************************************************************/
461 fdstrategy(bp)
462 struct buf *bp; /* buffer header */
463 {
464 unsigned bytes_left;
465 daddr_t secno;
466 struct unit_info *uip = &unit_info[UNIT(bp->b_dev)];
467 struct fddrtab *dr = &uip->d_drtab;
468 struct fddrtab *sdr;
469
470 bp->b_error = 0;
471 /* set b_resid to b_bcount because we haven't done anything yet */
472 bp->b_resid = bp->b_bcount;
473 if (!(dr->dr_type & OKTYPE) ||
474 ((sdr = getparm(MEDIATYPE(bp->b_dev)))==(struct fddrtab *)ERROR) ||
475 /* wrong parameters */
476 (sdr->dr_ncyl != dr->dr_ncyl) || (sdr->dr_nsec != dr->dr_nsec) ||
477 ((sdr->dr_type|OKTYPE) != dr->dr_type) ||
478 (sdr->dr_rwgpl != dr->dr_rwgpl) ||
479 (sdr->dr_fgpl != dr->dr_fgpl)) {
480 bp->b_flags |= B_ERROR;
481 bp->b_error = EIO;
482 biodone(bp);
483 return(0);
484 }
485 /*
486 * Figure "secno" from b_blkno. Adjust sector # for partition.
487 *
488 * If reading just past the end of the device, it's
489 * End of File. If not reading, or if read starts further in
490 * than the first sector after the partition, it's an error.
491 *
492 * secno is logical blockno / # of logical blocks per sector */
493 secno = (bp->b_blkno * NBPSCTR) >> 9;
494 if (secno >= dr->p_nsec) {
495 if (!((bp->b_flags & B_READ) && (secno == dr->p_nsec))){
496 /* off the deep end */
497 bp->b_flags |= B_ERROR;
498 bp->b_error = ENXIO;
499 }
500 biodone(bp);
501 return(0);
502 }
503 /* At this point, it is no longer possible to directly return from strategy.
504 We now set b_resid to the number of bytes we cannot transfer because
505 they lie beyond the end of the request's partition. This value is 0
506 if the entire request is within the partition. */
507 bytes_left = (dr->p_nsec - secno) << 9;
508 bp->b_resid = ((bp->b_bcount<=bytes_left)?0:(bp->b_bcount-bytes_left));
509 bp->b_pfcent = secno;
510 setqueue(bp, uip);
511 return(0);
512 }
513
514 /***************************************************************************
515 *
516 * set queue to buffer
517 *
518 ***************************************************************************/
519 setqueue(bp, uip)
520 struct buf *bp;
521 struct unit_info *uip;
522 {
523 spl_t x = SPL();
524 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
525 struct fdcmd *cmdp = uip->b_cmd;
526
527 openchk(cmdp); /* openning check */
528 cmdp->c_devflag |= STRCHK;
529 fd_disksort(uip, bp); /* queue the request */
530 /*
531 * If no requests are in progress, start this one up. Else
532 * leave it on the queue, and fdintr will call m765io later.
533 */
534 if(!cip->b_uip)
535 m765io(uip);
536 splx(x);
537 }
538 /***************************************************************************
539 *
540 * check io_busy routine
541 *
542 ***************************************************************************/
543 chkbusy(cmdp)
544 struct fdcmd *cmdp;
545 {
546 while(cmdp->c_devflag & STRCHK){
547 cmdp->c_devflag |= STRWAIT;
548 sleep(&cmdp->c_devflag,PZERO);
549 }
550 }
551 /***************************************************************************
552 *
553 * check fdopen() routine
554 *
555 ***************************************************************************/
556 openchk(cmdp)
557 struct fdcmd *cmdp;
558 {
559 while(cmdp->c_devflag & FDMCHK ){
560 cmdp->c_devflag |= FDWAIT;
561 sleep(&cmdp->c_devflag,PZERO);
562 }
563 }
564 /***************************************************************************
565 *
566 * free fdopen() routine
567 *
568 ***************************************************************************/
569 openfre(cmdp)
570 struct fdcmd *cmdp;
571 {
572 cmdp->c_devflag &= ~FDMCHK;
573 if(cmdp->c_devflag & FDWAIT){
574 cmdp->c_devflag &= ~FDWAIT;
575 wakeup(&cmdp->c_devflag);
576 }
577 }
578 /*****************************************************************************
579 *
580 * TITLE: m765io
581 *
582 * ABSTRACT: Start handling an I/O request.
583 *
584 ****************************************************************************/
585 m765io(uip)
586 struct unit_info *uip;
587 {
588 extern int(m765iosub)();
589 register struct buf *bp;
590 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
591
592 bp = uip->av_forw; /*move bp to ctrl_info[ctrl].b_buf*/
593 cip->b_buf = bp;
594 cip->b_uip = uip;
595 cip->b_xferaddr = bp->b_un.b_addr;
596 cip->b_xfercount = bp->b_bcount - bp->b_resid;
597 cip->b_sector = bp->b_pfcent;
598 uip->b_cmd->c_stsflag |= MTRFLAG;
599 if(!mtr_start(uip))
600 timeout(m765iosub, uip, HZ);
601 else
602 m765iosub(uip);
603 }
604 /****************************************************************************
605 *
606 * m765io subroutine
607 *
608 ****************************************************************************/
609 m765iosub(uip)
610 struct unit_info *uip;
611 {
612 struct fddrtab *dr = &uip->d_drtab;
613 int startsec;
614 int slave = uip->dev->slave;
615 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
616 struct fdcmd *cmdp = uip->b_cmd;
617
618 rwcmdset(uip);
619 if(cip->b_buf->b_flags&B_FORMAT)
620 goto skipchk;
621 startsec = (cmdp->c_rwdata[3] * dr->dr_nsec) + cmdp->c_rwdata[4];
622 if(startsec+(cip->b_xfercount>>9)-1 > dr->dr_spc)
623 cip->b_xferdma = (dr->dr_spc-startsec+1) << 9;
624 else
625 skipchk: cip->b_xferdma = cip->b_xfercount;
626 if(!(cmdp->c_rbmtr & (1<<(RBSHIFT+slave))))
627 cip->b_status = rbirate(uip);
628 else if(uip->b_seekaddr != cmdp->c_saddr)
629 cip->b_status = fdiseek(uip,cmdp->c_saddr);
630 else
631 cip->b_status = outicmd(uip);
632 if(cip->b_status)
633 intrerr0(uip);
634 return;
635 }
636 /***************************************************************************
637 *
638 * read / write / format / verify command set to command table
639 *
640 ***************************************************************************/
641 rwcmdset(uip)
642 struct unit_info *uip;
643 {
644 short resid;
645 int slave = uip->dev->slave;
646 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
647 struct fdcmd *cmdp = uip->b_cmd;
648
649 switch(cip->b_buf->b_flags&(B_FORMAT|B_VERIFY|B_READ|B_WRITE)){
650 case B_VERIFY|B_WRITE: /* VERIFY after WRITE */
651 cmdp->c_rwdata[0] = RDMV;
652 break;
653 case B_FORMAT:
654 cmdp->c_dcount = FMTCNT;
655 cmdp->c_rwdata[0] = FMTM;
656 cmdp->c_saddr = cip->b_sector / uip->d_drtab.dr_spc;
657 resid = cip->b_sector % uip->d_drtab.dr_spc;
658 cmdp->c_rwdata[1] = slave|((resid/uip->d_drtab.dr_nsec)<<2);
659 cmdp->c_rwdata[2] =
660 ((struct fmttbl *)cip->b_buf->b_un.b_addr)->s_type;
661 cmdp->c_rwdata[3] = uip->d_drtab.dr_nsec;
662 cmdp->c_rwdata[4] = uip->d_drtab.dr_fgpl;
663 cmdp->c_rwdata[5] = FMTDATA;
664 break;
665 case B_WRITE:
666 case B_READ:
667 case B_READ|B_VERIFY:
668 cmdp->c_dcount = RWCNT;
669 if(cip->b_buf->b_flags&B_READ)
670 if(cip->b_buf->b_flags&B_VERIFY)
671 cmdp->c_rwdata[0] = RDMV;
672 else
673 cmdp->c_rwdata[0] = RDM;
674 else
675 cmdp->c_rwdata[0] = WTM; /* format or write */
676 resid = cip->b_sector % uip->d_drtab.dr_spc;
677 cmdp->c_rwdata[3] = resid / uip->d_drtab.dr_nsec;
678 cmdp->c_rwdata[1] = slave|(cmdp->c_rwdata[3]<<2);
679 cmdp->c_rwdata[2] = cmdp->c_saddr =
680 cip->b_sector / uip->d_drtab.dr_spc;
681 cmdp->c_rwdata[4] = (resid % uip->d_drtab.dr_nsec) + 1;
682 cmdp->c_rwdata[5] = 2;
683 cmdp->c_rwdata[6] = uip->d_drtab.dr_nsec;
684 cmdp->c_rwdata[7] = uip->d_drtab.dr_rwgpl;
685 cmdp->c_rwdata[8] = DTL;
686 D(printf("SET %x %x C%x H%x S%x %x %x %x %x ",
687 cmdp->c_rwdata[0], cmdp->c_rwdata[1],
688 cmdp->c_rwdata[2], cmdp->c_rwdata[3],
689 cmdp->c_rwdata[4], cmdp->c_rwdata[5],
690 cmdp->c_rwdata[6], cmdp->c_rwdata[7],
691 cmdp->c_rwdata[8]));
692 break;
693 }
694 }
695 /*****************************************************************************
696 *
697 * TITLE: fdread
698 *
699 * ABSTRACT: "Raw" read. Use physio().
700 *
701 * CALLS: m765breakup (indirectly, thru physio)
702 *
703 ****************************************************************************/
704 fdread(dev, uio)
705 register dev_t dev;
706 struct uio *uio;
707 {
708 #ifdef MACH_KERNEL
709 /* no need for page-size restriction */
710 return (block_io(fdstrategy, minphys, uio));
711 #else MACH_KERNEL
712 return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_READ,fdminphys,uio));
713 #endif MACH_KERNEL
714 }
715 /*****************************************************************************
716 *
717 * TITLE: fdwrite
718 *
719 * ABSTRACT: "Raw" write. Use physio().
720 *
721 * CALLS: m765breakup (indirectly, thru physio)
722 *
723 ****************************************************************************/
724 fdwrite(dev, uio)
725 register dev_t dev;
726 struct uio *uio;
727 {
728 #ifdef MACH_KERNEL
729 /* no need for page-size restriction */
730 return (block_io(fdstrategy, minphys, uio));
731 #else MACH_KERNEL
732 return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_WRITE,fdminphys,uio));
733 #endif MACH_KERNEL
734 }
735 /*****************************************************************************
736 *
737 * TITLE: fdminphys
738 *
739 * ABSTRACT: Trim buffer length if buffer-size is bigger than page size
740 *
741 * CALLS: physio
742 *
743 ****************************************************************************/
744 fdminphys(bp)
745 struct buf *bp;
746 {
747 if (bp->b_bcount > PAGESIZ)
748 bp->b_bcount = PAGESIZ;
749 }
750 #ifdef MACH_KERNEL
751 /* IOC_OUT only and not IOC_INOUT */
752 io_return_t fdgetstat(dev, flavor, data, count)
753 dev_t dev;
754 int flavor;
755 int * data; /* pointer to OUT array */
756 unsigned int *count; /* OUT */
757 {
758 switch (flavor) {
759
760 /* Mandatory flavors */
761
762 case DEV_GET_SIZE: {
763 int ret;
764 struct disk_parms p;
765
766 ret = fd_getparms(dev, &p);
767 if (ret) return ret;
768 data[DEV_GET_SIZE_DEVICE_SIZE] = p.dp_pnumsec * NBPSCTR;
769 data[DEV_GET_SIZE_RECORD_SIZE] = NBPSCTR;
770 *count = DEV_GET_SIZE_COUNT;
771 break;
772 }
773
774 /* Extra flavors */
775
776 case V_GETPARMS:
777 if (*count < sizeof (struct disk_parms)/sizeof (int))
778 return (D_INVALID_OPERATION);
779 *count = sizeof (struct disk_parms)/sizeof(int);
780 return (fd_getparms(dev, data));
781 default:
782 return (D_INVALID_OPERATION);
783 }
784 }
785 /* IOC_VOID or IOC_IN or IOC_INOUT */
786 /*ARGSUSED*/
787 io_return_t fdsetstat(dev, flavor, data, count)
788 dev_t dev;
789 int flavor;
790 int * data;
791 unsigned int count;
792 {
793 int unit = UNIT(dev);
794 switch (flavor) {
795 case V_SETPARMS: /* Caller wants reset_parameters */
796 return(fd_setparms(unit,*(int *)data));
797 case V_FORMAT:
798 return(fd_format(dev,data));
799 case V_VERIFY: /* cmdarg : 0 == no verify, 0 != verify */
800 m765verify[unit] = *(int *)data;
801 return(D_SUCCESS);
802 default:
803 return(D_INVALID_OPERATION);
804 }
805 }
806
807 /*
808 * Get block size
809 */
810 int
811 fddevinfo(dev, flavor, info)
812 dev_t dev;
813 int flavor;
814 char *info;
815 {
816 register struct fddrtab *dr;
817 register struct fdpart *p;
818 register int result = D_SUCCESS;
819
820 switch (flavor) {
821 case D_INFO_BLOCK_SIZE:
822 dr = &unit_info[UNIT(dev)].d_drtab;
823
824 if(dr->dr_type & OKTYPE)
825 *((int *) info) = 512;
826 else
827 result = D_INVALID_OPERATION;
828
829 break;
830 default:
831 result = D_INVALID_OPERATION;
832 }
833
834 return(result);
835 }
836 #else MACH_KERNEL
837 /*****************************************************************************
838 *
839 * TITLE: fdioctl
840 *
841 * ABSTRACT: m765 driver special functions.
842 *
843 * CALLING ROUTINES: kernel
844 *
845 ****************************************************************************/
846 int
847 fdioctl(dev, cmd, cmdarg, flag)
848 dev_t dev; /* major, minor numbers */
849 int cmd; /* command code */
850 int *cmdarg; /* user structure with parameters */
851 int flag; /* not used */
852 {
853 register unsigned unit = UNIT(dev);
854 switch (cmd) {
855 case V_SETPARMS: /* Caller wants reset_parameters */
856 return(fd_setparms(unit,*cmdarg));
857 case V_GETPARMS: /* Caller wants device parameters */
858 return(fd_getparms(dev,cmdarg));
859 case V_FORMAT:
860 return(fd_format(dev,cmdarg));
861 case V_VERIFY: /* cmdarg : 0 == no verify, 0 != verify */
862 m765verify[unit] = *cmdarg;
863 return(0);
864 }
865 return(EINVAL);
866 }
867 #endif MACH_KERNEL
868 /****************************************************************************
869 *
870 * set fd parameters
871 *
872 ****************************************************************************/
873 int
874 fd_setparms(unit, cmdarg)
875 register unsigned int unit;
876 long cmdarg;
877 {
878 struct fddrtab *fdparm;
879 spl_t x;
880 struct unit_info *uip = &unit_info[unit];
881 struct fdcmd *cmdp = uip->b_cmd;
882
883 cmdp->c_rbmtr &= ~(1<<(RBSHIFT+uip->dev->slave));
884 if ((fdparm = getparm(MEDIATYPE(cmdarg))) == (struct fddrtab *)ERROR)
885 return(EINVAL);
886 x = SPL();
887 openchk(cmdp);
888 cmdp->c_devflag |= FDMCHK;
889 chkbusy(cmdp);
890 m765sweep(uip, fdparm);
891 uip->d_drtab.dr_type |= OKTYPE;
892 openfre(cmdp);
893 splx(x);
894 return(0);
895 }
896 /****************************************************************************
897 *
898 * get fd parameters
899 *
900 ****************************************************************************/
901 int
902 fd_getparms(dev,cmdarg)
903 dev_t dev; /* major, minor numbers */
904 int *cmdarg;
905 {
906 struct disk_parms *diskp = (struct disk_parms *)cmdarg;
907 register struct fddrtab *dr = &unit_info[UNIT(dev)].d_drtab;
908
909 if(dr->dr_type & OKTYPE){
910 diskp->dp_type = DPT_FLOPPY;
911 diskp->dp_heads = 2;
912 diskp->dp_sectors = dr->dr_nsec;
913 diskp->dp_pstartsec = 0;
914 diskp->dp_cyls = dr->dr_ncyl;
915 diskp->dp_pnumsec = dr->p_nsec;
916 return(0);
917 }
918 return(ENXIO);
919 }
920 /****************************************************************************
921 *
922 * format command
923 *
924 ****************************************************************************/
925 fd_format(dev,cmdarg)
926 dev_t dev; /* major, minor numbers */
927 int *cmdarg;
928
929 {
930 register struct buf *bp;
931 register daddr_t track;
932 union io_arg *varg;
933 u_short num_trks;
934 register struct fddrtab *dr = &unit_info[UNIT(dev)].d_drtab;
935
936 if(!(dr->dr_type & OKTYPE))
937 return(EINVAL);
938 varg = (union io_arg *)cmdarg;
939 num_trks = varg->ia_fmt.num_trks;
940 track = (daddr_t)(varg->ia_fmt.start_trk*dr->dr_nsec);
941 if((track + (num_trks*dr->dr_nsec))>dr->p_nsec)
942 return(EINVAL);
943 bp = geteblk(BLKSIZE); /* get struct buf area */
944 while (num_trks>0) {
945 bp->b_flags &= ~B_DONE;
946 bp->b_dev = dev;
947 bp->b_error = 0; bp->b_resid = 0;
948 bp->b_flags = B_FORMAT;
949 bp->b_bcount = dr->dr_nsec * FMTID;
950 bp->b_blkno = (daddr_t)((track << 9) / NBPSCTR);
951 if(makeidtbl(bp->b_un.b_addr,dr,
952 varg->ia_fmt.start_trk++,varg->ia_fmt.intlv))
953 return(EINVAL);
954 fdstrategy(bp);
955 biowait(bp);
956 if(bp->b_error)
957 if((bp->b_error == (char)EBBHARD) ||
958 (bp->b_error == (char)EBBSOFT))
959 return(EIO);
960 else
961 return(bp->b_error);
962 num_trks--;
963 track += dr->dr_nsec;
964 }
965 brelse(bp);
966 return(0);
967 }
968 /****************************************************************************
969 *
970 * make id table for format
971 *
972 ****************************************************************************/
973 makeidtbl(tblpt,dr,track,intlv)
974 struct fmttbl *tblpt;
975 struct fddrtab *dr;
976 unsigned short track;
977 unsigned short intlv;
978 {
979 register int i,j,secno;
980
981 if(intlv >= dr->dr_nsec)
982 return(1);
983 for(i=0; i<dr->dr_nsec; i++)
984 tblpt[i].sector = 0;
985 for(i=0,j=0,secno=1; i<dr->dr_nsec; i++){
986 tblpt[j].cyl = track >> 1;
987 tblpt[j].head = track & 1;
988 tblpt[j].sector = secno++;
989 tblpt[j].s_type = 2;
990 if((j+=intlv) < dr->dr_nsec)
991 continue;
992 for(j-=dr->dr_nsec; j < dr->dr_nsec ; j++)
993 if(!tblpt[j].sector)
994 break;
995 }
996 return(0);
997 }
998 /*****************************************************************************
999 *
1000 * TITLE: fdintr
1001 *
1002 * ABSTRACT: Handle interrupt.
1003 *
1004 * Interrupt procedure for m765 driver. Gets status of last
1005 * operation and performs service function according to the
1006 * type of interrupt. If it was an operation complete interrupt,
1007 * switches on the current driver state and either declares the
1008 * operation done, or starts the next operation
1009 *
1010 ****************************************************************************/
1011 fdintr(ctrl)
1012 int ctrl;
1013 {
1014 extern int(m765intrsub)();
1015 struct unit_info *uip = ctrl_info[ctrl].b_uip;
1016 struct unit_info *wup = ctrl_info[ctrl].b_wup;
1017 struct fdcmd *cmdp = &ctrl_info[ctrl].b_cmd;
1018 if(cmdp->c_stsflag & INTROUT)
1019 untimeout(fdintr, ctrl);
1020 cmdp->c_stsflag &= ~INTROUT;
1021 switch(cmdp->c_intr){
1022 case RWFLAG:
1023 rwintr(uip);
1024 break;
1025 case SKFLAG:
1026 case SKEFLAG|SKFLAG:
1027 case RBFLAG:
1028 timeout(m765intrsub, uip, SEEKWAIT);
1029 break;
1030 case WUPFLAG:
1031 cmdp->c_intr &= ~WUPFLAG;
1032 wakeup(wup);
1033 }
1034 return(0);
1035 }
1036 /*****************************************************************************
1037 *
1038 * interrup subroutine (seek recalibrate)
1039 *
1040 *****************************************************************************/
1041 m765intrsub(uip)
1042 struct unit_info *uip;
1043 {
1044 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1045
1046 if((cip->b_status = sis(uip))!= ST0OK)
1047 switch(uip->b_cmd->c_intr){
1048 case SKFLAG:
1049 seekintr(uip);
1050 break;
1051 case SKEFLAG|SKFLAG:
1052 seekintre(uip);
1053 break;
1054 case RBFLAG:
1055 rbintr(uip);
1056 }
1057 }
1058 /*****************************************************************************
1059 *
1060 * read / write / format / verify interrupt routine
1061 *
1062 *****************************************************************************/
1063 rwintr(uip)
1064 struct unit_info *uip;
1065 {
1066 int rsult[7];
1067 register int rtn, count;
1068 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1069 struct fdcmd *cmdp = uip->b_cmd;
1070
1071 cmdp->c_intr &= ~RWFLAG;
1072 if((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY))
1073 if(inb(VFOREG(uip->addr))&OPENBIT){
1074 if(cip->b_buf->b_flags&B_FORMAT){
1075 cip->b_status = TIMEOUT;
1076 intrerr0(uip);
1077 } else {
1078 if((inb(STSREG(uip->addr))&ST0OK)!=ST0OK)
1079 printf("%s %d : %s\n",
1080 fderr,
1081 uip-unit_info,
1082 fdmsg[DOORERR]);
1083 rstout(uip);
1084 specify(uip);
1085 cmdp->c_rbmtr &= RBRST;
1086 cmdp->c_intr |= SKEFLAG;
1087 if(cmdp->c_saddr > 2)
1088 fdiseek(uip, cmdp->c_saddr-2);
1089 else
1090 fdiseek(uip, cmdp->c_saddr+2);
1091 }
1092 return;
1093 }
1094 for( count = 0 ; count < 7 ; count++ ){
1095 if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */
1096 goto rwend;
1097 rsult[count] = inb(DATAREG(uip->addr));
1098 }
1099 rtn = 0;
1100 if(rsult[0]&0xc0){
1101 rtn = cmdp->c_rwdata[0]<<8;
1102 if(rsult[0]&0x80){ rtn |= FDCERR; goto rwend; }
1103 if(rsult[1]&0x80){ rtn |= NOREC; goto rwend; }
1104 if(rsult[1]&0x20){ rtn |= CRCERR; goto rwend; }
1105 if(rsult[1]&0x10){ rtn |= OVERRUN; goto rwend; }
1106 if(rsult[1]&0x04){ rtn |= NOREC; goto rwend; }
1107 if(rsult[1]&0x02){ rtn |= WTPRT; goto rwend; }
1108 if(rsult[1]&0x01){ rtn |= ADDRERR; goto rwend; }
1109 rtn |= FDCERR;
1110 rwend: outb(0x0a, 0x06);
1111 }
1112 if(cip->b_status = rtn) {
1113 D(printf("\n->rwierr %x ", rtn));
1114 rwierr(uip);
1115 } else { /* write command */
1116 if(((cip->b_buf->b_flags&(B_FORMAT|B_READ|B_WRITE))==B_WRITE)
1117 && !(cip->b_buf->b_flags & B_VERIFY)) {
1118 D(printf("->w/v "));
1119 cip->b_buf->b_flags |= B_VERIFY;
1120 rwcmdset(uip);
1121 if(cip->b_status = outicmd(uip))
1122 intrerr0(uip);
1123 return;
1124 }
1125 /* clear retry count */
1126 cip->b_buf->b_flags &= ~B_VERIFY;
1127 cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
1128 cip->b_xfercount -= cip->b_xferdma;
1129 cip->b_xferaddr += cip->b_xferdma;
1130 cip->b_sector = cip->b_sector+(cip->b_xferdma>>9);
1131 D(printf("->done%s\n", cip->b_xfercount?"":"." ));
1132 /* next address (cyl,head,sec) */
1133 if((int)cip->b_xfercount>0)
1134 m765iosub(uip);
1135 else
1136 quechk(uip);
1137 }
1138 }
1139 /*****************************************************************************
1140 *
1141 * read / write / format / verify error routine
1142 *
1143 *****************************************************************************/
1144 rwierr(uip)
1145 struct unit_info *uip;
1146 {
1147 short status;
1148 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1149 struct fdcmd *cmdp = uip->b_cmd;
1150
1151 D(printf("%x-%x-%x ", cip->b_rwerr&SRMASK, cip->b_rwerr&MRMASK, cip->b_rwerr&LRMASK));
1152 if((cip->b_buf->b_flags&(B_READ|B_VERIFY))==(B_READ|B_VERIFY)){
1153 if((cip->b_rwerr&SRMASK)<MEDIARD)
1154 goto rwrtry;
1155 if((cip->b_rwerr&MRMASK)<MEDIASEEK)
1156 goto rwseek;
1157 goto rwexit;
1158 } else
1159 if(cip->b_buf->b_flags&B_VERIFY){
1160 cip->b_buf->b_flags &= ~B_VERIFY;
1161 rwcmdset(uip);
1162 }
1163 rwrtry: status = cip->b_status;
1164 if((++cip->b_rwerr&SRMASK)<SRETRY)
1165 cip->b_status = outicmd(uip);
1166 else {
1167 rwseek: cip->b_rwerr = (cip->b_rwerr&RMRMASK)+MINC;
1168 if((cip->b_rwerr&MRMASK)<MRETRY){
1169 cmdp->c_intr |= SKEFLAG;
1170 if(cmdp->c_saddr > 2)
1171 cip->b_status=fdiseek(uip,cmdp->c_saddr-2);
1172 else
1173 cip->b_status=fdiseek(uip,cmdp->c_saddr+2);
1174 } else {
1175 cip->b_rwerr = (cip->b_rwerr&LRMASK)+LINC;
1176 if((cip->b_rwerr&LRMASK)<LRETRY)
1177 cip->b_status=rbirate(uip);
1178 }
1179 }
1180 if(cip->b_status){
1181 D(printf("ERR->intrerr0 "));
1182 cip->b_status = status;
1183 rwexit: intrerr0(uip);
1184 }
1185 }
1186 /*****************************************************************************
1187 *
1188 * recalibrate interrupt routine
1189 *
1190 *****************************************************************************/
1191 rbintr(uip)
1192 struct unit_info *uip;
1193 {
1194 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1195 struct fdcmd *cmdp = uip->b_cmd;
1196
1197 cmdp->c_intr &= ~RBFLAG;
1198 if(cip->b_status) {
1199 if(++cip->b_rberr<SRETRY)
1200 cip->b_status = rbirate(uip);
1201 } else {
1202 cmdp->c_rbmtr |= 1<<(RBSHIFT+uip->dev->slave);
1203 uip->b_seekaddr = 0;
1204 cip->b_rberr = 0;
1205 cip->b_status=fdiseek(uip, cmdp->c_saddr);
1206 }
1207 if(cip->b_status)
1208 intrerr0(uip);
1209 }
1210 /******************************************************************************
1211 *
1212 * seek interrupt routine
1213 *
1214 *****************************************************************************/
1215 seekintr(uip)
1216 struct unit_info *uip;
1217 {
1218 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1219 struct fdcmd *cmdp = uip->b_cmd;
1220
1221 cmdp->c_intr &= ~SKFLAG;
1222 if(cip->b_status)
1223 seekierr(uip, cmdp->c_saddr);
1224 else {
1225 uip->b_seekaddr = cmdp->c_saddr;
1226 cip->b_status = outicmd(uip);
1227 }
1228 if(cip->b_status)
1229 intrerr0(uip);
1230 else
1231 cip->b_seekerr = 0;
1232 }
1233 /*****************************************************************************
1234 *
1235 * seek error retry interrupt routine
1236 *
1237 *****************************************************************************/
1238 seekintre(uip)
1239 struct unit_info *uip;
1240 {
1241 register char seekpoint;
1242 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1243 struct fdcmd *cmdp = uip->b_cmd;
1244
1245 cmdp->c_intr &= ~(SKEFLAG|SKFLAG);
1246 if(cmdp->c_saddr > 2)
1247 seekpoint = cmdp->c_saddr-2;
1248 else
1249 seekpoint = cmdp->c_saddr+2;
1250 if(cip->b_status)
1251 seekierr(uip, seekpoint);
1252 else {
1253 uip->b_seekaddr = seekpoint;
1254 cip->b_status = fdiseek(uip, cmdp->c_saddr);
1255 }
1256 if(cip->b_status)
1257 intrerr0(uip);
1258 else
1259 cip->b_seekerr = 0;
1260 }
1261 /*****************************************************************************
1262 *
1263 * seek error routine
1264 *
1265 *****************************************************************************/
1266 seekierr(uip, seekpoint)
1267 struct unit_info *uip;
1268 register char seekpoint;
1269 {
1270 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1271
1272 if((++cip->b_seekerr&SRMASK)<SRETRY)
1273 cip->b_status=fdiseek(uip, seekpoint);
1274 else {
1275 cip->b_seekerr = (cip->b_seekerr&MRMASK) + MINC;
1276 if((cip->b_seekerr&MRMASK)<MRETRY)
1277 cip->b_status=rbirate(uip);
1278 }
1279 if(cip->b_status)
1280 intrerr0(uip);
1281 }
1282 /*****************************************************************************
1283 *
1284 * TITLE: m765sweep
1285 *
1286 * ABSTRACT: Perform an initialization sweep.
1287 *
1288 **************************************************************************/
1289 m765sweep(uip, cdr)
1290 struct unit_info *uip;
1291 register struct fddrtab *cdr; /* device initialization data */
1292 {
1293 register struct fddrtab *dr = &uip->d_drtab;
1294
1295 dr->dr_ncyl = cdr->dr_ncyl;
1296 dr->dr_nsec = cdr->dr_nsec;
1297 dr->dr_spc = cdr->dr_spc;
1298 dr->p_nsec = cdr->p_nsec;
1299 dr->dr_type = cdr->dr_type;
1300 dr->dr_rwgpl= cdr->dr_rwgpl;
1301 dr->dr_fgpl = cdr->dr_fgpl;
1302 }
1303 /*****************************************************************************
1304 *
1305 * TITLE: m765disksort
1306 *
1307 *****************************************************************************/
1308 fd_disksort(uip, bp)
1309 struct unit_info *uip; /* Pointer to head of active queue */
1310 register struct buf *bp; /* Pointer to buffer to be inserted */
1311 {
1312 register struct buf *bp2; /* Pointer to next buffer in queue */
1313 register struct buf *bp1; /* Pointer where to insert buffer */
1314
1315 if (!(bp1 = uip->av_forw)) {
1316 /* No other buffers to compare against */
1317 uip->av_forw = bp;
1318 bp->av_forw = 0;
1319 return;
1320 }
1321 bp2 = bp1->av_forw;
1322 while(bp2 && (relative(bp1->b_pfcent,bp->b_pfcent) >=
1323 relative(bp1->b_pfcent,bp2->b_pfcent))) {
1324 bp1 = bp2;
1325 bp2 = bp1->av_forw;
1326 }
1327 bp1->av_forw = bp;
1328 bp->av_forw = bp2;
1329 }
1330 /*****************************************************************************
1331 *
1332 * Set Interrupt error and FDC reset
1333 *
1334 *****************************************************************************/
1335 intrerr0(uip)
1336 struct unit_info *uip;
1337 {
1338 struct buf *bp; /* Pointer to next buffer in queue */
1339 int resid;
1340 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1341 struct fdcmd *cmdp = uip->b_cmd;
1342 register struct fddrtab *dr = &uip->d_drtab;
1343
1344 if((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY)){
1345 resid = cip->b_xfercount = cip->b_xferdma-1-inb(DMACNT)*0x101;
1346 resid = (cip->b_sector + (resid>>9)) % dr->dr_spc;
1347 printf("%s %d : %s\n",
1348 fderr,
1349 uip->dev->slave,
1350 fdmsg[cip->b_status&BYTEMASK]);
1351 printf("cylinder = %d ",cmdp->c_saddr);
1352 printf("head = %d sector = %d byte/sec = %d\n",
1353 resid / dr->dr_nsec , (resid % dr->dr_nsec)+1 , 512);
1354 }
1355 cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
1356 cmdp->c_intr = CMDRST;
1357 if(((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY)) &&
1358 uip->dev->slave)
1359 dr->dr_type &= ~OKTYPE;
1360 bp = cip->b_buf;
1361 bp->b_flags |= B_ERROR;
1362 switch(cip->b_status&BYTEMASK){
1363 case ADDRERR:
1364 case OVERRUN:
1365 case FDCERR:
1366 case TIMEOUT:
1367 bp->b_error = EIO;
1368 break;
1369 case WTPRT:
1370 #ifdef MACH_KERNEL
1371 bp->b_error = ENXIO;
1372 #else
1373 bp->b_error = ENODEV;
1374 #endif
1375 break;
1376 case NOREC:
1377 bp->b_error = EBBHARD;
1378 break;
1379 case CRCERR:
1380 bp->b_error = EBBSOFT;
1381 }
1382 rstout(uip);
1383 specify(uip);
1384 cmdp->c_rbmtr &= RBRST;
1385 quechk(uip);
1386 }
1387 /*****************************************************************************
1388 *
1389 * Next queue check routine
1390 *
1391 *****************************************************************************/
1392 quechk(uip)
1393 struct unit_info *uip;
1394 {
1395 register struct buf *bp = uip->av_forw;
1396 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1397 struct unit_info *loop;
1398 struct fdcmd *cmdp = uip->b_cmd;
1399 /* clear retry count */
1400 cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0;
1401 bp->b_resid = bp->b_resid + cip->b_xfercount;
1402 uip->av_forw=bp->av_forw;
1403 if (!uip->av_forw && uip->wakeme) {
1404 uip->wakeme = 0;
1405 wakeup(uip);
1406 }
1407 biodone(bp);
1408 loop = uip;
1409 do {
1410 loop=loop->b_unitf;
1411 if (loop->av_forw) {
1412 m765io(loop);
1413 return;
1414 }
1415 } while (loop!=uip);
1416 cip->b_uip = 0;
1417 cmdp->c_stsflag &= ~MTRFLAG;
1418 mtr_on(uip);
1419 cmdp->c_devflag &= ~STRCHK;
1420 if(cmdp->c_devflag & STRWAIT){
1421 cmdp->c_devflag &= ~STRWAIT;
1422 wakeup(&cmdp->c_devflag);
1423 }
1424 }
1425 fdprint(dev,str)
1426 dev_t dev;
1427 char *str;
1428 {
1429 printf("floppy disk driver: %s on bad dev %d, partition %d\n",
1430 str, UNIT(dev), 0);
1431 }
1432 fdsize()
1433 {
1434 printf("fdsize() -- not implemented\n");
1435 }
1436 fddump()
1437 {
1438 printf("fddump() -- not implemented\n");
1439 }
1440 /*****************************************************************************
1441 *
1442 * fdc reset routine
1443 *
1444 *****************************************************************************/
1445 rstout(uip)
1446 struct unit_info *uip;
1447 {
1448 register int outd;
1449
1450 outd = ((uip->b_cmd->c_rbmtr&MTRMASK)<<MTR_ON)|uip->dev->slave;
1451 outb(CTRLREG(uip->addr), outd);
1452 outd |= FDC_RST;
1453 outb(CTRLREG(uip->addr), outd);
1454 outd |= DMAREQ;
1455 outb(CTRLREG(uip->addr), outd);
1456 }
1457 /*****************************************************************************
1458 *
1459 * specify command routine
1460 *
1461 *****************************************************************************/
1462 specify(uip)
1463 struct unit_info *uip;
1464 {
1465 /* status check */
1466 if(fdc_sts(FD_OSTS, uip))
1467 return;
1468 /* Specify command */
1469 outb(DATAREG(uip->addr), SPCCMD);
1470 /* status check */
1471 if(fdc_sts(FD_OSTS, uip))
1472 return;
1473 /* Step rate,Head unload time */
1474 outb(DATAREG(uip->addr), SRTHUT);
1475 /* status check */
1476 if(fdc_sts(FD_OSTS, uip))
1477 return;
1478 /* Head load time,Non DMA Mode*/
1479 outb(DATAREG(uip->addr), HLTND);
1480 return;
1481 }
1482 /****************************************************************************
1483 *
1484 * recalibrate command routine
1485 *
1486 ****************************************************************************/
1487 rbrate(mtype,uip)
1488 char mtype;
1489 struct unit_info *uip;
1490 {
1491 register int rtn = 1, rty_flg=2;
1492 spl_t x;
1493 struct fdcmd *cmdp = uip->b_cmd;
1494
1495 rbskrate(uip, mtype); /* set transfer rate */
1496 while((rty_flg--)&&rtn){
1497 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
1498 break;
1499 /*recalibrate command*/
1500 outb(DATAREG(uip->addr), RBCMD);
1501 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
1502 break;
1503 /* Device to wake up specified in open */
1504 cmdp->c_intr |= WUPFLAG;
1505 x = SPL();
1506 outb(DATAREG(uip->addr), uip->dev->slave);
1507 rtn = ERROR;
1508 while(rtn) {
1509 uip->wakeme = 1;
1510 sleep(uip, PZERO);
1511 if((rtn = sis(uip)) == ST0OK)
1512 /* Device to wake up specified in open */
1513 cmdp->c_intr |= WUPFLAG;
1514 else
1515 break;
1516 }
1517 splx(x);
1518 }
1519 return(rtn);
1520 }
1521 /*****************************************************************************
1522 *
1523 * seek command routine
1524 *
1525 ****************************************************************************/
1526 fdseek(mtype, uip, cylno)
1527 register char mtype;
1528 struct unit_info *uip;
1529 register int cylno;
1530 {
1531 spl_t x;
1532 int rtn;
1533 struct fdcmd *cmdp = uip->b_cmd;
1534
1535 rbskrate(uip, mtype);
1536 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
1537 return(rtn);
1538 outb(DATAREG(uip->addr), SEEKCMD); /* seek command */
1539 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
1540 return(rtn);
1541 outb(DATAREG(uip->addr), uip->dev->slave); /* drive number */
1542 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
1543 return(rtn);
1544 x = SPL();
1545 /* Device to wake up specified in open */
1546 cmdp->c_intr |= WUPFLAG;
1547 outb(DATAREG(uip->addr), cylno); /* seek count */
1548 rtn = ERROR;
1549 while(rtn){
1550 uip->wakeme = 1;
1551 sleep(uip, PZERO);
1552 if((rtn = sis(uip)) == ST0OK)
1553 /* Device to wake up specified in open */
1554 cmdp->c_intr |= WUPFLAG;
1555 else
1556 break;
1557 }
1558 splx(x);
1559 return(rtn);
1560 }
1561 /*****************************************************************************
1562 *
1563 * seek commnd routine(use interrupt)
1564 *
1565 *****************************************************************************/
1566 fdiseek(uip, cylno)
1567 struct unit_info *uip;
1568 int cylno;
1569 {
1570 register int rtn;
1571
1572 D(printf("SK %x ", cylno));
1573 rbskrate(uip, uip->d_drtab.dr_type);/* set transfer rate */
1574 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
1575 goto fdiend;
1576 outb(DATAREG(uip->addr), SEEKCMD); /* seek command */
1577 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
1578 goto fdiend;
1579 outb(DATAREG(uip->addr), uip->dev->slave); /* drive number */
1580 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
1581 goto fdiend;
1582 uip->b_seekaddr = cylno;
1583 if(uip->d_drtab.dr_type&DOUBLE)
1584 cylno = cylno * 2;
1585 uip->b_cmd->c_intr |= SKFLAG;
1586 outb(DATAREG(uip->addr), cylno); /* seek count */
1587 fdiend:
1588 if(rtn)
1589 rtn |= SEEKCMD<<8;
1590 return(rtn);
1591 }
1592 /*****************************************************************************
1593 *
1594 * recalibrate command routine(use interrupt)
1595 *
1596 *****************************************************************************/
1597 rbirate(uip)
1598 struct unit_info *uip;
1599 {
1600 register int rtn;
1601
1602 rbskrate(uip, uip->d_drtab.dr_type);/* set transfer rate */
1603 if(!(rtn = fdc_sts(FD_OSTS, uip))) { /* status check */
1604 /* recalibrate command */
1605 outb(DATAREG(uip->addr), RBCMD);
1606 if(!(rtn = fdc_sts(FD_OSTS, uip))) { /* status check */
1607 uip->b_cmd->c_intr |= RBFLAG;
1608 outb(DATAREG(uip->addr), uip->dev->slave);
1609 }
1610 }
1611 return(rtn ? rtn|RBCMD<<8 : 0);
1612 }
1613 /*****************************************************************************
1614 *
1615 * read / write / format / verify command out routine(use interrupt)
1616 *
1617 *****************************************************************************/
1618 outicmd(uip)
1619 struct unit_info *uip;
1620 {
1621 int rtn;
1622 register int *data,cnt0,dmalen;
1623 register long address;
1624 struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr];
1625 struct fdcmd *cmdp = uip->b_cmd;
1626 spl_t x = splhi();
1627
1628 outb(DMACMD1,DMADATA0); /* DMA #1 command register */
1629 outb(DMAMSK1,DMADATA1); /* DMA #1 all mask register */
1630 /* Perhaps outb(0x0a,0x02); might work better on line above? */
1631 switch(cmdp->c_rwdata[0]){
1632 case RDM:
1633 D(printf("RDM"));
1634 outb(DMABPFF,DMARD);
1635 outb(DMAMODE,DMARD);
1636 break;
1637 case WTM:
1638 case FMTM:
1639 D(printf("W"));
1640 outb(DMABPFF,DMAWT);
1641 outb(DMAMODE,DMAWT);
1642 break;
1643 case RDMV:
1644 D(printf("RDMV"));
1645 outb(DMABPFF,DMAVRF);
1646 outb(DMAMODE,DMAVRF);
1647 }
1648 /* get work buffer physical address */
1649 address = kvtophys(cip->b_xferaddr);
1650 dmalen = i386_trunc_page(address) + I386_PGBYTES - address;
1651 if ( (cip->b_rwerr&MRMASK) >= 0x10)
1652 dmalen = 0x200;
1653 if (dmalen<=cip->b_xferdma)
1654 cip->b_xferdma = dmalen;
1655 else
1656 dmalen = cip->b_xferdma;
1657 D(printf(" %x L%x ", address, dmalen));
1658 /* set buffer address */
1659 outb(DMAADDR,(int)address&BYTEMASK);
1660 outb(DMAADDR,(((int)address>>8)&BYTEMASK));
1661 outb(DMAPAGE,(((int)address>>16)&BYTEMASK));
1662 /* set transfer count */
1663 outb(DMACNT,(--dmalen)&BYTEMASK);
1664 outb(DMACNT,((dmalen>>8)&BYTEMASK));
1665 outb(DMAMSK,CHANNEL2);
1666 splx(x);
1667 trfrate(uip, uip->d_drtab.dr_type); /* set transfer rate */
1668 data = &cmdp->c_rwdata[0];
1669 for(cnt0 = 0; cnt0<cmdp->c_dcount; cnt0++,data++){
1670 if(rtn = fdc_sts(FD_OSTS, uip)) /*status check*/
1671 break;
1672 outb(DATAREG(uip->addr), *data);
1673 }
1674 if(!rtn){
1675 cmdp->c_intr |= RWFLAG;
1676 cmdp->c_stsflag |= INTROUT;
1677 cnt0 = ((cip->b_buf->b_flags&(B_READ|B_VERIFY)) ==
1678 (B_READ|B_VERIFY))?TOUT:ITOUT;
1679 #ifdef MACH_KERNEL
1680 timeout(fdintr,uip->dev->ctlr,cnt0);
1681 #else MACH_KERNEL
1682 cmdp->c_timeid = timeout(fdintr,uip->dev->ctlr,cnt0);
1683 #endif MACH_KERNEL
1684 }
1685 return(rtn);
1686 }
1687 /*****************************************************************************
1688 *
1689 * sense interrupt status routine
1690 *
1691 *****************************************************************************/
1692 sis(uip)
1693 struct unit_info *uip;
1694 {
1695 register int rtn, st0;
1696
1697 if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */
1698 return(rtn);
1699 outb(DATAREG(uip->addr), SISCMD);
1700 if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */
1701 return(rtn);
1702 st0 = inb(DATAREG(uip->addr)) & ST0OK; /* get st0 */
1703 if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */
1704 return(rtn);
1705 inb(DATAREG(uip->addr)); /* get pcn */
1706 if (st0&(ST0AT|ST0IC))
1707 st0 = FDCERR;
1708 return(st0);
1709 }
1710
1711 /*****************************************************************************
1712 *
1713 * fdc status get routine
1714 *
1715 *****************************************************************************/
1716 fdc_sts(mode, uip)
1717 register int mode;
1718 struct unit_info *uip;
1719 {
1720 register int ind;
1721 int cnt0 = STSCHKCNT;
1722
1723 while(cnt0--)
1724 if(((ind=inb(STSREG(uip->addr))) & DATAOK) &&
1725 ((ind & DTOCPU) == mode))
1726 return(0);
1727 return(TIMEOUT);
1728 }
1729 /*****************************************************************************
1730 *
1731 * motor on routine
1732 *
1733 *****************************************************************************/
1734 mtr_on(uip)
1735 struct unit_info *uip;
1736 {
1737 extern int(mtr_off)();
1738 extern int(wakeup)();
1739 struct fdcmd *cmdp = uip->b_cmd;
1740
1741 if(!(mtr_start(uip))){
1742 timeout(wakeup,&cmdp->c_stsflag,HZ);
1743 sleep(&cmdp->c_stsflag,PZERO);
1744 }
1745 cmdp->c_stsflag |= MTROFF;
1746 #ifdef MACH_KERNEL
1747 timeout(mtr_off,uip,MTRSTOP);
1748 #else MACH_KERNEL
1749 cmdp->c_mtrid = timeout(mtr_off,uip,MTRSTOP);
1750 #endif MACH_KERNEL
1751 }
1752 /*****************************************************************************
1753 *
1754 * motor start routine
1755 *
1756 *****************************************************************************/
1757 mtr_start(uip)
1758 struct unit_info *uip;
1759 {
1760 int status;
1761 int (mtr_off)();
1762 struct fdcmd *cmdp = uip->b_cmd;
1763 int slave = uip->dev->slave;
1764 if(cmdp->c_stsflag & MTROFF){
1765 untimeout(mtr_off, uip);
1766 cmdp->c_stsflag &= ~MTROFF;
1767 }
1768 status = cmdp->c_rbmtr&(1<<slave);
1769 cmdp->c_rbmtr |= (1<<slave);
1770 outb(CTRLREG(uip->addr), ((cmdp->c_rbmtr&MTRMASK)<<MTR_ON)|
1771 FDC_RST|slave|DMAREQ);
1772 return(status);
1773 }
1774 /*****************************************************************************
1775 *
1776 * motor off routine
1777 *
1778 *****************************************************************************/
1779 mtr_off(uip)
1780 struct unit_info *uip;
1781 {
1782 struct fdcmd *cmdp = uip->b_cmd;
1783
1784 cmdp->c_stsflag &= ~MTROFF;
1785 if(!(cmdp->c_stsflag&MTRFLAG)){
1786 cmdp->c_rbmtr &= MTRRST;
1787 outb(CTRLREG(uip->addr), FDC_RST | DMAREQ);
1788 }
1789 }
Cache object: 214082c134c1d366246d1d8f9007c746
|