fd.c revision 1.22 1 1.22 mycroft /* $NetBSD: fd.c,v 1.22 1998/08/15 04:22:46 mycroft Exp $ */
2 1.22 mycroft
3 1.22 mycroft /*-
4 1.22 mycroft * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 1.22 mycroft * All rights reserved.
6 1.22 mycroft *
7 1.22 mycroft * This code is derived from software contributed to The NetBSD Foundation
8 1.22 mycroft * by Charles M. Hannum.
9 1.22 mycroft *
10 1.22 mycroft * Redistribution and use in source and binary forms, with or without
11 1.22 mycroft * modification, are permitted provided that the following conditions
12 1.22 mycroft * are met:
13 1.22 mycroft * 1. Redistributions of source code must retain the above copyright
14 1.22 mycroft * notice, this list of conditions and the following disclaimer.
15 1.22 mycroft * 2. Redistributions in binary form must reproduce the above copyright
16 1.22 mycroft * notice, this list of conditions and the following disclaimer in the
17 1.22 mycroft * documentation and/or other materials provided with the distribution.
18 1.22 mycroft * 3. All advertising materials mentioning features or use of this software
19 1.22 mycroft * must display the following acknowledgement:
20 1.22 mycroft * This product includes software developed by the NetBSD
21 1.22 mycroft * Foundation, Inc. and its contributors.
22 1.22 mycroft * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.22 mycroft * contributors may be used to endorse or promote products derived
24 1.22 mycroft * from this software without specific prior written permission.
25 1.22 mycroft *
26 1.22 mycroft * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.22 mycroft * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.22 mycroft * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.22 mycroft * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.22 mycroft * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.22 mycroft * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.22 mycroft * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.22 mycroft * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.22 mycroft * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.22 mycroft * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.22 mycroft * POSSIBILITY OF SUCH DAMAGE.
37 1.22 mycroft */
38 1.1 oki
39 1.1 oki /*-
40 1.1 oki * Copyright (c) 1990 The Regents of the University of California.
41 1.1 oki * All rights reserved.
42 1.1 oki *
43 1.1 oki * This code is derived from software contributed to Berkeley by
44 1.1 oki * Don Ahn.
45 1.1 oki *
46 1.1 oki * Redistribution and use in source and binary forms, with or without
47 1.1 oki * modification, are permitted provided that the following conditions
48 1.1 oki * are met:
49 1.1 oki * 1. Redistributions of source code must retain the above copyright
50 1.1 oki * notice, this list of conditions and the following disclaimer.
51 1.1 oki * 2. Redistributions in binary form must reproduce the above copyright
52 1.1 oki * notice, this list of conditions and the following disclaimer in the
53 1.1 oki * documentation and/or other materials provided with the distribution.
54 1.1 oki * 3. All advertising materials mentioning features or use of this software
55 1.1 oki * must display the following acknowledgement:
56 1.1 oki * This product includes software developed by the University of
57 1.1 oki * California, Berkeley and its contributors.
58 1.1 oki * 4. Neither the name of the University nor the names of its contributors
59 1.1 oki * may be used to endorse or promote products derived from this software
60 1.1 oki * without specific prior written permission.
61 1.1 oki *
62 1.1 oki * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 1.1 oki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 1.1 oki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 1.1 oki * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 1.1 oki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 1.1 oki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 1.1 oki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 1.1 oki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 1.1 oki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 1.1 oki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 1.1 oki * SUCH DAMAGE.
73 1.1 oki *
74 1.1 oki * @(#)fd.c 7.4 (Berkeley) 5/25/91
75 1.1 oki */
76 1.19 jonathan
77 1.19 jonathan #include "opt_ddb.h"
78 1.1 oki
79 1.1 oki #include <sys/param.h>
80 1.1 oki #include <sys/systm.h>
81 1.1 oki #include <sys/kernel.h>
82 1.1 oki #include <sys/conf.h>
83 1.1 oki #include <sys/file.h>
84 1.1 oki #include <sys/stat.h>
85 1.1 oki #include <sys/ioctl.h>
86 1.1 oki #include <sys/malloc.h>
87 1.1 oki #include <sys/device.h>
88 1.1 oki #include <sys/disklabel.h>
89 1.1 oki #include <sys/dkstat.h>
90 1.1 oki #include <sys/disk.h>
91 1.1 oki #include <sys/buf.h>
92 1.1 oki #include <sys/uio.h>
93 1.1 oki #include <sys/syslog.h>
94 1.1 oki #include <sys/queue.h>
95 1.1 oki
96 1.1 oki #include <machine/cpu.h>
97 1.1 oki
98 1.1 oki #include <x68k/x68k/iodevice.h>
99 1.1 oki #include <x68k/dev/dmavar.h>
100 1.1 oki #include <x68k/dev/fdreg.h>
101 1.1 oki #include <x68k/dev/opmreg.h>
102 1.1 oki
103 1.12 jtk #include "locators.h"
104 1.12 jtk
105 1.1 oki #define infdc (IODEVbase->io_fdc)
106 1.1 oki
107 1.1 oki #ifdef DEBUG
108 1.8 christos #define DPRINTF(x) if (fddebug) printf x
109 1.1 oki int fddebug = 0;
110 1.1 oki #else
111 1.1 oki #define DPRINTF(x)
112 1.1 oki #endif
113 1.1 oki
114 1.1 oki #define FDUNIT(dev) (minor(dev) / 8)
115 1.1 oki #define FDTYPE(dev) (minor(dev) % 8)
116 1.1 oki
117 1.1 oki #define b_cylin b_resid
118 1.1 oki
119 1.1 oki enum fdc_state {
120 1.1 oki DEVIDLE = 0,
121 1.1 oki MOTORWAIT,
122 1.1 oki DOSEEK,
123 1.1 oki SEEKWAIT,
124 1.1 oki SEEKTIMEDOUT,
125 1.1 oki SEEKCOMPLETE,
126 1.1 oki DOIO,
127 1.1 oki IOCOMPLETE,
128 1.1 oki IOTIMEDOUT,
129 1.1 oki DORESET,
130 1.1 oki RESETCOMPLETE,
131 1.1 oki RESETTIMEDOUT,
132 1.1 oki DORECAL,
133 1.1 oki RECALWAIT,
134 1.1 oki RECALTIMEDOUT,
135 1.1 oki RECALCOMPLETE,
136 1.1 oki DOCOPY,
137 1.1 oki DOIOHALF,
138 1.1 oki COPYCOMPLETE,
139 1.1 oki };
140 1.1 oki
141 1.1 oki /* software state, per controller */
142 1.1 oki struct fdc_softc {
143 1.1 oki struct device sc_dev; /* boilerplate */
144 1.1 oki u_char sc_flags;
145 1.1 oki
146 1.1 oki struct fd_softc *sc_fd[4]; /* pointers to children */
147 1.1 oki TAILQ_HEAD(drivehead, fd_softc) sc_drives;
148 1.1 oki enum fdc_state sc_state;
149 1.1 oki int sc_errors; /* number of retries so far */
150 1.1 oki u_char sc_status[7]; /* copy of registers */
151 1.1 oki } fdc_softc;
152 1.1 oki
153 1.14 oki bdev_decl(fd);
154 1.14 oki cdev_decl(fd);
155 1.14 oki
156 1.13 oki int fdcintr __P((void));
157 1.13 oki void fdcreset __P((void));
158 1.1 oki
159 1.1 oki /* controller driver configuration */
160 1.20 minoura int fdcprobe __P((struct device *, struct cfdata *, void *));
161 1.1 oki void fdcattach __P((struct device *, struct device *, void *));
162 1.13 oki int fdprint __P((void *, const char *));
163 1.1 oki
164 1.1 oki struct cfattach fdc_ca = {
165 1.1 oki sizeof(struct fdc_softc), fdcprobe, fdcattach
166 1.1 oki };
167 1.18 msaitoh
168 1.18 msaitoh extern struct cfdriver fdc_cd;
169 1.1 oki
170 1.1 oki /*
171 1.1 oki * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
172 1.1 oki * we tell them apart.
173 1.1 oki */
174 1.1 oki struct fd_type {
175 1.1 oki int sectrac; /* sectors per track */
176 1.1 oki int heads; /* number of heads */
177 1.1 oki int seccyl; /* sectors per cylinder */
178 1.1 oki int secsize; /* size code for sectors */
179 1.1 oki int datalen; /* data len when secsize = 0 */
180 1.1 oki int steprate; /* step rate and head unload time */
181 1.1 oki int gap1; /* gap len between sectors */
182 1.1 oki int gap2; /* formatting gap */
183 1.1 oki int tracks; /* total num of tracks */
184 1.1 oki int size; /* size of disk in sectors */
185 1.1 oki int step; /* steps per cylinder */
186 1.1 oki int rate; /* transfer speed code */
187 1.1 oki char *name;
188 1.1 oki };
189 1.1 oki
190 1.1 oki /* The order of entries in the following table is important -- BEWARE! */
191 1.1 oki struct fd_type fd_types[] = {
192 1.1 oki { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS, "1.2MB/[1024bytes/sector]" }, /* 1.2 MB japanese format */
193 1.1 oki { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,"1.44MB" }, /* 1.44MB diskette */
194 1.1 oki { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, "1.2MB" }, /* 1.2 MB AT-diskettes */
195 1.1 oki { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, "360KB/AT" }, /* 360kB in 1.2MB drive */
196 1.1 oki { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, "360KB/PC" }, /* 360kB PC diskettes */
197 1.1 oki { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, "720KB" }, /* 3.5" 720kB diskette */
198 1.1 oki { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, "720KB/x" }, /* 720kB in 1.2MB drive */
199 1.1 oki { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS, "360KB/x" }, /* 360kB in 720kB drive */
200 1.1 oki };
201 1.1 oki
202 1.1 oki /* software state, per disk (with up to 4 disks per ctlr) */
203 1.1 oki struct fd_softc {
204 1.1 oki struct device sc_dev;
205 1.1 oki struct disk sc_dk;
206 1.1 oki
207 1.1 oki struct fd_type *sc_deftype; /* default type descriptor */
208 1.1 oki struct fd_type *sc_type; /* current type descriptor */
209 1.1 oki
210 1.1 oki daddr_t sc_blkno; /* starting block number */
211 1.1 oki int sc_bcount; /* byte count left */
212 1.1 oki int sc_skip; /* bytes already transferred */
213 1.1 oki int sc_nblks; /* number of blocks currently tranferring */
214 1.1 oki int sc_nbytes; /* number of bytes currently tranferring */
215 1.1 oki
216 1.1 oki int sc_drive; /* physical unit number */
217 1.1 oki int sc_flags;
218 1.1 oki #define FD_BOPEN 0x01 /* it's open */
219 1.1 oki #define FD_COPEN 0x02 /* it's open */
220 1.1 oki #define FD_OPEN (FD_BOPEN|FD_COPEN) /* it's open */
221 1.1 oki #define FD_MOTOR 0x04 /* motor should be on */
222 1.1 oki #define FD_MOTOR_WAIT 0x08 /* motor coming up */
223 1.1 oki #define FD_ALIVE 0x10 /* alive */
224 1.1 oki int sc_cylin; /* where we think the head is */
225 1.1 oki
226 1.1 oki TAILQ_ENTRY(fd_softc) sc_drivechain;
227 1.1 oki int sc_ops; /* I/O ops since last switch */
228 1.1 oki struct buf sc_q; /* head of buf chain */
229 1.1 oki u_char *sc_copybuf; /* for secsize >=3 */
230 1.1 oki u_char sc_part; /* for secsize >=3 */
231 1.1 oki #define SEC_P10 0x02 /* first part */
232 1.1 oki #define SEC_P01 0x01 /* second part */
233 1.1 oki #define SEC_P11 0x03 /* both part */
234 1.1 oki };
235 1.1 oki
236 1.1 oki /* floppy driver configuration */
237 1.20 minoura int fdprobe __P((struct device *, struct cfdata *, void *));
238 1.1 oki void fdattach __P((struct device *, struct device *, void *));
239 1.1 oki
240 1.1 oki struct cfattach fd_ca = {
241 1.1 oki sizeof(struct fd_softc), fdprobe, fdattach
242 1.1 oki };
243 1.1 oki
244 1.15 thorpej extern struct cfdriver fd_cd;
245 1.1 oki
246 1.13 oki void fdstrategy __P((struct buf *));
247 1.1 oki void fdstart __P((struct fd_softc *fd));
248 1.1 oki
249 1.1 oki struct dkdriver fddkdriver = { fdstrategy };
250 1.1 oki
251 1.1 oki void fd_set_motor __P((struct fdc_softc *fdc, int reset));
252 1.1 oki void fd_motor_off __P((void *arg));
253 1.1 oki void fd_motor_on __P((void *arg));
254 1.1 oki int fdcresult __P((struct fdc_softc *fdc));
255 1.1 oki int out_fdc __P((u_char x));
256 1.1 oki void fdcstart __P((struct fdc_softc *fdc));
257 1.1 oki void fdcstatus __P((struct device *dv, int n, char *s));
258 1.1 oki void fdctimeout __P((void *arg));
259 1.1 oki void fdcpseudointr __P((void *arg));
260 1.1 oki void fdcretry __P((struct fdc_softc *fdc));
261 1.1 oki void fdfinish __P((struct fd_softc *fd, struct buf *bp));
262 1.13 oki __inline struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t));
263 1.13 oki static int fdcpoll __P((struct fdc_softc *));
264 1.1 oki static int fdgetdisklabel __P((struct fd_softc *, dev_t));
265 1.1 oki static void fd_do_eject __P((int));
266 1.13 oki
267 1.4 oki void fd_mountroot_hook __P((struct device *));
268 1.1 oki
269 1.14 oki /* dma transfer routines */
270 1.14 oki __inline static void fdc_dmastart __P((int, caddr_t, int));
271 1.14 oki void fdcdmaintr __P((void));
272 1.14 oki void fdcdmaerrintr __P((void));
273 1.14 oki
274 1.1 oki #define FDDI_EN 0x02
275 1.1 oki #define FDCI_EN 0x04
276 1.1 oki #define FDD_INT 0x40
277 1.1 oki #define FDC_INT 0x80
278 1.1 oki
279 1.1 oki #define DMA_BRD 0x01
280 1.1 oki #define DMA_BWR 0x02
281 1.1 oki
282 1.1 oki #define DRQ 0
283 1.1 oki
284 1.1 oki static u_char *fdc_dmabuf;
285 1.1 oki
286 1.13 oki __inline static void
287 1.1 oki fdc_dmastart(read, addr, count)
288 1.1 oki int read;
289 1.1 oki caddr_t addr;
290 1.1 oki int count;
291 1.1 oki {
292 1.1 oki volatile struct dmac *dmac = &IODEVbase->io_dma[DRQ];
293 1.1 oki
294 1.2 oki DPRINTF(("fdc_dmastart: (%s, addr = %p, count = %d\n",
295 1.1 oki read ? "read" : "write", addr, count));
296 1.1 oki if (dmarangecheck((vm_offset_t)addr, count)) {
297 1.1 oki dma_bouncebytes[DRQ] = count;
298 1.1 oki dma_dataaddr[DRQ] = addr;
299 1.1 oki if (!(read)) {
300 1.1 oki bcopy(addr, dma_bouncebuf[DRQ], count);
301 1.1 oki dma_bounced[DRQ] = DMA_BWR;
302 1.1 oki } else {
303 1.1 oki dma_bounced[DRQ] = DMA_BRD;
304 1.1 oki }
305 1.1 oki addr = dma_bouncebuf[DRQ];
306 1.1 oki } else {
307 1.1 oki dma_bounced[DRQ] = 0;
308 1.1 oki }
309 1.1 oki
310 1.1 oki dmac->csr = 0xff;
311 1.1 oki dmac->ocr = read ? 0xb2 : 0x32;
312 1.1 oki dmac->mtc = (unsigned short)count;
313 1.1 oki asm("nop");
314 1.1 oki asm("nop");
315 1.1 oki dmac->mar = (unsigned long)kvtop(addr);
316 1.13 oki #if defined(M68040) || defined(M68060)
317 1.1 oki /*
318 1.1 oki * Push back dirty cache lines
319 1.1 oki */
320 1.1 oki if (mmutype == MMU_68040)
321 1.1 oki DCFP(kvtop(addr));
322 1.1 oki #endif
323 1.1 oki dmac->ccr = 0x88;
324 1.1 oki }
325 1.1 oki
326 1.1 oki void
327 1.1 oki fdcdmaintr()
328 1.1 oki {
329 1.1 oki volatile struct dmac *dmac = &IODEVbase->io_dma[DRQ];
330 1.1 oki dmac->csr = 0xff;
331 1.1 oki PCIA(); /* XXX? by oki */
332 1.1 oki if (dma_bounced[DRQ] == DMA_BRD) {
333 1.1 oki bcopy(dma_bouncebuf[DRQ], dma_dataaddr[DRQ], dma_bouncebytes[DRQ]);
334 1.1 oki }
335 1.1 oki dma_bounced[DRQ] = 0;
336 1.1 oki }
337 1.1 oki
338 1.1 oki void
339 1.1 oki fdcdmaerrintr()
340 1.1 oki {
341 1.1 oki volatile struct dmac *dmac = &IODEVbase->io_dma[DRQ];
342 1.8 christos printf("fdcdmaerrintr: csr=%x, cer=%x\n", dmac->csr, dmac->cer);
343 1.1 oki dmac->csr = 0xff;
344 1.1 oki }
345 1.1 oki
346 1.20 minoura /* ARGSUSED */
347 1.1 oki int
348 1.20 minoura fdcprobe(parent, cf, aux)
349 1.1 oki struct device *parent;
350 1.20 minoura struct cfdata *cf;
351 1.20 minoura void *aux;
352 1.1 oki {
353 1.1 oki if (strcmp("fdc", aux) != 0)
354 1.1 oki return 0;
355 1.1 oki return 1;
356 1.1 oki }
357 1.1 oki
358 1.1 oki /*
359 1.1 oki * Arguments passed between fdcattach and fdprobe.
360 1.1 oki */
361 1.1 oki struct fdc_attach_args {
362 1.1 oki int fa_drive;
363 1.1 oki struct fd_type *fa_deftype;
364 1.1 oki };
365 1.1 oki
366 1.1 oki /*
367 1.1 oki * Print the location of a disk drive (called just before attaching the
368 1.1 oki * the drive). If `fdc' is not NULL, the drive was found but was not
369 1.1 oki * in the system config file; print the drive name as well.
370 1.1 oki * Return QUIET (config_find ignores this if the device was configured) to
371 1.1 oki * avoid printing `fdN not configured' messages.
372 1.1 oki */
373 1.1 oki int
374 1.1 oki fdprint(aux, fdc)
375 1.1 oki void *aux;
376 1.6 cgd const char *fdc;
377 1.1 oki {
378 1.1 oki register struct fdc_attach_args *fa = aux;
379 1.1 oki
380 1.1 oki if (!fdc)
381 1.8 christos printf(" drive %d", fa->fa_drive);
382 1.1 oki return QUIET;
383 1.1 oki }
384 1.1 oki
385 1.1 oki void
386 1.1 oki fdcattach(parent, self, aux)
387 1.1 oki struct device *parent, *self;
388 1.1 oki void *aux;
389 1.1 oki {
390 1.1 oki struct fdc_softc *fdc = (void *)self;
391 1.1 oki volatile struct dmac *dmac = &IODEVbase->io_dma[DRQ];
392 1.1 oki struct fdc_attach_args fa;
393 1.1 oki
394 1.1 oki fdc->sc_state = DEVIDLE;
395 1.1 oki TAILQ_INIT(&fdc->sc_drives);
396 1.1 oki
397 1.1 oki fdc->sc_flags = 0;
398 1.1 oki
399 1.1 oki /* reset */
400 1.1 oki ioctlr.intr &= (~FDDI_EN);
401 1.1 oki ioctlr.intr |= FDCI_EN;
402 1.1 oki fdcresult(fdc);
403 1.1 oki fdcreset();
404 1.1 oki
405 1.1 oki /* Initialize DMAC channel */
406 1.1 oki dmac->dcr = 0x80;
407 1.1 oki dmac->scr = 0x04;
408 1.1 oki dmac->csr = 0xff;
409 1.1 oki dmac->cpr = 0x00;
410 1.3 oki dmac->dar = (unsigned long) kvtop((void *)&infdc.data);
411 1.1 oki dmac->mfc = 0x05;
412 1.1 oki dmac->dfc = 0x05;
413 1.1 oki dmac->bfc = 0x05;
414 1.1 oki dmac->niv = 0x64;
415 1.1 oki dmac->eiv = 0x65;
416 1.1 oki
417 1.8 christos printf(": uPD72065 FDC\n");
418 1.1 oki out_fdc(NE7CMD_SPECIFY);/* specify command */
419 1.1 oki out_fdc(0xd0);
420 1.1 oki out_fdc(0x10);
421 1.1 oki
422 1.1 oki fdc_dmabuf = (u_char *)malloc(NBPG, M_DEVBUF, M_WAITOK);
423 1.1 oki if (fdc_dmabuf == 0)
424 1.13 oki printf("fdcattach: WARNING!! malloc() failed.\n");
425 1.1 oki dma_bouncebuf[DRQ] = fdc_dmabuf;
426 1.1 oki
427 1.1 oki /* physical limit: four drives per controller. */
428 1.1 oki for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
429 1.1 oki (void)config_found(self, (void *)&fa, fdprint);
430 1.1 oki }
431 1.1 oki }
432 1.1 oki
433 1.1 oki void
434 1.1 oki fdcreset()
435 1.1 oki {
436 1.1 oki infdc.stat = FDC_RESET;
437 1.1 oki }
438 1.1 oki
439 1.1 oki static int
440 1.1 oki fdcpoll(fdc)
441 1.1 oki struct fdc_softc *fdc;
442 1.1 oki {
443 1.1 oki int i = 25000;
444 1.1 oki while (--i > 0) {
445 1.1 oki if ((ioctlr.intr & 0x80)) {
446 1.1 oki out_fdc(NE7CMD_SENSEI);
447 1.1 oki fdcresult(fdc);
448 1.1 oki break;
449 1.1 oki }
450 1.1 oki DELAY(100);
451 1.1 oki }
452 1.1 oki return i;
453 1.1 oki }
454 1.1 oki
455 1.1 oki int
456 1.20 minoura fdprobe(parent, cf, aux)
457 1.1 oki struct device *parent;
458 1.20 minoura struct cfdata *cf;
459 1.20 minoura void *aux;
460 1.1 oki {
461 1.1 oki struct fdc_softc *fdc = (void *)parent;
462 1.1 oki struct fd_type *type;
463 1.1 oki int drive = cf->cf_unit;
464 1.1 oki int n;
465 1.1 oki int found = 0;
466 1.1 oki int i;
467 1.1 oki
468 1.12 jtk if (cf->cf_loc[FDCCF_UNIT] != FDCCF_UNIT_DEFAULT &&
469 1.12 jtk cf->cf_loc[FDCCF_UNIT] != drive)
470 1.1 oki return 0;
471 1.1 oki
472 1.1 oki type = &fd_types[0]; /* XXX 1.2MB */
473 1.1 oki
474 1.1 oki ioctlr.intr &= (~FDCI_EN);
475 1.1 oki
476 1.1 oki /* select drive and turn on motor */
477 1.1 oki infdc.select = 0x80 | (type->rate << 4)| drive;
478 1.1 oki fdc_force_ready(FDCRDY);
479 1.1 oki fdcpoll(fdc);
480 1.1 oki
481 1.1 oki retry:
482 1.1 oki out_fdc(NE7CMD_RECAL);
483 1.1 oki out_fdc(drive);
484 1.1 oki
485 1.1 oki i = 25000;
486 1.1 oki while (--i > 0) {
487 1.1 oki if ((ioctlr.intr & 0x80)) {
488 1.1 oki out_fdc(NE7CMD_SENSEI);
489 1.1 oki n = fdcresult(fdc);
490 1.1 oki break;
491 1.1 oki }
492 1.1 oki DELAY(100);
493 1.1 oki }
494 1.1 oki
495 1.1 oki #ifdef FDDEBUG
496 1.1 oki {
497 1.1 oki int i;
498 1.8 christos printf("fdprobe: status");
499 1.1 oki for (i = 0; i < n; i++)
500 1.8 christos printf(" %x", fdc->sc_status[i]);
501 1.8 christos printf("\n");
502 1.1 oki }
503 1.1 oki #endif
504 1.1 oki
505 1.1 oki if (n == 2) {
506 1.1 oki if ((fdc->sc_status[0] & 0xf0) == 0x20) {
507 1.1 oki found = 1;
508 1.1 oki } else if ((fdc->sc_status[0] & 0xf0) == 0xc0) {
509 1.1 oki goto retry;
510 1.1 oki }
511 1.1 oki }
512 1.1 oki
513 1.1 oki /* turn off motor */
514 1.1 oki infdc.select = (type->rate << 4)| drive;
515 1.1 oki fdc_force_ready(FDCSTBY);
516 1.1 oki if (!found) {
517 1.1 oki ioctlr.intr |= FDCI_EN;
518 1.1 oki return 0;
519 1.1 oki }
520 1.1 oki
521 1.1 oki return 1;
522 1.1 oki }
523 1.1 oki
524 1.1 oki void
525 1.1 oki fdattach(parent, self, aux)
526 1.1 oki struct device *parent;
527 1.1 oki struct device *self;
528 1.1 oki void *aux;
529 1.1 oki {
530 1.1 oki struct fdc_softc *fdc = (void *)parent;
531 1.1 oki register struct fd_softc *fd = (void *)self;
532 1.1 oki struct fdc_attach_args *fa = aux;
533 1.1 oki int drive = fa->fa_drive;
534 1.1 oki struct fd_type *type = &fd_types[0]; /* XXX 1.2MB */
535 1.1 oki
536 1.1 oki fd->sc_flags = 0;
537 1.1 oki
538 1.1 oki ioctlr.intr |= FDCI_EN;
539 1.1 oki
540 1.1 oki if (type)
541 1.8 christos printf(": %s %d cyl, %d head, %d sec\n", type->name,
542 1.1 oki type->tracks, type->heads, type->sectrac);
543 1.1 oki else
544 1.8 christos printf(": density unknown\n");
545 1.1 oki
546 1.1 oki fd->sc_cylin = -1;
547 1.1 oki fd->sc_drive = drive;
548 1.1 oki fd->sc_deftype = type;
549 1.1 oki fdc->sc_fd[drive] = fd;
550 1.1 oki
551 1.1 oki fd->sc_copybuf = (u_char *)malloc(NBPG, M_DEVBUF, M_WAITOK);
552 1.1 oki if (fd->sc_copybuf == 0)
553 1.8 christos printf("fdprobe: WARNING!! malloc() failed.\n");
554 1.1 oki fd->sc_flags |= FD_ALIVE;
555 1.1 oki
556 1.1 oki /*
557 1.1 oki * Initialize and attach the disk structure.
558 1.1 oki */
559 1.1 oki fd->sc_dk.dk_name = fd->sc_dev.dv_xname;
560 1.1 oki fd->sc_dk.dk_driver = &fddkdriver;
561 1.1 oki disk_attach(&fd->sc_dk);
562 1.4 oki
563 1.4 oki /*
564 1.4 oki * Establish a mountroot_hook anyway in case we booted
565 1.4 oki * with RB_ASKNAME and get selected as the boot device.
566 1.4 oki */
567 1.9 thorpej mountroothook_establish(fd_mountroot_hook, &fd->sc_dev);
568 1.1 oki }
569 1.1 oki
570 1.13 oki __inline struct fd_type *
571 1.1 oki fd_dev_to_type(fd, dev)
572 1.1 oki struct fd_softc *fd;
573 1.1 oki dev_t dev;
574 1.1 oki {
575 1.1 oki int type = FDTYPE(dev);
576 1.1 oki
577 1.1 oki if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
578 1.1 oki return NULL;
579 1.1 oki return &fd_types[type];
580 1.1 oki }
581 1.1 oki
582 1.1 oki void
583 1.1 oki fdstrategy(bp)
584 1.1 oki register struct buf *bp; /* IO operation to perform */
585 1.1 oki {
586 1.1 oki struct fd_softc *fd;
587 1.1 oki int unit = FDUNIT(bp->b_dev);
588 1.1 oki int sz;
589 1.1 oki int s;
590 1.1 oki
591 1.1 oki if (unit >= fd_cd.cd_ndevs ||
592 1.1 oki (fd = fd_cd.cd_devs[unit]) == 0 ||
593 1.1 oki bp->b_blkno < 0 ||
594 1.1 oki (bp->b_bcount % FDC_BSIZE) != 0) {
595 1.1 oki #ifdef FDDEBUG
596 1.8 christos printf("fdstrategy: unit=%d, blkno=%d, bcount=%d\n", unit,
597 1.1 oki bp->b_blkno, bp->b_bcount);
598 1.1 oki #endif
599 1.1 oki bp->b_error = EINVAL;
600 1.1 oki goto bad;
601 1.1 oki }
602 1.1 oki
603 1.1 oki /* If it's a null transfer, return immediately. */
604 1.1 oki if (bp->b_bcount == 0)
605 1.1 oki goto done;
606 1.1 oki
607 1.1 oki sz = howmany(bp->b_bcount, FDC_BSIZE);
608 1.1 oki
609 1.1 oki if (bp->b_blkno + sz > (fd->sc_type->size << (fd->sc_type->secsize - 2))) {
610 1.1 oki sz = (fd->sc_type->size << (fd->sc_type->secsize - 2)) - bp->b_blkno;
611 1.1 oki if (sz == 0) {
612 1.1 oki /* If exactly at end of disk, return EOF. */
613 1.1 oki bp->b_resid = bp->b_bcount;
614 1.1 oki goto done;
615 1.1 oki }
616 1.1 oki if (sz < 0) {
617 1.1 oki /* If past end of disk, return EINVAL. */
618 1.1 oki bp->b_error = EINVAL;
619 1.1 oki goto bad;
620 1.1 oki }
621 1.1 oki /* Otherwise, truncate request. */
622 1.1 oki bp->b_bcount = sz << DEV_BSHIFT;
623 1.1 oki }
624 1.1 oki
625 1.1 oki bp->b_cylin = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE)
626 1.1 oki / (fd->sc_type->seccyl * (1 << (fd->sc_type->secsize - 2)));
627 1.1 oki
628 1.2 oki DPRINTF(("fdstrategy: %s b_blkno %d b_bcount %ld cylin %ld\n",
629 1.1 oki bp->b_flags & B_READ ? "read" : "write",
630 1.1 oki bp->b_blkno, bp->b_bcount, bp->b_cylin));
631 1.1 oki /* Queue transfer on drive, activate drive and controller if idle. */
632 1.1 oki s = splbio();
633 1.1 oki disksort(&fd->sc_q, bp);
634 1.1 oki untimeout(fd_motor_off, fd); /* a good idea */
635 1.1 oki if (!fd->sc_q.b_active)
636 1.1 oki fdstart(fd);
637 1.1 oki #ifdef DIAGNOSTIC
638 1.1 oki else {
639 1.20 minoura struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
640 1.1 oki if (fdc->sc_state == DEVIDLE) {
641 1.8 christos printf("fdstrategy: controller inactive\n");
642 1.1 oki fdcstart(fdc);
643 1.1 oki }
644 1.1 oki }
645 1.1 oki #endif
646 1.1 oki splx(s);
647 1.1 oki return;
648 1.1 oki
649 1.1 oki bad:
650 1.1 oki bp->b_flags |= B_ERROR;
651 1.1 oki done:
652 1.1 oki /* Toss transfer; we're done early. */
653 1.1 oki biodone(bp);
654 1.1 oki }
655 1.1 oki
656 1.1 oki void
657 1.1 oki fdstart(fd)
658 1.1 oki struct fd_softc *fd;
659 1.1 oki {
660 1.1 oki struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
661 1.1 oki int active = fdc->sc_drives.tqh_first != 0;
662 1.1 oki
663 1.1 oki /* Link into controller queue. */
664 1.1 oki fd->sc_q.b_active = 1;
665 1.1 oki TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
666 1.1 oki
667 1.1 oki /* If controller not already active, start it. */
668 1.1 oki if (!active)
669 1.1 oki fdcstart(fdc);
670 1.1 oki }
671 1.1 oki
672 1.1 oki void
673 1.1 oki fdfinish(fd, bp)
674 1.1 oki struct fd_softc *fd;
675 1.1 oki struct buf *bp;
676 1.1 oki {
677 1.1 oki struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
678 1.1 oki
679 1.1 oki /*
680 1.1 oki * Move this drive to the end of the queue to give others a `fair'
681 1.1 oki * chance. We only force a switch if N operations are completed while
682 1.1 oki * another drive is waiting to be serviced, since there is a long motor
683 1.1 oki * startup delay whenever we switch.
684 1.1 oki */
685 1.1 oki if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) {
686 1.1 oki fd->sc_ops = 0;
687 1.1 oki TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
688 1.1 oki if (bp->b_actf) {
689 1.1 oki TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
690 1.1 oki } else
691 1.1 oki fd->sc_q.b_active = 0;
692 1.1 oki }
693 1.1 oki bp->b_resid = fd->sc_bcount;
694 1.1 oki fd->sc_skip = 0;
695 1.1 oki fd->sc_q.b_actf = bp->b_actf;
696 1.1 oki biodone(bp);
697 1.1 oki /* turn off motor 5s from now */
698 1.1 oki timeout(fd_motor_off, fd, 5 * hz);
699 1.1 oki fdc->sc_state = DEVIDLE;
700 1.1 oki }
701 1.1 oki
702 1.1 oki int
703 1.14 oki fdread(dev, uio, flags)
704 1.1 oki dev_t dev;
705 1.1 oki struct uio *uio;
706 1.14 oki int flags;
707 1.1 oki {
708 1.1 oki
709 1.1 oki return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
710 1.1 oki }
711 1.1 oki
712 1.1 oki int
713 1.14 oki fdwrite(dev, uio, flags)
714 1.1 oki dev_t dev;
715 1.1 oki struct uio *uio;
716 1.14 oki int flags;
717 1.1 oki {
718 1.1 oki
719 1.1 oki return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
720 1.1 oki }
721 1.1 oki
722 1.1 oki void
723 1.1 oki fd_set_motor(fdc, reset)
724 1.1 oki struct fdc_softc *fdc;
725 1.1 oki int reset;
726 1.1 oki {
727 1.1 oki struct fd_softc *fd;
728 1.1 oki int n;
729 1.1 oki
730 1.1 oki DPRINTF(("fd_set_motor:\n"));
731 1.1 oki for (n = 0; n < 4; n++)
732 1.1 oki if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR)) {
733 1.1 oki infdc.select = 0x80 | (fd->sc_type->rate << 4)| n;
734 1.1 oki }
735 1.1 oki }
736 1.1 oki
737 1.1 oki void
738 1.1 oki fd_motor_off(arg)
739 1.1 oki void *arg;
740 1.1 oki {
741 1.1 oki struct fd_softc *fd = arg;
742 1.1 oki int s;
743 1.1 oki
744 1.1 oki DPRINTF(("fd_motor_off:\n"));
745 1.1 oki
746 1.1 oki s = splbio();
747 1.1 oki fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
748 1.1 oki infdc.select = (fd->sc_type->rate << 4) | fd->sc_drive;
749 1.1 oki #if 0
750 1.1 oki fd_set_motor((struct fdc_softc *)&fdc_softc[0], 0); /* XXX */
751 1.1 oki #endif
752 1.1 oki splx(s);
753 1.1 oki }
754 1.1 oki
755 1.1 oki void
756 1.1 oki fd_motor_on(arg)
757 1.1 oki void *arg;
758 1.1 oki {
759 1.1 oki struct fd_softc *fd = arg;
760 1.1 oki struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
761 1.1 oki int s;
762 1.1 oki
763 1.1 oki DPRINTF(("fd_motor_on:\n"));
764 1.1 oki
765 1.1 oki s = splbio();
766 1.1 oki fd->sc_flags &= ~FD_MOTOR_WAIT;
767 1.1 oki if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
768 1.1 oki (void) fdcintr();
769 1.1 oki splx(s);
770 1.1 oki }
771 1.1 oki
772 1.1 oki int
773 1.1 oki fdcresult(fdc)
774 1.1 oki struct fdc_softc *fdc;
775 1.1 oki {
776 1.1 oki u_char i;
777 1.1 oki int j = 100000,
778 1.1 oki n = 0;
779 1.1 oki
780 1.1 oki for (; j; j--) {
781 1.1 oki
782 1.1 oki i = infdc.stat & (NE7_DIO | NE7_RQM | NE7_CB);
783 1.1 oki
784 1.1 oki
785 1.1 oki if (i == NE7_RQM)
786 1.1 oki return n;
787 1.1 oki if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
788 1.1 oki if (n >= sizeof(fdc->sc_status)) {
789 1.1 oki log(LOG_ERR, "fdcresult: overrun\n");
790 1.1 oki return -1;
791 1.1 oki }
792 1.1 oki fdc->sc_status[n++] = infdc.data;
793 1.1 oki }
794 1.1 oki }
795 1.1 oki log(LOG_ERR, "fdcresult: timeout\n");
796 1.1 oki return -1;
797 1.1 oki }
798 1.1 oki
799 1.1 oki int
800 1.1 oki out_fdc(x)
801 1.1 oki u_char x;
802 1.1 oki {
803 1.1 oki int i = 100000;
804 1.1 oki
805 1.1 oki while ((infdc.stat & NE7_DIO) && i-- > 0);
806 1.1 oki if (i <= 0)
807 1.1 oki return -1;
808 1.1 oki while ((infdc.stat & NE7_RQM) == 0 && i-- > 0);
809 1.1 oki if (i <= 0)
810 1.1 oki return -1;
811 1.1 oki
812 1.1 oki infdc.data = x;
813 1.1 oki
814 1.1 oki return 0;
815 1.1 oki }
816 1.1 oki
817 1.1 oki int
818 1.14 oki fdopen(dev, flags, mode, p)
819 1.1 oki dev_t dev;
820 1.14 oki int flags, mode;
821 1.14 oki struct proc *p;
822 1.1 oki {
823 1.1 oki int unit;
824 1.1 oki struct fd_softc *fd;
825 1.1 oki struct fd_type *type;
826 1.1 oki
827 1.1 oki unit = FDUNIT(dev);
828 1.1 oki if (unit >= fd_cd.cd_ndevs)
829 1.1 oki return ENXIO;
830 1.1 oki fd = fd_cd.cd_devs[unit];
831 1.1 oki if (fd == 0)
832 1.1 oki return ENXIO;
833 1.1 oki type = fd_dev_to_type(fd, dev);
834 1.1 oki if (type == NULL)
835 1.1 oki return ENXIO;
836 1.1 oki
837 1.1 oki if ((fd->sc_flags & FD_OPEN) != 0 &&
838 1.1 oki fd->sc_type != type)
839 1.1 oki return EBUSY;
840 1.1 oki
841 1.1 oki if ((fd->sc_flags & FD_OPEN) == 0) {
842 1.1 oki /* Lock eject button */
843 1.1 oki infdc.drvstat = 0x40 | ( 1 << unit);
844 1.1 oki infdc.drvstat = 0x40;
845 1.1 oki }
846 1.1 oki
847 1.1 oki fd->sc_type = type;
848 1.1 oki fd->sc_cylin = -1;
849 1.1 oki
850 1.14 oki switch (mode) {
851 1.1 oki case S_IFCHR:
852 1.1 oki fd->sc_flags |= FD_COPEN;
853 1.1 oki break;
854 1.1 oki case S_IFBLK:
855 1.1 oki fd->sc_flags |= FD_BOPEN;
856 1.1 oki break;
857 1.1 oki }
858 1.1 oki
859 1.1 oki fdgetdisklabel(fd, dev);
860 1.1 oki
861 1.1 oki return 0;
862 1.1 oki }
863 1.1 oki
864 1.1 oki int
865 1.14 oki fdclose(dev, flags, mode, p)
866 1.1 oki dev_t dev;
867 1.14 oki int flags, mode;
868 1.14 oki struct proc *p;
869 1.1 oki {
870 1.1 oki int unit = FDUNIT(dev);
871 1.1 oki struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
872 1.1 oki
873 1.1 oki DPRINTF(("fdclose %d\n", unit));
874 1.1 oki
875 1.14 oki switch (mode) {
876 1.1 oki case S_IFCHR:
877 1.1 oki fd->sc_flags &= ~FD_COPEN;
878 1.1 oki break;
879 1.1 oki case S_IFBLK:
880 1.1 oki fd->sc_flags &= ~FD_BOPEN;
881 1.1 oki break;
882 1.1 oki }
883 1.1 oki
884 1.1 oki if ((fd->sc_flags & FD_OPEN) == 0) {
885 1.1 oki infdc.drvstat = ( 1 << unit);
886 1.1 oki infdc.drvstat = 0x00;
887 1.1 oki }
888 1.1 oki return 0;
889 1.1 oki }
890 1.1 oki
891 1.1 oki void
892 1.1 oki fdcstart(fdc)
893 1.1 oki struct fdc_softc *fdc;
894 1.1 oki {
895 1.1 oki
896 1.1 oki #ifdef DIAGNOSTIC
897 1.1 oki /* only got here if controller's drive queue was inactive; should
898 1.1 oki be in idle state */
899 1.1 oki if (fdc->sc_state != DEVIDLE) {
900 1.8 christos printf("fdcstart: not idle\n");
901 1.1 oki return;
902 1.1 oki }
903 1.1 oki #endif
904 1.1 oki (void) fdcintr();
905 1.1 oki }
906 1.1 oki
907 1.1 oki void
908 1.1 oki fdcstatus(dv, n, s)
909 1.1 oki struct device *dv;
910 1.1 oki int n;
911 1.1 oki char *s;
912 1.1 oki {
913 1.1 oki struct fdc_softc *fdc = (void *)dv->dv_parent;
914 1.10 oki char bits[64];
915 1.1 oki
916 1.1 oki if (n == 0) {
917 1.1 oki out_fdc(NE7CMD_SENSEI);
918 1.1 oki (void) fdcresult(fdc);
919 1.1 oki n = 2;
920 1.1 oki }
921 1.1 oki
922 1.8 christos printf("%s: %s: state %d", dv->dv_xname, s, fdc->sc_state);
923 1.1 oki
924 1.1 oki switch (n) {
925 1.1 oki case 0:
926 1.8 christos printf("\n");
927 1.1 oki break;
928 1.1 oki case 2:
929 1.10 oki printf(" (st0 %s cyl %d)\n",
930 1.10 oki bitmask_snprintf(fdc->sc_status[0], NE7_ST0BITS,
931 1.10 oki bits, sizeof(bits)), fdc->sc_status[1]);
932 1.1 oki break;
933 1.1 oki case 7:
934 1.10 oki printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0],
935 1.10 oki NE7_ST0BITS, bits, sizeof(bits)));
936 1.10 oki printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1],
937 1.10 oki NE7_ST1BITS, bits, sizeof(bits)));
938 1.10 oki printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2],
939 1.10 oki NE7_ST2BITS, bits, sizeof(bits)));
940 1.10 oki printf(" cyl %d head %d sec %d)\n",
941 1.1 oki fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
942 1.1 oki break;
943 1.1 oki #ifdef DIAGNOSTIC
944 1.1 oki default:
945 1.8 christos printf(" fdcstatus: weird size: %d\n", n);
946 1.1 oki break;
947 1.1 oki #endif
948 1.1 oki }
949 1.1 oki }
950 1.1 oki
951 1.1 oki void
952 1.1 oki fdctimeout(arg)
953 1.1 oki void *arg;
954 1.1 oki {
955 1.1 oki struct fdc_softc *fdc = arg;
956 1.1 oki struct fd_softc *fd = fdc->sc_drives.tqh_first;
957 1.1 oki int s;
958 1.1 oki
959 1.1 oki s = splbio();
960 1.1 oki fdcstatus(&fd->sc_dev, 0, "timeout");
961 1.1 oki
962 1.1 oki if (fd->sc_q.b_actf)
963 1.1 oki fdc->sc_state++;
964 1.1 oki else
965 1.1 oki fdc->sc_state = DEVIDLE;
966 1.1 oki
967 1.1 oki (void) fdcintr();
968 1.1 oki splx(s);
969 1.1 oki }
970 1.1 oki
971 1.1 oki void
972 1.1 oki fdcpseudointr(arg)
973 1.1 oki void *arg;
974 1.1 oki {
975 1.1 oki int s;
976 1.1 oki
977 1.1 oki /* just ensure it has the right spl */
978 1.1 oki s = splbio();
979 1.1 oki (void) fdcintr();
980 1.1 oki splx(s);
981 1.1 oki }
982 1.1 oki
983 1.1 oki int
984 1.1 oki fdcintr()
985 1.1 oki {
986 1.20 minoura struct fdc_softc *fdc = (void *)((struct fd_softc*)fd_cd.cd_devs[0])->sc_dev.dv_parent; /* XXX */
987 1.1 oki #define st0 fdc->sc_status[0]
988 1.1 oki #define cyl fdc->sc_status[1]
989 1.1 oki struct fd_softc *fd;
990 1.1 oki struct buf *bp;
991 1.1 oki int read, head, sec, pos, i, sectrac, nblks;
992 1.1 oki int tmp;
993 1.1 oki struct fd_type *type;
994 1.1 oki
995 1.1 oki loop:
996 1.1 oki fd = fdc->sc_drives.tqh_first;
997 1.1 oki if (fd == NULL) {
998 1.1 oki DPRINTF(("fdcintr: set DEVIDLE\n"));
999 1.1 oki if (fdc->sc_state == DEVIDLE) {
1000 1.1 oki if ((ioctlr.intr & 0x80)) {
1001 1.1 oki out_fdc(NE7CMD_SENSEI);
1002 1.1 oki if ((tmp = fdcresult(fdc)) != 2 || (st0 & 0xf8) != 0x20) {
1003 1.1 oki goto loop;
1004 1.1 oki }
1005 1.1 oki }
1006 1.1 oki }
1007 1.1 oki /* no drives waiting; end */
1008 1.1 oki fdc->sc_state = DEVIDLE;
1009 1.1 oki return 1;
1010 1.1 oki }
1011 1.1 oki
1012 1.1 oki /* Is there a transfer to this drive? If not, deactivate drive. */
1013 1.1 oki bp = fd->sc_q.b_actf;
1014 1.1 oki if (bp == NULL) {
1015 1.1 oki fd->sc_ops = 0;
1016 1.1 oki TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
1017 1.1 oki fd->sc_q.b_active = 0;
1018 1.1 oki goto loop;
1019 1.1 oki }
1020 1.1 oki
1021 1.1 oki switch (fdc->sc_state) {
1022 1.1 oki case DEVIDLE:
1023 1.1 oki DPRINTF(("fdcintr: in DEVIDLE\n"));
1024 1.1 oki fdc->sc_errors = 0;
1025 1.1 oki fd->sc_skip = 0;
1026 1.1 oki fd->sc_bcount = bp->b_bcount;
1027 1.1 oki fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE);
1028 1.1 oki untimeout(fd_motor_off, fd);
1029 1.1 oki if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
1030 1.1 oki fdc->sc_state = MOTORWAIT;
1031 1.1 oki return 1;
1032 1.1 oki }
1033 1.1 oki if ((fd->sc_flags & FD_MOTOR) == 0) {
1034 1.5 oki /* Turn on the motor */
1035 1.5 oki /* being careful about other drives. */
1036 1.5 oki for (i = 0; i < 4; i++) {
1037 1.5 oki struct fd_softc *ofd = fdc->sc_fd[i];
1038 1.5 oki if (ofd && ofd->sc_flags & FD_MOTOR) {
1039 1.5 oki untimeout(fd_motor_off, ofd);
1040 1.5 oki ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
1041 1.5 oki break;
1042 1.5 oki }
1043 1.1 oki }
1044 1.1 oki fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
1045 1.1 oki fd_set_motor(fdc, 0);
1046 1.1 oki fdc->sc_state = MOTORWAIT;
1047 1.1 oki /* allow .5s for motor to stabilize */
1048 1.1 oki timeout(fd_motor_on, fd, hz / 2);
1049 1.1 oki return 1;
1050 1.1 oki }
1051 1.1 oki /* Make sure the right drive is selected. */
1052 1.1 oki fd_set_motor(fdc, 0);
1053 1.1 oki
1054 1.1 oki /* fall through */
1055 1.1 oki case DOSEEK:
1056 1.1 oki doseek:
1057 1.1 oki DPRINTF(("fdcintr: in DOSEEK\n"));
1058 1.1 oki if (fd->sc_cylin == bp->b_cylin)
1059 1.1 oki goto doio;
1060 1.1 oki
1061 1.1 oki out_fdc(NE7CMD_SPECIFY);/* specify command */
1062 1.1 oki out_fdc(0xd0); /* XXX const */
1063 1.1 oki out_fdc(0x10);
1064 1.1 oki
1065 1.1 oki out_fdc(NE7CMD_SEEK); /* seek function */
1066 1.1 oki out_fdc(fd->sc_drive); /* drive number */
1067 1.1 oki out_fdc(bp->b_cylin * fd->sc_type->step);
1068 1.1 oki
1069 1.1 oki fd->sc_cylin = -1;
1070 1.1 oki fdc->sc_state = SEEKWAIT;
1071 1.1 oki
1072 1.1 oki fd->sc_dk.dk_seek++;
1073 1.1 oki disk_busy(&fd->sc_dk);
1074 1.1 oki
1075 1.1 oki timeout(fdctimeout, fdc, 4 * hz);
1076 1.1 oki return 1;
1077 1.1 oki
1078 1.1 oki case DOIO:
1079 1.1 oki doio:
1080 1.1 oki DPRINTF(("fdcintr: DOIO: "));
1081 1.1 oki type = fd->sc_type;
1082 1.1 oki sectrac = type->sectrac;
1083 1.1 oki pos = fd->sc_blkno % (sectrac * (1 << (type->secsize - 2)));
1084 1.1 oki sec = pos / (1 << (type->secsize - 2));
1085 1.1 oki if (type->secsize == 2) {
1086 1.1 oki fd->sc_part = SEC_P11;
1087 1.1 oki nblks = (sectrac - sec) << (type->secsize - 2);
1088 1.1 oki nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
1089 1.1 oki DPRINTF(("nblks(0)"));
1090 1.1 oki } else if ((fd->sc_blkno % 2) == 0) {
1091 1.1 oki if (fd->sc_bcount & 0x00000200) {
1092 1.1 oki if (fd->sc_bcount == FDC_BSIZE) {
1093 1.1 oki fd->sc_part = SEC_P10;
1094 1.1 oki nblks = 1;
1095 1.1 oki DPRINTF(("nblks(1)"));
1096 1.1 oki } else {
1097 1.1 oki fd->sc_part = SEC_P11;
1098 1.1 oki nblks = (sectrac - sec) * 2;
1099 1.1 oki nblks = min(nblks, fd->sc_bcount
1100 1.1 oki / FDC_BSIZE - 1);
1101 1.1 oki DPRINTF(("nblks(2)"));
1102 1.1 oki }
1103 1.1 oki } else {
1104 1.1 oki fd->sc_part = SEC_P11;
1105 1.1 oki nblks = (sectrac - sec)
1106 1.1 oki << (type->secsize - 2);
1107 1.1 oki nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
1108 1.1 oki DPRINTF(("nblks(3)"));
1109 1.1 oki }
1110 1.1 oki } else {
1111 1.1 oki fd->sc_part = SEC_P01;
1112 1.1 oki nblks = 1;
1113 1.1 oki DPRINTF(("nblks(4)"));
1114 1.1 oki }
1115 1.1 oki nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE);
1116 1.1 oki DPRINTF((" %d\n", nblks));
1117 1.1 oki fd->sc_nblks = nblks;
1118 1.1 oki fd->sc_nbytes = nblks * FDC_BSIZE;
1119 1.1 oki head = (fd->sc_blkno
1120 1.1 oki % (type->seccyl * (1 << (type->secsize - 2))))
1121 1.1 oki / (type->sectrac * (1 << (type->secsize - 2)));
1122 1.1 oki
1123 1.1 oki #ifdef DIAGNOSTIC
1124 1.1 oki {int block;
1125 1.1 oki block = ((fd->sc_cylin * type->heads + head) * type->sectrac
1126 1.1 oki + sec) * (1 << (type->secsize - 2));
1127 1.1 oki block += (fd->sc_part == SEC_P01) ? 1 : 0;
1128 1.1 oki if (block != fd->sc_blkno) {
1129 1.8 christos printf("C H R N: %d %d %d %d\n", fd->sc_cylin, head, sec, type->secsize);
1130 1.8 christos printf("fdcintr: doio: block %d != blkno %d\n", block, fd->sc_blkno);
1131 1.1 oki #ifdef DDB
1132 1.1 oki Debugger();
1133 1.1 oki #endif
1134 1.1 oki }}
1135 1.1 oki #endif
1136 1.1 oki read = bp->b_flags & B_READ;
1137 1.1 oki DPRINTF(("fdcintr: %s drive %d track %d head %d sec %d nblks %d, skip %d\n",
1138 1.1 oki read ? "read" : "write", fd->sc_drive, fd->sc_cylin,
1139 1.1 oki head, sec, nblks, fd->sc_skip));
1140 1.1 oki DPRINTF(("C H R N: %d %d %d %d\n", fd->sc_cylin, head, sec,
1141 1.1 oki type->secsize));
1142 1.1 oki
1143 1.1 oki if (fd->sc_part != SEC_P11)
1144 1.1 oki goto docopy;
1145 1.1 oki
1146 1.1 oki fdc_dmastart(read, bp->b_data + fd->sc_skip, fd->sc_nbytes);
1147 1.1 oki if (read)
1148 1.1 oki out_fdc(NE7CMD_READ); /* READ */
1149 1.1 oki else
1150 1.1 oki out_fdc(NE7CMD_WRITE); /* WRITE */
1151 1.1 oki out_fdc((head << 2) | fd->sc_drive);
1152 1.1 oki out_fdc(bp->b_cylin); /* cylinder */
1153 1.1 oki out_fdc(head);
1154 1.1 oki out_fdc(sec + 1); /* sector +1 */
1155 1.1 oki out_fdc(type->secsize); /* sector size */
1156 1.1 oki out_fdc(type->sectrac); /* sectors/track */
1157 1.1 oki out_fdc(type->gap1); /* gap1 size */
1158 1.1 oki out_fdc(type->datalen); /* data length */
1159 1.1 oki fdc->sc_state = IOCOMPLETE;
1160 1.1 oki
1161 1.1 oki disk_busy(&fd->sc_dk);
1162 1.1 oki
1163 1.1 oki /* allow 2 seconds for operation */
1164 1.1 oki timeout(fdctimeout, fdc, 2 * hz);
1165 1.1 oki return 1; /* will return later */
1166 1.1 oki
1167 1.1 oki case DOCOPY:
1168 1.1 oki docopy:
1169 1.1 oki DPRINTF(("fdcintr: DOCOPY:\n"));
1170 1.1 oki fdc_dmastart(B_READ, fd->sc_copybuf, 1024);
1171 1.1 oki out_fdc(NE7CMD_READ); /* READ */
1172 1.1 oki out_fdc((head << 2) | fd->sc_drive);
1173 1.1 oki out_fdc(bp->b_cylin); /* cylinder */
1174 1.1 oki out_fdc(head);
1175 1.1 oki out_fdc(sec + 1); /* sector +1 */
1176 1.1 oki out_fdc(type->secsize); /* sector size */
1177 1.1 oki out_fdc(type->sectrac); /* sectors/track */
1178 1.1 oki out_fdc(type->gap1); /* gap1 size */
1179 1.1 oki out_fdc(type->datalen); /* data length */
1180 1.1 oki fdc->sc_state = COPYCOMPLETE;
1181 1.1 oki /* allow 2 seconds for operation */
1182 1.1 oki timeout(fdctimeout, fdc, 2 * hz);
1183 1.1 oki return 1; /* will return later */
1184 1.1 oki
1185 1.1 oki case DOIOHALF:
1186 1.1 oki doiohalf:
1187 1.1 oki DPRINTF((" DOIOHALF:\n"));
1188 1.1 oki
1189 1.1 oki #ifdef DIAGNOSTIC
1190 1.1 oki type = fd->sc_type;
1191 1.1 oki sectrac = type->sectrac;
1192 1.1 oki pos = fd->sc_blkno % (sectrac * (1 << (type->secsize - 2)));
1193 1.1 oki sec = pos / (1 << (type->secsize - 2));
1194 1.1 oki head = (fd->sc_blkno
1195 1.1 oki % (type->seccyl * (1 << (type->secsize - 2))))
1196 1.1 oki / (type->sectrac * (1 << (type->secsize - 2)));
1197 1.1 oki {int block;
1198 1.1 oki block = ((fd->sc_cylin * type->heads + head) * type->sectrac + sec)
1199 1.1 oki * (1 << (type->secsize - 2));
1200 1.1 oki block += (fd->sc_part == SEC_P01) ? 1 : 0;
1201 1.1 oki if (block != fd->sc_blkno) {
1202 1.8 christos printf("fdcintr: block %d != blkno %d\n", block, fd->sc_blkno);
1203 1.1 oki #ifdef DDB
1204 1.1 oki Debugger();
1205 1.1 oki #endif
1206 1.1 oki }}
1207 1.1 oki #endif
1208 1.1 oki if (read = bp->b_flags & B_READ) {
1209 1.1 oki bcopy(fd->sc_copybuf
1210 1.1 oki + (fd->sc_part & SEC_P01 ? FDC_BSIZE : 0),
1211 1.1 oki bp->b_data + fd->sc_skip,
1212 1.1 oki FDC_BSIZE);
1213 1.1 oki fdc->sc_state = IOCOMPLETE;
1214 1.1 oki goto iocomplete2;
1215 1.1 oki } else {
1216 1.1 oki bcopy(bp->b_data + fd->sc_skip,
1217 1.1 oki fd->sc_copybuf
1218 1.1 oki + (fd->sc_part & SEC_P01 ? FDC_BSIZE : 0),
1219 1.1 oki FDC_BSIZE);
1220 1.1 oki fdc_dmastart(read, fd->sc_copybuf, 1024);
1221 1.1 oki }
1222 1.1 oki out_fdc(NE7CMD_WRITE); /* WRITE */
1223 1.1 oki out_fdc((head << 2) | fd->sc_drive);
1224 1.1 oki out_fdc(bp->b_cylin); /* cylinder */
1225 1.1 oki out_fdc(head);
1226 1.1 oki out_fdc(sec + 1); /* sector +1 */
1227 1.1 oki out_fdc(fd->sc_type->secsize); /* sector size */
1228 1.1 oki out_fdc(sectrac); /* sectors/track */
1229 1.1 oki out_fdc(fd->sc_type->gap1); /* gap1 size */
1230 1.1 oki out_fdc(fd->sc_type->datalen); /* data length */
1231 1.1 oki fdc->sc_state = IOCOMPLETE;
1232 1.1 oki /* allow 2 seconds for operation */
1233 1.1 oki timeout(fdctimeout, fdc, 2 * hz);
1234 1.1 oki return 1; /* will return later */
1235 1.1 oki
1236 1.1 oki case SEEKWAIT:
1237 1.1 oki untimeout(fdctimeout, fdc);
1238 1.1 oki fdc->sc_state = SEEKCOMPLETE;
1239 1.1 oki /* allow 1/50 second for heads to settle */
1240 1.1 oki /* timeout(fdcpseudointr, fdc, hz / 50);*/
1241 1.1 oki return 1;
1242 1.1 oki
1243 1.1 oki case SEEKCOMPLETE:
1244 1.1 oki /* Make sure seek really happened */
1245 1.1 oki DPRINTF(("fdcintr: SEEKCOMPLETE: FDC status = %x\n",
1246 1.1 oki infdc.stat));
1247 1.1 oki out_fdc(NE7CMD_SENSEI);
1248 1.1 oki tmp = fdcresult(fdc);
1249 1.1 oki if ((st0 & 0xf8) == 0xc0) {
1250 1.1 oki DPRINTF(("fdcintr: first seek!\n"));
1251 1.1 oki fdc->sc_state = DORECAL;
1252 1.1 oki goto loop;
1253 1.1 oki } else if (tmp != 2 || (st0 & 0xf8) != 0x20 || cyl != bp->b_cylin) {
1254 1.1 oki #ifdef FDDEBUG
1255 1.1 oki fdcstatus(&fd->sc_dev, 2, "seek failed");
1256 1.1 oki #endif
1257 1.1 oki fdcretry(fdc);
1258 1.1 oki goto loop;
1259 1.1 oki }
1260 1.1 oki fd->sc_cylin = bp->b_cylin;
1261 1.1 oki goto doio;
1262 1.1 oki
1263 1.1 oki case IOTIMEDOUT:
1264 1.1 oki #if 0
1265 1.1 oki isa_dmaabort(fdc->sc_drq);
1266 1.1 oki #endif
1267 1.1 oki case SEEKTIMEDOUT:
1268 1.1 oki case RECALTIMEDOUT:
1269 1.1 oki case RESETTIMEDOUT:
1270 1.1 oki fdcretry(fdc);
1271 1.1 oki goto loop;
1272 1.1 oki
1273 1.1 oki case IOCOMPLETE: /* IO DONE, post-analyze */
1274 1.1 oki untimeout(fdctimeout, fdc);
1275 1.1 oki DPRINTF(("fdcintr: in IOCOMPLETE\n"));
1276 1.1 oki if ((tmp = fdcresult(fdc)) != 7 || (st0 & 0xf8) != 0) {
1277 1.8 christos printf("fdcintr: resnum=%d, st0=%x\n", tmp, st0);
1278 1.1 oki #if 0
1279 1.1 oki isa_dmaabort(fdc->sc_drq);
1280 1.1 oki #endif
1281 1.1 oki fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
1282 1.1 oki "read failed" : "write failed");
1283 1.8 christos printf("blkno %d nblks %d\n",
1284 1.1 oki fd->sc_blkno, fd->sc_nblks);
1285 1.1 oki fdcretry(fdc);
1286 1.1 oki goto loop;
1287 1.1 oki }
1288 1.1 oki #if 0
1289 1.1 oki isa_dmadone(bp->b_flags & B_READ, bp->b_data + fd->sc_skip,
1290 1.1 oki nblks * FDC_BSIZE, fdc->sc_drq);
1291 1.1 oki #endif
1292 1.1 oki iocomplete2:
1293 1.1 oki if (fdc->sc_errors) {
1294 1.1 oki diskerr(bp, "fd", "soft error", LOG_PRINTF,
1295 1.1 oki fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
1296 1.8 christos printf("\n");
1297 1.1 oki fdc->sc_errors = 0;
1298 1.1 oki }
1299 1.1 oki fd->sc_blkno += fd->sc_nblks;
1300 1.1 oki fd->sc_skip += fd->sc_nbytes;
1301 1.1 oki fd->sc_bcount -= fd->sc_nbytes;
1302 1.1 oki DPRINTF(("fd->sc_bcount = %d\n", fd->sc_bcount));
1303 1.1 oki if (fd->sc_bcount > 0) {
1304 1.1 oki bp->b_cylin = fd->sc_blkno
1305 1.1 oki / (fd->sc_type->seccyl
1306 1.1 oki * (1 << (fd->sc_type->secsize - 2)));
1307 1.1 oki goto doseek;
1308 1.1 oki }
1309 1.1 oki fdfinish(fd, bp);
1310 1.1 oki goto loop;
1311 1.1 oki
1312 1.1 oki case COPYCOMPLETE: /* IO DONE, post-analyze */
1313 1.1 oki DPRINTF(("fdcintr: COPYCOMPLETE:"));
1314 1.1 oki untimeout(fdctimeout, fdc);
1315 1.1 oki if ((tmp = fdcresult(fdc)) != 7 || (st0 & 0xf8) != 0) {
1316 1.8 christos printf("fdcintr: resnum=%d, st0=%x\n", tmp, st0);
1317 1.1 oki #if 0
1318 1.1 oki isa_dmaabort(fdc->sc_drq);
1319 1.1 oki #endif
1320 1.1 oki fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
1321 1.1 oki "read failed" : "write failed");
1322 1.8 christos printf("blkno %d nblks %d\n",
1323 1.1 oki fd->sc_blkno, fd->sc_nblks);
1324 1.1 oki fdcretry(fdc);
1325 1.1 oki goto loop;
1326 1.1 oki }
1327 1.1 oki goto doiohalf;
1328 1.1 oki
1329 1.1 oki case DORESET:
1330 1.1 oki DPRINTF(("fdcintr: in DORESET\n"));
1331 1.1 oki /* try a reset, keep motor on */
1332 1.1 oki fd_set_motor(fdc, 1);
1333 1.1 oki DELAY(100);
1334 1.1 oki fd_set_motor(fdc, 0);
1335 1.1 oki fdc->sc_state = RESETCOMPLETE;
1336 1.1 oki timeout(fdctimeout, fdc, hz / 2);
1337 1.1 oki return 1; /* will return later */
1338 1.1 oki
1339 1.1 oki case RESETCOMPLETE:
1340 1.1 oki DPRINTF(("fdcintr: in RESETCOMPLETE\n"));
1341 1.1 oki untimeout(fdctimeout, fdc);
1342 1.1 oki /* clear the controller output buffer */
1343 1.1 oki for (i = 0; i < 4; i++) {
1344 1.1 oki out_fdc(NE7CMD_SENSEI);
1345 1.1 oki (void) fdcresult(fdc);
1346 1.1 oki }
1347 1.1 oki
1348 1.1 oki /* fall through */
1349 1.1 oki case DORECAL:
1350 1.1 oki DPRINTF(("fdcintr: in DORECAL\n"));
1351 1.1 oki out_fdc(NE7CMD_RECAL); /* recalibrate function */
1352 1.1 oki out_fdc(fd->sc_drive);
1353 1.1 oki fdc->sc_state = RECALWAIT;
1354 1.1 oki timeout(fdctimeout, fdc, 5 * hz);
1355 1.1 oki return 1; /* will return later */
1356 1.1 oki
1357 1.1 oki case RECALWAIT:
1358 1.1 oki DPRINTF(("fdcintr: in RECALWAIT\n"));
1359 1.1 oki untimeout(fdctimeout, fdc);
1360 1.1 oki fdc->sc_state = RECALCOMPLETE;
1361 1.1 oki /* allow 1/30 second for heads to settle */
1362 1.1 oki /* timeout(fdcpseudointr, fdc, hz / 30);*/
1363 1.1 oki return 1; /* will return later */
1364 1.1 oki
1365 1.1 oki case RECALCOMPLETE:
1366 1.1 oki DPRINTF(("fdcintr: in RECALCOMPLETE\n"));
1367 1.1 oki out_fdc(NE7CMD_SENSEI);
1368 1.1 oki tmp = fdcresult(fdc);
1369 1.1 oki if ((st0 & 0xf8) == 0xc0) {
1370 1.1 oki DPRINTF(("fdcintr: first seek!\n"));
1371 1.1 oki fdc->sc_state = DORECAL;
1372 1.1 oki goto loop;
1373 1.1 oki } else if (tmp != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
1374 1.1 oki #ifdef FDDEBUG
1375 1.1 oki fdcstatus(&fd->sc_dev, 2, "recalibrate failed");
1376 1.1 oki #endif
1377 1.1 oki fdcretry(fdc);
1378 1.1 oki goto loop;
1379 1.1 oki }
1380 1.1 oki fd->sc_cylin = 0;
1381 1.1 oki goto doseek;
1382 1.1 oki
1383 1.1 oki case MOTORWAIT:
1384 1.1 oki if (fd->sc_flags & FD_MOTOR_WAIT)
1385 1.1 oki return 1; /* time's not up yet */
1386 1.1 oki goto doseek;
1387 1.1 oki
1388 1.1 oki default:
1389 1.1 oki fdcstatus(&fd->sc_dev, 0, "stray interrupt");
1390 1.1 oki return 1;
1391 1.1 oki }
1392 1.1 oki #ifdef DIAGNOSTIC
1393 1.1 oki panic("fdcintr: impossible");
1394 1.1 oki #endif
1395 1.1 oki #undef st0
1396 1.1 oki #undef cyl
1397 1.1 oki }
1398 1.1 oki
1399 1.1 oki void
1400 1.1 oki fdcretry(fdc)
1401 1.1 oki struct fdc_softc *fdc;
1402 1.1 oki {
1403 1.1 oki struct fd_softc *fd;
1404 1.1 oki struct buf *bp;
1405 1.11 oki char bits[64];
1406 1.1 oki
1407 1.1 oki DPRINTF(("fdcretry:\n"));
1408 1.1 oki fd = fdc->sc_drives.tqh_first;
1409 1.1 oki bp = fd->sc_q.b_actf;
1410 1.1 oki
1411 1.1 oki switch (fdc->sc_errors) {
1412 1.1 oki case 0:
1413 1.1 oki /* try again */
1414 1.1 oki fdc->sc_state = SEEKCOMPLETE;
1415 1.1 oki break;
1416 1.1 oki
1417 1.1 oki case 1: case 2: case 3:
1418 1.1 oki /* didn't work; try recalibrating */
1419 1.1 oki fdc->sc_state = DORECAL;
1420 1.1 oki break;
1421 1.1 oki
1422 1.1 oki case 4:
1423 1.1 oki /* still no go; reset the bastard */
1424 1.1 oki fdc->sc_state = DORESET;
1425 1.1 oki break;
1426 1.1 oki
1427 1.1 oki default:
1428 1.1 oki diskerr(bp, "fd", "hard error", LOG_PRINTF,
1429 1.1 oki fd->sc_skip, (struct disklabel *)NULL);
1430 1.10 oki printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0],
1431 1.10 oki NE7_ST0BITS, bits,
1432 1.10 oki sizeof(bits)));
1433 1.10 oki printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1],
1434 1.10 oki NE7_ST1BITS, bits,
1435 1.10 oki sizeof(bits)));
1436 1.10 oki printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2],
1437 1.10 oki NE7_ST2BITS, bits,
1438 1.10 oki sizeof(bits)));
1439 1.10 oki printf(" cyl %d head %d sec %d)\n",
1440 1.10 oki fdc->sc_status[3],
1441 1.10 oki fdc->sc_status[4],
1442 1.10 oki fdc->sc_status[5]);
1443 1.1 oki
1444 1.1 oki bp->b_flags |= B_ERROR;
1445 1.1 oki bp->b_error = EIO;
1446 1.1 oki fdfinish(fd, bp);
1447 1.1 oki }
1448 1.1 oki fdc->sc_errors++;
1449 1.1 oki }
1450 1.1 oki
1451 1.1 oki int
1452 1.1 oki fdsize(dev)
1453 1.1 oki dev_t dev;
1454 1.1 oki {
1455 1.1 oki
1456 1.1 oki /* Swapping to floppies would not make sense. */
1457 1.1 oki return -1;
1458 1.1 oki }
1459 1.1 oki
1460 1.1 oki int
1461 1.1 oki fddump(dev, blkno, va, size)
1462 1.1 oki dev_t dev;
1463 1.1 oki daddr_t blkno;
1464 1.1 oki caddr_t va;
1465 1.1 oki size_t size;
1466 1.1 oki {
1467 1.1 oki
1468 1.1 oki /* Not implemented. */
1469 1.1 oki return ENXIO;
1470 1.1 oki }
1471 1.1 oki
1472 1.1 oki int
1473 1.14 oki fdioctl(dev, cmd, addr, flag, p)
1474 1.1 oki dev_t dev;
1475 1.1 oki u_long cmd;
1476 1.1 oki caddr_t addr;
1477 1.1 oki int flag;
1478 1.14 oki struct proc *p;
1479 1.1 oki {
1480 1.1 oki struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
1481 1.1 oki int unit = FDUNIT(dev);
1482 1.1 oki struct disklabel buffer;
1483 1.1 oki int error;
1484 1.1 oki
1485 1.1 oki DPRINTF(("fdioctl:\n"));
1486 1.1 oki switch (cmd) {
1487 1.1 oki case DIOCGDINFO:
1488 1.1 oki #if 1
1489 1.1 oki *(struct disklabel *)addr = *(fd->sc_dk.dk_label);
1490 1.1 oki return(0);
1491 1.1 oki #else
1492 1.1 oki bzero(&buffer, sizeof(buffer));
1493 1.1 oki
1494 1.1 oki buffer.d_secpercyl = fd->sc_type->seccyl;
1495 1.1 oki buffer.d_type = DTYPE_FLOPPY;
1496 1.1 oki buffer.d_secsize = 128 << fd->sc_type->secsize;
1497 1.1 oki
1498 1.1 oki if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL)
1499 1.1 oki return EINVAL;
1500 1.1 oki
1501 1.1 oki *(struct disklabel *)addr = buffer;
1502 1.1 oki return 0;
1503 1.1 oki #endif
1504 1.1 oki
1505 1.1 oki case DIOCGPART:
1506 1.1 oki ((struct partinfo *)addr)->disklab = fd->sc_dk.dk_label;
1507 1.1 oki ((struct partinfo *)addr)->part =
1508 1.1 oki &fd->sc_dk.dk_label->d_partitions[DISKPART(dev)];
1509 1.1 oki return(0);
1510 1.1 oki
1511 1.1 oki case DIOCWLABEL:
1512 1.1 oki if ((flag & FWRITE) == 0)
1513 1.1 oki return EBADF;
1514 1.1 oki /* XXX do something */
1515 1.1 oki return 0;
1516 1.1 oki
1517 1.1 oki case DIOCWDINFO:
1518 1.1 oki if ((flag & FWRITE) == 0)
1519 1.1 oki return EBADF;
1520 1.1 oki
1521 1.1 oki error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL);
1522 1.1 oki if (error)
1523 1.1 oki return error;
1524 1.1 oki
1525 1.1 oki error = writedisklabel(dev, fdstrategy, &buffer, NULL);
1526 1.1 oki return error;
1527 1.1 oki
1528 1.1 oki case DIOCLOCK:
1529 1.1 oki /*
1530 1.1 oki * Nothing to do here, really.
1531 1.1 oki */
1532 1.1 oki return 0; /* XXX */
1533 1.1 oki
1534 1.1 oki case DIOCEJECT:
1535 1.1 oki fd_do_eject(unit);
1536 1.1 oki return 0;
1537 1.1 oki
1538 1.1 oki default:
1539 1.1 oki return ENOTTY;
1540 1.1 oki }
1541 1.1 oki
1542 1.1 oki #ifdef DIAGNOSTIC
1543 1.1 oki panic("fdioctl: impossible");
1544 1.1 oki #endif
1545 1.1 oki }
1546 1.1 oki
1547 1.1 oki void
1548 1.1 oki fd_do_eject(unit)
1549 1.1 oki int unit;
1550 1.1 oki {
1551 1.1 oki infdc.drvstat = 0x20 | ( 1 << unit);
1552 1.1 oki DELAY(1); /* XXX */
1553 1.1 oki infdc.drvstat = 0x20;
1554 1.1 oki }
1555 1.1 oki
1556 1.1 oki /*
1557 1.1 oki * Build disk label. For now we only create a label from what we know
1558 1.1 oki * from 'sc'.
1559 1.1 oki */
1560 1.1 oki static int
1561 1.1 oki fdgetdisklabel(sc, dev)
1562 1.1 oki struct fd_softc *sc;
1563 1.1 oki dev_t dev;
1564 1.1 oki {
1565 1.1 oki struct disklabel *lp;
1566 1.1 oki int part;
1567 1.1 oki
1568 1.1 oki #ifdef FDDEBUG
1569 1.8 christos printf("fdgetdisklabel()\n");
1570 1.1 oki #endif
1571 1.1 oki
1572 1.1 oki part = DISKPART(dev);
1573 1.1 oki lp = sc->sc_dk.dk_label;
1574 1.1 oki bzero(lp, sizeof(struct disklabel));
1575 1.1 oki
1576 1.1 oki lp->d_secsize = 128 << sc->sc_type->secsize;
1577 1.1 oki lp->d_ntracks = sc->sc_type->heads;
1578 1.1 oki lp->d_nsectors = sc->sc_type->sectrac;
1579 1.1 oki lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1580 1.1 oki lp->d_ncylinders = sc->sc_type->size / lp->d_secpercyl;
1581 1.1 oki lp->d_secperunit = sc->sc_type->size;
1582 1.1 oki
1583 1.1 oki lp->d_type = DTYPE_FLOPPY;
1584 1.1 oki lp->d_rpm = 300; /* XXX */
1585 1.1 oki lp->d_interleave = 1; /* FIXME: is this OK? */
1586 1.1 oki lp->d_bbsize = 0;
1587 1.1 oki lp->d_sbsize = 0;
1588 1.1 oki lp->d_npartitions = part + 1;
1589 1.1 oki #define STEP_DELAY 6000 /* 6ms (6000us) delay after stepping */
1590 1.1 oki lp->d_trkseek = STEP_DELAY; /* XXX */
1591 1.1 oki lp->d_magic = DISKMAGIC;
1592 1.1 oki lp->d_magic2 = DISKMAGIC;
1593 1.1 oki lp->d_checksum = dkcksum(lp);
1594 1.1 oki lp->d_partitions[part].p_size = lp->d_secperunit;
1595 1.1 oki lp->d_partitions[part].p_fstype = FS_UNUSED;
1596 1.1 oki lp->d_partitions[part].p_fsize = 1024;
1597 1.1 oki lp->d_partitions[part].p_frag = 8;
1598 1.1 oki
1599 1.1 oki return(0);
1600 1.1 oki }
1601 1.1 oki
1602 1.14 oki /*
1603 1.14 oki * Mountroot hook: prompt the user to enter the root file system
1604 1.14 oki * floppy.
1605 1.14 oki */
1606 1.4 oki void
1607 1.4 oki fd_mountroot_hook(dev)
1608 1.4 oki struct device *dev;
1609 1.4 oki {
1610 1.4 oki int c;
1611 1.4 oki
1612 1.4 oki fd_do_eject(dev->dv_unit);
1613 1.8 christos printf("Insert filesystem floppy and press return.");
1614 1.4 oki for (;;) {
1615 1.4 oki c = cngetc();
1616 1.4 oki if ((c == '\r') || (c == '\n')) {
1617 1.8 christos printf("\n");
1618 1.14 oki break;
1619 1.4 oki }
1620 1.4 oki }
1621 1.4 oki }
1622