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