Annotation of src/sys/arch/atari/dev/fd.c, Revision 1.46.2.5
1.46.2.5! skrll 1: /* $NetBSD: fd.c,v 1.46.2.4 2004/11/02 07:50:22 skrll Exp $ */
1.1 leo 2:
3: /*
4: * Copyright (c) 1995 Leo Weppelman.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Leo Weppelman.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: /*
34: * This file contains a driver for the Floppy Disk Controller (FDC)
35: * on the Atari TT. It uses the WD 1772 chip, modified for steprates.
36: *
37: * The ST floppy disk controller shares the access to the DMA circuitry
38: * with other devices. For this reason the floppy disk controller makes
39: * use of some special DMA accessing code.
40: *
41: * Interrupts from the FDC are in fact DMA interrupts which get their
42: * first level handling in 'dma.c' . If the floppy driver is currently
43: * using DMA the interrupt is signalled to 'fdcint'.
44: *
45: * TODO:
46: * - Test it with 2 drives (I don't have them)
47: * - Test it with an HD-drive (Don't have that either)
48: * - Finish ioctl's
49: */
50:
1.46.2.1 skrll 51: #include <sys/cdefs.h>
1.46.2.5! skrll 52: __KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.46.2.4 2004/11/02 07:50:22 skrll Exp $");
1.46.2.1 skrll 53:
1.14 mycroft 54: #include <sys/param.h>
55: #include <sys/systm.h>
1.35 thorpej 56: #include <sys/callout.h>
1.14 mycroft 57: #include <sys/kernel.h>
58: #include <sys/malloc.h>
59: #include <sys/buf.h>
1.46.2.4 skrll 60: #include <sys/bufq.h>
1.15 leo 61: #include <sys/proc.h>
1.14 mycroft 62: #include <sys/device.h>
63: #include <sys/ioctl.h>
64: #include <sys/fcntl.h>
65: #include <sys/conf.h>
66: #include <sys/disklabel.h>
67: #include <sys/disk.h>
68: #include <sys/dkbad.h>
69: #include <atari/atari/device.h>
1.19 leo 70: #include <atari/atari/stalloc.h>
1.14 mycroft 71: #include <machine/disklabel.h>
72: #include <machine/iomap.h>
73: #include <machine/mfp.h>
74: #include <machine/dma.h>
75: #include <machine/video.h>
1.20 leo 76: #include <machine/cpu.h>
1.18 leo 77: #include <atari/dev/ym2149reg.h>
1.14 mycroft 78: #include <atari/dev/fdreg.h>
1.1 leo 79:
80: /*
81: * Be verbose for debugging
82: */
1.4 leo 83: /*#define FLP_DEBUG 1 */
1.1 leo 84:
85: #define FDC_MAX_DMA_AD 0x1000000 /* No DMA possible beyond */
86:
87: /* Parameters for the disk drive. */
88: #define SECTOR_SIZE 512 /* physical sector size in bytes */
89: #define NR_DRIVES 2 /* maximum number of drives */
90: #define NR_TYPES 3 /* number of diskette/drive combinations*/
91: #define MAX_ERRORS 10 /* how often to try rd/wt before quitting*/
92: #define STEP_DELAY 6000 /* 6ms (6000us) delay after stepping */
93:
94:
95: #define INV_TRK 32000 /* Should fit in unsigned short */
96: #define INV_PART NR_TYPES
97:
98: /*
99: * Driver states
100: */
101: #define FLP_IDLE 0x00 /* floppy is idle */
102: #define FLP_MON 0x01 /* idle with motor on */
103: #define FLP_STAT 0x02 /* determine floppy status */
104: #define FLP_XFER 0x04 /* read/write data from floppy */
105:
106: /*
107: * Timer delay's
108: */
109: #define FLP_MONDELAY (3 * hz) /* motor-on delay */
110: #define FLP_XFERDELAY (2 * hz) /* timeout on transfer */
111:
1.8 leo 112: /*
113: * The density codes
114: */
115: #define FLP_DD 0 /* Double density */
116: #define FLP_HD 1 /* High density */
117:
1.1 leo 118:
119: #define b_block b_resid /* FIXME: this is not the place */
120:
121: /*
122: * Global data for all physical floppy devices
123: */
124: static short selected = 0; /* drive/head currently selected*/
125: static short motoron = 0; /* motor is spinning */
126: static short nopens = 0; /* Number of opens executed */
127:
1.4 leo 128: static short fd_state = FLP_IDLE; /* Current driver state */
1.46 wiz 129: static int lock_stat= 0; /* DMA locking status */
1.1 leo 130: static short fd_cmd = 0; /* command being executed */
131: static char *fd_error= NULL; /* error from fd_xfer_ok() */
132:
133: /*
134: * Private per device data
135: */
136: struct fd_softc {
1.13 thorpej 137: struct device sc_dv; /* generic device info */
138: struct disk dkdev; /* generic disk info */
1.38 hannken 139: struct bufq_state bufq; /* queue of buf's */
1.35 thorpej 140: struct callout sc_motor_ch;
1.1 leo 141: int unit; /* unit for atari controlling hw*/
142: int nheads; /* number of heads in use */
143: int nsectors; /* number of sectors/track */
1.8 leo 144: int density; /* density code */
1.1 leo 145: int nblocks; /* number of blocks on disk */
146: int curtrk; /* track head positioned on */
147: short flags; /* misc flags */
148: short part; /* Current open partition */
149: int sector; /* logical sector for I/O */
150: caddr_t io_data; /* KVA for data transfer */
151: int io_bytes; /* bytes left for I/O */
152: int io_dir; /* B_READ/B_WRITE */
153: int errcnt; /* current error count */
154: u_char *bounceb; /* Bounce buffer */
1.10 mycroft 155:
1.1 leo 156: };
157:
158: /*
159: * Flags in fd_softc:
160: */
1.4 leo 161: #define FLPF_NOTRESP 0x001 /* Unit not responding */
162: #define FLPF_ISOPEN 0x002 /* Unit is open */
1.8 leo 163: #define FLPF_SPARE 0x004 /* Not used */
1.4 leo 164: #define FLPF_HAVELAB 0x008 /* We have a valid label */
165: #define FLPF_BOUNCE 0x010 /* Now using the bounce buffer */
166: #define FLPF_WRTPROT 0x020 /* Unit is write-protected */
167: #define FLPF_EMPTY 0x040 /* Unit is empty */
168: #define FLPF_INOPEN 0x080 /* Currently being opened */
169: #define FLPF_GETSTAT 0x100 /* Getting unit status */
1.1 leo 170:
171: struct fd_types {
172: int nheads; /* Heads in use */
173: int nsectors; /* sectors per track */
174: int nblocks; /* number of blocks */
1.8 leo 175: int density; /* density code */
1.24 leo 176: const char *descr; /* type description */
1.1 leo 177: } fdtypes[NR_TYPES] = {
1.24 leo 178: { 1, 9, 720 , FLP_DD , "360KB" }, /* 360 Kb */
179: { 2, 9, 1440 , FLP_DD , "720KB" }, /* 720 Kb */
180: { 2, 18, 2880 , FLP_HD , "1.44MB" }, /* 1.44 Mb */
1.1 leo 181: };
182:
1.30 leo 183: #define FLP_TYPE_360 0 /* XXX: Please keep these in */
184: #define FLP_TYPE_720 1 /* sync with the numbering in */
185: #define FLP_TYPE_144 2 /* 'fdtypes' right above! */
186:
187: /*
188: * This is set only once at attach time. The value is determined by reading
189: * the configuration switches and is one of the FLP_TYPE_*'s.
190: * This is simular to the way Atari handles the _FLP cookie.
191: */
192: static short def_type = 0; /* Reflects config-switches */
193:
1.24 leo 194: #define FLP_DEFTYPE 1 /* 720Kb, reasonable default */
1.30 leo 195: #define FLP_TYPE(dev) ( DISKPART(dev) == 0 ? def_type : DISKPART(dev) - 1 )
1.24 leo 196:
1.17 leo 197: typedef void (*FPV) __P((void *));
1.1 leo 198:
1.24 leo 199: dev_type_open(fdopen);
1.15 leo 200: dev_type_close(fdclose);
201: dev_type_read(fdread);
202: dev_type_write(fdwrite);
203: dev_type_ioctl(fdioctl);
1.39 gehenna 204: dev_type_strategy(fdstrategy);
1.15 leo 205:
206: /*
1.1 leo 207: * Private drive functions....
208: */
209: static void fdstart __P((struct fd_softc *));
210: static void fddone __P((struct fd_softc *));
1.4 leo 211: static void fdstatus __P((struct fd_softc *));
1.1 leo 212: static void fd_xfer __P((struct fd_softc *));
1.4 leo 213: static void fdcint __P((struct fd_softc *));
1.1 leo 214: static int fd_xfer_ok __P((struct fd_softc *));
215: static void fdmotoroff __P((struct fd_softc *));
1.10 mycroft 216: static void fdminphys __P((struct buf *));
1.1 leo 217: static void fdtestdrv __P((struct fd_softc *));
1.26 thorpej 218: static void fdgetdefaultlabel __P((struct fd_softc *, struct disklabel *,
219: int));
1.1 leo 220: static int fdgetdisklabel __P((struct fd_softc *, dev_t));
1.8 leo 221: static int fdselect __P((int, int, int));
222: static void fddeselect __P((void));
1.12 leo 223: static void fdmoff __P((struct fd_softc *));
1.17 leo 224: u_char read_fdreg __P((u_short));
225: void write_fdreg __P((u_short, u_short));
226: u_char read_dmastat __P((void));
1.1 leo 227:
1.4 leo 228: extern __inline__ u_char read_fdreg(u_short regno)
229: {
230: DMA->dma_mode = regno;
231: return(DMA->dma_data);
232: }
233:
234: extern __inline__ void write_fdreg(u_short regno, u_short val)
235: {
236: DMA->dma_mode = regno;
237: DMA->dma_data = val;
238: }
239:
240: extern __inline__ u_char read_dmastat(void)
241: {
242: DMA->dma_mode = FDC_CS | DMA_SCREG;
243: return(DMA->dma_stat);
244: }
245:
1.1 leo 246: /*
1.30 leo 247: * Config switch stuff. Used only for the floppy type for now. That's
248: * why it's here...
249: * XXX: If needed in more places, it should be moved to it's own include file.
250: * Note: This location _must_ be read as an u_short. Failure to do so
251: * will return garbage!
252: */
253: static u_short rd_cfg_switch __P((void));
254: static u_short rd_cfg_switch(void)
255: {
256: return(*((u_short*)AD_CFG_SWITCH));
257: }
258:
259: /*
260: * Switch definitions.
261: * Note: ON reads as a zero bit!
262: */
263: #define CFG_SWITCH_NOHD 0x4000
264:
265: /*
1.1 leo 266: * Autoconfig stuff....
267: */
1.28 leo 268: extern struct cfdriver fd_cd;
269:
1.25 leo 270: static int fdcmatch __P((struct device *, struct cfdata *, void *));
1.21 cgd 271: static int fdcprint __P((void *, const char *));
1.1 leo 272: static void fdcattach __P((struct device *, struct device *, void *));
273:
1.42 thorpej 274: CFATTACH_DECL(fdc, sizeof(struct device),
275: fdcmatch, fdcattach, NULL, NULL);
1.16 thorpej 276:
1.39 gehenna 277: const struct bdevsw fd_bdevsw = {
278: fdopen, fdclose, fdstrategy, fdioctl, nodump, nosize, D_DISK
279: };
280:
281: const struct cdevsw fd_cdevsw = {
282: fdopen, fdclose, fdread, fdwrite, fdioctl,
1.43 jdolecek 283: nostop, notty, nopoll, nommap, nokqfilter, D_DISK
1.39 gehenna 284: };
285:
1.1 leo 286: static int
1.25 leo 287: fdcmatch(pdp, cfp, auxp)
1.1 leo 288: struct device *pdp;
1.25 leo 289: struct cfdata *cfp;
290: void *auxp;
1.1 leo 291: {
1.36 leo 292: static int fdc_matched = 0;
293:
294: /* Match only once */
295: if(strcmp("fdc", auxp) || fdc_matched)
1.1 leo 296: return(0);
1.36 leo 297: fdc_matched = 1;
1.1 leo 298: return(1);
299: }
300:
301: static void
302: fdcattach(pdp, dp, auxp)
303: struct device *pdp, *dp;
304: void *auxp;
305: {
306: struct fd_softc fdsoftc;
1.15 leo 307: int i, nfound, first_found;
1.1 leo 308:
1.15 leo 309: nfound = first_found = 0;
1.23 christos 310: printf("\n");
1.8 leo 311: fddeselect();
1.1 leo 312: for(i = 0; i < NR_DRIVES; i++) {
313:
314: /*
315: * Test if unit is present
316: */
317: fdsoftc.unit = i;
318: fdsoftc.flags = 0;
1.15 leo 319: st_dmagrab((dma_farg)fdcint, (dma_farg)fdtestdrv, &fdsoftc,
320: &lock_stat, 0);
1.5 leo 321: st_dmafree(&fdsoftc, &lock_stat);
1.1 leo 322:
323: if(!(fdsoftc.flags & FLPF_NOTRESP)) {
1.12 leo 324: if(!nfound)
325: first_found = i;
1.1 leo 326: nfound++;
327: config_found(dp, (void*)i, fdcprint);
328: }
329: }
330:
331: if(nfound) {
1.35 thorpej 332: struct fd_softc *fdsc = getsoftc(fd_cd, first_found);
1.12 leo 333:
334: /*
335: * Make sure motor will be turned of when a floppy is
336: * inserted in the first selected drive.
337: */
338: fdselect(first_found, 0, FLP_DD);
339: fd_state = FLP_MON;
1.35 thorpej 340: callout_reset(&fdsc->sc_motor_ch, 0, (FPV)fdmotoroff, fdsc);
1.12 leo 341:
1.1 leo 342: /*
343: * enable disk related interrupts
344: */
1.29 leo 345: MFP->mf_ierb |= IB_DINT;
346: MFP->mf_iprb = (u_int8_t)~IB_DINT;
347: MFP->mf_imrb |= IB_DINT;
1.1 leo 348: }
349: }
350:
351: static int
352: fdcprint(auxp, pnp)
353: void *auxp;
1.21 cgd 354: const char *pnp;
1.1 leo 355: {
1.24 leo 356: if (pnp != NULL)
1.45 thorpej 357: aprint_normal("fd%d at %s:", (int)auxp, pnp);
1.24 leo 358:
1.1 leo 359: return(UNCONF);
360: }
361:
1.25 leo 362: static int fdmatch __P((struct device *, struct cfdata *, void *));
1.1 leo 363: static void fdattach __P((struct device *, struct device *, void *));
1.24 leo 364:
1.1 leo 365: struct dkdriver fddkdriver = { fdstrategy };
366:
1.42 thorpej 367: CFATTACH_DECL(fd, sizeof(struct fd_softc),
368: fdmatch, fdattach, NULL, NULL);
1.16 thorpej 369:
1.27 thorpej 370: extern struct cfdriver fd_cd;
1.1 leo 371:
372: static int
1.25 leo 373: fdmatch(pdp, cfp, auxp)
1.1 leo 374: struct device *pdp;
1.25 leo 375: struct cfdata *cfp;
376: void *auxp;
1.1 leo 377: {
378: return(1);
379: }
380:
381: static void
382: fdattach(pdp, dp, auxp)
383: struct device *pdp, *dp;
384: void *auxp;
385: {
386: struct fd_softc *sc;
1.30 leo 387: struct fd_types *type;
388: u_short swtch;
1.1 leo 389:
390: sc = (struct fd_softc *)dp;
1.30 leo 391:
1.35 thorpej 392: callout_init(&sc->sc_motor_ch);
393:
1.30 leo 394: /*
395: * Find out if an Ajax chip might be installed. Set the default
396: * floppy type accordingly.
397: */
398: swtch = rd_cfg_switch();
399: def_type = (swtch & CFG_SWITCH_NOHD) ? FLP_TYPE_720 : FLP_TYPE_144;
400: type = &fdtypes[def_type];
1.1 leo 401:
1.24 leo 402: printf(": %s %d cyl, %d head, %d sec\n", type->descr,
403: type->nblocks / (type->nsectors * type->nheads), type->nheads,
404: type->nsectors);
1.1 leo 405:
1.13 thorpej 406: /*
407: * Initialize and attach the disk structure.
408: */
409: sc->dkdev.dk_name = sc->sc_dv.dv_xname;
1.1 leo 410: sc->dkdev.dk_driver = &fddkdriver;
1.13 thorpej 411: disk_attach(&sc->dkdev);
1.1 leo 412: }
413:
1.15 leo 414: int
1.46.2.5! skrll 415: fdioctl(dev, cmd, addr, flag, l)
1.1 leo 416: dev_t dev;
417: u_long cmd;
418: int flag;
419: caddr_t addr;
1.46.2.5! skrll 420: struct lwp *l;
1.1 leo 421: {
422: struct fd_softc *sc;
423:
1.16 thorpej 424: sc = getsoftc(fd_cd, DISKUNIT(dev));
1.10 mycroft 425:
1.1 leo 426: if((sc->flags & FLPF_HAVELAB) == 0)
427: return(EBADF);
428:
429: switch(cmd) {
430: case DIOCSBAD:
431: return(EINVAL);
432: case DIOCGDINFO:
1.13 thorpej 433: *(struct disklabel *)addr = *(sc->dkdev.dk_label);
1.1 leo 434: return(0);
435: case DIOCGPART:
436: ((struct partinfo *)addr)->disklab =
1.13 thorpej 437: sc->dkdev.dk_label;
1.10 mycroft 438: ((struct partinfo *)addr)->part =
1.24 leo 439: &sc->dkdev.dk_label->d_partitions[RAW_PART];
1.1 leo 440: return(0);
441: #ifdef notyet /* XXX LWP */
442: case DIOCSRETRIES:
443: case DIOCSSTEP:
444: case DIOCSDINFO:
445: case DIOCWDINFO:
446: case DIOCWLABEL:
1.26 thorpej 447: break;
1.1 leo 448: #endif /* notyet */
1.26 thorpej 449: case DIOCGDEFLABEL:
450: fdgetdefaultlabel(sc, (struct disklabel *)addr,
451: RAW_PART);
452: return(0);
1.1 leo 453: }
1.15 leo 454: return(ENOTTY);
1.1 leo 455: }
456:
457: /*
458: * Open the device. If this is the first open on both the floppy devices,
459: * intialize the controller.
460: * Note that partition info on the floppy device is used to distinguise
461: * between 780Kb and 360Kb floppy's.
462: * partition 0: 360Kb
1.3 leo 463: * partition 1: 780Kb
1.1 leo 464: */
1.15 leo 465: int
1.46.2.5! skrll 466: fdopen(dev, flags, devtype, l)
1.1 leo 467: dev_t dev;
468: int flags, devtype;
1.46.2.5! skrll 469: struct lwp *l;
1.1 leo 470: {
471: struct fd_softc *sc;
472: int sps;
473:
474: #ifdef FLP_DEBUG
1.24 leo 475: printf("fdopen dev=0x%x\n", dev);
1.1 leo 476: #endif
477:
1.24 leo 478: if(FLP_TYPE(dev) >= NR_TYPES)
1.1 leo 479: return(ENXIO);
480:
1.16 thorpej 481: if((sc = getsoftc(fd_cd, DISKUNIT(dev))) == NULL)
1.1 leo 482: return(ENXIO);
483:
484: /*
485: * If no floppy currently open, reset the controller and select
486: * floppy type.
487: */
488: if(!nopens) {
489:
490: #ifdef FLP_DEBUG
1.24 leo 491: printf("fdopen device not yet open\n");
1.1 leo 492: #endif
493: nopens++;
1.4 leo 494: write_fdreg(FDC_CS, IRUPT);
1.8 leo 495: delay(40);
1.1 leo 496: }
497:
1.4 leo 498: /*
499: * Sleep while other process is opening the device
500: */
501: sps = splbio();
502: while(sc->flags & FLPF_INOPEN)
1.24 leo 503: tsleep((caddr_t)sc, PRIBIO, "fdopen", 0);
1.4 leo 504: splx(sps);
505:
1.1 leo 506: if(!(sc->flags & FLPF_ISOPEN)) {
507: /*
508: * Initialise some driver values.
509: */
1.24 leo 510: int type;
1.1 leo 511: void *addr;
512:
1.24 leo 513: type = FLP_TYPE(dev);
514:
1.38 hannken 515: bufq_alloc(&sc->bufq, BUFQ_DISKSORT|BUFQ_SORT_RAWBLOCK);
1.1 leo 516: sc->unit = DISKUNIT(dev);
1.24 leo 517: sc->part = RAW_PART;
518: sc->nheads = fdtypes[type].nheads;
519: sc->nsectors = fdtypes[type].nsectors;
520: sc->nblocks = fdtypes[type].nblocks;
521: sc->density = fdtypes[type].density;
1.1 leo 522: sc->curtrk = INV_TRK;
523: sc->sector = 0;
524: sc->errcnt = 0;
525: sc->bounceb = (u_char*)alloc_stmem(SECTOR_SIZE, &addr);
526: if(sc->bounceb == NULL)
527: return(ENOMEM); /* XXX */
528:
1.4 leo 529: /*
530: * Go get write protect + loaded status
531: */
1.6 leo 532: sc->flags |= FLPF_INOPEN|FLPF_GETSTAT;
1.4 leo 533: sps = splbio();
1.15 leo 534: st_dmagrab((dma_farg)fdcint, (dma_farg)fdstatus, sc,
535: &lock_stat, 0);
1.4 leo 536: while(sc->flags & FLPF_GETSTAT)
1.24 leo 537: tsleep((caddr_t)sc, PRIBIO, "fdopen", 0);
1.4 leo 538: splx(sps);
539: wakeup((caddr_t)sc);
540:
541: if((sc->flags & FLPF_WRTPROT) && (flags & FWRITE)) {
542: sc->flags = 0;
543: return(EPERM);
544: }
545: if(sc->flags & FLPF_EMPTY) {
546: sc->flags = 0;
547: return(ENXIO);
548: }
1.6 leo 549: sc->flags &= ~(FLPF_INOPEN|FLPF_GETSTAT);
550: sc->flags |= FLPF_ISOPEN;
1.1 leo 551: }
552: else {
553: /*
554: * Multiply opens are granted when accessing the same type of
555: * floppy (eq. the same partition).
556: */
1.24 leo 557: if(sc->density != fdtypes[DISKPART(dev)].density)
1.1 leo 558: return(ENXIO); /* XXX temporarely out of business */
559: }
560: fdgetdisklabel(sc, dev);
561: #ifdef FLP_DEBUG
1.24 leo 562: printf("fdopen open succeeded on type %d\n", sc->part);
1.1 leo 563: #endif
1.15 leo 564: return (0);
1.1 leo 565: }
566:
1.15 leo 567: int
1.46.2.5! skrll 568: fdclose(dev, flags, devtype, l)
1.1 leo 569: dev_t dev;
570: int flags, devtype;
1.46.2.5! skrll 571: struct lwp *l;
1.1 leo 572: {
573: struct fd_softc *sc;
574:
1.16 thorpej 575: sc = getsoftc(fd_cd, DISKUNIT(dev));
1.1 leo 576: free_stmem(sc->bounceb);
577: sc->flags = 0;
578: nopens--;
579:
580: #ifdef FLP_DEBUG
1.23 christos 581: printf("Closed floppy device -- nopens: %d\n", nopens);
1.1 leo 582: #endif
1.4 leo 583: return(0);
1.1 leo 584: }
585:
586: void
587: fdstrategy(bp)
588: struct buf *bp;
589: {
1.11 leo 590: struct fd_softc *sc;
591: struct disklabel *lp;
1.24 leo 592: int sps, sz;
1.1 leo 593:
1.16 thorpej 594: sc = getsoftc(fd_cd, DISKUNIT(bp->b_dev));
1.1 leo 595:
596: #ifdef FLP_DEBUG
1.24 leo 597: printf("fdstrategy: %p, b_bcount: %ld\n", bp, bp->b_bcount);
1.1 leo 598: #endif
599:
600: /*
601: * check for valid partition and bounds
602: */
1.13 thorpej 603: lp = sc->dkdev.dk_label;
1.11 leo 604: if ((sc->flags & FLPF_HAVELAB) == 0) {
605: bp->b_error = EIO;
606: goto bad;
1.1 leo 607: }
1.24 leo 608: if (bp->b_blkno < 0 || (bp->b_bcount % SECTOR_SIZE)) {
609: bp->b_error = EINVAL;
610: goto bad;
611: }
612: if (bp->b_bcount == 0)
1.1 leo 613: goto done;
614:
1.24 leo 615: sz = howmany(bp->b_bcount, SECTOR_SIZE);
616:
617: if (bp->b_blkno + sz > sc->nblocks) {
618: sz = sc->nblocks - bp->b_blkno;
619: if (sz == 0) /* Exactly at EndOfDisk */
620: goto done;
621: if (sz < 0) { /* Past EndOfDisk */
622: bp->b_error = EINVAL;
623: goto bad;
624: }
625: /* Trucate it */
626: if (bp->b_flags & B_RAW)
627: bp->b_bcount = sz << DEV_BSHIFT;
628: else bp->b_bcount = sz * lp->d_secsize;
629: }
1.32 thorpej 630:
631: /* No partition translation. */
632: bp->b_rawblkno = bp->b_blkno;
1.1 leo 633:
634: /*
635: * queue the buf and kick the low level code
636: */
637: sps = splbio();
1.38 hannken 638: BUFQ_PUT(&sc->bufq, bp); /* XXX disksort_cylinder */
1.11 leo 639: if (!lock_stat) {
640: if (fd_state & FLP_MON)
1.35 thorpej 641: callout_stop(&sc->sc_motor_ch);
1.1 leo 642: fd_state = FLP_IDLE;
1.15 leo 643: st_dmagrab((dma_farg)fdcint, (dma_farg)fdstart, sc,
644: &lock_stat, 0);
1.1 leo 645: }
646: splx(sps);
647:
648: return;
1.11 leo 649: bad:
650: bp->b_flags |= B_ERROR;
1.1 leo 651: done:
652: bp->b_resid = bp->b_bcount;
653: biodone(bp);
654: }
655:
656: int
1.15 leo 657: fdread(dev, uio, flags)
1.1 leo 658: dev_t dev;
659: struct uio *uio;
1.15 leo 660: int flags;
1.1 leo 661: {
1.8 leo 662: return(physio(fdstrategy, NULL, dev, B_READ, fdminphys, uio));
1.1 leo 663: }
664:
665: int
1.15 leo 666: fdwrite(dev, uio, flags)
1.1 leo 667: dev_t dev;
668: struct uio *uio;
1.15 leo 669: int flags;
1.1 leo 670: {
1.8 leo 671: return(physio(fdstrategy, NULL, dev, B_WRITE, fdminphys, uio));
1.1 leo 672: }
673:
674: /*
1.4 leo 675: * Called through DMA-dispatcher, get status.
676: */
677: static void
678: fdstatus(sc)
679: struct fd_softc *sc;
680: {
681: #ifdef FLP_DEBUG
1.23 christos 682: printf("fdstatus\n");
1.4 leo 683: #endif
684: sc->errcnt = 0;
685: fd_state = FLP_STAT;
686: fd_xfer(sc);
687: }
688:
689: /*
1.46 wiz 690: * Called through the DMA-dispatcher. So we know we are the only ones
1.46.2.1 skrll 691: * messing with the floppy-controller.
1.1 leo 692: * Initialize some fields in the fdsoftc for the state-machine and get
693: * it going.
694: */
695: static void
696: fdstart(sc)
697: struct fd_softc *sc;
698: {
699: struct buf *bp;
700:
1.38 hannken 701: bp = BUFQ_PEEK(&sc->bufq);
1.1 leo 702: sc->sector = bp->b_blkno; /* Start sector for I/O */
703: sc->io_data = bp->b_data; /* KVA base for I/O */
704: sc->io_bytes = bp->b_bcount; /* Transfer size in bytes */
705: sc->io_dir = bp->b_flags & B_READ;/* Direction of transfer */
706: sc->errcnt = 0; /* No errors yet */
707: fd_state = FLP_XFER; /* Yes, we're going to transfer */
708:
1.13 thorpej 709: /* Instrumentation. */
710: disk_busy(&sc->dkdev);
711:
1.1 leo 712: fd_xfer(sc);
713: }
714:
715: /*
716: * The current transaction is finished (for good or bad). Let go of
1.46 wiz 717: * the DMA-resources. Call biodone() to finish the transaction.
1.1 leo 718: * Find a new transaction to work on.
719: */
720: static void
721: fddone(sc)
722: register struct fd_softc *sc;
723: {
1.33 leo 724: struct buf *bp;
1.1 leo 725: struct fd_softc *sc1;
1.5 leo 726: int i, sps;
1.1 leo 727:
728: /*
1.46 wiz 729: * Give others a chance to use the DMA.
1.1 leo 730: */
1.5 leo 731: st_dmafree(sc, &lock_stat);
1.4 leo 732:
1.1 leo 733:
1.4 leo 734: if(fd_state != FLP_STAT) {
735: /*
736: * Finish current transaction.
737: */
1.5 leo 738: sps = splbio();
1.38 hannken 739: bp = BUFQ_GET(&sc->bufq);
1.31 thorpej 740: if (bp == NULL)
1.4 leo 741: panic("fddone");
1.5 leo 742: splx(sps);
1.4 leo 743:
744: #ifdef FLP_DEBUG
1.24 leo 745: printf("fddone: unit: %d, buf: %p, resid: %d\n",sc->unit,bp,
1.4 leo 746: sc->io_bytes);
747: #endif
748: bp->b_resid = sc->io_bytes;
1.13 thorpej 749:
1.44 mrg 750: disk_unbusy(&sc->dkdev, (bp->b_bcount - bp->b_resid),
751: (bp->b_flags & B_READ));
1.13 thorpej 752:
1.4 leo 753: biodone(bp);
754: }
755: fd_state = FLP_MON;
1.1 leo 756:
1.5 leo 757: if(lock_stat)
1.1 leo 758: return; /* XXX Is this possible? */
759:
760: /*
761: * Find a new transaction on round-robin basis.
762: */
763: for(i = sc->unit + 1; ;i++) {
1.16 thorpej 764: if(i >= fd_cd.cd_ndevs)
1.1 leo 765: i = 0;
1.16 thorpej 766: if((sc1 = fd_cd.cd_devs[i]) == NULL)
1.1 leo 767: continue;
1.38 hannken 768: if (BUFQ_PEEK(&sc1->bufq) != NULL)
1.1 leo 769: break;
770: if(i == sc->unit) {
1.35 thorpej 771: callout_reset(&sc->sc_motor_ch, FLP_MONDELAY,
772: (FPV)fdmotoroff, sc);
1.1 leo 773: #ifdef FLP_DEBUG
1.23 christos 774: printf("fddone: Nothing to do\n");
1.1 leo 775: #endif
776: return; /* No work */
777: }
778: }
779: fd_state = FLP_IDLE;
780: #ifdef FLP_DEBUG
1.23 christos 781: printf("fddone: Staring job on unit %d\n", sc1->unit);
1.1 leo 782: #endif
1.15 leo 783: st_dmagrab((dma_farg)fdcint, (dma_farg)fdstart, sc1, &lock_stat, 0);
1.1 leo 784: }
785:
1.8 leo 786: static int
787: fdselect(drive, head, dense)
788: int drive, head, dense;
789: {
1.18 leo 790: int i, spinning;
1.8 leo 791: #ifdef FLP_DEBUG
1.23 christos 792: printf("fdselect: drive=%d, head=%d, dense=%d\n", drive, head, dense);
1.8 leo 793: #endif
794: i = ((drive == 1) ? PA_FLOP1 : PA_FLOP0) | head;
795: spinning = motoron;
796: motoron = 1;
797:
798: switch(dense) {
799: case FLP_DD:
800: DMA->dma_drvmode = 0;
801: break;
802: case FLP_HD:
803: DMA->dma_drvmode = (FDC_HDSET|FDC_HDSIG);
804: break;
805: default:
1.40 provos 806: panic("fdselect: unknown density code");
1.8 leo 807: }
808: if(i != selected) {
809: selected = i;
1.20 leo 810: ym2149_fd_select((i ^ PA_FDSEL));
1.8 leo 811: }
812: return(spinning);
813: }
814:
815: static void
816: fddeselect()
817: {
1.18 leo 818: ym2149_fd_select(PA_FDSEL);
1.8 leo 819: motoron = selected = 0;
820: DMA->dma_drvmode = 0;
821: }
822:
1.1 leo 823: /****************************************************************************
824: * The following functions assume to be running as a result of a *
825: * disk-interrupt (e.q. spl = splbio). *
826: * They form the finit-state machine, the actual driver. *
827: * *
828: * fdstart()/ --> fd_xfer() -> activate hardware *
829: * fdopen() ^ *
830: * | *
831: * +-- not ready -<------------+ *
832: * | *
833: * fdmotoroff()/ --> fdcint() -> fd_xfer_ok() ---+ *
834: * h/w interrupt | *
835: * \|/ *
836: * finished ---> fdone() *
837: * *
838: ****************************************************************************/
839: static void
840: fd_xfer(sc)
841: struct fd_softc *sc;
842: {
1.15 leo 843: register int head;
1.1 leo 844: register int track, sector, hbit;
845: u_long phys_addr;
846:
1.15 leo 847: head = track = 0;
1.4 leo 848: switch(fd_state) {
849: case FLP_XFER:
850: /*
851: * Calculate head/track values
852: */
853: track = sc->sector / sc->nsectors;
854: head = track % sc->nheads;
855: track = track / sc->nheads;
1.1 leo 856: #ifdef FLP_DEBUG
1.23 christos 857: printf("fd_xfer: sector:%d,head:%d,track:%d\n", sc->sector,head,
1.4 leo 858: track);
1.1 leo 859: #endif
1.4 leo 860: break;
861:
862: case FLP_STAT:
863: /*
864: * FLP_STAT only wants to recalibrate
865: */
866: sc->curtrk = INV_TRK;
867: break;
868: default:
869: panic("fd_xfer: wrong state (0x%x)", fd_state);
870: }
1.1 leo 871:
872: /*
1.8 leo 873: * Select the drive.
1.1 leo 874: */
1.8 leo 875: hbit = fdselect(sc->unit, head, sc->density) ? HBIT : 0;
1.1 leo 876:
877: if(sc->curtrk == INV_TRK) {
1.10 mycroft 878: /*
1.1 leo 879: * Recalibrate, since we lost track of head positioning.
880: * The floppy disk controller has no way of determining its
881: * absolute arm position (track). Instead, it steps the
882: * arm a track at a time and keeps track of where it
883: * thinks it is (in software). However, after a SEEK, the
884: * hardware reads information from the diskette telling
885: * where the arm actually is. If the arm is in the wrong place,
886: * a recalibration is done, which forces the arm to track 0.
887: * This way the controller can get back into sync with reality.
888: */
1.8 leo 889: fd_cmd = RESTORE;
1.4 leo 890: write_fdreg(FDC_CS, RESTORE|VBIT|hbit);
1.35 thorpej 891: callout_reset(&sc->sc_motor_ch, FLP_XFERDELAY,
892: (FPV)fdmotoroff, sc);
1.1 leo 893:
894: #ifdef FLP_DEBUG
1.23 christos 895: printf("fd_xfer:Recalibrating drive %d\n", sc->unit);
1.1 leo 896: #endif
897: return;
898: }
899:
1.4 leo 900: write_fdreg(FDC_TR, sc->curtrk);
1.1 leo 901:
902: /*
903: * Issue a SEEK command on the indicated drive unless the arm is
904: * already positioned on the correct track.
905: */
906: if(track != sc->curtrk) {
907: sc->curtrk = track; /* be optimistic */
1.4 leo 908: write_fdreg(FDC_DR, track);
909: write_fdreg(FDC_CS, SEEK|RATE6|VBIT|hbit);
1.35 thorpej 910: callout_reset(&sc->sc_motor_ch, FLP_XFERDELAY,
911: (FPV)fdmotoroff, sc);
1.1 leo 912: fd_cmd = SEEK;
913: #ifdef FLP_DEBUG
1.23 christos 914: printf("fd_xfer:Seek to track %d on drive %d\n",track,sc->unit);
1.1 leo 915: #endif
916: return;
917: }
918:
919: /*
920: * The drive is now on the proper track. Read or write 1 block.
921: */
922: sector = sc->sector % sc->nsectors;
923: sector++; /* start numbering at 1 */
924:
1.4 leo 925: write_fdreg(FDC_SR, sector);
1.1 leo 926:
927: phys_addr = (u_long)kvtop(sc->io_data);
928: if(phys_addr >= FDC_MAX_DMA_AD) {
929: /*
930: * We _must_ bounce this address
931: */
932: phys_addr = (u_long)kvtop(sc->bounceb);
933: if(sc->io_dir == B_WRITE)
934: bcopy(sc->io_data, sc->bounceb, SECTOR_SIZE);
935: sc->flags |= FLPF_BOUNCE;
936: }
1.7 leo 937: st_dmaaddr_set((caddr_t)phys_addr); /* DMA address setup */
1.1 leo 938:
939: #ifdef FLP_DEBUG
1.24 leo 940: printf("fd_xfer:Start io (io_addr:%lx)\n", (u_long)kvtop(sc->io_data));
1.1 leo 941: #endif
942:
943: if(sc->io_dir == B_READ) {
944: /* Issue the command */
1.4 leo 945: st_dmacomm(DMA_FDC | DMA_SCREG, 1);
946: write_fdreg(FDC_CS, F_READ|hbit);
1.1 leo 947: fd_cmd = F_READ;
948: }
949: else {
950: /* Issue the command */
1.4 leo 951: st_dmacomm(DMA_WRBIT | DMA_FDC | DMA_SCREG, 1);
952: write_fdreg(DMA_WRBIT | FDC_CS, F_WRITE|hbit|EBIT|PBIT);
1.1 leo 953: fd_cmd = F_WRITE;
954: }
1.35 thorpej 955: callout_reset(&sc->sc_motor_ch, FLP_XFERDELAY, (FPV)fdmotoroff, sc);
1.1 leo 956: }
957:
958: /* return values of fd_xfer_ok(): */
959: #define X_OK 0
960: #define X_AGAIN 1
961: #define X_ERROR 2
962: #define X_FAIL 3
963:
964: /*
965: * Hardware interrupt function.
966: */
1.4 leo 967: static void
1.1 leo 968: fdcint(sc)
969: struct fd_softc *sc;
970: {
971: struct buf *bp;
972:
973: #ifdef FLP_DEBUG
1.23 christos 974: printf("fdcint: unit = %d\n", sc->unit);
1.1 leo 975: #endif
976:
977: /*
978: * Cancel timeout (we made it, didn't we)
979: */
1.35 thorpej 980: callout_stop(&sc->sc_motor_ch);
1.1 leo 981:
982: switch(fd_xfer_ok(sc)) {
983: case X_ERROR :
984: if(++(sc->errcnt) < MAX_ERRORS) {
985: /*
986: * Command failed but still retries left.
987: */
988: break;
989: }
990: /* FALL THROUGH */
991: case X_FAIL :
992: /*
993: * Non recoverable error. Fall back to motor-on
994: * idle-state.
995: */
1.8 leo 996: if(fd_error != NULL) {
1.23 christos 997: printf("Floppy error: %s\n", fd_error);
1.8 leo 998: fd_error = NULL;
999: }
1000:
1.4 leo 1001: if(fd_state == FLP_STAT) {
1002: sc->flags |= FLPF_EMPTY;
1003: sc->flags &= ~FLPF_GETSTAT;
1004: wakeup((caddr_t)sc);
1005: fddone(sc);
1006: return;
1007: }
1008:
1.38 hannken 1009: bp = BUFQ_PEEK(&sc->bufq);
1.1 leo 1010:
1011: bp->b_error = EIO;
1012: bp->b_flags |= B_ERROR;
1.8 leo 1013: fd_state = FLP_MON;
1.1 leo 1014:
1015: break;
1016: case X_AGAIN:
1017: /*
1018: * Start next part of state machine.
1019: */
1020: break;
1021: case X_OK:
1022: /*
1023: * Command ok and finished. Reset error-counter.
1024: * If there are no more bytes to transfer fall back
1025: * to motor-on idle state.
1026: */
1027: sc->errcnt = 0;
1.4 leo 1028:
1029: if(fd_state == FLP_STAT) {
1030: sc->flags &= ~FLPF_GETSTAT;
1031: wakeup((caddr_t)sc);
1032: fddone(sc);
1033: return;
1034: }
1035:
1.1 leo 1036: if((sc->flags & FLPF_BOUNCE) && (sc->io_dir == B_READ))
1037: bcopy(sc->bounceb, sc->io_data, SECTOR_SIZE);
1038: sc->flags &= ~FLPF_BOUNCE;
1039:
1040: sc->sector++;
1041: sc->io_data += SECTOR_SIZE;
1042: sc->io_bytes -= SECTOR_SIZE;
1043: if(sc->io_bytes <= 0)
1044: fd_state = FLP_MON;
1045: }
1046: if(fd_state == FLP_MON)
1047: fddone(sc);
1048: else fd_xfer(sc);
1049: }
1050:
1051: /*
1052: * Determine status of last command. Should only be called through
1053: * 'fdcint()'.
1054: * Returns:
1055: * X_ERROR : Error on command; might succeed next time.
1056: * X_FAIL : Error on command; will never succeed.
1057: * X_AGAIN : Part of a command succeeded, call 'fd_xfer()' to complete.
1058: * X_OK : Command succeeded and is complete.
1059: *
1060: * This function only affects sc->curtrk.
1061: */
1062: static int
1063: fd_xfer_ok(sc)
1064: register struct fd_softc *sc;
1065: {
1066: register int status;
1067:
1.4 leo 1068: #ifdef FLP_DEBUG
1.23 christos 1069: printf("fd_xfer_ok: cmd: 0x%x, state: 0x%x\n", fd_cmd, fd_state);
1.4 leo 1070: #endif
1.1 leo 1071: switch(fd_cmd) {
1072: case IRUPT:
1073: /*
1074: * Timeout. Force a recalibrate before we try again.
1075: */
1.8 leo 1076: status = read_fdreg(FDC_CS);
1077:
1.1 leo 1078: fd_error = "Timeout";
1079: sc->curtrk = INV_TRK;
1080: return(X_ERROR);
1081: case F_READ:
1082: /*
1083: * Test for DMA error
1084: */
1.4 leo 1085: status = read_dmastat();
1.1 leo 1086: if(!(status & DMAOK)) {
1.46 wiz 1087: fd_error = "DMA error";
1.1 leo 1088: return(X_ERROR);
1089: }
1090: /*
1091: * Get controller status and check for errors.
1092: */
1.4 leo 1093: status = read_fdreg(FDC_CS);
1.1 leo 1094: if(status & (RNF | CRCERR | LD_T00)) {
1095: fd_error = "Read error";
1096: if(status & RNF)
1097: sc->curtrk = INV_TRK;
1098: return(X_ERROR);
1099: }
1100: break;
1101: case F_WRITE:
1102: /*
1.4 leo 1103: * Test for DMA error
1104: */
1105: status = read_dmastat();
1106: if(!(status & DMAOK)) {
1.46 wiz 1107: fd_error = "DMA error";
1.4 leo 1108: return(X_ERROR);
1109: }
1110: /*
1.1 leo 1111: * Get controller status and check for errors.
1112: */
1.4 leo 1113: status = read_fdreg(FDC_CS);
1.1 leo 1114: if(status & WRI_PRO) {
1115: fd_error = "Write protected";
1116: return(X_FAIL);
1117: }
1118: if(status & (RNF | CRCERR | LD_T00)) {
1119: fd_error = "Write error";
1120: sc->curtrk = INV_TRK;
1121: return(X_ERROR);
1122: }
1123: break;
1124: case SEEK:
1.4 leo 1125: status = read_fdreg(FDC_CS);
1.1 leo 1126: if(status & (RNF | CRCERR)) {
1127: fd_error = "Seek error";
1128: sc->curtrk = INV_TRK;
1129: return(X_ERROR);
1130: }
1131: return(X_AGAIN);
1132: case RESTORE:
1133: /*
1134: * Determine if the recalibration succeeded.
1135: */
1.4 leo 1136: status = read_fdreg(FDC_CS);
1.1 leo 1137: if(status & RNF) {
1138: fd_error = "Recalibrate error";
1139: /* reset controller */
1.4 leo 1140: write_fdreg(FDC_CS, IRUPT);
1.1 leo 1141: sc->curtrk = INV_TRK;
1142: return(X_ERROR);
1143: }
1144: sc->curtrk = 0;
1.4 leo 1145: if(fd_state == FLP_STAT) {
1146: if(status & WRI_PRO)
1147: sc->flags |= FLPF_WRTPROT;
1148: break;
1149: }
1.1 leo 1150: return(X_AGAIN);
1151: default:
1152: fd_error = "Driver error: fd_xfer_ok : Unknown state";
1153: return(X_FAIL);
1154: }
1155: return(X_OK);
1156: }
1157:
1158: /*
1159: * All timeouts will call this function.
1160: */
1161: static void
1162: fdmotoroff(sc)
1163: struct fd_softc *sc;
1164: {
1.8 leo 1165: int sps;
1.1 leo 1166:
1167: /*
1168: * Get at harware interrupt level
1169: */
1170: sps = splbio();
1171:
1172: #if FLP_DEBUG
1.23 christos 1173: printf("fdmotoroff, state = 0x%x\n", fd_state);
1.1 leo 1174: #endif
1175:
1176: switch(fd_state) {
1.4 leo 1177: case FLP_STAT :
1.1 leo 1178: case FLP_XFER :
1179: /*
1180: * Timeout during a transfer; cancel transaction
1181: * set command to 'IRUPT'.
1182: * A drive-interrupt is simulated to trigger the state
1183: * machine.
1184: */
1185: /*
1186: * Cancel current transaction
1187: */
1188: fd_cmd = IRUPT;
1.8 leo 1189: write_fdreg(FDC_CS, IRUPT);
1190: delay(20);
1191: (void)read_fdreg(FDC_CS);
1192: write_fdreg(FDC_CS, RESTORE);
1193: break;
1.1 leo 1194:
1195: case FLP_MON :
1196: /*
1197: * Turn motor off.
1198: */
1.12 leo 1199: if(selected) {
1200: int tmp;
1201:
1.15 leo 1202: st_dmagrab((dma_farg)fdcint, (dma_farg)fdmoff,
1203: sc, &tmp, 0);
1.12 leo 1204: }
1205: else fd_state = FLP_IDLE;
1.1 leo 1206: break;
1207: }
1208: splx(sps);
1209: }
1210:
1211: /*
1212: * min byte count to whats left of the track in question
1213: */
1.10 mycroft 1214: static void
1.1 leo 1215: fdminphys(bp)
1216: struct buf *bp;
1217: {
1218: struct fd_softc *sc;
1219: int sec, toff, tsz;
1220:
1.16 thorpej 1221: if((sc = getsoftc(fd_cd, DISKUNIT(bp->b_dev))) == NULL)
1.9 cgd 1222: panic("fdminphys: couldn't get softc");
1.1 leo 1223:
1224: sec = bp->b_blkno % (sc->nsectors * sc->nheads);
1225: toff = sec * SECTOR_SIZE;
1226: tsz = sc->nsectors * sc->nheads * SECTOR_SIZE;
1227:
1228: #ifdef FLP_DEBUG
1.24 leo 1229: printf("fdminphys: before %ld", bp->b_bcount);
1.1 leo 1230: #endif
1231:
1232: bp->b_bcount = min(bp->b_bcount, tsz - toff);
1233:
1234: #ifdef FLP_DEBUG
1.24 leo 1235: printf(" after %ld\n", bp->b_bcount);
1.1 leo 1236: #endif
1237:
1.10 mycroft 1238: minphys(bp);
1.12 leo 1239: }
1240:
1241: /*
1242: * Called from fdmotoroff to turn the motor actually off....
1243: * This can't be done in fdmotoroff itself, because exclusive access to the
1244: * DMA controller is needed to read the FDC-status register. The function
1245: * 'fdmoff()' always runs as the result of a 'dmagrab()'.
1246: * We need to test the status-register because we want to be sure that the
1247: * drive motor is really off before deselecting the drive. The FDC only
1248: * turns off the drive motor after having seen 10 index-pulses. You only
1249: * get index-pulses when a drive is selected....This means that if the
1250: * drive is deselected when the motor is still spinning, it will continue
1251: * to spin _even_ when you insert a floppy later on...
1252: */
1253: static void
1254: fdmoff(fdsoftc)
1255: struct fd_softc *fdsoftc;
1256: {
1257: int tmp;
1258:
1259: if ((fd_state == FLP_MON) && selected) {
1260: tmp = read_fdreg(FDC_CS);
1261: if (!(tmp & MOTORON)) {
1262: fddeselect();
1263: fd_state = FLP_IDLE;
1264: }
1.35 thorpej 1265: else
1266: callout_reset(&fdsoftc->sc_motor_ch, 10*FLP_MONDELAY,
1267: (FPV)fdmotoroff, fdsoftc);
1.12 leo 1268: }
1269: st_dmafree(fdsoftc, &tmp);
1.1 leo 1270: }
1271:
1272: /*
1.37 wiz 1273: * Used to find out wich drives are actually connected. We do this by issuing
1.1 leo 1274: * is 'RESTORE' command and check if the 'track-0' bit is set. This also works
1275: * if the drive is present but no floppy is inserted.
1276: */
1277: static void
1278: fdtestdrv(fdsoftc)
1279: struct fd_softc *fdsoftc;
1280: {
1.15 leo 1281: int status;
1.1 leo 1282:
1283: /*
1284: * Select the right unit and head.
1285: */
1.8 leo 1286: fdselect(fdsoftc->unit, 0, FLP_DD);
1.1 leo 1287:
1.8 leo 1288: write_fdreg(FDC_CS, RESTORE|HBIT);
1.1 leo 1289:
1290: /*
1291: * Wait for about 2 seconds.
1292: */
1293: delay(2000000);
1294:
1.4 leo 1295: status = read_fdreg(FDC_CS);
1.8 leo 1296: if(status & (RNF|BUSY)) {
1.4 leo 1297: write_fdreg(FDC_CS, IRUPT); /* reset controller */
1.8 leo 1298: delay(40);
1299: }
1.1 leo 1300:
1301: if(!(status & LD_T00))
1302: fdsoftc->flags |= FLPF_NOTRESP;
1.8 leo 1303:
1304: fddeselect();
1.1 leo 1305: }
1306:
1.26 thorpej 1307: static void
1308: fdgetdefaultlabel(sc, lp, part)
1309: struct fd_softc *sc;
1310: struct disklabel *lp;
1311: int part;
1.1 leo 1312: {
1313:
1314: bzero(lp, sizeof(struct disklabel));
1.10 mycroft 1315:
1.1 leo 1316: lp->d_secsize = SECTOR_SIZE;
1317: lp->d_ntracks = sc->nheads;
1318: lp->d_nsectors = sc->nsectors;
1319: lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1320: lp->d_ncylinders = sc->nblocks / lp->d_secpercyl;
1321: lp->d_secperunit = sc->nblocks;
1322:
1323: lp->d_type = DTYPE_FLOPPY;
1324: lp->d_rpm = 300; /* good guess I suppose. */
1325: lp->d_interleave = 1; /* FIXME: is this OK? */
1326: lp->d_bbsize = 0;
1327: lp->d_sbsize = 0;
1328: lp->d_npartitions = part + 1;
1.10 mycroft 1329: lp->d_trkseek = STEP_DELAY;
1.1 leo 1330: lp->d_magic = DISKMAGIC;
1331: lp->d_magic2 = DISKMAGIC;
1332: lp->d_checksum = dkcksum(lp);
1333: lp->d_partitions[part].p_size = lp->d_secperunit;
1334: lp->d_partitions[part].p_fstype = FS_UNUSED;
1335: lp->d_partitions[part].p_fsize = 1024;
1336: lp->d_partitions[part].p_frag = 8;
1.26 thorpej 1337: }
1338:
1339: /*
1340: * Build disk label. For now we only create a label from what we know
1341: * from 'sc'.
1342: */
1343: static int
1344: fdgetdisklabel(sc, dev)
1345: struct fd_softc *sc;
1346: dev_t dev;
1347: {
1348: struct disklabel *lp;
1349: int part;
1350:
1351: /*
1352: * If we already got one, get out.
1353: */
1354: if(sc->flags & FLPF_HAVELAB)
1355: return(0);
1356:
1357: #ifdef FLP_DEBUG
1358: printf("fdgetdisklabel()\n");
1359: #endif
1360:
1361: part = RAW_PART;
1362: lp = sc->dkdev.dk_label;
1363: fdgetdefaultlabel(sc, lp, part);
1.1 leo 1364: sc->flags |= FLPF_HAVELAB;
1.10 mycroft 1365:
1.1 leo 1366: return(0);
1367: }
CVSweb <webmaster@jp.NetBSD.org>