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