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