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