fd.c revision 1.2 1 1.2 thorpej /* $NetBSD: fd.c,v 1.2 2001/11/22 18:34:33 thorpej Exp $ */
2 1.1 reinoud
3 1.1 reinoud /*-
4 1.1 reinoud * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 1.1 reinoud * All rights reserved.
6 1.1 reinoud *
7 1.1 reinoud * This code is derived from software contributed to The NetBSD Foundation
8 1.1 reinoud * by Charles M. Hannum.
9 1.1 reinoud *
10 1.1 reinoud * Redistribution and use in source and binary forms, with or without
11 1.1 reinoud * modification, are permitted provided that the following conditions
12 1.1 reinoud * are met:
13 1.1 reinoud * 1. Redistributions of source code must retain the above copyright
14 1.1 reinoud * notice, this list of conditions and the following disclaimer.
15 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 reinoud * notice, this list of conditions and the following disclaimer in the
17 1.1 reinoud * documentation and/or other materials provided with the distribution.
18 1.1 reinoud * 3. All advertising materials mentioning features or use of this software
19 1.1 reinoud * must display the following acknowledgement:
20 1.1 reinoud * This product includes software developed by the NetBSD
21 1.1 reinoud * Foundation, Inc. and its contributors.
22 1.1 reinoud * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 reinoud * contributors may be used to endorse or promote products derived
24 1.1 reinoud * from this software without specific prior written permission.
25 1.1 reinoud *
26 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 reinoud * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 reinoud * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 reinoud * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 reinoud * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 reinoud * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 reinoud * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 reinoud * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 reinoud * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 reinoud * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 reinoud * POSSIBILITY OF SUCH DAMAGE.
37 1.1 reinoud */
38 1.1 reinoud
39 1.1 reinoud /*-
40 1.1 reinoud * Copyright (c) 1990 The Regents of the University of California.
41 1.1 reinoud * All rights reserved.
42 1.1 reinoud *
43 1.1 reinoud * This code is derived from software contributed to Berkeley by
44 1.1 reinoud * Don Ahn.
45 1.1 reinoud *
46 1.1 reinoud * Redistribution and use in source and binary forms, with or without
47 1.1 reinoud * modification, are permitted provided that the following conditions
48 1.1 reinoud * are met:
49 1.1 reinoud * 1. Redistributions of source code must retain the above copyright
50 1.1 reinoud * notice, this list of conditions and the following disclaimer.
51 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright
52 1.1 reinoud * notice, this list of conditions and the following disclaimer in the
53 1.1 reinoud * documentation and/or other materials provided with the distribution.
54 1.1 reinoud * 3. All advertising materials mentioning features or use of this software
55 1.1 reinoud * must display the following acknowledgement:
56 1.1 reinoud * This product includes software developed by the University of
57 1.1 reinoud * California, Berkeley and its contributors.
58 1.1 reinoud * 4. Neither the name of the University nor the names of its contributors
59 1.1 reinoud * may be used to endorse or promote products derived from this software
60 1.1 reinoud * without specific prior written permission.
61 1.1 reinoud *
62 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 1.1 reinoud * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 1.1 reinoud * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 1.1 reinoud * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 1.1 reinoud * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 1.1 reinoud * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 1.1 reinoud * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 1.1 reinoud * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 1.1 reinoud * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 1.1 reinoud * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 1.1 reinoud * SUCH DAMAGE.
73 1.1 reinoud *
74 1.1 reinoud * @(#)fd.c 7.4 (Berkeley) 5/25/91
75 1.1 reinoud * from: fd.c,v 1.104 1997/01/09 04:30:08 mycroft Exp
76 1.1 reinoud */
77 1.1 reinoud
78 1.1 reinoud /*
79 1.1 reinoud * Floppy formatting facilities merged from FreeBSD fd.c driver:
80 1.1 reinoud * Id: fd.c,v 1.53 1995/03/12 22:40:56 joerg Exp
81 1.1 reinoud * which carries the same copyright/redistribution notice as shown above with
82 1.1 reinoud * the addition of the following statement before the "Redistribution and
83 1.1 reinoud * use ..." clause:
84 1.1 reinoud *
85 1.1 reinoud * Copyright (c) 1993, 1994 by
86 1.1 reinoud * jc (at) irbs.UUCP (John Capo)
87 1.1 reinoud * vak (at) zebub.msk.su (Serge Vakulenko)
88 1.1 reinoud * ache (at) astral.msk.su (Andrew A. Chernov)
89 1.1 reinoud *
90 1.1 reinoud * Copyright (c) 1993, 1994, 1995 by
91 1.1 reinoud * joerg_wunsch (at) uriah.sax.de (Joerg Wunsch)
92 1.1 reinoud * dufault (at) hda.com (Peter Dufault)
93 1.1 reinoud */
94 1.1 reinoud
95 1.1 reinoud #include "opt_ddb.h"
96 1.1 reinoud
97 1.1 reinoud #include <sys/param.h>
98 1.1 reinoud #include <sys/systm.h>
99 1.1 reinoud #include <sys/callout.h>
100 1.1 reinoud #include <sys/kernel.h>
101 1.1 reinoud #include <sys/file.h>
102 1.1 reinoud #include <sys/ioctl.h>
103 1.1 reinoud #include <sys/device.h>
104 1.1 reinoud #include <sys/disklabel.h>
105 1.1 reinoud #include <sys/dkstat.h>
106 1.1 reinoud #include <sys/disk.h>
107 1.1 reinoud #include <sys/buf.h>
108 1.1 reinoud #include <sys/malloc.h>
109 1.1 reinoud #include <sys/uio.h>
110 1.1 reinoud #include <sys/syslog.h>
111 1.1 reinoud #include <sys/queue.h>
112 1.1 reinoud #include <sys/proc.h>
113 1.1 reinoud #include <sys/fdio.h>
114 1.1 reinoud
115 1.1 reinoud #include <uvm/uvm_extern.h>
116 1.1 reinoud
117 1.1 reinoud #include <machine/cpu.h>
118 1.1 reinoud #include <machine/irqhandler.h>
119 1.1 reinoud #include <machine/conf.h>
120 1.1 reinoud #include <machine/io.h>
121 1.2 thorpej #include <arm/arm32/katelib.h>
122 1.1 reinoud #include <machine/bus.h>
123 1.1 reinoud #include <arm/iomd/iomdreg.h>
124 1.1 reinoud #include <acorn32/mainbus/piocvar.h>
125 1.1 reinoud #include <acorn32/mainbus/fdreg.h>
126 1.1 reinoud
127 1.1 reinoud #include "locators.h"
128 1.1 reinoud
129 1.1 reinoud #define NE7CMD_CONFIGURE 0x13
130 1.1 reinoud
131 1.1 reinoud #define FDUNIT(dev) (minor(dev) / 8)
132 1.1 reinoud #define FDTYPE(dev) (minor(dev) % 8)
133 1.1 reinoud
134 1.1 reinoud /* XXX misuse a flag to identify format operation */
135 1.1 reinoud #define B_FORMAT B_XXX
136 1.1 reinoud
137 1.1 reinoud enum fdc_state {
138 1.1 reinoud DEVIDLE = 0,
139 1.1 reinoud MOTORWAIT,
140 1.1 reinoud DOSEEK,
141 1.1 reinoud SEEKWAIT,
142 1.1 reinoud SEEKTIMEDOUT,
143 1.1 reinoud SEEKCOMPLETE,
144 1.1 reinoud DOIO,
145 1.1 reinoud IOCOMPLETE,
146 1.1 reinoud IOTIMEDOUT,
147 1.1 reinoud DORESET,
148 1.1 reinoud RESETCOMPLETE,
149 1.1 reinoud RESETTIMEDOUT,
150 1.1 reinoud DORECAL,
151 1.1 reinoud RECALWAIT,
152 1.1 reinoud RECALTIMEDOUT,
153 1.1 reinoud RECALCOMPLETE,
154 1.1 reinoud };
155 1.1 reinoud
156 1.1 reinoud /* software state, per controller */
157 1.1 reinoud struct fdc_softc {
158 1.1 reinoud struct device sc_dev; /* boilerplate */
159 1.1 reinoud #ifdef NEWCONFIG
160 1.1 reinoud struct isadev sc_id;
161 1.1 reinoud #endif
162 1.1 reinoud void *sc_ih;
163 1.1 reinoud
164 1.1 reinoud bus_space_tag_t sc_iot; /* ISA i/o space identifier */
165 1.1 reinoud bus_space_handle_t sc_ioh; /* ISA io handle */
166 1.1 reinoud
167 1.1 reinoud struct callout sc_timo_ch; /* timeout callout */
168 1.1 reinoud struct callout sc_intr_ch; /* pseudo-intr callout */
169 1.1 reinoud
170 1.1 reinoud int sc_drq;
171 1.1 reinoud
172 1.1 reinoud struct fd_softc *sc_fd[4]; /* pointers to children */
173 1.1 reinoud TAILQ_HEAD(drivehead, fd_softc) sc_drives;
174 1.1 reinoud enum fdc_state sc_state;
175 1.1 reinoud int sc_errors; /* number of retries so far */
176 1.1 reinoud u_char sc_status[7]; /* copy of registers */
177 1.1 reinoud };
178 1.1 reinoud
179 1.1 reinoud /* controller driver configuration */
180 1.1 reinoud int fdcprobe __P((struct device *, struct cfdata *, void *));
181 1.1 reinoud int fdprint __P((void *, const char *));
182 1.1 reinoud #ifdef NEWCONFIG
183 1.1 reinoud void fdcforceintr __P((void *));
184 1.1 reinoud #endif
185 1.1 reinoud void fdcattach __P((struct device *, struct device *, void *));
186 1.1 reinoud
187 1.1 reinoud struct cfattach fdc_ca = {
188 1.1 reinoud sizeof(struct fdc_softc), fdcprobe, fdcattach
189 1.1 reinoud };
190 1.1 reinoud
191 1.1 reinoud /*
192 1.1 reinoud * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
193 1.1 reinoud * we tell them apart.
194 1.1 reinoud */
195 1.1 reinoud struct fd_type {
196 1.1 reinoud int sectrac; /* sectors per track */
197 1.1 reinoud int heads; /* number of heads */
198 1.1 reinoud int seccyl; /* sectors per cylinder */
199 1.1 reinoud int secsize; /* size code for sectors */
200 1.1 reinoud int datalen; /* data len when secsize = 0 */
201 1.1 reinoud int steprate; /* step rate and head unload time */
202 1.1 reinoud int gap1; /* gap len between sectors */
203 1.1 reinoud int gap2; /* formatting gap */
204 1.1 reinoud int cyls; /* total num of cylinders */
205 1.1 reinoud int size; /* size of disk in sectors */
206 1.1 reinoud int step; /* steps per cylinder */
207 1.1 reinoud int rate; /* transfer speed code */
208 1.1 reinoud u_char fillbyte; /* format fill byte */
209 1.1 reinoud u_char interleave; /* interleave factor (formatting) */
210 1.1 reinoud char *name;
211 1.1 reinoud };
212 1.1 reinoud
213 1.1 reinoud /* The order of entries in the following table is important -- BEWARE! */
214 1.1 reinoud struct fd_type fd_types[] = {
215 1.1 reinoud { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB" }, /* 1.44MB diskette */
216 1.1 reinoud { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS,0xf6,1, "1.2MB" }, /* 1.2 MB AT-diskettes */
217 1.1 reinoud { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS,0xf6,1, "360KB/AT" }, /* 360kB in 1.2MB drive */
218 1.1 reinoud { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS,0xf6,1, "360KB/PC" }, /* 360kB PC diskettes */
219 1.1 reinoud { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB" }, /* 3.5" 720kB diskette */
220 1.1 reinoud { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS,0xf6,1, "720KB/x" }, /* 720kB in 1.2MB drive */
221 1.1 reinoud { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS,0xf6,1, "360KB/x" }, /* 360kB in 720kB drive */
222 1.1 reinoud };
223 1.1 reinoud
224 1.1 reinoud /* software state, per disk (with up to 4 disks per ctlr) */
225 1.1 reinoud struct fd_softc {
226 1.1 reinoud struct device sc_dev;
227 1.1 reinoud struct disk sc_dk;
228 1.1 reinoud
229 1.1 reinoud struct fd_type *sc_deftype; /* default type descriptor */
230 1.1 reinoud struct fd_type *sc_type; /* current type descriptor */
231 1.1 reinoud struct fd_type sc_type_copy; /* copy for fiddling when formatting */
232 1.1 reinoud
233 1.1 reinoud struct callout sc_motoron_ch;
234 1.1 reinoud struct callout sc_motoroff_ch;
235 1.1 reinoud
236 1.1 reinoud daddr_t sc_blkno; /* starting block number */
237 1.1 reinoud int sc_bcount; /* byte count left */
238 1.1 reinoud int sc_opts; /* user-set options */
239 1.1 reinoud int sc_skip; /* bytes already transferred */
240 1.1 reinoud int sc_nblks; /* number of blocks currently transferring */
241 1.1 reinoud int sc_nbytes; /* number of bytes currently transferring */
242 1.1 reinoud
243 1.1 reinoud int sc_drive; /* physical unit number */
244 1.1 reinoud int sc_flags;
245 1.1 reinoud #define FD_OPEN 0x01 /* it's open */
246 1.1 reinoud #define FD_MOTOR 0x02 /* motor should be on */
247 1.1 reinoud #define FD_MOTOR_WAIT 0x04 /* motor coming up */
248 1.1 reinoud int sc_cylin; /* where we think the head is */
249 1.1 reinoud
250 1.1 reinoud void *sc_sdhook; /* saved shutdown hook for drive. */
251 1.1 reinoud
252 1.1 reinoud TAILQ_ENTRY(fd_softc) sc_drivechain;
253 1.1 reinoud int sc_ops; /* I/O ops since last switch */
254 1.1 reinoud struct buf_queue sc_q; /* pending I/O requests */
255 1.1 reinoud int sc_active; /* number of active I/O operations */
256 1.1 reinoud };
257 1.1 reinoud
258 1.1 reinoud /* floppy driver configuration */
259 1.1 reinoud int fdprobe __P((struct device *, struct cfdata *, void *));
260 1.1 reinoud void fdattach __P((struct device *, struct device *, void *));
261 1.1 reinoud
262 1.1 reinoud static fiqhandler_t fiqhandler;
263 1.1 reinoud
264 1.1 reinoud void floppy_read_fiq __P((void));
265 1.1 reinoud void floppy_write_fiq __P((void));
266 1.1 reinoud
267 1.1 reinoud struct cfattach fd_ca = {
268 1.1 reinoud sizeof(struct fd_softc), fdprobe, fdattach
269 1.1 reinoud };
270 1.1 reinoud
271 1.1 reinoud extern struct cfdriver fd_cd;
272 1.1 reinoud
273 1.1 reinoud void fdgetdisklabel __P((struct fd_softc *));
274 1.1 reinoud int fd_get_parms __P((struct fd_softc *));
275 1.1 reinoud void fdstrategy __P((struct buf *));
276 1.1 reinoud void fdstart __P((struct fd_softc *));
277 1.1 reinoud
278 1.1 reinoud struct dkdriver fddkdriver = { fdstrategy };
279 1.1 reinoud
280 1.1 reinoud struct fd_type *fd_nvtotype __P((char *, int, int));
281 1.1 reinoud void fd_set_motor __P((struct fdc_softc *fdc, int reset));
282 1.1 reinoud void fd_motor_off __P((void *arg));
283 1.1 reinoud void fd_motor_on __P((void *arg));
284 1.1 reinoud int fdcresult __P((struct fdc_softc *fdc));
285 1.1 reinoud int out_fdc __P((bus_space_tag_t iot, bus_space_handle_t ioh, u_char x));
286 1.1 reinoud void fdcstart __P((struct fdc_softc *fdc));
287 1.1 reinoud void fdcstatus __P((struct device *dv, int n, char *s));
288 1.1 reinoud void fdctimeout __P((void *arg));
289 1.1 reinoud void fdcpseudointr __P((void *arg));
290 1.1 reinoud int fdcintr __P((void *));
291 1.1 reinoud void fdcretry __P((struct fdc_softc *fdc));
292 1.1 reinoud void fdfinish __P((struct fd_softc *fd, struct buf *bp));
293 1.1 reinoud __inline struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t));
294 1.1 reinoud int fdformat __P((dev_t, struct ne7_fd_formb *, struct proc *));
295 1.1 reinoud
296 1.1 reinoud int
297 1.1 reinoud fdcprobe(parent, cf, aux)
298 1.1 reinoud struct device *parent;
299 1.1 reinoud struct cfdata *cf;
300 1.1 reinoud void *aux;
301 1.1 reinoud {
302 1.1 reinoud struct pioc_attach_args *pa = aux;
303 1.1 reinoud bus_space_tag_t iot;
304 1.1 reinoud bus_space_handle_t ioh;
305 1.1 reinoud int rv;
306 1.1 reinoud
307 1.1 reinoud if (pa->pa_name && strcmp(pa->pa_name, "fdc") != 0)
308 1.1 reinoud return(0);
309 1.1 reinoud
310 1.1 reinoud iot = pa->pa_iot;
311 1.1 reinoud rv = 0;
312 1.1 reinoud
313 1.1 reinoud /* Map the i/o space. */
314 1.1 reinoud if (bus_space_map(iot, pa->pa_iobase + pa->pa_offset, FDC_NPORT, 0, &ioh))
315 1.1 reinoud return 0;
316 1.1 reinoud
317 1.1 reinoud /* reset */
318 1.1 reinoud bus_space_write_2(iot, ioh, fdout, 0);
319 1.1 reinoud delay(100);
320 1.1 reinoud bus_space_write_2(iot, ioh, fdout, FDO_FRST);
321 1.1 reinoud
322 1.1 reinoud /* see if it can handle a command */
323 1.1 reinoud if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0)
324 1.1 reinoud goto out;
325 1.1 reinoud out_fdc(iot, ioh, 0xdf);
326 1.1 reinoud out_fdc(iot, ioh, 2);
327 1.1 reinoud
328 1.1 reinoud #ifdef NEWCONFIG
329 1.1 reinoud if (pa->pa_iobase == PIOCCF_BASE_DEFAULT || pa->pa_drq == PIOCCF_DACK_DEFAULT)
330 1.1 reinoud return 0;
331 1.1 reinoud
332 1.1 reinoud if (pa->pa_irq == PIOCCF_IRQ_DEFAULT) {
333 1.1 reinoud pa->pa_irq = isa_discoverintr(fdcforceintr, aux);
334 1.1 reinoud if (pa->pa_irq == IRQNONE)
335 1.1 reinoud goto out;
336 1.1 reinoud
337 1.1 reinoud /* reset it again */
338 1.1 reinoud bus_space_write_2(iot, ioh, fdout, 0);
339 1.1 reinoud delay(100);
340 1.1 reinoud bus_space_write_2(iot, ioh, fdout, FDO_FRST);
341 1.1 reinoud }
342 1.1 reinoud #endif
343 1.1 reinoud
344 1.1 reinoud rv = 1;
345 1.1 reinoud pa->pa_iosize = FDC_NPORT;
346 1.1 reinoud
347 1.1 reinoud out:
348 1.1 reinoud bus_space_unmap(iot, ioh, FDC_NPORT);
349 1.1 reinoud return rv;
350 1.1 reinoud }
351 1.1 reinoud
352 1.1 reinoud #ifdef NEWCONFIG
353 1.1 reinoud /*
354 1.1 reinoud * XXX This is broken, and needs fixing. In general, the interface needs
355 1.1 reinoud * XXX to change.
356 1.1 reinoud */
357 1.1 reinoud void
358 1.1 reinoud fdcforceintr(aux)
359 1.1 reinoud void *aux;
360 1.1 reinoud {
361 1.1 reinoud struct isa_attach_args *ia = aux;
362 1.1 reinoud int iobase = ia->ia_iobase;
363 1.1 reinoud
364 1.1 reinoud /* the motor is off; this should generate an error with or
365 1.1 reinoud without a disk drive present */
366 1.1 reinoud out_fdc(iot, ioh, NE7CMD_SEEK);
367 1.1 reinoud out_fdc(iot, ioh, 0);
368 1.1 reinoud out_fdc(iot, ioh, 0);
369 1.1 reinoud }
370 1.1 reinoud #endif
371 1.1 reinoud
372 1.1 reinoud /*
373 1.1 reinoud * Arguments passed between fdcattach and fdprobe.
374 1.1 reinoud */
375 1.1 reinoud struct fdc_attach_args {
376 1.1 reinoud int fa_drive;
377 1.1 reinoud struct fd_type *fa_deftype;
378 1.1 reinoud };
379 1.1 reinoud
380 1.1 reinoud /*
381 1.1 reinoud * Print the location of a disk drive (called just before attaching the
382 1.1 reinoud * the drive). If `fdc' is not NULL, the drive was found but was not
383 1.1 reinoud * in the system config file; print the drive name as well.
384 1.1 reinoud * Return QUIET (config_find ignores this if the device was configured) to
385 1.1 reinoud * avoid printing `fdN not configured' messages.
386 1.1 reinoud */
387 1.1 reinoud int
388 1.1 reinoud fdprint(aux, fdc)
389 1.1 reinoud void *aux;
390 1.1 reinoud const char *fdc;
391 1.1 reinoud {
392 1.1 reinoud register struct fdc_attach_args *fa = aux;
393 1.1 reinoud
394 1.1 reinoud if (!fdc)
395 1.1 reinoud printf(" drive %d", fa->fa_drive);
396 1.1 reinoud return QUIET;
397 1.1 reinoud }
398 1.1 reinoud
399 1.1 reinoud void
400 1.1 reinoud fdcattach(parent, self, aux)
401 1.1 reinoud struct device *parent, *self;
402 1.1 reinoud void *aux;
403 1.1 reinoud {
404 1.1 reinoud struct fdc_softc *fdc = (void *)self;
405 1.1 reinoud bus_space_tag_t iot;
406 1.1 reinoud bus_space_handle_t ioh;
407 1.1 reinoud struct pioc_attach_args *pa = aux;
408 1.1 reinoud struct fdc_attach_args fa;
409 1.1 reinoud int type;
410 1.1 reinoud
411 1.1 reinoud iot = pa->pa_iot;
412 1.1 reinoud
413 1.1 reinoud /* Re-map the I/O space. */
414 1.1 reinoud if (bus_space_map(iot, pa->pa_iobase + pa->pa_offset, FDC_NPORT, 0, &ioh))
415 1.1 reinoud panic("fdcattach: couldn't map I/O ports");
416 1.1 reinoud
417 1.1 reinoud fdc->sc_iot = iot;
418 1.1 reinoud fdc->sc_ioh = ioh;
419 1.1 reinoud
420 1.1 reinoud fdc->sc_drq = pa->pa_iobase + pa->pa_offset + pa->pa_drq;
421 1.1 reinoud fdc->sc_state = DEVIDLE;
422 1.1 reinoud TAILQ_INIT(&fdc->sc_drives);
423 1.1 reinoud
424 1.1 reinoud printf("\n");
425 1.1 reinoud
426 1.1 reinoud callout_init(&fdc->sc_timo_ch);
427 1.1 reinoud callout_init(&fdc->sc_intr_ch);
428 1.1 reinoud
429 1.1 reinoud #ifdef NEWCONFIG
430 1.1 reinoud at_setup_dmachan(fdc->sc_drq, FDC_MAXIOSIZE);
431 1.1 reinoud isa_establish(&fdc->sc_id, &fdc->sc_dev);
432 1.1 reinoud #endif
433 1.1 reinoud fdc->sc_ih = intr_claim(pa->pa_irq, IPL_BIO, "fdc",
434 1.1 reinoud fdcintr, fdc);
435 1.1 reinoud if (!fdc->sc_ih)
436 1.1 reinoud panic("%s: Cannot claim IRQ %d\n", self->dv_xname, pa->pa_irq);
437 1.1 reinoud
438 1.1 reinoud #if 0
439 1.1 reinoud /*
440 1.1 reinoud * The NVRAM info only tells us about the first two disks on the
441 1.1 reinoud * `primary' floppy controller.
442 1.1 reinoud */
443 1.1 reinoud if (fdc->sc_dev.dv_unit == 0)
444 1.1 reinoud type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */
445 1.1 reinoud else
446 1.1 reinoud type = -1;
447 1.1 reinoud #endif
448 1.1 reinoud type = 0x10; /* XXX - hardcoded for 1 floppy */
449 1.1 reinoud
450 1.1 reinoud /* physical limit: four drives per controller. */
451 1.1 reinoud for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
452 1.1 reinoud if (type >= 0 && fa.fa_drive < 2)
453 1.1 reinoud fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
454 1.1 reinoud type, fa.fa_drive);
455 1.1 reinoud else
456 1.1 reinoud fa.fa_deftype = NULL; /* unknown */
457 1.1 reinoud (void)config_found(self, (void *)&fa, fdprint);
458 1.1 reinoud }
459 1.1 reinoud }
460 1.1 reinoud
461 1.1 reinoud int
462 1.1 reinoud fdprobe(parent, cf, aux)
463 1.1 reinoud struct device *parent;
464 1.1 reinoud struct cfdata *cf;
465 1.1 reinoud void *aux;
466 1.1 reinoud {
467 1.1 reinoud struct fdc_softc *fdc = (void *)parent;
468 1.1 reinoud struct fdc_attach_args *fa = aux;
469 1.1 reinoud int drive = fa->fa_drive;
470 1.1 reinoud bus_space_tag_t iot = fdc->sc_iot;
471 1.1 reinoud bus_space_handle_t ioh = fdc->sc_ioh;
472 1.1 reinoud int n;
473 1.1 reinoud
474 1.1 reinoud if (cf->cf_loc[FDCCF_DRIVE] != FDCCF_DRIVE_DEFAULT
475 1.1 reinoud && cf->cf_loc[FDCCF_DRIVE] != drive)
476 1.1 reinoud return 0;
477 1.1 reinoud /*
478 1.1 reinoud * XXX
479 1.1 reinoud * This is to work around some odd interactions between this driver
480 1.1 reinoud * and SMC Ethernet cards.
481 1.1 reinoud */
482 1.1 reinoud
483 1.1 reinoud /* Don't need this for arm32 port but leave for the time being (it won't hurt) */
484 1.1 reinoud
485 1.1 reinoud if (cf->cf_loc[FDCCF_DRIVE] == FDCCF_DRIVE_DEFAULT && drive >= 2)
486 1.1 reinoud return 0;
487 1.1 reinoud
488 1.1 reinoud /* select drive and turn on motor */
489 1.1 reinoud bus_space_write_2(iot, ioh, fdout, drive | FDO_FRST | FDO_MOEN(drive));
490 1.1 reinoud /* wait for motor to spin up */
491 1.1 reinoud delay(250000);
492 1.1 reinoud out_fdc(iot, ioh, NE7CMD_RECAL);
493 1.1 reinoud out_fdc(iot, ioh, drive);
494 1.1 reinoud /* wait for recalibrate */
495 1.1 reinoud delay(2000000);
496 1.1 reinoud out_fdc(iot, ioh, NE7CMD_SENSEI);
497 1.1 reinoud n = fdcresult(fdc);
498 1.1 reinoud #ifdef FD_DEBUG
499 1.1 reinoud {
500 1.1 reinoud int i;
501 1.1 reinoud printf("fdprobe: status");
502 1.1 reinoud for (i = 0; i < n; i++)
503 1.1 reinoud printf(" %x", fdc->sc_status[i]);
504 1.1 reinoud printf("\n");
505 1.1 reinoud }
506 1.1 reinoud #endif
507 1.1 reinoud /* turn off motor */
508 1.1 reinoud bus_space_write_1(iot, ioh, fdout, FDO_FRST);
509 1.1 reinoud
510 1.1 reinoud if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20)
511 1.1 reinoud return 0;
512 1.1 reinoud
513 1.1 reinoud return 1;
514 1.1 reinoud }
515 1.1 reinoud
516 1.1 reinoud /*
517 1.1 reinoud * Controller is working, and drive responded. Attach it.
518 1.1 reinoud */
519 1.1 reinoud void
520 1.1 reinoud fdattach(parent, self, aux)
521 1.1 reinoud struct device *parent, *self;
522 1.1 reinoud void *aux;
523 1.1 reinoud {
524 1.1 reinoud struct fdc_softc *fdc = (void *)parent;
525 1.1 reinoud struct fd_softc *fd = (void *)self;
526 1.1 reinoud struct fdc_attach_args *fa = aux;
527 1.1 reinoud struct fd_type *type = fa->fa_deftype;
528 1.1 reinoud int drive = fa->fa_drive;
529 1.1 reinoud
530 1.1 reinoud callout_init(&fd->sc_motoron_ch);
531 1.1 reinoud callout_init(&fd->sc_motoroff_ch);
532 1.1 reinoud
533 1.1 reinoud /* XXX Allow `flags' to override device type? */
534 1.1 reinoud
535 1.1 reinoud if (type)
536 1.1 reinoud printf(": %s %d cyl, %d head, %d sec\n", type->name,
537 1.1 reinoud type->cyls, type->heads, type->sectrac);
538 1.1 reinoud else
539 1.1 reinoud printf(": density unknown\n");
540 1.1 reinoud
541 1.1 reinoud BUFQ_INIT(&fd->sc_q);
542 1.1 reinoud fd->sc_cylin = -1;
543 1.1 reinoud fd->sc_drive = drive;
544 1.1 reinoud fd->sc_deftype = type;
545 1.1 reinoud fdc->sc_fd[drive] = fd;
546 1.1 reinoud
547 1.1 reinoud /*
548 1.1 reinoud * Initialize and attach the disk structure.
549 1.1 reinoud */
550 1.1 reinoud fd->sc_dk.dk_name = fd->sc_dev.dv_xname;
551 1.1 reinoud fd->sc_dk.dk_driver = &fddkdriver;
552 1.1 reinoud disk_attach(&fd->sc_dk);
553 1.1 reinoud
554 1.1 reinoud /* Needed to power off if the motor is on when we halt. */
555 1.1 reinoud
556 1.1 reinoud }
557 1.1 reinoud
558 1.1 reinoud /*
559 1.1 reinoud * Translate nvram type into internal data structure. Return NULL for
560 1.1 reinoud * none/unknown/unusable.
561 1.1 reinoud */
562 1.1 reinoud struct fd_type *
563 1.1 reinoud fd_nvtotype(fdc, nvraminfo, drive)
564 1.1 reinoud char *fdc;
565 1.1 reinoud int nvraminfo, drive;
566 1.1 reinoud {
567 1.1 reinoud int type;
568 1.1 reinoud
569 1.1 reinoud type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0;
570 1.1 reinoud switch (type) {
571 1.1 reinoud #ifndef RC7500
572 1.1 reinoud case 0x00 :
573 1.1 reinoud return NULL;
574 1.1 reinoud #else
575 1.1 reinoud case 0x00 :
576 1.1 reinoud #endif /* !RC7500 */
577 1.1 reinoud case 0x10 :
578 1.1 reinoud return &fd_types[0];
579 1.1 reinoud default:
580 1.1 reinoud printf("%s: drive %d: unknown device type 0x%x\n",
581 1.1 reinoud fdc, drive, type);
582 1.1 reinoud return NULL;
583 1.1 reinoud }
584 1.1 reinoud }
585 1.1 reinoud
586 1.1 reinoud __inline struct fd_type *
587 1.1 reinoud fd_dev_to_type(fd, dev)
588 1.1 reinoud struct fd_softc *fd;
589 1.1 reinoud dev_t dev;
590 1.1 reinoud {
591 1.1 reinoud int type = FDTYPE(dev);
592 1.1 reinoud
593 1.1 reinoud if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
594 1.1 reinoud return NULL;
595 1.1 reinoud return type ? &fd_types[type - 1] : fd->sc_deftype;
596 1.1 reinoud }
597 1.1 reinoud
598 1.1 reinoud void
599 1.1 reinoud fdstrategy(bp)
600 1.1 reinoud register struct buf *bp; /* IO operation to perform */
601 1.1 reinoud {
602 1.1 reinoud struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(bp->b_dev)];
603 1.1 reinoud int sz;
604 1.1 reinoud int s;
605 1.1 reinoud
606 1.1 reinoud /* Valid unit, controller, and request? */
607 1.1 reinoud if (bp->b_blkno < 0 ||
608 1.1 reinoud ((bp->b_bcount % FDC_BSIZE) != 0 &&
609 1.1 reinoud (bp->b_flags & B_FORMAT) == 0)) {
610 1.1 reinoud bp->b_error = EINVAL;
611 1.1 reinoud goto bad;
612 1.1 reinoud }
613 1.1 reinoud
614 1.1 reinoud /* If it's a null transfer, return immediately. */
615 1.1 reinoud if (bp->b_bcount == 0)
616 1.1 reinoud goto done;
617 1.1 reinoud
618 1.1 reinoud sz = howmany(bp->b_bcount, FDC_BSIZE);
619 1.1 reinoud
620 1.1 reinoud if (bp->b_blkno + sz > fd->sc_type->size) {
621 1.1 reinoud sz = fd->sc_type->size - bp->b_blkno;
622 1.1 reinoud if (sz == 0) {
623 1.1 reinoud /* If exactly at end of disk, return EOF. */
624 1.1 reinoud goto done;
625 1.1 reinoud }
626 1.1 reinoud if (sz < 0) {
627 1.1 reinoud /* If past end of disk, return EINVAL. */
628 1.1 reinoud bp->b_error = EINVAL;
629 1.1 reinoud goto bad;
630 1.1 reinoud }
631 1.1 reinoud /* Otherwise, truncate request. */
632 1.1 reinoud bp->b_bcount = sz << DEV_BSHIFT;
633 1.1 reinoud }
634 1.1 reinoud
635 1.1 reinoud bp->b_rawblkno = bp->b_blkno;
636 1.1 reinoud bp->b_cylinder = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl;
637 1.1 reinoud
638 1.1 reinoud #ifdef FD_DEBUG
639 1.1 reinoud printf("fdstrategy: b_blkno %d b_bcount %d blkno %d cylin %d sz %d\n",
640 1.1 reinoud bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylinder, sz);
641 1.1 reinoud #endif
642 1.1 reinoud
643 1.1 reinoud /* Queue transfer on drive, activate drive and controller if idle. */
644 1.1 reinoud s = splbio();
645 1.1 reinoud disksort_cylinder(&fd->sc_q, bp);
646 1.1 reinoud callout_stop(&fd->sc_motoroff_ch); /* a good idea */
647 1.1 reinoud if (fd->sc_active == 0)
648 1.1 reinoud fdstart(fd);
649 1.1 reinoud #ifdef DIAGNOSTIC
650 1.1 reinoud else {
651 1.1 reinoud struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
652 1.1 reinoud if (fdc->sc_state == DEVIDLE) {
653 1.1 reinoud printf("fdstrategy: controller inactive\n");
654 1.1 reinoud fdcstart(fdc);
655 1.1 reinoud }
656 1.1 reinoud }
657 1.1 reinoud #endif
658 1.1 reinoud splx(s);
659 1.1 reinoud return;
660 1.1 reinoud
661 1.1 reinoud bad:
662 1.1 reinoud bp->b_flags |= B_ERROR;
663 1.1 reinoud done:
664 1.1 reinoud /* Toss transfer; we're done early. */
665 1.1 reinoud bp->b_resid = bp->b_bcount;
666 1.1 reinoud biodone(bp);
667 1.1 reinoud }
668 1.1 reinoud
669 1.1 reinoud void
670 1.1 reinoud fdstart(fd)
671 1.1 reinoud struct fd_softc *fd;
672 1.1 reinoud {
673 1.1 reinoud struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
674 1.1 reinoud int active = fdc->sc_drives.tqh_first != 0;
675 1.1 reinoud
676 1.1 reinoud /* Link into controller queue. */
677 1.1 reinoud fd->sc_active = 1;
678 1.1 reinoud TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
679 1.1 reinoud
680 1.1 reinoud /* If controller not already active, start it. */
681 1.1 reinoud if (!active)
682 1.1 reinoud fdcstart(fdc);
683 1.1 reinoud }
684 1.1 reinoud
685 1.1 reinoud void
686 1.1 reinoud fdfinish(fd, bp)
687 1.1 reinoud struct fd_softc *fd;
688 1.1 reinoud struct buf *bp;
689 1.1 reinoud {
690 1.1 reinoud struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
691 1.1 reinoud
692 1.1 reinoud /*
693 1.1 reinoud * Move this drive to the end of the queue to give others a `fair'
694 1.1 reinoud * chance. We only force a switch if N operations are completed while
695 1.1 reinoud * another drive is waiting to be serviced, since there is a long motor
696 1.1 reinoud * startup delay whenever we switch.
697 1.1 reinoud */
698 1.1 reinoud if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) {
699 1.1 reinoud fd->sc_ops = 0;
700 1.1 reinoud TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
701 1.1 reinoud if (BUFQ_NEXT(bp) != NULL)
702 1.1 reinoud TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
703 1.1 reinoud else
704 1.1 reinoud fd->sc_active = 0;
705 1.1 reinoud }
706 1.1 reinoud bp->b_resid = fd->sc_bcount;
707 1.1 reinoud fd->sc_skip = 0;
708 1.1 reinoud BUFQ_REMOVE(&fd->sc_q, bp);
709 1.1 reinoud
710 1.1 reinoud biodone(bp);
711 1.1 reinoud /* turn off motor 5s from now */
712 1.1 reinoud callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd);
713 1.1 reinoud fdc->sc_state = DEVIDLE;
714 1.1 reinoud }
715 1.1 reinoud
716 1.1 reinoud int
717 1.1 reinoud fdread(dev, uio, flags)
718 1.1 reinoud dev_t dev;
719 1.1 reinoud struct uio *uio;
720 1.1 reinoud int flags;
721 1.1 reinoud {
722 1.1 reinoud
723 1.1 reinoud return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
724 1.1 reinoud }
725 1.1 reinoud
726 1.1 reinoud int
727 1.1 reinoud fdwrite(dev, uio, flags)
728 1.1 reinoud dev_t dev;
729 1.1 reinoud struct uio *uio;
730 1.1 reinoud int flags;
731 1.1 reinoud {
732 1.1 reinoud
733 1.1 reinoud return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
734 1.1 reinoud }
735 1.1 reinoud
736 1.1 reinoud void
737 1.1 reinoud fd_set_motor(fdc, reset)
738 1.1 reinoud struct fdc_softc *fdc;
739 1.1 reinoud int reset;
740 1.1 reinoud {
741 1.1 reinoud struct fd_softc *fd;
742 1.1 reinoud u_char status;
743 1.1 reinoud int n;
744 1.1 reinoud
745 1.1 reinoud if ((fd = fdc->sc_drives.tqh_first) != NULL)
746 1.1 reinoud status = fd->sc_drive;
747 1.1 reinoud else
748 1.1 reinoud status = 0;
749 1.1 reinoud if (!reset)
750 1.1 reinoud status |= FDO_FRST | FDO_FDMAEN;
751 1.1 reinoud for (n = 0; n < 4; n++)
752 1.1 reinoud if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
753 1.1 reinoud status |= FDO_MOEN(n);
754 1.1 reinoud bus_space_write_2(fdc->sc_iot, fdc->sc_ioh, fdout, status);
755 1.1 reinoud }
756 1.1 reinoud
757 1.1 reinoud void
758 1.1 reinoud fd_motor_off(arg)
759 1.1 reinoud void *arg;
760 1.1 reinoud {
761 1.1 reinoud struct fd_softc *fd = arg;
762 1.1 reinoud int s;
763 1.1 reinoud
764 1.1 reinoud s = splbio();
765 1.1 reinoud fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
766 1.1 reinoud fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0);
767 1.1 reinoud splx(s);
768 1.1 reinoud }
769 1.1 reinoud
770 1.1 reinoud void
771 1.1 reinoud fd_motor_on(arg)
772 1.1 reinoud void *arg;
773 1.1 reinoud {
774 1.1 reinoud struct fd_softc *fd = arg;
775 1.1 reinoud struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
776 1.1 reinoud int s;
777 1.1 reinoud
778 1.1 reinoud s = splbio();
779 1.1 reinoud fd->sc_flags &= ~FD_MOTOR_WAIT;
780 1.1 reinoud if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
781 1.1 reinoud (void) fdcintr(fdc);
782 1.1 reinoud splx(s);
783 1.1 reinoud }
784 1.1 reinoud
785 1.1 reinoud int
786 1.1 reinoud fdcresult(fdc)
787 1.1 reinoud struct fdc_softc *fdc;
788 1.1 reinoud {
789 1.1 reinoud bus_space_tag_t iot = fdc->sc_iot;
790 1.1 reinoud bus_space_handle_t ioh = fdc->sc_ioh;
791 1.1 reinoud u_char i;
792 1.1 reinoud int j = 100000,
793 1.1 reinoud n = 0;
794 1.1 reinoud
795 1.1 reinoud for (; j; j--) {
796 1.1 reinoud i = bus_space_read_1(iot, ioh, fdsts) &
797 1.1 reinoud (NE7_DIO | NE7_RQM | NE7_CB);
798 1.1 reinoud if (i == NE7_RQM)
799 1.1 reinoud return n;
800 1.1 reinoud if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
801 1.1 reinoud if (n >= sizeof(fdc->sc_status)) {
802 1.1 reinoud log(LOG_ERR, "fdcresult: overrun\n");
803 1.1 reinoud return -1;
804 1.1 reinoud }
805 1.1 reinoud fdc->sc_status[n++] =
806 1.1 reinoud bus_space_read_1(iot, ioh, fddata);
807 1.1 reinoud }
808 1.1 reinoud delay(10);
809 1.1 reinoud }
810 1.1 reinoud log(LOG_ERR, "fdcresult: timeout\n");
811 1.1 reinoud return -1;
812 1.1 reinoud }
813 1.1 reinoud
814 1.1 reinoud int
815 1.1 reinoud out_fdc(iot, ioh, x)
816 1.1 reinoud bus_space_tag_t iot;
817 1.1 reinoud bus_space_handle_t ioh;
818 1.1 reinoud u_char x;
819 1.1 reinoud {
820 1.1 reinoud int i = 100000;
821 1.1 reinoud
822 1.1 reinoud while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0);
823 1.1 reinoud if (i <= 0)
824 1.1 reinoud return -1;
825 1.1 reinoud while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
826 1.1 reinoud if (i <= 0)
827 1.1 reinoud return -1;
828 1.1 reinoud bus_space_write_2(iot, ioh, fddata, x);
829 1.1 reinoud return 0;
830 1.1 reinoud }
831 1.1 reinoud
832 1.1 reinoud int
833 1.1 reinoud fdopen(dev, flags, mode, p)
834 1.1 reinoud dev_t dev;
835 1.1 reinoud int flags;
836 1.1 reinoud int mode;
837 1.1 reinoud struct proc *p;
838 1.1 reinoud {
839 1.1 reinoud int unit;
840 1.1 reinoud struct fd_softc *fd;
841 1.1 reinoud struct fd_type *type;
842 1.1 reinoud
843 1.1 reinoud unit = FDUNIT(dev);
844 1.1 reinoud if (unit >= fd_cd.cd_ndevs)
845 1.1 reinoud return ENXIO;
846 1.1 reinoud fd = fd_cd.cd_devs[unit];
847 1.1 reinoud if (fd == 0)
848 1.1 reinoud return ENXIO;
849 1.1 reinoud type = fd_dev_to_type(fd, dev);
850 1.1 reinoud if (type == NULL)
851 1.1 reinoud return ENXIO;
852 1.1 reinoud
853 1.1 reinoud if ((fd->sc_flags & FD_OPEN) != 0 &&
854 1.1 reinoud memcmp(fd->sc_type, type, sizeof(*type)))
855 1.1 reinoud return EBUSY;
856 1.1 reinoud
857 1.1 reinoud fd->sc_type_copy = *type;
858 1.1 reinoud fd->sc_type = &fd->sc_type_copy;
859 1.1 reinoud fd->sc_cylin = -1;
860 1.1 reinoud fd->sc_flags |= FD_OPEN;
861 1.1 reinoud
862 1.1 reinoud return 0;
863 1.1 reinoud }
864 1.1 reinoud
865 1.1 reinoud int
866 1.1 reinoud fdclose(dev, flags, mode, p)
867 1.1 reinoud dev_t dev;
868 1.1 reinoud int flags;
869 1.1 reinoud int mode;
870 1.1 reinoud struct proc *p;
871 1.1 reinoud {
872 1.1 reinoud struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
873 1.1 reinoud
874 1.1 reinoud fd->sc_flags &= ~FD_OPEN;
875 1.1 reinoud fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT);
876 1.1 reinoud return 0;
877 1.1 reinoud }
878 1.1 reinoud
879 1.1 reinoud void
880 1.1 reinoud fdcstart(fdc)
881 1.1 reinoud struct fdc_softc *fdc;
882 1.1 reinoud {
883 1.1 reinoud
884 1.1 reinoud #ifdef DIAGNOSTIC
885 1.1 reinoud /* only got here if controller's drive queue was inactive; should
886 1.1 reinoud be in idle state */
887 1.1 reinoud if (fdc->sc_state != DEVIDLE) {
888 1.1 reinoud printf("fdcstart: not idle\n");
889 1.1 reinoud return;
890 1.1 reinoud }
891 1.1 reinoud #endif
892 1.1 reinoud (void) fdcintr(fdc);
893 1.1 reinoud }
894 1.1 reinoud
895 1.1 reinoud void
896 1.1 reinoud fdcstatus(dv, n, s)
897 1.1 reinoud struct device *dv;
898 1.1 reinoud int n;
899 1.1 reinoud char *s;
900 1.1 reinoud {
901 1.1 reinoud struct fdc_softc *fdc = (void *)dv->dv_parent;
902 1.1 reinoud char bits[64];
903 1.1 reinoud
904 1.1 reinoud if (n == 0) {
905 1.1 reinoud out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI);
906 1.1 reinoud (void) fdcresult(fdc);
907 1.1 reinoud n = 2;
908 1.1 reinoud }
909 1.1 reinoud
910 1.1 reinoud printf("%s: %s", dv->dv_xname, s);
911 1.1 reinoud
912 1.1 reinoud switch (n) {
913 1.1 reinoud case 0:
914 1.1 reinoud printf("\n");
915 1.1 reinoud break;
916 1.1 reinoud case 2:
917 1.1 reinoud printf(" (st0 %s cyl %d)\n",
918 1.1 reinoud bitmask_snprintf(fdc->sc_status[0], NE7_ST0BITS,
919 1.1 reinoud bits, sizeof(bits)), fdc->sc_status[1]);
920 1.1 reinoud break;
921 1.1 reinoud case 7:
922 1.1 reinoud printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0],
923 1.1 reinoud NE7_ST0BITS, bits, sizeof(bits)));
924 1.1 reinoud printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1],
925 1.1 reinoud NE7_ST1BITS, bits, sizeof(bits)));
926 1.1 reinoud printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2],
927 1.1 reinoud NE7_ST2BITS, bits, sizeof(bits)));
928 1.1 reinoud printf(" cyl %d head %d sec %d)\n",
929 1.1 reinoud fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
930 1.1 reinoud break;
931 1.1 reinoud #ifdef DIAGNOSTIC
932 1.1 reinoud default:
933 1.1 reinoud printf("\nfdcstatus: weird size");
934 1.1 reinoud break;
935 1.1 reinoud #endif
936 1.1 reinoud }
937 1.1 reinoud }
938 1.1 reinoud
939 1.1 reinoud void
940 1.1 reinoud fdctimeout(arg)
941 1.1 reinoud void *arg;
942 1.1 reinoud {
943 1.1 reinoud struct fdc_softc *fdc = arg;
944 1.1 reinoud struct fd_softc *fd = fdc->sc_drives.tqh_first;
945 1.1 reinoud int s;
946 1.1 reinoud
947 1.1 reinoud s = splbio();
948 1.1 reinoud #ifdef DEBUG
949 1.1 reinoud log(LOG_ERR,"fdctimeout: state %d\n", fdc->sc_state);
950 1.1 reinoud #endif
951 1.1 reinoud fdcstatus(&fd->sc_dev, 0, "timeout");
952 1.1 reinoud
953 1.1 reinoud if (BUFQ_FIRST(&fd->sc_q) != NULL)
954 1.1 reinoud fdc->sc_state++;
955 1.1 reinoud else
956 1.1 reinoud fdc->sc_state = DEVIDLE;
957 1.1 reinoud
958 1.1 reinoud (void) fdcintr(fdc);
959 1.1 reinoud splx(s);
960 1.1 reinoud }
961 1.1 reinoud
962 1.1 reinoud void
963 1.1 reinoud fdcpseudointr(arg)
964 1.1 reinoud void *arg;
965 1.1 reinoud {
966 1.1 reinoud int s;
967 1.1 reinoud
968 1.1 reinoud /* Just ensure it has the right spl. */
969 1.1 reinoud s = splbio();
970 1.1 reinoud (void) fdcintr(arg);
971 1.1 reinoud splx(s);
972 1.1 reinoud }
973 1.1 reinoud
974 1.1 reinoud int
975 1.1 reinoud fdcintr(arg)
976 1.1 reinoud void *arg;
977 1.1 reinoud {
978 1.1 reinoud struct fdc_softc *fdc = arg;
979 1.1 reinoud #define st0 fdc->sc_status[0]
980 1.1 reinoud #define cyl fdc->sc_status[1]
981 1.1 reinoud struct fd_softc *fd;
982 1.1 reinoud struct buf *bp;
983 1.1 reinoud bus_space_tag_t iot = fdc->sc_iot;
984 1.1 reinoud bus_space_handle_t ioh = fdc->sc_ioh;
985 1.1 reinoud int read, head, sec, i, nblks;
986 1.1 reinoud struct fd_type *type;
987 1.1 reinoud struct ne7_fd_formb *finfo = NULL;
988 1.1 reinoud
989 1.1 reinoud loop:
990 1.1 reinoud /* Is there a drive for the controller to do a transfer with? */
991 1.1 reinoud fd = fdc->sc_drives.tqh_first;
992 1.1 reinoud if (fd == NULL) {
993 1.1 reinoud fdc->sc_state = DEVIDLE;
994 1.1 reinoud return 1;
995 1.1 reinoud }
996 1.1 reinoud
997 1.1 reinoud /* Is there a transfer to this drive? If not, deactivate drive. */
998 1.1 reinoud bp = BUFQ_FIRST(&fd->sc_q);
999 1.1 reinoud if (bp == NULL) {
1000 1.1 reinoud fd->sc_ops = 0;
1001 1.1 reinoud TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
1002 1.1 reinoud fd->sc_active = 0;
1003 1.1 reinoud goto loop;
1004 1.1 reinoud }
1005 1.1 reinoud
1006 1.1 reinoud if (bp->b_flags & B_FORMAT)
1007 1.1 reinoud finfo = (struct ne7_fd_formb *)bp->b_data;
1008 1.1 reinoud
1009 1.1 reinoud switch (fdc->sc_state) {
1010 1.1 reinoud case DEVIDLE:
1011 1.1 reinoud fdc->sc_errors = 0;
1012 1.1 reinoud fd->sc_skip = 0;
1013 1.1 reinoud fd->sc_bcount = bp->b_bcount;
1014 1.1 reinoud fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE);
1015 1.1 reinoud callout_stop(&fd->sc_motoroff_ch);
1016 1.1 reinoud if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
1017 1.1 reinoud fdc->sc_state = MOTORWAIT;
1018 1.1 reinoud return 1;
1019 1.1 reinoud }
1020 1.1 reinoud if ((fd->sc_flags & FD_MOTOR) == 0) {
1021 1.1 reinoud /* Turn on the motor, being careful about pairing. */
1022 1.1 reinoud struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1];
1023 1.1 reinoud if (ofd && ofd->sc_flags & FD_MOTOR) {
1024 1.1 reinoud callout_stop(&ofd->sc_motoroff_ch);
1025 1.1 reinoud ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
1026 1.1 reinoud }
1027 1.1 reinoud fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
1028 1.1 reinoud fd_set_motor(fdc, 0);
1029 1.1 reinoud fdc->sc_state = MOTORWAIT;
1030 1.1 reinoud /* Allow .25s for motor to stabilize. */
1031 1.1 reinoud callout_reset(&fd->sc_motoron_ch, hz / 4,
1032 1.1 reinoud fd_motor_on, fd);
1033 1.1 reinoud return 1;
1034 1.1 reinoud }
1035 1.1 reinoud /* Make sure the right drive is selected. */
1036 1.1 reinoud fd_set_motor(fdc, 0);
1037 1.1 reinoud
1038 1.1 reinoud /* fall through */
1039 1.1 reinoud case DOSEEK:
1040 1.1 reinoud doseek:
1041 1.1 reinoud if (fd->sc_cylin == bp->b_cylinder)
1042 1.1 reinoud goto doio;
1043 1.1 reinoud
1044 1.1 reinoud #if 1
1045 1.1 reinoud out_fdc(iot, ioh, NE7CMD_CONFIGURE);/* configure command */
1046 1.1 reinoud out_fdc(iot, ioh, 0);
1047 1.1 reinoud out_fdc(iot, ioh, 0x18);
1048 1.1 reinoud out_fdc(iot, ioh, 0);
1049 1.1 reinoud #endif
1050 1.1 reinoud out_fdc(iot, ioh, NE7CMD_SPECIFY);/* specify command */
1051 1.1 reinoud out_fdc(iot, ioh, fd->sc_type->steprate);
1052 1.1 reinoud out_fdc(iot, ioh, 6); /* XXX head load time == 6ms */
1053 1.1 reinoud
1054 1.1 reinoud out_fdc(iot, ioh, NE7CMD_SEEK); /* seek function */
1055 1.1 reinoud out_fdc(iot, ioh, fd->sc_drive); /* drive number */
1056 1.1 reinoud out_fdc(iot, ioh, bp->b_cylinder * fd->sc_type->step);
1057 1.1 reinoud
1058 1.1 reinoud fd->sc_cylin = -1;
1059 1.1 reinoud fdc->sc_state = SEEKWAIT;
1060 1.1 reinoud
1061 1.1 reinoud fd->sc_dk.dk_seek++;
1062 1.1 reinoud disk_busy(&fd->sc_dk);
1063 1.1 reinoud
1064 1.1 reinoud callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
1065 1.1 reinoud return 1;
1066 1.1 reinoud
1067 1.1 reinoud case DOIO:
1068 1.1 reinoud doio:
1069 1.1 reinoud type = fd->sc_type;
1070 1.1 reinoud if (finfo)
1071 1.1 reinoud fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) -
1072 1.1 reinoud (char *)finfo;
1073 1.1 reinoud sec = fd->sc_blkno % type->seccyl;
1074 1.1 reinoud nblks = type->seccyl - sec;
1075 1.1 reinoud nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
1076 1.1 reinoud nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE);
1077 1.1 reinoud fd->sc_nblks = nblks;
1078 1.1 reinoud fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FDC_BSIZE;
1079 1.1 reinoud head = sec / type->sectrac;
1080 1.1 reinoud sec -= head * type->sectrac;
1081 1.1 reinoud #ifdef DIAGNOSTIC
1082 1.1 reinoud {int block;
1083 1.1 reinoud block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
1084 1.1 reinoud if (block != fd->sc_blkno) {
1085 1.1 reinoud printf("fdcintr: block %d != blkno %d\n",
1086 1.1 reinoud block, fd->sc_blkno);
1087 1.1 reinoud #ifdef DDB
1088 1.1 reinoud Debugger();
1089 1.1 reinoud #endif
1090 1.1 reinoud }}
1091 1.1 reinoud #endif
1092 1.1 reinoud read = bp->b_flags & B_READ;
1093 1.1 reinoud #ifdef NEWCONFIG
1094 1.1 reinoud at_dma(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
1095 1.1 reinoud fdc->sc_drq);
1096 1.1 reinoud #else
1097 1.1 reinoud /* isa_dmastart(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
1098 1.1 reinoud fdc->sc_drq);*/
1099 1.1 reinoud if (read)
1100 1.1 reinoud fiqhandler.fh_func = floppy_read_fiq;
1101 1.1 reinoud else
1102 1.1 reinoud fiqhandler.fh_func = floppy_write_fiq;
1103 1.1 reinoud fiqhandler.fh_r9 = IOMD_BASE + (IOMD_FIQRQ << 2);
1104 1.1 reinoud fiqhandler.fh_r10 = fd->sc_nbytes;
1105 1.1 reinoud fiqhandler.fh_r11 = (u_int)(bp->b_data + fd->sc_skip);
1106 1.1 reinoud fiqhandler.fh_r12 = fdc->sc_drq;
1107 1.1 reinoud /* fiqhandler.fh_r13 = 0;*/
1108 1.1 reinoud fiqhandler.fh_mask = 0x01;
1109 1.1 reinoud #ifdef FD_DEBUG
1110 1.1 reinoud printf("fdc-doio:r9=%x r10=%x r11=%x r12=%x data=%x skip=%x\n", fiqhandler.fh_r9,
1111 1.1 reinoud fiqhandler.fh_r10, fiqhandler.fh_r11,
1112 1.1 reinoud fiqhandler.fh_r12, (u_int)bp->b_data, fd->sc_skip);
1113 1.1 reinoud #endif
1114 1.1 reinoud if (fiq_claim(&fiqhandler) == -1)
1115 1.1 reinoud panic("%s: Cannot claim FIQ vector\n", fdc->sc_dev.dv_xname);
1116 1.1 reinoud #endif
1117 1.1 reinoud bus_space_write_2(iot, ioh, fdctl, type->rate);
1118 1.1 reinoud #ifdef FD_DEBUG
1119 1.1 reinoud printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
1120 1.1 reinoud read ? "read" : "write", fd->sc_drive, fd->sc_cylin,
1121 1.1 reinoud head, sec, nblks);
1122 1.1 reinoud #endif
1123 1.1 reinoud if (finfo) {
1124 1.1 reinoud /* formatting */
1125 1.1 reinoud if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) {
1126 1.1 reinoud fdc->sc_errors = 4;
1127 1.1 reinoud fdcretry(fdc);
1128 1.1 reinoud goto loop;
1129 1.1 reinoud }
1130 1.1 reinoud out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
1131 1.1 reinoud out_fdc(iot, ioh, finfo->fd_formb_secshift);
1132 1.1 reinoud out_fdc(iot, ioh, finfo->fd_formb_nsecs);
1133 1.1 reinoud out_fdc(iot, ioh, finfo->fd_formb_gaplen);
1134 1.1 reinoud out_fdc(iot, ioh, finfo->fd_formb_fillbyte);
1135 1.1 reinoud } else {
1136 1.1 reinoud if (read)
1137 1.1 reinoud out_fdc(iot, ioh, NE7CMD_READ); /* READ */
1138 1.1 reinoud else
1139 1.1 reinoud out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */
1140 1.1 reinoud out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
1141 1.1 reinoud out_fdc(iot, ioh, fd->sc_cylin); /* track */
1142 1.1 reinoud out_fdc(iot, ioh, head);
1143 1.1 reinoud out_fdc(iot, ioh, sec + 1); /* sector +1 */
1144 1.1 reinoud out_fdc(iot, ioh, type->secsize);/* sector size */
1145 1.1 reinoud out_fdc(iot, ioh, type->sectrac);/* sectors/track */
1146 1.1 reinoud out_fdc(iot, ioh, type->gap1); /* gap1 size */
1147 1.1 reinoud out_fdc(iot, ioh, type->datalen);/* data length */
1148 1.1 reinoud }
1149 1.1 reinoud fdc->sc_state = IOCOMPLETE;
1150 1.1 reinoud
1151 1.1 reinoud disk_busy(&fd->sc_dk);
1152 1.1 reinoud
1153 1.1 reinoud /* allow 2 seconds for operation */
1154 1.1 reinoud callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
1155 1.1 reinoud return 1; /* will return later */
1156 1.1 reinoud
1157 1.1 reinoud case SEEKWAIT:
1158 1.1 reinoud callout_stop(&fdc->sc_timo_ch);
1159 1.1 reinoud fdc->sc_state = SEEKCOMPLETE;
1160 1.1 reinoud /* allow 1/50 second for heads to settle */
1161 1.1 reinoud #if 0
1162 1.1 reinoud callout_reset(&fdc->sc_intr_ch, hz / 50, fdcpseudointr, fdc);
1163 1.1 reinoud #endif
1164 1.1 reinoud return 1;
1165 1.1 reinoud
1166 1.1 reinoud case SEEKCOMPLETE:
1167 1.1 reinoud disk_unbusy(&fd->sc_dk, 0); /* no data on seek */
1168 1.1 reinoud
1169 1.1 reinoud /* Make sure seek really happened. */
1170 1.1 reinoud out_fdc(iot, ioh, NE7CMD_SENSEI);
1171 1.1 reinoud if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
1172 1.1 reinoud cyl != bp->b_cylinder * fd->sc_type->step) {
1173 1.1 reinoud #ifdef FD_DEBUG
1174 1.1 reinoud fdcstatus(&fd->sc_dev, 2, "seek failed");
1175 1.1 reinoud #endif
1176 1.1 reinoud fdcretry(fdc);
1177 1.1 reinoud goto loop;
1178 1.1 reinoud }
1179 1.1 reinoud fd->sc_cylin = bp->b_cylinder;
1180 1.1 reinoud goto doio;
1181 1.1 reinoud
1182 1.1 reinoud case IOTIMEDOUT:
1183 1.1 reinoud #ifdef NEWCONFIG
1184 1.1 reinoud at_dma_abort(fdc->sc_drq);
1185 1.1 reinoud #else
1186 1.1 reinoud /* isa_dmaabort(fdc->sc_drq);*/
1187 1.1 reinoud if (fiq_release(&fiqhandler) == -1)
1188 1.1 reinoud panic("%s: Cannot release FIQ vector\n", fdc->sc_dev.dv_xname);
1189 1.1 reinoud #endif
1190 1.1 reinoud case SEEKTIMEDOUT:
1191 1.1 reinoud case RECALTIMEDOUT:
1192 1.1 reinoud case RESETTIMEDOUT:
1193 1.1 reinoud fdcretry(fdc);
1194 1.1 reinoud goto loop;
1195 1.1 reinoud
1196 1.1 reinoud case IOCOMPLETE: /* IO DONE, post-analyze */
1197 1.1 reinoud callout_stop(&fdc->sc_timo_ch);
1198 1.1 reinoud
1199 1.1 reinoud disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid));
1200 1.1 reinoud
1201 1.1 reinoud if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
1202 1.1 reinoud #ifdef NEWCONFIG
1203 1.1 reinoud at_dma_abort(fdc->sc_drq);
1204 1.1 reinoud #else
1205 1.1 reinoud /* isa_dmaabort(fdc->sc_drq);*/
1206 1.1 reinoud if (fiq_release(&fiqhandler) == -1)
1207 1.1 reinoud panic("%s: Cannot release FIQ vector\n", fdc->sc_dev.dv_xname);
1208 1.1 reinoud #endif
1209 1.1 reinoud #ifdef FD_DEBUG
1210 1.1 reinoud fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
1211 1.1 reinoud "read failed" : "write failed");
1212 1.1 reinoud printf("blkno %d nblks %d\n",
1213 1.1 reinoud fd->sc_blkno, fd->sc_nblks);
1214 1.1 reinoud #endif
1215 1.1 reinoud fdcretry(fdc);
1216 1.1 reinoud goto loop;
1217 1.1 reinoud }
1218 1.1 reinoud #ifdef NEWCONFIG
1219 1.1 reinoud at_dma_terminate(fdc->sc_drq);
1220 1.1 reinoud #else
1221 1.1 reinoud /* read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE;
1222 1.1 reinoud isa_dmadone(read, bp->b_data + fd->sc_skip, fd->sc_nbytes,
1223 1.1 reinoud fdc->sc_drq);*/
1224 1.1 reinoud if (fiq_release(&fiqhandler) == -1)
1225 1.1 reinoud panic("%s: Cannot release FIQ vector\n", fdc->sc_dev.dv_xname);
1226 1.1 reinoud #endif
1227 1.1 reinoud if (fdc->sc_errors) {
1228 1.1 reinoud #if 0
1229 1.1 reinoud diskerr(bp, "fd", "soft error (corrected)", LOG_PRINTF,
1230 1.1 reinoud fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
1231 1.1 reinoud printf("\n");
1232 1.1 reinoud #endif
1233 1.1 reinoud fdc->sc_errors = 0;
1234 1.1 reinoud }
1235 1.1 reinoud fd->sc_blkno += fd->sc_nblks;
1236 1.1 reinoud fd->sc_skip += fd->sc_nbytes;
1237 1.1 reinoud fd->sc_bcount -= fd->sc_nbytes;
1238 1.1 reinoud if (!finfo && fd->sc_bcount > 0) {
1239 1.1 reinoud bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl;
1240 1.1 reinoud goto doseek;
1241 1.1 reinoud }
1242 1.1 reinoud fdfinish(fd, bp);
1243 1.1 reinoud goto loop;
1244 1.1 reinoud
1245 1.1 reinoud case DORESET:
1246 1.1 reinoud /* try a reset, keep motor on */
1247 1.1 reinoud fd_set_motor(fdc, 1);
1248 1.1 reinoud delay(100);
1249 1.1 reinoud fd_set_motor(fdc, 0);
1250 1.1 reinoud fdc->sc_state = RESETCOMPLETE;
1251 1.1 reinoud callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc);
1252 1.1 reinoud return 1; /* will return later */
1253 1.1 reinoud
1254 1.1 reinoud case RESETCOMPLETE:
1255 1.1 reinoud callout_stop(&fdc->sc_timo_ch);
1256 1.1 reinoud /* clear the controller output buffer */
1257 1.1 reinoud for (i = 0; i < 4; i++) {
1258 1.1 reinoud out_fdc(iot, ioh, NE7CMD_SENSEI);
1259 1.1 reinoud (void) fdcresult(fdc);
1260 1.1 reinoud }
1261 1.1 reinoud
1262 1.1 reinoud /* fall through */
1263 1.1 reinoud case DORECAL:
1264 1.1 reinoud out_fdc(iot, ioh, NE7CMD_RECAL); /* recalibrate function */
1265 1.1 reinoud out_fdc(iot, ioh, fd->sc_drive);
1266 1.1 reinoud fdc->sc_state = RECALWAIT;
1267 1.1 reinoud callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc);
1268 1.1 reinoud return 1; /* will return later */
1269 1.1 reinoud
1270 1.1 reinoud case RECALWAIT:
1271 1.1 reinoud callout_stop(&fdc->sc_timo_ch);
1272 1.1 reinoud fdc->sc_state = RECALCOMPLETE;
1273 1.1 reinoud /* allow 1/30 second for heads to settle */
1274 1.1 reinoud #if 0
1275 1.1 reinoud callout_reset(&fdc->sc_intr_ch, hz / 30, fdcpseudointr, fdc);
1276 1.1 reinoud #endif
1277 1.1 reinoud return 1; /* will return later */
1278 1.1 reinoud
1279 1.1 reinoud case RECALCOMPLETE:
1280 1.1 reinoud out_fdc(iot, ioh, NE7CMD_SENSEI);
1281 1.1 reinoud if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
1282 1.1 reinoud #ifdef FD_DEBUG
1283 1.1 reinoud fdcstatus(&fd->sc_dev, 2, "recalibrate failed");
1284 1.1 reinoud #endif
1285 1.1 reinoud fdcretry(fdc);
1286 1.1 reinoud goto loop;
1287 1.1 reinoud }
1288 1.1 reinoud fd->sc_cylin = 0;
1289 1.1 reinoud goto doseek;
1290 1.1 reinoud
1291 1.1 reinoud case MOTORWAIT:
1292 1.1 reinoud if (fd->sc_flags & FD_MOTOR_WAIT)
1293 1.1 reinoud return 1; /* time's not up yet */
1294 1.1 reinoud goto doseek;
1295 1.1 reinoud
1296 1.1 reinoud default:
1297 1.1 reinoud fdcstatus(&fd->sc_dev, 0, "stray interrupt");
1298 1.1 reinoud return 1;
1299 1.1 reinoud }
1300 1.1 reinoud #ifdef DIAGNOSTIC
1301 1.1 reinoud panic("fdcintr: impossible");
1302 1.1 reinoud #endif
1303 1.1 reinoud #undef st0
1304 1.1 reinoud #undef cyl
1305 1.1 reinoud }
1306 1.1 reinoud
1307 1.1 reinoud void
1308 1.1 reinoud fdcretry(fdc)
1309 1.1 reinoud struct fdc_softc *fdc;
1310 1.1 reinoud {
1311 1.1 reinoud char bits[64];
1312 1.1 reinoud struct fd_softc *fd;
1313 1.1 reinoud struct buf *bp;
1314 1.1 reinoud
1315 1.1 reinoud fd = fdc->sc_drives.tqh_first;
1316 1.1 reinoud bp = BUFQ_FIRST(&fd->sc_q);
1317 1.1 reinoud
1318 1.1 reinoud if (fd->sc_opts & FDOPT_NORETRY)
1319 1.1 reinoud goto fail;
1320 1.1 reinoud switch (fdc->sc_errors) {
1321 1.1 reinoud case 0:
1322 1.1 reinoud /* try again */
1323 1.1 reinoud fdc->sc_state = DOSEEK;
1324 1.1 reinoud break;
1325 1.1 reinoud
1326 1.1 reinoud case 1: case 2: case 3:
1327 1.1 reinoud /* didn't work; try recalibrating */
1328 1.1 reinoud fdc->sc_state = DORECAL;
1329 1.1 reinoud break;
1330 1.1 reinoud
1331 1.1 reinoud case 4:
1332 1.1 reinoud /* still no go; reset the bastard */
1333 1.1 reinoud fdc->sc_state = DORESET;
1334 1.1 reinoud break;
1335 1.1 reinoud
1336 1.1 reinoud default:
1337 1.1 reinoud fail:
1338 1.1 reinoud if ((fd->sc_opts & FDOPT_SILENT) == 0) {
1339 1.1 reinoud diskerr(bp, "fd", "hard error", LOG_PRINTF,
1340 1.1 reinoud fd->sc_skip / FDC_BSIZE,
1341 1.1 reinoud (struct disklabel *)NULL);
1342 1.1 reinoud
1343 1.1 reinoud printf(" (st0 %s",
1344 1.1 reinoud bitmask_snprintf(fdc->sc_status[0],
1345 1.1 reinoud NE7_ST0BITS, bits,
1346 1.1 reinoud sizeof(bits)));
1347 1.1 reinoud printf(" st1 %s",
1348 1.1 reinoud bitmask_snprintf(fdc->sc_status[1],
1349 1.1 reinoud NE7_ST1BITS, bits,
1350 1.1 reinoud sizeof(bits)));
1351 1.1 reinoud printf(" st2 %s",
1352 1.1 reinoud bitmask_snprintf(fdc->sc_status[2],
1353 1.1 reinoud NE7_ST2BITS, bits,
1354 1.1 reinoud sizeof(bits)));
1355 1.1 reinoud printf(" cyl %d head %d sec %d)\n",
1356 1.1 reinoud fdc->sc_status[3],
1357 1.1 reinoud fdc->sc_status[4],
1358 1.1 reinoud fdc->sc_status[5]);
1359 1.1 reinoud }
1360 1.1 reinoud
1361 1.1 reinoud bp->b_flags |= B_ERROR;
1362 1.1 reinoud bp->b_error = EIO;
1363 1.1 reinoud fdfinish(fd, bp);
1364 1.1 reinoud }
1365 1.1 reinoud fdc->sc_errors++;
1366 1.1 reinoud }
1367 1.1 reinoud
1368 1.1 reinoud int
1369 1.1 reinoud fdsize(dev)
1370 1.1 reinoud dev_t dev;
1371 1.1 reinoud {
1372 1.1 reinoud
1373 1.1 reinoud /* Swapping to floppies would not make sense. */
1374 1.1 reinoud return -1;
1375 1.1 reinoud }
1376 1.1 reinoud
1377 1.1 reinoud int
1378 1.1 reinoud fddump(dev, blkno, va, size)
1379 1.1 reinoud dev_t dev;
1380 1.1 reinoud daddr_t blkno;
1381 1.1 reinoud caddr_t va;
1382 1.1 reinoud size_t size;
1383 1.1 reinoud {
1384 1.1 reinoud
1385 1.1 reinoud /* Not implemented. */
1386 1.1 reinoud return ENXIO;
1387 1.1 reinoud }
1388 1.1 reinoud
1389 1.1 reinoud int
1390 1.1 reinoud fdioctl(dev, cmd, addr, flag, p)
1391 1.1 reinoud dev_t dev;
1392 1.1 reinoud u_long cmd;
1393 1.1 reinoud caddr_t addr;
1394 1.1 reinoud int flag;
1395 1.1 reinoud struct proc *p;
1396 1.1 reinoud {
1397 1.1 reinoud struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
1398 1.1 reinoud struct fdformat_parms *form_parms;
1399 1.1 reinoud struct fdformat_cmd *form_cmd;
1400 1.1 reinoud struct ne7_fd_formb *fd_formb;
1401 1.1 reinoud struct disklabel buffer;
1402 1.1 reinoud int error;
1403 1.1 reinoud unsigned int scratch;
1404 1.1 reinoud int il[FD_MAX_NSEC + 1];
1405 1.1 reinoud register int i, j;
1406 1.1 reinoud
1407 1.1 reinoud switch (cmd) {
1408 1.1 reinoud case DIOCGDINFO:
1409 1.1 reinoud memset(&buffer, 0, sizeof(buffer));
1410 1.1 reinoud
1411 1.1 reinoud buffer.d_secpercyl = fd->sc_type->seccyl;
1412 1.1 reinoud buffer.d_type = DTYPE_FLOPPY;
1413 1.1 reinoud buffer.d_secsize = FDC_BSIZE;
1414 1.1 reinoud
1415 1.1 reinoud if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL)
1416 1.1 reinoud return EINVAL;
1417 1.1 reinoud
1418 1.1 reinoud *(struct disklabel *)addr = buffer;
1419 1.1 reinoud return 0;
1420 1.1 reinoud
1421 1.1 reinoud case DIOCWLABEL:
1422 1.1 reinoud if ((flag & FWRITE) == 0)
1423 1.1 reinoud return EBADF;
1424 1.1 reinoud /* XXX do something */
1425 1.1 reinoud return 0;
1426 1.1 reinoud
1427 1.1 reinoud case DIOCWDINFO:
1428 1.1 reinoud if ((flag & FWRITE) == 0)
1429 1.1 reinoud return EBADF;
1430 1.1 reinoud
1431 1.1 reinoud error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL);
1432 1.1 reinoud if (error)
1433 1.1 reinoud return error;
1434 1.1 reinoud
1435 1.1 reinoud error = writedisklabel(dev, fdstrategy, &buffer, NULL);
1436 1.1 reinoud return error;
1437 1.1 reinoud
1438 1.1 reinoud case FDIOCGETFORMAT:
1439 1.1 reinoud form_parms = (struct fdformat_parms *)addr;
1440 1.1 reinoud form_parms->fdformat_version = FDFORMAT_VERSION;
1441 1.1 reinoud form_parms->nbps = 128 * (1 << fd->sc_type->secsize);
1442 1.1 reinoud form_parms->ncyl = fd->sc_type->cyls;
1443 1.1 reinoud form_parms->nspt = fd->sc_type->sectrac;
1444 1.1 reinoud form_parms->ntrk = fd->sc_type->heads;
1445 1.1 reinoud form_parms->stepspercyl = fd->sc_type->step;
1446 1.1 reinoud form_parms->gaplen = fd->sc_type->gap2;
1447 1.1 reinoud form_parms->fillbyte = fd->sc_type->fillbyte;
1448 1.1 reinoud form_parms->interleave = fd->sc_type->interleave;
1449 1.1 reinoud switch (fd->sc_type->rate) {
1450 1.1 reinoud case FDC_500KBPS:
1451 1.1 reinoud form_parms->xfer_rate = 500 * 1024;
1452 1.1 reinoud break;
1453 1.1 reinoud case FDC_300KBPS:
1454 1.1 reinoud form_parms->xfer_rate = 300 * 1024;
1455 1.1 reinoud break;
1456 1.1 reinoud case FDC_250KBPS:
1457 1.1 reinoud form_parms->xfer_rate = 250 * 1024;
1458 1.1 reinoud break;
1459 1.1 reinoud default:
1460 1.1 reinoud return EINVAL;
1461 1.1 reinoud }
1462 1.1 reinoud return 0;
1463 1.1 reinoud
1464 1.1 reinoud case FDIOCSETFORMAT:
1465 1.1 reinoud if((flag & FWRITE) == 0)
1466 1.1 reinoud return EBADF; /* must be opened for writing */
1467 1.1 reinoud form_parms = (struct fdformat_parms *)addr;
1468 1.1 reinoud if (form_parms->fdformat_version != FDFORMAT_VERSION)
1469 1.1 reinoud return EINVAL; /* wrong version of formatting prog */
1470 1.1 reinoud
1471 1.1 reinoud scratch = form_parms->nbps >> 7;
1472 1.1 reinoud if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 ||
1473 1.1 reinoud scratch & ~(1 << (ffs(scratch)-1)))
1474 1.1 reinoud /* not a power-of-two multiple of 128 */
1475 1.1 reinoud return EINVAL;
1476 1.1 reinoud
1477 1.1 reinoud switch (form_parms->xfer_rate) {
1478 1.1 reinoud case 500 * 1024:
1479 1.1 reinoud fd->sc_type->rate = FDC_500KBPS;
1480 1.1 reinoud break;
1481 1.1 reinoud case 300 * 1024:
1482 1.1 reinoud fd->sc_type->rate = FDC_300KBPS;
1483 1.1 reinoud break;
1484 1.1 reinoud case 250 * 1024:
1485 1.1 reinoud fd->sc_type->rate = FDC_250KBPS;
1486 1.1 reinoud break;
1487 1.1 reinoud default:
1488 1.1 reinoud return EINVAL;
1489 1.1 reinoud }
1490 1.1 reinoud
1491 1.1 reinoud if (form_parms->nspt > FD_MAX_NSEC ||
1492 1.1 reinoud form_parms->fillbyte > 0xff ||
1493 1.1 reinoud form_parms->interleave > 0xff)
1494 1.1 reinoud return EINVAL;
1495 1.1 reinoud fd->sc_type->sectrac = form_parms->nspt;
1496 1.1 reinoud if (form_parms->ntrk != 2 && form_parms->ntrk != 1)
1497 1.1 reinoud return EINVAL;
1498 1.1 reinoud fd->sc_type->heads = form_parms->ntrk;
1499 1.1 reinoud fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk;
1500 1.1 reinoud fd->sc_type->secsize = ffs(scratch)-1;
1501 1.1 reinoud fd->sc_type->gap2 = form_parms->gaplen;
1502 1.1 reinoud fd->sc_type->cyls = form_parms->ncyl;
1503 1.1 reinoud fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl *
1504 1.1 reinoud form_parms->nbps / DEV_BSIZE;
1505 1.1 reinoud fd->sc_type->step = form_parms->stepspercyl;
1506 1.1 reinoud fd->sc_type->fillbyte = form_parms->fillbyte;
1507 1.1 reinoud fd->sc_type->interleave = form_parms->interleave;
1508 1.1 reinoud return 0;
1509 1.1 reinoud
1510 1.1 reinoud case FDIOCFORMAT_TRACK:
1511 1.1 reinoud if((flag & FWRITE) == 0)
1512 1.1 reinoud return EBADF; /* must be opened for writing */
1513 1.1 reinoud form_cmd = (struct fdformat_cmd *)addr;
1514 1.1 reinoud if (form_cmd->formatcmd_version != FDFORMAT_VERSION)
1515 1.1 reinoud return EINVAL; /* wrong version of formatting prog */
1516 1.1 reinoud
1517 1.1 reinoud if (form_cmd->head >= fd->sc_type->heads ||
1518 1.1 reinoud form_cmd->cylinder >= fd->sc_type->cyls) {
1519 1.1 reinoud return EINVAL;
1520 1.1 reinoud }
1521 1.1 reinoud
1522 1.1 reinoud fd_formb = malloc(sizeof(struct ne7_fd_formb),
1523 1.1 reinoud M_TEMP, M_NOWAIT);
1524 1.1 reinoud if(fd_formb == 0)
1525 1.1 reinoud return ENOMEM;
1526 1.1 reinoud
1527 1.1 reinoud
1528 1.1 reinoud fd_formb->head = form_cmd->head;
1529 1.1 reinoud fd_formb->cyl = form_cmd->cylinder;
1530 1.1 reinoud fd_formb->transfer_rate = fd->sc_type->rate;
1531 1.1 reinoud fd_formb->fd_formb_secshift = fd->sc_type->secsize;
1532 1.1 reinoud fd_formb->fd_formb_nsecs = fd->sc_type->sectrac;
1533 1.1 reinoud fd_formb->fd_formb_gaplen = fd->sc_type->gap2;
1534 1.1 reinoud fd_formb->fd_formb_fillbyte = fd->sc_type->fillbyte;
1535 1.1 reinoud
1536 1.1 reinoud memset(il, 0, sizeof il);
1537 1.1 reinoud for (j = 0, i = 1; i <= fd_formb->fd_formb_nsecs; i++) {
1538 1.1 reinoud while (il[(j%fd_formb->fd_formb_nsecs)+1])
1539 1.1 reinoud j++;
1540 1.1 reinoud il[(j%fd_formb->fd_formb_nsecs)+1] = i;
1541 1.1 reinoud j += fd->sc_type->interleave;
1542 1.1 reinoud }
1543 1.1 reinoud for (i = 0; i < fd_formb->fd_formb_nsecs; i++) {
1544 1.1 reinoud fd_formb->fd_formb_cylno(i) = form_cmd->cylinder;
1545 1.1 reinoud fd_formb->fd_formb_headno(i) = form_cmd->head;
1546 1.1 reinoud fd_formb->fd_formb_secno(i) = il[i+1];
1547 1.1 reinoud fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize;
1548 1.1 reinoud }
1549 1.1 reinoud
1550 1.1 reinoud error = fdformat(dev, fd_formb, p);
1551 1.1 reinoud free(fd_formb, M_TEMP);
1552 1.1 reinoud return error;
1553 1.1 reinoud
1554 1.1 reinoud case FDIOCGETOPTS: /* get drive options */
1555 1.1 reinoud *(int *)addr = fd->sc_opts;
1556 1.1 reinoud return 0;
1557 1.1 reinoud
1558 1.1 reinoud case FDIOCSETOPTS: /* set drive options */
1559 1.1 reinoud fd->sc_opts = *(int *)addr;
1560 1.1 reinoud return 0;
1561 1.1 reinoud
1562 1.1 reinoud default:
1563 1.1 reinoud return ENOTTY;
1564 1.1 reinoud }
1565 1.1 reinoud
1566 1.1 reinoud #ifdef DIAGNOSTIC
1567 1.1 reinoud panic("fdioctl: impossible");
1568 1.1 reinoud #endif
1569 1.1 reinoud }
1570 1.1 reinoud
1571 1.1 reinoud int
1572 1.1 reinoud fdformat(dev, finfo, p)
1573 1.1 reinoud dev_t dev;
1574 1.1 reinoud struct ne7_fd_formb *finfo;
1575 1.1 reinoud struct proc *p;
1576 1.1 reinoud {
1577 1.1 reinoud int rv = 0, s;
1578 1.1 reinoud struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
1579 1.1 reinoud struct fd_type *type = fd->sc_type;
1580 1.1 reinoud struct buf *bp;
1581 1.1 reinoud
1582 1.1 reinoud /* set up a buffer header for fdstrategy() */
1583 1.1 reinoud bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
1584 1.1 reinoud if(bp == 0)
1585 1.1 reinoud return ENOBUFS;
1586 1.1 reinoud memset((void *)bp, 0, sizeof(struct buf));
1587 1.1 reinoud bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
1588 1.1 reinoud bp->b_proc = p;
1589 1.1 reinoud bp->b_dev = dev;
1590 1.1 reinoud
1591 1.1 reinoud /*
1592 1.1 reinoud * calculate a fake blkno, so fdstrategy() would initiate a
1593 1.1 reinoud * seek to the requested cylinder
1594 1.1 reinoud */
1595 1.1 reinoud bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads)
1596 1.1 reinoud + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE;
1597 1.1 reinoud
1598 1.1 reinoud bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
1599 1.1 reinoud bp->b_data = (caddr_t)finfo;
1600 1.1 reinoud
1601 1.1 reinoud #ifdef DEBUG
1602 1.1 reinoud printf("fdformat: blkno %x count %lx\n", bp->b_blkno, bp->b_bcount);
1603 1.1 reinoud #endif
1604 1.1 reinoud
1605 1.1 reinoud /* now do the format */
1606 1.1 reinoud fdstrategy(bp);
1607 1.1 reinoud
1608 1.1 reinoud /* ...and wait for it to complete */
1609 1.1 reinoud s = splbio();
1610 1.1 reinoud while(!(bp->b_flags & B_DONE)) {
1611 1.1 reinoud rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
1612 1.1 reinoud if (rv == EWOULDBLOCK)
1613 1.1 reinoud break;
1614 1.1 reinoud }
1615 1.1 reinoud splx(s);
1616 1.1 reinoud
1617 1.1 reinoud if (rv == EWOULDBLOCK) {
1618 1.1 reinoud /* timed out */
1619 1.1 reinoud rv = EIO;
1620 1.1 reinoud biodone(bp);
1621 1.1 reinoud }
1622 1.1 reinoud if(bp->b_flags & B_ERROR) {
1623 1.1 reinoud rv = bp->b_error;
1624 1.1 reinoud }
1625 1.1 reinoud free(bp, M_TEMP);
1626 1.1 reinoud return rv;
1627 1.1 reinoud }
1628 1.1 reinoud
1629 1.1 reinoud #include "md.h"
1630 1.1 reinoud #if NMD > 0
1631 1.1 reinoud
1632 1.1 reinoud #include <dev/md.h>
1633 1.1 reinoud
1634 1.1 reinoud int load_memory_disc_from_floppy __P((struct md_conf *md, dev_t dev));
1635 1.1 reinoud
1636 1.1 reinoud int
1637 1.1 reinoud load_memory_disc_from_floppy(md, dev)
1638 1.1 reinoud struct md_conf *md;
1639 1.1 reinoud dev_t dev;
1640 1.1 reinoud {
1641 1.1 reinoud struct buf *bp;
1642 1.1 reinoud int loop;
1643 1.1 reinoud int s;
1644 1.1 reinoud int type;
1645 1.1 reinoud int floppysize;
1646 1.1 reinoud
1647 1.1 reinoud if (major(dev) != 17) /* XXX - nice if the major was defined elsewhere */
1648 1.1 reinoud return(EINVAL);
1649 1.1 reinoud
1650 1.1 reinoud if (md->md_type == MD_UNCONFIGURED || md->md_addr == 0)
1651 1.1 reinoud return(EBUSY);
1652 1.1 reinoud
1653 1.1 reinoud type = FDTYPE(dev) - 1;
1654 1.1 reinoud if (type < 0) type = 0;
1655 1.1 reinoud floppysize = fd_types[type].size << (fd_types[type].secsize + 7);
1656 1.1 reinoud
1657 1.1 reinoud if (md->md_size < floppysize) {
1658 1.1 reinoud printf("Memory disc is not big enough for floppy image\n");
1659 1.1 reinoud return(EINVAL);
1660 1.1 reinoud }
1661 1.1 reinoud
1662 1.1 reinoud /* We have the memory disk ! */
1663 1.1 reinoud
1664 1.1 reinoud printf("Loading memory disc : %4dK ", 0);
1665 1.1 reinoud
1666 1.1 reinoud /* obtain a buffer */
1667 1.1 reinoud
1668 1.1 reinoud bp = geteblk(fd_types[type].sectrac * DEV_BSIZE);
1669 1.1 reinoud
1670 1.1 reinoud /* request no partition relocation by driver on I/O operations */
1671 1.1 reinoud
1672 1.1 reinoud bp->b_dev = dev;
1673 1.1 reinoud
1674 1.1 reinoud s = spl0();
1675 1.1 reinoud
1676 1.1 reinoud if (fdopen(bp->b_dev, 0, 0, curproc) != 0) {
1677 1.1 reinoud brelse(bp);
1678 1.1 reinoud printf("Cannot open floppy device\n");
1679 1.1 reinoud return(EINVAL);
1680 1.1 reinoud }
1681 1.1 reinoud
1682 1.1 reinoud for (loop = 0;
1683 1.1 reinoud loop < (floppysize / DEV_BSIZE / fd_types[type].sectrac);
1684 1.1 reinoud ++loop) {
1685 1.1 reinoud printf("\x08\x08\x08\x08\x08\x08%4dK ",
1686 1.1 reinoud loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
1687 1.1 reinoud bp->b_blkno = loop * fd_types[type].sectrac;
1688 1.1 reinoud bp->b_bcount = fd_types[type].sectrac * DEV_BSIZE;
1689 1.1 reinoud bp->b_flags |= B_READ;
1690 1.1 reinoud bp->b_error = 0;
1691 1.1 reinoud bp->b_resid = 0;
1692 1.1 reinoud fdstrategy(bp);
1693 1.1 reinoud
1694 1.1 reinoud if (biowait(bp))
1695 1.1 reinoud panic("Cannot load floppy image\n");
1696 1.1 reinoud
1697 1.1 reinoud memcpy((caddr_t)md->md_addr + loop * fd_types[type].sectrac
1698 1.1 reinoud * DEV_BSIZE, (caddr_t)bp->b_data,
1699 1.1 reinoud fd_types[type].sectrac * DEV_BSIZE);
1700 1.1 reinoud }
1701 1.1 reinoud printf("\x08\x08\x08\x08\x08\x08%4dK done\n",
1702 1.1 reinoud loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
1703 1.1 reinoud
1704 1.1 reinoud fdclose(bp->b_dev, 0, 0, curproc);
1705 1.1 reinoud
1706 1.1 reinoud brelse(bp);
1707 1.1 reinoud
1708 1.1 reinoud splx(s);
1709 1.1 reinoud return(0);
1710 1.1 reinoud }
1711 1.1 reinoud
1712 1.1 reinoud #endif
1713