fd.c revision 1.1.4.6 1 1.1.4.6 nathanw /* $NetBSD: fd.c,v 1.1.4.6 2002/09/17 21:12:26 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.6 nathanw #include <sys/conf.h>
115 1.1.4.2 thorpej
116 1.1.4.2 thorpej #include <uvm/uvm_extern.h>
117 1.1.4.2 thorpej
118 1.1.4.3 nathanw #include <arm/fiq.h>
119 1.1.4.3 nathanw
120 1.1.4.2 thorpej #include <machine/cpu.h>
121 1.1.4.3 nathanw #include <machine/intr.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.6 nathanw dev_type_open(fdopen);
274 1.1.4.6 nathanw dev_type_close(fdclose);
275 1.1.4.6 nathanw dev_type_read(fdread);
276 1.1.4.6 nathanw dev_type_write(fdwrite);
277 1.1.4.6 nathanw dev_type_ioctl(fdioctl);
278 1.1.4.6 nathanw dev_type_strategy(fdstrategy);
279 1.1.4.6 nathanw
280 1.1.4.6 nathanw const struct bdevsw fd_bdevsw = {
281 1.1.4.6 nathanw fdopen, fdclose, fdstrategy, fdioctl, nodump, nosize, D_DISK
282 1.1.4.6 nathanw };
283 1.1.4.6 nathanw
284 1.1.4.6 nathanw const struct cdevsw fd_cdevsw = {
285 1.1.4.6 nathanw fdopen, fdclose, fdread, fdwrite, fdioctl,
286 1.1.4.6 nathanw nostop, notty, nopoll, nommap, D_DISK
287 1.1.4.6 nathanw };
288 1.1.4.6 nathanw
289 1.1.4.2 thorpej void fdgetdisklabel __P((struct fd_softc *));
290 1.1.4.2 thorpej int fd_get_parms __P((struct fd_softc *));
291 1.1.4.2 thorpej void fdstart __P((struct fd_softc *));
292 1.1.4.2 thorpej
293 1.1.4.2 thorpej struct dkdriver fddkdriver = { fdstrategy };
294 1.1.4.2 thorpej
295 1.1.4.2 thorpej struct fd_type *fd_nvtotype __P((char *, int, int));
296 1.1.4.2 thorpej void fd_set_motor __P((struct fdc_softc *fdc, int reset));
297 1.1.4.2 thorpej void fd_motor_off __P((void *arg));
298 1.1.4.2 thorpej void fd_motor_on __P((void *arg));
299 1.1.4.2 thorpej int fdcresult __P((struct fdc_softc *fdc));
300 1.1.4.2 thorpej int out_fdc __P((bus_space_tag_t iot, bus_space_handle_t ioh, u_char x));
301 1.1.4.2 thorpej void fdcstart __P((struct fdc_softc *fdc));
302 1.1.4.2 thorpej void fdcstatus __P((struct device *dv, int n, char *s));
303 1.1.4.2 thorpej void fdctimeout __P((void *arg));
304 1.1.4.2 thorpej void fdcpseudointr __P((void *arg));
305 1.1.4.2 thorpej int fdcintr __P((void *));
306 1.1.4.2 thorpej void fdcretry __P((struct fdc_softc *fdc));
307 1.1.4.2 thorpej void fdfinish __P((struct fd_softc *fd, struct buf *bp));
308 1.1.4.2 thorpej __inline struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t));
309 1.1.4.2 thorpej int fdformat __P((dev_t, struct ne7_fd_formb *, struct proc *));
310 1.1.4.2 thorpej
311 1.1.4.2 thorpej int
312 1.1.4.2 thorpej fdcprobe(parent, cf, aux)
313 1.1.4.2 thorpej struct device *parent;
314 1.1.4.2 thorpej struct cfdata *cf;
315 1.1.4.2 thorpej void *aux;
316 1.1.4.2 thorpej {
317 1.1.4.2 thorpej struct pioc_attach_args *pa = aux;
318 1.1.4.2 thorpej bus_space_tag_t iot;
319 1.1.4.2 thorpej bus_space_handle_t ioh;
320 1.1.4.2 thorpej int rv;
321 1.1.4.2 thorpej
322 1.1.4.2 thorpej if (pa->pa_name && strcmp(pa->pa_name, "fdc") != 0)
323 1.1.4.2 thorpej return(0);
324 1.1.4.2 thorpej
325 1.1.4.2 thorpej iot = pa->pa_iot;
326 1.1.4.2 thorpej rv = 0;
327 1.1.4.2 thorpej
328 1.1.4.2 thorpej /* Map the i/o space. */
329 1.1.4.2 thorpej if (bus_space_map(iot, pa->pa_iobase + pa->pa_offset, FDC_NPORT, 0, &ioh))
330 1.1.4.2 thorpej return 0;
331 1.1.4.2 thorpej
332 1.1.4.2 thorpej /* reset */
333 1.1.4.2 thorpej bus_space_write_2(iot, ioh, fdout, 0);
334 1.1.4.2 thorpej delay(100);
335 1.1.4.2 thorpej bus_space_write_2(iot, ioh, fdout, FDO_FRST);
336 1.1.4.2 thorpej
337 1.1.4.2 thorpej /* see if it can handle a command */
338 1.1.4.2 thorpej if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0)
339 1.1.4.2 thorpej goto out;
340 1.1.4.2 thorpej out_fdc(iot, ioh, 0xdf);
341 1.1.4.2 thorpej out_fdc(iot, ioh, 2);
342 1.1.4.2 thorpej
343 1.1.4.2 thorpej rv = 1;
344 1.1.4.2 thorpej pa->pa_iosize = FDC_NPORT;
345 1.1.4.2 thorpej
346 1.1.4.2 thorpej out:
347 1.1.4.2 thorpej bus_space_unmap(iot, ioh, FDC_NPORT);
348 1.1.4.2 thorpej return rv;
349 1.1.4.2 thorpej }
350 1.1.4.2 thorpej
351 1.1.4.2 thorpej /*
352 1.1.4.2 thorpej * Arguments passed between fdcattach and fdprobe.
353 1.1.4.2 thorpej */
354 1.1.4.2 thorpej struct fdc_attach_args {
355 1.1.4.2 thorpej int fa_drive;
356 1.1.4.2 thorpej struct fd_type *fa_deftype;
357 1.1.4.2 thorpej };
358 1.1.4.2 thorpej
359 1.1.4.2 thorpej /*
360 1.1.4.2 thorpej * Print the location of a disk drive (called just before attaching the
361 1.1.4.2 thorpej * the drive). If `fdc' is not NULL, the drive was found but was not
362 1.1.4.2 thorpej * in the system config file; print the drive name as well.
363 1.1.4.2 thorpej * Return QUIET (config_find ignores this if the device was configured) to
364 1.1.4.2 thorpej * avoid printing `fdN not configured' messages.
365 1.1.4.2 thorpej */
366 1.1.4.2 thorpej int
367 1.1.4.2 thorpej fdprint(aux, fdc)
368 1.1.4.2 thorpej void *aux;
369 1.1.4.2 thorpej const char *fdc;
370 1.1.4.2 thorpej {
371 1.1.4.2 thorpej register struct fdc_attach_args *fa = aux;
372 1.1.4.2 thorpej
373 1.1.4.2 thorpej if (!fdc)
374 1.1.4.2 thorpej printf(" drive %d", fa->fa_drive);
375 1.1.4.2 thorpej return QUIET;
376 1.1.4.2 thorpej }
377 1.1.4.2 thorpej
378 1.1.4.2 thorpej void
379 1.1.4.2 thorpej fdcattach(parent, self, aux)
380 1.1.4.2 thorpej struct device *parent, *self;
381 1.1.4.2 thorpej void *aux;
382 1.1.4.2 thorpej {
383 1.1.4.2 thorpej struct fdc_softc *fdc = (void *)self;
384 1.1.4.2 thorpej bus_space_tag_t iot;
385 1.1.4.2 thorpej bus_space_handle_t ioh;
386 1.1.4.2 thorpej struct pioc_attach_args *pa = aux;
387 1.1.4.2 thorpej struct fdc_attach_args fa;
388 1.1.4.2 thorpej int type;
389 1.1.4.2 thorpej
390 1.1.4.2 thorpej iot = pa->pa_iot;
391 1.1.4.2 thorpej
392 1.1.4.2 thorpej /* Re-map the I/O space. */
393 1.1.4.2 thorpej if (bus_space_map(iot, pa->pa_iobase + pa->pa_offset, FDC_NPORT, 0, &ioh))
394 1.1.4.2 thorpej panic("fdcattach: couldn't map I/O ports");
395 1.1.4.2 thorpej
396 1.1.4.2 thorpej fdc->sc_iot = iot;
397 1.1.4.2 thorpej fdc->sc_ioh = ioh;
398 1.1.4.2 thorpej
399 1.1.4.2 thorpej fdc->sc_drq = pa->pa_iobase + pa->pa_offset + pa->pa_drq;
400 1.1.4.2 thorpej fdc->sc_state = DEVIDLE;
401 1.1.4.2 thorpej TAILQ_INIT(&fdc->sc_drives);
402 1.1.4.2 thorpej
403 1.1.4.2 thorpej printf("\n");
404 1.1.4.2 thorpej
405 1.1.4.2 thorpej callout_init(&fdc->sc_timo_ch);
406 1.1.4.2 thorpej callout_init(&fdc->sc_intr_ch);
407 1.1.4.2 thorpej
408 1.1.4.2 thorpej fdc->sc_ih = intr_claim(pa->pa_irq, IPL_BIO, "fdc",
409 1.1.4.2 thorpej fdcintr, fdc);
410 1.1.4.2 thorpej if (!fdc->sc_ih)
411 1.1.4.2 thorpej panic("%s: Cannot claim IRQ %d\n", self->dv_xname, pa->pa_irq);
412 1.1.4.2 thorpej
413 1.1.4.2 thorpej #if 0
414 1.1.4.2 thorpej /*
415 1.1.4.2 thorpej * The NVRAM info only tells us about the first two disks on the
416 1.1.4.2 thorpej * `primary' floppy controller.
417 1.1.4.2 thorpej */
418 1.1.4.2 thorpej if (fdc->sc_dev.dv_unit == 0)
419 1.1.4.2 thorpej type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */
420 1.1.4.2 thorpej else
421 1.1.4.2 thorpej type = -1;
422 1.1.4.2 thorpej #endif
423 1.1.4.2 thorpej type = 0x10; /* XXX - hardcoded for 1 floppy */
424 1.1.4.2 thorpej
425 1.1.4.2 thorpej /* physical limit: four drives per controller. */
426 1.1.4.2 thorpej for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
427 1.1.4.2 thorpej if (type >= 0 && fa.fa_drive < 2)
428 1.1.4.2 thorpej fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
429 1.1.4.2 thorpej type, fa.fa_drive);
430 1.1.4.2 thorpej else
431 1.1.4.2 thorpej fa.fa_deftype = NULL; /* unknown */
432 1.1.4.2 thorpej (void)config_found(self, (void *)&fa, fdprint);
433 1.1.4.2 thorpej }
434 1.1.4.2 thorpej }
435 1.1.4.2 thorpej
436 1.1.4.2 thorpej int
437 1.1.4.2 thorpej fdprobe(parent, cf, aux)
438 1.1.4.2 thorpej struct device *parent;
439 1.1.4.2 thorpej struct cfdata *cf;
440 1.1.4.2 thorpej void *aux;
441 1.1.4.2 thorpej {
442 1.1.4.2 thorpej struct fdc_softc *fdc = (void *)parent;
443 1.1.4.2 thorpej struct fdc_attach_args *fa = aux;
444 1.1.4.2 thorpej int drive = fa->fa_drive;
445 1.1.4.2 thorpej bus_space_tag_t iot = fdc->sc_iot;
446 1.1.4.2 thorpej bus_space_handle_t ioh = fdc->sc_ioh;
447 1.1.4.2 thorpej int n;
448 1.1.4.2 thorpej
449 1.1.4.2 thorpej if (cf->cf_loc[FDCCF_DRIVE] != FDCCF_DRIVE_DEFAULT
450 1.1.4.2 thorpej && cf->cf_loc[FDCCF_DRIVE] != drive)
451 1.1.4.2 thorpej return 0;
452 1.1.4.2 thorpej /*
453 1.1.4.2 thorpej * XXX
454 1.1.4.2 thorpej * This is to work around some odd interactions between this driver
455 1.1.4.2 thorpej * and SMC Ethernet cards.
456 1.1.4.2 thorpej */
457 1.1.4.2 thorpej
458 1.1.4.2 thorpej /* Don't need this for arm32 port but leave for the time being (it won't hurt) */
459 1.1.4.2 thorpej
460 1.1.4.2 thorpej if (cf->cf_loc[FDCCF_DRIVE] == FDCCF_DRIVE_DEFAULT && drive >= 2)
461 1.1.4.2 thorpej return 0;
462 1.1.4.2 thorpej
463 1.1.4.2 thorpej /* select drive and turn on motor */
464 1.1.4.2 thorpej bus_space_write_2(iot, ioh, fdout, drive | FDO_FRST | FDO_MOEN(drive));
465 1.1.4.2 thorpej /* wait for motor to spin up */
466 1.1.4.2 thorpej delay(250000);
467 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_RECAL);
468 1.1.4.2 thorpej out_fdc(iot, ioh, drive);
469 1.1.4.2 thorpej /* wait for recalibrate */
470 1.1.4.2 thorpej delay(2000000);
471 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_SENSEI);
472 1.1.4.2 thorpej n = fdcresult(fdc);
473 1.1.4.2 thorpej #ifdef FD_DEBUG
474 1.1.4.2 thorpej {
475 1.1.4.2 thorpej int i;
476 1.1.4.2 thorpej printf("fdprobe: status");
477 1.1.4.2 thorpej for (i = 0; i < n; i++)
478 1.1.4.2 thorpej printf(" %x", fdc->sc_status[i]);
479 1.1.4.2 thorpej printf("\n");
480 1.1.4.2 thorpej }
481 1.1.4.2 thorpej #endif
482 1.1.4.2 thorpej /* turn off motor */
483 1.1.4.2 thorpej bus_space_write_1(iot, ioh, fdout, FDO_FRST);
484 1.1.4.2 thorpej
485 1.1.4.2 thorpej if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20)
486 1.1.4.2 thorpej return 0;
487 1.1.4.2 thorpej
488 1.1.4.2 thorpej return 1;
489 1.1.4.2 thorpej }
490 1.1.4.2 thorpej
491 1.1.4.2 thorpej /*
492 1.1.4.2 thorpej * Controller is working, and drive responded. Attach it.
493 1.1.4.2 thorpej */
494 1.1.4.2 thorpej void
495 1.1.4.2 thorpej fdattach(parent, self, aux)
496 1.1.4.2 thorpej struct device *parent, *self;
497 1.1.4.2 thorpej void *aux;
498 1.1.4.2 thorpej {
499 1.1.4.2 thorpej struct fdc_softc *fdc = (void *)parent;
500 1.1.4.2 thorpej struct fd_softc *fd = (void *)self;
501 1.1.4.2 thorpej struct fdc_attach_args *fa = aux;
502 1.1.4.2 thorpej struct fd_type *type = fa->fa_deftype;
503 1.1.4.2 thorpej int drive = fa->fa_drive;
504 1.1.4.2 thorpej
505 1.1.4.2 thorpej callout_init(&fd->sc_motoron_ch);
506 1.1.4.2 thorpej callout_init(&fd->sc_motoroff_ch);
507 1.1.4.2 thorpej
508 1.1.4.2 thorpej /* XXX Allow `flags' to override device type? */
509 1.1.4.2 thorpej
510 1.1.4.2 thorpej if (type)
511 1.1.4.2 thorpej printf(": %s %d cyl, %d head, %d sec\n", type->name,
512 1.1.4.2 thorpej type->cyls, type->heads, type->sectrac);
513 1.1.4.2 thorpej else
514 1.1.4.2 thorpej printf(": density unknown\n");
515 1.1.4.2 thorpej
516 1.1.4.5 nathanw bufq_alloc(&fd->sc_q, BUFQ_DISKSORT|BUFQ_SORT_CYLINDER);
517 1.1.4.2 thorpej fd->sc_cylin = -1;
518 1.1.4.2 thorpej fd->sc_drive = drive;
519 1.1.4.2 thorpej fd->sc_deftype = type;
520 1.1.4.2 thorpej fdc->sc_fd[drive] = fd;
521 1.1.4.2 thorpej
522 1.1.4.2 thorpej /*
523 1.1.4.2 thorpej * Initialize and attach the disk structure.
524 1.1.4.2 thorpej */
525 1.1.4.2 thorpej fd->sc_dk.dk_name = fd->sc_dev.dv_xname;
526 1.1.4.2 thorpej fd->sc_dk.dk_driver = &fddkdriver;
527 1.1.4.2 thorpej disk_attach(&fd->sc_dk);
528 1.1.4.2 thorpej
529 1.1.4.2 thorpej /* Needed to power off if the motor is on when we halt. */
530 1.1.4.2 thorpej
531 1.1.4.2 thorpej }
532 1.1.4.2 thorpej
533 1.1.4.2 thorpej /*
534 1.1.4.2 thorpej * Translate nvram type into internal data structure. Return NULL for
535 1.1.4.2 thorpej * none/unknown/unusable.
536 1.1.4.2 thorpej */
537 1.1.4.2 thorpej struct fd_type *
538 1.1.4.2 thorpej fd_nvtotype(fdc, nvraminfo, drive)
539 1.1.4.2 thorpej char *fdc;
540 1.1.4.2 thorpej int nvraminfo, drive;
541 1.1.4.2 thorpej {
542 1.1.4.2 thorpej int type;
543 1.1.4.2 thorpej
544 1.1.4.2 thorpej type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0;
545 1.1.4.2 thorpej switch (type) {
546 1.1.4.2 thorpej #ifndef RC7500
547 1.1.4.2 thorpej case 0x00 :
548 1.1.4.2 thorpej return NULL;
549 1.1.4.2 thorpej #else
550 1.1.4.2 thorpej case 0x00 :
551 1.1.4.2 thorpej #endif /* !RC7500 */
552 1.1.4.2 thorpej case 0x10 :
553 1.1.4.2 thorpej return &fd_types[0];
554 1.1.4.2 thorpej default:
555 1.1.4.2 thorpej printf("%s: drive %d: unknown device type 0x%x\n",
556 1.1.4.2 thorpej fdc, drive, type);
557 1.1.4.2 thorpej return NULL;
558 1.1.4.2 thorpej }
559 1.1.4.2 thorpej }
560 1.1.4.2 thorpej
561 1.1.4.2 thorpej __inline struct fd_type *
562 1.1.4.2 thorpej fd_dev_to_type(fd, dev)
563 1.1.4.2 thorpej struct fd_softc *fd;
564 1.1.4.2 thorpej dev_t dev;
565 1.1.4.2 thorpej {
566 1.1.4.2 thorpej int type = FDTYPE(dev);
567 1.1.4.2 thorpej
568 1.1.4.2 thorpej if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
569 1.1.4.2 thorpej return NULL;
570 1.1.4.2 thorpej return type ? &fd_types[type - 1] : fd->sc_deftype;
571 1.1.4.2 thorpej }
572 1.1.4.2 thorpej
573 1.1.4.2 thorpej void
574 1.1.4.2 thorpej fdstrategy(bp)
575 1.1.4.2 thorpej register struct buf *bp; /* IO operation to perform */
576 1.1.4.2 thorpej {
577 1.1.4.2 thorpej struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(bp->b_dev)];
578 1.1.4.2 thorpej int sz;
579 1.1.4.2 thorpej int s;
580 1.1.4.2 thorpej
581 1.1.4.2 thorpej /* Valid unit, controller, and request? */
582 1.1.4.2 thorpej if (bp->b_blkno < 0 ||
583 1.1.4.2 thorpej ((bp->b_bcount % FDC_BSIZE) != 0 &&
584 1.1.4.2 thorpej (bp->b_flags & B_FORMAT) == 0)) {
585 1.1.4.2 thorpej bp->b_error = EINVAL;
586 1.1.4.2 thorpej goto bad;
587 1.1.4.2 thorpej }
588 1.1.4.2 thorpej
589 1.1.4.2 thorpej /* If it's a null transfer, return immediately. */
590 1.1.4.2 thorpej if (bp->b_bcount == 0)
591 1.1.4.2 thorpej goto done;
592 1.1.4.2 thorpej
593 1.1.4.2 thorpej sz = howmany(bp->b_bcount, FDC_BSIZE);
594 1.1.4.2 thorpej
595 1.1.4.2 thorpej if (bp->b_blkno + sz > fd->sc_type->size) {
596 1.1.4.2 thorpej sz = fd->sc_type->size - bp->b_blkno;
597 1.1.4.2 thorpej if (sz == 0) {
598 1.1.4.2 thorpej /* If exactly at end of disk, return EOF. */
599 1.1.4.2 thorpej goto done;
600 1.1.4.2 thorpej }
601 1.1.4.2 thorpej if (sz < 0) {
602 1.1.4.2 thorpej /* If past end of disk, return EINVAL. */
603 1.1.4.2 thorpej bp->b_error = EINVAL;
604 1.1.4.2 thorpej goto bad;
605 1.1.4.2 thorpej }
606 1.1.4.2 thorpej /* Otherwise, truncate request. */
607 1.1.4.2 thorpej bp->b_bcount = sz << DEV_BSHIFT;
608 1.1.4.2 thorpej }
609 1.1.4.2 thorpej
610 1.1.4.2 thorpej bp->b_rawblkno = bp->b_blkno;
611 1.1.4.2 thorpej bp->b_cylinder = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl;
612 1.1.4.2 thorpej
613 1.1.4.2 thorpej #ifdef FD_DEBUG
614 1.1.4.2 thorpej printf("fdstrategy: b_blkno %d b_bcount %d blkno %d cylin %d sz %d\n",
615 1.1.4.2 thorpej bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylinder, sz);
616 1.1.4.2 thorpej #endif
617 1.1.4.2 thorpej
618 1.1.4.2 thorpej /* Queue transfer on drive, activate drive and controller if idle. */
619 1.1.4.2 thorpej s = splbio();
620 1.1.4.5 nathanw BUFQ_PUT(&fd->sc_q, bp);
621 1.1.4.2 thorpej callout_stop(&fd->sc_motoroff_ch); /* a good idea */
622 1.1.4.2 thorpej if (fd->sc_active == 0)
623 1.1.4.2 thorpej fdstart(fd);
624 1.1.4.2 thorpej #ifdef DIAGNOSTIC
625 1.1.4.2 thorpej else {
626 1.1.4.2 thorpej struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
627 1.1.4.2 thorpej if (fdc->sc_state == DEVIDLE) {
628 1.1.4.2 thorpej printf("fdstrategy: controller inactive\n");
629 1.1.4.2 thorpej fdcstart(fdc);
630 1.1.4.2 thorpej }
631 1.1.4.2 thorpej }
632 1.1.4.2 thorpej #endif
633 1.1.4.2 thorpej splx(s);
634 1.1.4.2 thorpej return;
635 1.1.4.2 thorpej
636 1.1.4.2 thorpej bad:
637 1.1.4.2 thorpej bp->b_flags |= B_ERROR;
638 1.1.4.2 thorpej done:
639 1.1.4.2 thorpej /* Toss transfer; we're done early. */
640 1.1.4.2 thorpej bp->b_resid = bp->b_bcount;
641 1.1.4.2 thorpej biodone(bp);
642 1.1.4.2 thorpej }
643 1.1.4.2 thorpej
644 1.1.4.2 thorpej void
645 1.1.4.2 thorpej fdstart(fd)
646 1.1.4.2 thorpej struct fd_softc *fd;
647 1.1.4.2 thorpej {
648 1.1.4.2 thorpej struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
649 1.1.4.2 thorpej int active = fdc->sc_drives.tqh_first != 0;
650 1.1.4.2 thorpej
651 1.1.4.2 thorpej /* Link into controller queue. */
652 1.1.4.2 thorpej fd->sc_active = 1;
653 1.1.4.2 thorpej TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
654 1.1.4.2 thorpej
655 1.1.4.2 thorpej /* If controller not already active, start it. */
656 1.1.4.2 thorpej if (!active)
657 1.1.4.2 thorpej fdcstart(fdc);
658 1.1.4.2 thorpej }
659 1.1.4.2 thorpej
660 1.1.4.2 thorpej void
661 1.1.4.2 thorpej fdfinish(fd, bp)
662 1.1.4.2 thorpej struct fd_softc *fd;
663 1.1.4.2 thorpej struct buf *bp;
664 1.1.4.2 thorpej {
665 1.1.4.2 thorpej struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
666 1.1.4.2 thorpej
667 1.1.4.2 thorpej /*
668 1.1.4.2 thorpej * Move this drive to the end of the queue to give others a `fair'
669 1.1.4.2 thorpej * chance. We only force a switch if N operations are completed while
670 1.1.4.2 thorpej * another drive is waiting to be serviced, since there is a long motor
671 1.1.4.2 thorpej * startup delay whenever we switch.
672 1.1.4.2 thorpej */
673 1.1.4.5 nathanw (void)BUFQ_GET(&fd->sc_q);
674 1.1.4.2 thorpej if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) {
675 1.1.4.2 thorpej fd->sc_ops = 0;
676 1.1.4.2 thorpej TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
677 1.1.4.5 nathanw if (BUFQ_PEEK(&fd->sc_q) != NULL)
678 1.1.4.2 thorpej TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
679 1.1.4.2 thorpej else
680 1.1.4.2 thorpej fd->sc_active = 0;
681 1.1.4.2 thorpej }
682 1.1.4.2 thorpej bp->b_resid = fd->sc_bcount;
683 1.1.4.2 thorpej fd->sc_skip = 0;
684 1.1.4.2 thorpej
685 1.1.4.2 thorpej biodone(bp);
686 1.1.4.2 thorpej /* turn off motor 5s from now */
687 1.1.4.2 thorpej callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd);
688 1.1.4.2 thorpej fdc->sc_state = DEVIDLE;
689 1.1.4.2 thorpej }
690 1.1.4.2 thorpej
691 1.1.4.2 thorpej int
692 1.1.4.2 thorpej fdread(dev, uio, flags)
693 1.1.4.2 thorpej dev_t dev;
694 1.1.4.2 thorpej struct uio *uio;
695 1.1.4.2 thorpej int flags;
696 1.1.4.2 thorpej {
697 1.1.4.2 thorpej
698 1.1.4.2 thorpej return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
699 1.1.4.2 thorpej }
700 1.1.4.2 thorpej
701 1.1.4.2 thorpej int
702 1.1.4.2 thorpej fdwrite(dev, uio, flags)
703 1.1.4.2 thorpej dev_t dev;
704 1.1.4.2 thorpej struct uio *uio;
705 1.1.4.2 thorpej int flags;
706 1.1.4.2 thorpej {
707 1.1.4.2 thorpej
708 1.1.4.2 thorpej return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
709 1.1.4.2 thorpej }
710 1.1.4.2 thorpej
711 1.1.4.2 thorpej void
712 1.1.4.2 thorpej fd_set_motor(fdc, reset)
713 1.1.4.2 thorpej struct fdc_softc *fdc;
714 1.1.4.2 thorpej int reset;
715 1.1.4.2 thorpej {
716 1.1.4.2 thorpej struct fd_softc *fd;
717 1.1.4.2 thorpej u_char status;
718 1.1.4.2 thorpej int n;
719 1.1.4.2 thorpej
720 1.1.4.2 thorpej if ((fd = fdc->sc_drives.tqh_first) != NULL)
721 1.1.4.2 thorpej status = fd->sc_drive;
722 1.1.4.2 thorpej else
723 1.1.4.2 thorpej status = 0;
724 1.1.4.2 thorpej if (!reset)
725 1.1.4.2 thorpej status |= FDO_FRST | FDO_FDMAEN;
726 1.1.4.2 thorpej for (n = 0; n < 4; n++)
727 1.1.4.2 thorpej if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
728 1.1.4.2 thorpej status |= FDO_MOEN(n);
729 1.1.4.2 thorpej bus_space_write_2(fdc->sc_iot, fdc->sc_ioh, fdout, status);
730 1.1.4.2 thorpej }
731 1.1.4.2 thorpej
732 1.1.4.2 thorpej void
733 1.1.4.2 thorpej fd_motor_off(arg)
734 1.1.4.2 thorpej void *arg;
735 1.1.4.2 thorpej {
736 1.1.4.2 thorpej struct fd_softc *fd = arg;
737 1.1.4.2 thorpej int s;
738 1.1.4.2 thorpej
739 1.1.4.2 thorpej s = splbio();
740 1.1.4.2 thorpej fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
741 1.1.4.2 thorpej fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0);
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 void
746 1.1.4.2 thorpej fd_motor_on(arg)
747 1.1.4.2 thorpej void *arg;
748 1.1.4.2 thorpej {
749 1.1.4.2 thorpej struct fd_softc *fd = arg;
750 1.1.4.2 thorpej struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
751 1.1.4.2 thorpej int s;
752 1.1.4.2 thorpej
753 1.1.4.2 thorpej s = splbio();
754 1.1.4.2 thorpej fd->sc_flags &= ~FD_MOTOR_WAIT;
755 1.1.4.2 thorpej if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
756 1.1.4.2 thorpej (void) fdcintr(fdc);
757 1.1.4.2 thorpej splx(s);
758 1.1.4.2 thorpej }
759 1.1.4.2 thorpej
760 1.1.4.2 thorpej int
761 1.1.4.2 thorpej fdcresult(fdc)
762 1.1.4.2 thorpej struct fdc_softc *fdc;
763 1.1.4.2 thorpej {
764 1.1.4.2 thorpej bus_space_tag_t iot = fdc->sc_iot;
765 1.1.4.2 thorpej bus_space_handle_t ioh = fdc->sc_ioh;
766 1.1.4.2 thorpej u_char i;
767 1.1.4.2 thorpej int j = 100000,
768 1.1.4.2 thorpej n = 0;
769 1.1.4.2 thorpej
770 1.1.4.2 thorpej for (; j; j--) {
771 1.1.4.2 thorpej i = bus_space_read_1(iot, ioh, fdsts) &
772 1.1.4.2 thorpej (NE7_DIO | NE7_RQM | NE7_CB);
773 1.1.4.2 thorpej if (i == NE7_RQM)
774 1.1.4.2 thorpej return n;
775 1.1.4.2 thorpej if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
776 1.1.4.2 thorpej if (n >= sizeof(fdc->sc_status)) {
777 1.1.4.2 thorpej log(LOG_ERR, "fdcresult: overrun\n");
778 1.1.4.2 thorpej return -1;
779 1.1.4.2 thorpej }
780 1.1.4.2 thorpej fdc->sc_status[n++] =
781 1.1.4.2 thorpej bus_space_read_1(iot, ioh, fddata);
782 1.1.4.2 thorpej }
783 1.1.4.2 thorpej delay(10);
784 1.1.4.2 thorpej }
785 1.1.4.2 thorpej log(LOG_ERR, "fdcresult: timeout\n");
786 1.1.4.2 thorpej return -1;
787 1.1.4.2 thorpej }
788 1.1.4.2 thorpej
789 1.1.4.2 thorpej int
790 1.1.4.2 thorpej out_fdc(iot, ioh, x)
791 1.1.4.2 thorpej bus_space_tag_t iot;
792 1.1.4.2 thorpej bus_space_handle_t ioh;
793 1.1.4.2 thorpej u_char x;
794 1.1.4.2 thorpej {
795 1.1.4.2 thorpej int i = 100000;
796 1.1.4.2 thorpej
797 1.1.4.2 thorpej while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0);
798 1.1.4.2 thorpej if (i <= 0)
799 1.1.4.2 thorpej return -1;
800 1.1.4.2 thorpej while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
801 1.1.4.2 thorpej if (i <= 0)
802 1.1.4.2 thorpej return -1;
803 1.1.4.2 thorpej bus_space_write_2(iot, ioh, fddata, x);
804 1.1.4.2 thorpej return 0;
805 1.1.4.2 thorpej }
806 1.1.4.2 thorpej
807 1.1.4.2 thorpej int
808 1.1.4.2 thorpej fdopen(dev, flags, mode, p)
809 1.1.4.2 thorpej dev_t dev;
810 1.1.4.2 thorpej int flags;
811 1.1.4.2 thorpej int mode;
812 1.1.4.2 thorpej struct proc *p;
813 1.1.4.2 thorpej {
814 1.1.4.2 thorpej int unit;
815 1.1.4.2 thorpej struct fd_softc *fd;
816 1.1.4.2 thorpej struct fd_type *type;
817 1.1.4.2 thorpej
818 1.1.4.2 thorpej unit = FDUNIT(dev);
819 1.1.4.2 thorpej if (unit >= fd_cd.cd_ndevs)
820 1.1.4.2 thorpej return ENXIO;
821 1.1.4.2 thorpej fd = fd_cd.cd_devs[unit];
822 1.1.4.2 thorpej if (fd == 0)
823 1.1.4.2 thorpej return ENXIO;
824 1.1.4.2 thorpej type = fd_dev_to_type(fd, dev);
825 1.1.4.2 thorpej if (type == NULL)
826 1.1.4.2 thorpej return ENXIO;
827 1.1.4.2 thorpej
828 1.1.4.2 thorpej if ((fd->sc_flags & FD_OPEN) != 0 &&
829 1.1.4.2 thorpej memcmp(fd->sc_type, type, sizeof(*type)))
830 1.1.4.2 thorpej return EBUSY;
831 1.1.4.2 thorpej
832 1.1.4.2 thorpej fd->sc_type_copy = *type;
833 1.1.4.2 thorpej fd->sc_type = &fd->sc_type_copy;
834 1.1.4.2 thorpej fd->sc_cylin = -1;
835 1.1.4.2 thorpej fd->sc_flags |= FD_OPEN;
836 1.1.4.2 thorpej
837 1.1.4.2 thorpej return 0;
838 1.1.4.2 thorpej }
839 1.1.4.2 thorpej
840 1.1.4.2 thorpej int
841 1.1.4.2 thorpej fdclose(dev, flags, mode, p)
842 1.1.4.2 thorpej dev_t dev;
843 1.1.4.2 thorpej int flags;
844 1.1.4.2 thorpej int mode;
845 1.1.4.2 thorpej struct proc *p;
846 1.1.4.2 thorpej {
847 1.1.4.2 thorpej struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
848 1.1.4.2 thorpej
849 1.1.4.2 thorpej fd->sc_flags &= ~FD_OPEN;
850 1.1.4.2 thorpej fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT);
851 1.1.4.2 thorpej return 0;
852 1.1.4.2 thorpej }
853 1.1.4.2 thorpej
854 1.1.4.2 thorpej void
855 1.1.4.2 thorpej fdcstart(fdc)
856 1.1.4.2 thorpej struct fdc_softc *fdc;
857 1.1.4.2 thorpej {
858 1.1.4.2 thorpej
859 1.1.4.2 thorpej #ifdef DIAGNOSTIC
860 1.1.4.2 thorpej /* only got here if controller's drive queue was inactive; should
861 1.1.4.2 thorpej be in idle state */
862 1.1.4.2 thorpej if (fdc->sc_state != DEVIDLE) {
863 1.1.4.2 thorpej printf("fdcstart: not idle\n");
864 1.1.4.2 thorpej return;
865 1.1.4.2 thorpej }
866 1.1.4.2 thorpej #endif
867 1.1.4.2 thorpej (void) fdcintr(fdc);
868 1.1.4.2 thorpej }
869 1.1.4.2 thorpej
870 1.1.4.2 thorpej void
871 1.1.4.2 thorpej fdcstatus(dv, n, s)
872 1.1.4.2 thorpej struct device *dv;
873 1.1.4.2 thorpej int n;
874 1.1.4.2 thorpej char *s;
875 1.1.4.2 thorpej {
876 1.1.4.2 thorpej struct fdc_softc *fdc = (void *)dv->dv_parent;
877 1.1.4.2 thorpej char bits[64];
878 1.1.4.2 thorpej
879 1.1.4.2 thorpej if (n == 0) {
880 1.1.4.2 thorpej out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI);
881 1.1.4.2 thorpej (void) fdcresult(fdc);
882 1.1.4.2 thorpej n = 2;
883 1.1.4.2 thorpej }
884 1.1.4.2 thorpej
885 1.1.4.2 thorpej printf("%s: %s", dv->dv_xname, s);
886 1.1.4.2 thorpej
887 1.1.4.2 thorpej switch (n) {
888 1.1.4.2 thorpej case 0:
889 1.1.4.2 thorpej printf("\n");
890 1.1.4.2 thorpej break;
891 1.1.4.2 thorpej case 2:
892 1.1.4.2 thorpej printf(" (st0 %s cyl %d)\n",
893 1.1.4.2 thorpej bitmask_snprintf(fdc->sc_status[0], NE7_ST0BITS,
894 1.1.4.2 thorpej bits, sizeof(bits)), fdc->sc_status[1]);
895 1.1.4.2 thorpej break;
896 1.1.4.2 thorpej case 7:
897 1.1.4.2 thorpej printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0],
898 1.1.4.2 thorpej NE7_ST0BITS, bits, sizeof(bits)));
899 1.1.4.2 thorpej printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1],
900 1.1.4.2 thorpej NE7_ST1BITS, bits, sizeof(bits)));
901 1.1.4.2 thorpej printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2],
902 1.1.4.2 thorpej NE7_ST2BITS, bits, sizeof(bits)));
903 1.1.4.2 thorpej printf(" cyl %d head %d sec %d)\n",
904 1.1.4.2 thorpej fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
905 1.1.4.2 thorpej break;
906 1.1.4.2 thorpej #ifdef DIAGNOSTIC
907 1.1.4.2 thorpej default:
908 1.1.4.2 thorpej printf("\nfdcstatus: weird size");
909 1.1.4.2 thorpej break;
910 1.1.4.2 thorpej #endif
911 1.1.4.2 thorpej }
912 1.1.4.2 thorpej }
913 1.1.4.2 thorpej
914 1.1.4.2 thorpej void
915 1.1.4.2 thorpej fdctimeout(arg)
916 1.1.4.2 thorpej void *arg;
917 1.1.4.2 thorpej {
918 1.1.4.2 thorpej struct fdc_softc *fdc = arg;
919 1.1.4.2 thorpej struct fd_softc *fd = fdc->sc_drives.tqh_first;
920 1.1.4.2 thorpej int s;
921 1.1.4.2 thorpej
922 1.1.4.2 thorpej s = splbio();
923 1.1.4.2 thorpej #ifdef DEBUG
924 1.1.4.2 thorpej log(LOG_ERR,"fdctimeout: state %d\n", fdc->sc_state);
925 1.1.4.2 thorpej #endif
926 1.1.4.2 thorpej fdcstatus(&fd->sc_dev, 0, "timeout");
927 1.1.4.2 thorpej
928 1.1.4.5 nathanw if (BUFQ_PEEK(&fd->sc_q) != NULL)
929 1.1.4.2 thorpej fdc->sc_state++;
930 1.1.4.2 thorpej else
931 1.1.4.2 thorpej fdc->sc_state = DEVIDLE;
932 1.1.4.2 thorpej
933 1.1.4.2 thorpej (void) fdcintr(fdc);
934 1.1.4.2 thorpej splx(s);
935 1.1.4.2 thorpej }
936 1.1.4.2 thorpej
937 1.1.4.2 thorpej void
938 1.1.4.2 thorpej fdcpseudointr(arg)
939 1.1.4.2 thorpej void *arg;
940 1.1.4.2 thorpej {
941 1.1.4.2 thorpej int s;
942 1.1.4.2 thorpej
943 1.1.4.2 thorpej /* Just ensure it has the right spl. */
944 1.1.4.2 thorpej s = splbio();
945 1.1.4.2 thorpej (void) fdcintr(arg);
946 1.1.4.2 thorpej splx(s);
947 1.1.4.2 thorpej }
948 1.1.4.2 thorpej
949 1.1.4.2 thorpej int
950 1.1.4.2 thorpej fdcintr(arg)
951 1.1.4.2 thorpej void *arg;
952 1.1.4.2 thorpej {
953 1.1.4.2 thorpej struct fdc_softc *fdc = arg;
954 1.1.4.2 thorpej #define st0 fdc->sc_status[0]
955 1.1.4.2 thorpej #define cyl fdc->sc_status[1]
956 1.1.4.2 thorpej struct fd_softc *fd;
957 1.1.4.2 thorpej struct buf *bp;
958 1.1.4.2 thorpej bus_space_tag_t iot = fdc->sc_iot;
959 1.1.4.2 thorpej bus_space_handle_t ioh = fdc->sc_ioh;
960 1.1.4.2 thorpej int read, head, sec, i, nblks;
961 1.1.4.2 thorpej struct fd_type *type;
962 1.1.4.2 thorpej struct ne7_fd_formb *finfo = NULL;
963 1.1.4.2 thorpej
964 1.1.4.2 thorpej loop:
965 1.1.4.2 thorpej /* Is there a drive for the controller to do a transfer with? */
966 1.1.4.2 thorpej fd = fdc->sc_drives.tqh_first;
967 1.1.4.2 thorpej if (fd == NULL) {
968 1.1.4.2 thorpej fdc->sc_state = DEVIDLE;
969 1.1.4.2 thorpej return 1;
970 1.1.4.2 thorpej }
971 1.1.4.2 thorpej
972 1.1.4.2 thorpej /* Is there a transfer to this drive? If not, deactivate drive. */
973 1.1.4.5 nathanw bp = BUFQ_PEEK(&fd->sc_q);
974 1.1.4.2 thorpej if (bp == NULL) {
975 1.1.4.2 thorpej fd->sc_ops = 0;
976 1.1.4.2 thorpej TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
977 1.1.4.2 thorpej fd->sc_active = 0;
978 1.1.4.2 thorpej goto loop;
979 1.1.4.2 thorpej }
980 1.1.4.2 thorpej
981 1.1.4.2 thorpej if (bp->b_flags & B_FORMAT)
982 1.1.4.2 thorpej finfo = (struct ne7_fd_formb *)bp->b_data;
983 1.1.4.2 thorpej
984 1.1.4.2 thorpej switch (fdc->sc_state) {
985 1.1.4.2 thorpej case DEVIDLE:
986 1.1.4.2 thorpej fdc->sc_errors = 0;
987 1.1.4.2 thorpej fd->sc_skip = 0;
988 1.1.4.2 thorpej fd->sc_bcount = bp->b_bcount;
989 1.1.4.2 thorpej fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE);
990 1.1.4.2 thorpej callout_stop(&fd->sc_motoroff_ch);
991 1.1.4.2 thorpej if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
992 1.1.4.2 thorpej fdc->sc_state = MOTORWAIT;
993 1.1.4.2 thorpej return 1;
994 1.1.4.2 thorpej }
995 1.1.4.2 thorpej if ((fd->sc_flags & FD_MOTOR) == 0) {
996 1.1.4.2 thorpej /* Turn on the motor, being careful about pairing. */
997 1.1.4.2 thorpej struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1];
998 1.1.4.2 thorpej if (ofd && ofd->sc_flags & FD_MOTOR) {
999 1.1.4.2 thorpej callout_stop(&ofd->sc_motoroff_ch);
1000 1.1.4.2 thorpej ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
1001 1.1.4.2 thorpej }
1002 1.1.4.2 thorpej fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
1003 1.1.4.2 thorpej fd_set_motor(fdc, 0);
1004 1.1.4.2 thorpej fdc->sc_state = MOTORWAIT;
1005 1.1.4.2 thorpej /* Allow .25s for motor to stabilize. */
1006 1.1.4.2 thorpej callout_reset(&fd->sc_motoron_ch, hz / 4,
1007 1.1.4.2 thorpej fd_motor_on, fd);
1008 1.1.4.2 thorpej return 1;
1009 1.1.4.2 thorpej }
1010 1.1.4.2 thorpej /* Make sure the right drive is selected. */
1011 1.1.4.2 thorpej fd_set_motor(fdc, 0);
1012 1.1.4.2 thorpej
1013 1.1.4.2 thorpej /* fall through */
1014 1.1.4.2 thorpej case DOSEEK:
1015 1.1.4.2 thorpej doseek:
1016 1.1.4.2 thorpej if (fd->sc_cylin == bp->b_cylinder)
1017 1.1.4.2 thorpej goto doio;
1018 1.1.4.2 thorpej
1019 1.1.4.2 thorpej #if 1
1020 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_CONFIGURE);/* configure command */
1021 1.1.4.2 thorpej out_fdc(iot, ioh, 0);
1022 1.1.4.2 thorpej out_fdc(iot, ioh, 0x18);
1023 1.1.4.2 thorpej out_fdc(iot, ioh, 0);
1024 1.1.4.2 thorpej #endif
1025 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_SPECIFY);/* specify command */
1026 1.1.4.2 thorpej out_fdc(iot, ioh, fd->sc_type->steprate);
1027 1.1.4.2 thorpej out_fdc(iot, ioh, 6); /* XXX head load time == 6ms */
1028 1.1.4.2 thorpej
1029 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_SEEK); /* seek function */
1030 1.1.4.2 thorpej out_fdc(iot, ioh, fd->sc_drive); /* drive number */
1031 1.1.4.2 thorpej out_fdc(iot, ioh, bp->b_cylinder * fd->sc_type->step);
1032 1.1.4.2 thorpej
1033 1.1.4.2 thorpej fd->sc_cylin = -1;
1034 1.1.4.2 thorpej fdc->sc_state = SEEKWAIT;
1035 1.1.4.2 thorpej
1036 1.1.4.2 thorpej fd->sc_dk.dk_seek++;
1037 1.1.4.2 thorpej disk_busy(&fd->sc_dk);
1038 1.1.4.2 thorpej
1039 1.1.4.2 thorpej callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
1040 1.1.4.2 thorpej return 1;
1041 1.1.4.2 thorpej
1042 1.1.4.2 thorpej case DOIO:
1043 1.1.4.2 thorpej doio:
1044 1.1.4.2 thorpej type = fd->sc_type;
1045 1.1.4.2 thorpej if (finfo)
1046 1.1.4.2 thorpej fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) -
1047 1.1.4.2 thorpej (char *)finfo;
1048 1.1.4.2 thorpej sec = fd->sc_blkno % type->seccyl;
1049 1.1.4.2 thorpej nblks = type->seccyl - sec;
1050 1.1.4.2 thorpej nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
1051 1.1.4.2 thorpej nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE);
1052 1.1.4.2 thorpej fd->sc_nblks = nblks;
1053 1.1.4.2 thorpej fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FDC_BSIZE;
1054 1.1.4.2 thorpej head = sec / type->sectrac;
1055 1.1.4.2 thorpej sec -= head * type->sectrac;
1056 1.1.4.2 thorpej #ifdef DIAGNOSTIC
1057 1.1.4.2 thorpej {int block;
1058 1.1.4.2 thorpej block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
1059 1.1.4.2 thorpej if (block != fd->sc_blkno) {
1060 1.1.4.2 thorpej printf("fdcintr: block %d != blkno %d\n",
1061 1.1.4.2 thorpej block, fd->sc_blkno);
1062 1.1.4.2 thorpej #ifdef DDB
1063 1.1.4.2 thorpej Debugger();
1064 1.1.4.2 thorpej #endif
1065 1.1.4.2 thorpej }}
1066 1.1.4.2 thorpej #endif
1067 1.1.4.2 thorpej read = bp->b_flags & B_READ;
1068 1.1.4.3 nathanw if (read) {
1069 1.1.4.3 nathanw fdc->sc_fh.fh_func = floppy_read_fiq;
1070 1.1.4.3 nathanw fdc->sc_fh.fh_size = floppy_read_fiq_end -
1071 1.1.4.3 nathanw floppy_read_fiq;
1072 1.1.4.3 nathanw } else {
1073 1.1.4.3 nathanw fdc->sc_fh.fh_func = floppy_write_fiq;
1074 1.1.4.3 nathanw fdc->sc_fh.fh_size = floppy_read_fiq_end -
1075 1.1.4.3 nathanw floppy_read_fiq;
1076 1.1.4.3 nathanw }
1077 1.1.4.3 nathanw fdc->sc_fh.fh_flags = 0;
1078 1.1.4.3 nathanw fdc->sc_fh.fh_regs = &fdc->sc_fr;
1079 1.1.4.3 nathanw fdc->sc_fr.fr_r9 = IOMD_BASE + (IOMD_FIQRQ << 2);
1080 1.1.4.3 nathanw fdc->sc_fr.fr_r10 = fd->sc_nbytes;
1081 1.1.4.3 nathanw fdc->sc_fr.fr_r11 = (u_int)(bp->b_data + fd->sc_skip);
1082 1.1.4.3 nathanw fdc->sc_fr.fr_r12 = fdc->sc_drq;
1083 1.1.4.2 thorpej #ifdef FD_DEBUG
1084 1.1.4.3 nathanw printf("fdc-doio:r9=%x r10=%x r11=%x r12=%x data=%x skip=%x\n",
1085 1.1.4.3 nathanw fdc->sc_fr.fr_r9, fdc->sc_fr.fh_r10, fdc->sc_fr.fh_r11,
1086 1.1.4.3 nathanw fdc->sc_fr.fh_r12, (u_int)bp->b_data, fd->sc_skip);
1087 1.1.4.2 thorpej #endif
1088 1.1.4.3 nathanw if (fiq_claim(&fdc->sc_fh) == -1)
1089 1.1.4.2 thorpej panic("%s: Cannot claim FIQ vector\n", fdc->sc_dev.dv_xname);
1090 1.1.4.3 nathanw IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x01);
1091 1.1.4.2 thorpej bus_space_write_2(iot, ioh, fdctl, type->rate);
1092 1.1.4.2 thorpej #ifdef FD_DEBUG
1093 1.1.4.2 thorpej printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
1094 1.1.4.2 thorpej read ? "read" : "write", fd->sc_drive, fd->sc_cylin,
1095 1.1.4.2 thorpej head, sec, nblks);
1096 1.1.4.2 thorpej #endif
1097 1.1.4.2 thorpej if (finfo) {
1098 1.1.4.2 thorpej /* formatting */
1099 1.1.4.2 thorpej if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) {
1100 1.1.4.2 thorpej fdc->sc_errors = 4;
1101 1.1.4.2 thorpej fdcretry(fdc);
1102 1.1.4.2 thorpej goto loop;
1103 1.1.4.2 thorpej }
1104 1.1.4.2 thorpej out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
1105 1.1.4.2 thorpej out_fdc(iot, ioh, finfo->fd_formb_secshift);
1106 1.1.4.2 thorpej out_fdc(iot, ioh, finfo->fd_formb_nsecs);
1107 1.1.4.2 thorpej out_fdc(iot, ioh, finfo->fd_formb_gaplen);
1108 1.1.4.2 thorpej out_fdc(iot, ioh, finfo->fd_formb_fillbyte);
1109 1.1.4.2 thorpej } else {
1110 1.1.4.2 thorpej if (read)
1111 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_READ); /* READ */
1112 1.1.4.2 thorpej else
1113 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */
1114 1.1.4.2 thorpej out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
1115 1.1.4.2 thorpej out_fdc(iot, ioh, fd->sc_cylin); /* track */
1116 1.1.4.2 thorpej out_fdc(iot, ioh, head);
1117 1.1.4.2 thorpej out_fdc(iot, ioh, sec + 1); /* sector +1 */
1118 1.1.4.2 thorpej out_fdc(iot, ioh, type->secsize);/* sector size */
1119 1.1.4.2 thorpej out_fdc(iot, ioh, type->sectrac);/* sectors/track */
1120 1.1.4.2 thorpej out_fdc(iot, ioh, type->gap1); /* gap1 size */
1121 1.1.4.2 thorpej out_fdc(iot, ioh, type->datalen);/* data length */
1122 1.1.4.2 thorpej }
1123 1.1.4.2 thorpej fdc->sc_state = IOCOMPLETE;
1124 1.1.4.2 thorpej
1125 1.1.4.2 thorpej disk_busy(&fd->sc_dk);
1126 1.1.4.2 thorpej
1127 1.1.4.2 thorpej /* allow 2 seconds for operation */
1128 1.1.4.2 thorpej callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
1129 1.1.4.2 thorpej return 1; /* will return later */
1130 1.1.4.2 thorpej
1131 1.1.4.2 thorpej case SEEKWAIT:
1132 1.1.4.2 thorpej callout_stop(&fdc->sc_timo_ch);
1133 1.1.4.2 thorpej fdc->sc_state = SEEKCOMPLETE;
1134 1.1.4.2 thorpej /* allow 1/50 second for heads to settle */
1135 1.1.4.2 thorpej #if 0
1136 1.1.4.2 thorpej callout_reset(&fdc->sc_intr_ch, hz / 50, fdcpseudointr, fdc);
1137 1.1.4.2 thorpej #endif
1138 1.1.4.2 thorpej return 1;
1139 1.1.4.2 thorpej
1140 1.1.4.2 thorpej case SEEKCOMPLETE:
1141 1.1.4.2 thorpej disk_unbusy(&fd->sc_dk, 0); /* no data on seek */
1142 1.1.4.2 thorpej
1143 1.1.4.2 thorpej /* Make sure seek really happened. */
1144 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_SENSEI);
1145 1.1.4.2 thorpej if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
1146 1.1.4.2 thorpej cyl != bp->b_cylinder * fd->sc_type->step) {
1147 1.1.4.2 thorpej #ifdef FD_DEBUG
1148 1.1.4.2 thorpej fdcstatus(&fd->sc_dev, 2, "seek failed");
1149 1.1.4.2 thorpej #endif
1150 1.1.4.2 thorpej fdcretry(fdc);
1151 1.1.4.2 thorpej goto loop;
1152 1.1.4.2 thorpej }
1153 1.1.4.2 thorpej fd->sc_cylin = bp->b_cylinder;
1154 1.1.4.2 thorpej goto doio;
1155 1.1.4.2 thorpej
1156 1.1.4.2 thorpej case IOTIMEDOUT:
1157 1.1.4.3 nathanw fiq_release(&fdc->sc_fh);
1158 1.1.4.3 nathanw IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
1159 1.1.4.2 thorpej case SEEKTIMEDOUT:
1160 1.1.4.2 thorpej case RECALTIMEDOUT:
1161 1.1.4.2 thorpej case RESETTIMEDOUT:
1162 1.1.4.2 thorpej fdcretry(fdc);
1163 1.1.4.2 thorpej goto loop;
1164 1.1.4.2 thorpej
1165 1.1.4.2 thorpej case IOCOMPLETE: /* IO DONE, post-analyze */
1166 1.1.4.2 thorpej callout_stop(&fdc->sc_timo_ch);
1167 1.1.4.2 thorpej
1168 1.1.4.2 thorpej disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid));
1169 1.1.4.2 thorpej
1170 1.1.4.2 thorpej if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
1171 1.1.4.3 nathanw fiq_release(&fdc->sc_fh);
1172 1.1.4.3 nathanw IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
1173 1.1.4.2 thorpej #ifdef FD_DEBUG
1174 1.1.4.2 thorpej fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
1175 1.1.4.2 thorpej "read failed" : "write failed");
1176 1.1.4.2 thorpej printf("blkno %d nblks %d\n",
1177 1.1.4.2 thorpej fd->sc_blkno, fd->sc_nblks);
1178 1.1.4.2 thorpej #endif
1179 1.1.4.2 thorpej fdcretry(fdc);
1180 1.1.4.2 thorpej goto loop;
1181 1.1.4.2 thorpej }
1182 1.1.4.3 nathanw fiq_release(&fdc->sc_fh);
1183 1.1.4.3 nathanw IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
1184 1.1.4.2 thorpej if (fdc->sc_errors) {
1185 1.1.4.2 thorpej #if 0
1186 1.1.4.2 thorpej diskerr(bp, "fd", "soft error (corrected)", LOG_PRINTF,
1187 1.1.4.2 thorpej fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
1188 1.1.4.2 thorpej printf("\n");
1189 1.1.4.2 thorpej #endif
1190 1.1.4.2 thorpej fdc->sc_errors = 0;
1191 1.1.4.2 thorpej }
1192 1.1.4.2 thorpej fd->sc_blkno += fd->sc_nblks;
1193 1.1.4.2 thorpej fd->sc_skip += fd->sc_nbytes;
1194 1.1.4.2 thorpej fd->sc_bcount -= fd->sc_nbytes;
1195 1.1.4.2 thorpej if (!finfo && fd->sc_bcount > 0) {
1196 1.1.4.2 thorpej bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl;
1197 1.1.4.2 thorpej goto doseek;
1198 1.1.4.2 thorpej }
1199 1.1.4.2 thorpej fdfinish(fd, bp);
1200 1.1.4.2 thorpej goto loop;
1201 1.1.4.2 thorpej
1202 1.1.4.2 thorpej case DORESET:
1203 1.1.4.2 thorpej /* try a reset, keep motor on */
1204 1.1.4.2 thorpej fd_set_motor(fdc, 1);
1205 1.1.4.2 thorpej delay(100);
1206 1.1.4.2 thorpej fd_set_motor(fdc, 0);
1207 1.1.4.2 thorpej fdc->sc_state = RESETCOMPLETE;
1208 1.1.4.2 thorpej callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc);
1209 1.1.4.2 thorpej return 1; /* will return later */
1210 1.1.4.2 thorpej
1211 1.1.4.2 thorpej case RESETCOMPLETE:
1212 1.1.4.2 thorpej callout_stop(&fdc->sc_timo_ch);
1213 1.1.4.2 thorpej /* clear the controller output buffer */
1214 1.1.4.2 thorpej for (i = 0; i < 4; i++) {
1215 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_SENSEI);
1216 1.1.4.2 thorpej (void) fdcresult(fdc);
1217 1.1.4.2 thorpej }
1218 1.1.4.2 thorpej
1219 1.1.4.2 thorpej /* fall through */
1220 1.1.4.2 thorpej case DORECAL:
1221 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_RECAL); /* recalibrate function */
1222 1.1.4.2 thorpej out_fdc(iot, ioh, fd->sc_drive);
1223 1.1.4.2 thorpej fdc->sc_state = RECALWAIT;
1224 1.1.4.2 thorpej callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc);
1225 1.1.4.2 thorpej return 1; /* will return later */
1226 1.1.4.2 thorpej
1227 1.1.4.2 thorpej case RECALWAIT:
1228 1.1.4.2 thorpej callout_stop(&fdc->sc_timo_ch);
1229 1.1.4.2 thorpej fdc->sc_state = RECALCOMPLETE;
1230 1.1.4.2 thorpej /* allow 1/30 second for heads to settle */
1231 1.1.4.2 thorpej #if 0
1232 1.1.4.2 thorpej callout_reset(&fdc->sc_intr_ch, hz / 30, fdcpseudointr, fdc);
1233 1.1.4.2 thorpej #endif
1234 1.1.4.2 thorpej return 1; /* will return later */
1235 1.1.4.2 thorpej
1236 1.1.4.2 thorpej case RECALCOMPLETE:
1237 1.1.4.2 thorpej out_fdc(iot, ioh, NE7CMD_SENSEI);
1238 1.1.4.2 thorpej if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
1239 1.1.4.2 thorpej #ifdef FD_DEBUG
1240 1.1.4.2 thorpej fdcstatus(&fd->sc_dev, 2, "recalibrate failed");
1241 1.1.4.2 thorpej #endif
1242 1.1.4.2 thorpej fdcretry(fdc);
1243 1.1.4.2 thorpej goto loop;
1244 1.1.4.2 thorpej }
1245 1.1.4.2 thorpej fd->sc_cylin = 0;
1246 1.1.4.2 thorpej goto doseek;
1247 1.1.4.2 thorpej
1248 1.1.4.2 thorpej case MOTORWAIT:
1249 1.1.4.2 thorpej if (fd->sc_flags & FD_MOTOR_WAIT)
1250 1.1.4.2 thorpej return 1; /* time's not up yet */
1251 1.1.4.2 thorpej goto doseek;
1252 1.1.4.2 thorpej
1253 1.1.4.2 thorpej default:
1254 1.1.4.2 thorpej fdcstatus(&fd->sc_dev, 0, "stray interrupt");
1255 1.1.4.2 thorpej return 1;
1256 1.1.4.2 thorpej }
1257 1.1.4.2 thorpej #ifdef DIAGNOSTIC
1258 1.1.4.2 thorpej panic("fdcintr: impossible");
1259 1.1.4.2 thorpej #endif
1260 1.1.4.2 thorpej #undef st0
1261 1.1.4.2 thorpej #undef cyl
1262 1.1.4.2 thorpej }
1263 1.1.4.2 thorpej
1264 1.1.4.2 thorpej void
1265 1.1.4.2 thorpej fdcretry(fdc)
1266 1.1.4.2 thorpej struct fdc_softc *fdc;
1267 1.1.4.2 thorpej {
1268 1.1.4.2 thorpej char bits[64];
1269 1.1.4.2 thorpej struct fd_softc *fd;
1270 1.1.4.2 thorpej struct buf *bp;
1271 1.1.4.2 thorpej
1272 1.1.4.2 thorpej fd = fdc->sc_drives.tqh_first;
1273 1.1.4.5 nathanw bp = BUFQ_PEEK(&fd->sc_q);
1274 1.1.4.2 thorpej
1275 1.1.4.2 thorpej if (fd->sc_opts & FDOPT_NORETRY)
1276 1.1.4.2 thorpej goto fail;
1277 1.1.4.2 thorpej switch (fdc->sc_errors) {
1278 1.1.4.2 thorpej case 0:
1279 1.1.4.2 thorpej /* try again */
1280 1.1.4.2 thorpej fdc->sc_state = DOSEEK;
1281 1.1.4.2 thorpej break;
1282 1.1.4.2 thorpej
1283 1.1.4.2 thorpej case 1: case 2: case 3:
1284 1.1.4.2 thorpej /* didn't work; try recalibrating */
1285 1.1.4.2 thorpej fdc->sc_state = DORECAL;
1286 1.1.4.2 thorpej break;
1287 1.1.4.2 thorpej
1288 1.1.4.2 thorpej case 4:
1289 1.1.4.2 thorpej /* still no go; reset the bastard */
1290 1.1.4.2 thorpej fdc->sc_state = DORESET;
1291 1.1.4.2 thorpej break;
1292 1.1.4.2 thorpej
1293 1.1.4.2 thorpej default:
1294 1.1.4.2 thorpej fail:
1295 1.1.4.2 thorpej if ((fd->sc_opts & FDOPT_SILENT) == 0) {
1296 1.1.4.2 thorpej diskerr(bp, "fd", "hard error", LOG_PRINTF,
1297 1.1.4.2 thorpej fd->sc_skip / FDC_BSIZE,
1298 1.1.4.2 thorpej (struct disklabel *)NULL);
1299 1.1.4.2 thorpej
1300 1.1.4.2 thorpej printf(" (st0 %s",
1301 1.1.4.2 thorpej bitmask_snprintf(fdc->sc_status[0],
1302 1.1.4.2 thorpej NE7_ST0BITS, bits,
1303 1.1.4.2 thorpej sizeof(bits)));
1304 1.1.4.2 thorpej printf(" st1 %s",
1305 1.1.4.2 thorpej bitmask_snprintf(fdc->sc_status[1],
1306 1.1.4.2 thorpej NE7_ST1BITS, bits,
1307 1.1.4.2 thorpej sizeof(bits)));
1308 1.1.4.2 thorpej printf(" st2 %s",
1309 1.1.4.2 thorpej bitmask_snprintf(fdc->sc_status[2],
1310 1.1.4.2 thorpej NE7_ST2BITS, bits,
1311 1.1.4.2 thorpej sizeof(bits)));
1312 1.1.4.2 thorpej printf(" cyl %d head %d sec %d)\n",
1313 1.1.4.2 thorpej fdc->sc_status[3],
1314 1.1.4.2 thorpej fdc->sc_status[4],
1315 1.1.4.2 thorpej fdc->sc_status[5]);
1316 1.1.4.2 thorpej }
1317 1.1.4.2 thorpej
1318 1.1.4.2 thorpej bp->b_flags |= B_ERROR;
1319 1.1.4.2 thorpej bp->b_error = EIO;
1320 1.1.4.2 thorpej fdfinish(fd, bp);
1321 1.1.4.2 thorpej }
1322 1.1.4.2 thorpej fdc->sc_errors++;
1323 1.1.4.2 thorpej }
1324 1.1.4.2 thorpej
1325 1.1.4.2 thorpej int
1326 1.1.4.2 thorpej fdioctl(dev, cmd, addr, flag, p)
1327 1.1.4.2 thorpej dev_t dev;
1328 1.1.4.2 thorpej u_long cmd;
1329 1.1.4.2 thorpej caddr_t addr;
1330 1.1.4.2 thorpej int flag;
1331 1.1.4.2 thorpej struct proc *p;
1332 1.1.4.2 thorpej {
1333 1.1.4.2 thorpej struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
1334 1.1.4.2 thorpej struct fdformat_parms *form_parms;
1335 1.1.4.2 thorpej struct fdformat_cmd *form_cmd;
1336 1.1.4.2 thorpej struct ne7_fd_formb *fd_formb;
1337 1.1.4.2 thorpej struct disklabel buffer;
1338 1.1.4.2 thorpej int error;
1339 1.1.4.2 thorpej unsigned int scratch;
1340 1.1.4.2 thorpej int il[FD_MAX_NSEC + 1];
1341 1.1.4.2 thorpej register int i, j;
1342 1.1.4.2 thorpej
1343 1.1.4.2 thorpej switch (cmd) {
1344 1.1.4.2 thorpej case DIOCGDINFO:
1345 1.1.4.2 thorpej memset(&buffer, 0, sizeof(buffer));
1346 1.1.4.2 thorpej
1347 1.1.4.2 thorpej buffer.d_secpercyl = fd->sc_type->seccyl;
1348 1.1.4.2 thorpej buffer.d_type = DTYPE_FLOPPY;
1349 1.1.4.2 thorpej buffer.d_secsize = FDC_BSIZE;
1350 1.1.4.2 thorpej
1351 1.1.4.2 thorpej if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL)
1352 1.1.4.2 thorpej return EINVAL;
1353 1.1.4.2 thorpej
1354 1.1.4.2 thorpej *(struct disklabel *)addr = buffer;
1355 1.1.4.2 thorpej return 0;
1356 1.1.4.2 thorpej
1357 1.1.4.2 thorpej case DIOCWLABEL:
1358 1.1.4.2 thorpej if ((flag & FWRITE) == 0)
1359 1.1.4.2 thorpej return EBADF;
1360 1.1.4.2 thorpej /* XXX do something */
1361 1.1.4.2 thorpej return 0;
1362 1.1.4.2 thorpej
1363 1.1.4.2 thorpej case DIOCWDINFO:
1364 1.1.4.2 thorpej if ((flag & FWRITE) == 0)
1365 1.1.4.2 thorpej return EBADF;
1366 1.1.4.2 thorpej
1367 1.1.4.2 thorpej error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL);
1368 1.1.4.2 thorpej if (error)
1369 1.1.4.2 thorpej return error;
1370 1.1.4.2 thorpej
1371 1.1.4.2 thorpej error = writedisklabel(dev, fdstrategy, &buffer, NULL);
1372 1.1.4.2 thorpej return error;
1373 1.1.4.2 thorpej
1374 1.1.4.2 thorpej case FDIOCGETFORMAT:
1375 1.1.4.2 thorpej form_parms = (struct fdformat_parms *)addr;
1376 1.1.4.2 thorpej form_parms->fdformat_version = FDFORMAT_VERSION;
1377 1.1.4.2 thorpej form_parms->nbps = 128 * (1 << fd->sc_type->secsize);
1378 1.1.4.2 thorpej form_parms->ncyl = fd->sc_type->cyls;
1379 1.1.4.2 thorpej form_parms->nspt = fd->sc_type->sectrac;
1380 1.1.4.2 thorpej form_parms->ntrk = fd->sc_type->heads;
1381 1.1.4.2 thorpej form_parms->stepspercyl = fd->sc_type->step;
1382 1.1.4.2 thorpej form_parms->gaplen = fd->sc_type->gap2;
1383 1.1.4.2 thorpej form_parms->fillbyte = fd->sc_type->fillbyte;
1384 1.1.4.2 thorpej form_parms->interleave = fd->sc_type->interleave;
1385 1.1.4.2 thorpej switch (fd->sc_type->rate) {
1386 1.1.4.2 thorpej case FDC_500KBPS:
1387 1.1.4.2 thorpej form_parms->xfer_rate = 500 * 1024;
1388 1.1.4.2 thorpej break;
1389 1.1.4.2 thorpej case FDC_300KBPS:
1390 1.1.4.2 thorpej form_parms->xfer_rate = 300 * 1024;
1391 1.1.4.2 thorpej break;
1392 1.1.4.2 thorpej case FDC_250KBPS:
1393 1.1.4.2 thorpej form_parms->xfer_rate = 250 * 1024;
1394 1.1.4.2 thorpej break;
1395 1.1.4.2 thorpej default:
1396 1.1.4.2 thorpej return EINVAL;
1397 1.1.4.2 thorpej }
1398 1.1.4.2 thorpej return 0;
1399 1.1.4.2 thorpej
1400 1.1.4.2 thorpej case FDIOCSETFORMAT:
1401 1.1.4.2 thorpej if((flag & FWRITE) == 0)
1402 1.1.4.2 thorpej return EBADF; /* must be opened for writing */
1403 1.1.4.2 thorpej form_parms = (struct fdformat_parms *)addr;
1404 1.1.4.2 thorpej if (form_parms->fdformat_version != FDFORMAT_VERSION)
1405 1.1.4.2 thorpej return EINVAL; /* wrong version of formatting prog */
1406 1.1.4.2 thorpej
1407 1.1.4.2 thorpej scratch = form_parms->nbps >> 7;
1408 1.1.4.2 thorpej if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 ||
1409 1.1.4.2 thorpej scratch & ~(1 << (ffs(scratch)-1)))
1410 1.1.4.2 thorpej /* not a power-of-two multiple of 128 */
1411 1.1.4.2 thorpej return EINVAL;
1412 1.1.4.2 thorpej
1413 1.1.4.2 thorpej switch (form_parms->xfer_rate) {
1414 1.1.4.2 thorpej case 500 * 1024:
1415 1.1.4.2 thorpej fd->sc_type->rate = FDC_500KBPS;
1416 1.1.4.2 thorpej break;
1417 1.1.4.2 thorpej case 300 * 1024:
1418 1.1.4.2 thorpej fd->sc_type->rate = FDC_300KBPS;
1419 1.1.4.2 thorpej break;
1420 1.1.4.2 thorpej case 250 * 1024:
1421 1.1.4.2 thorpej fd->sc_type->rate = FDC_250KBPS;
1422 1.1.4.2 thorpej break;
1423 1.1.4.2 thorpej default:
1424 1.1.4.2 thorpej return EINVAL;
1425 1.1.4.2 thorpej }
1426 1.1.4.2 thorpej
1427 1.1.4.2 thorpej if (form_parms->nspt > FD_MAX_NSEC ||
1428 1.1.4.2 thorpej form_parms->fillbyte > 0xff ||
1429 1.1.4.2 thorpej form_parms->interleave > 0xff)
1430 1.1.4.2 thorpej return EINVAL;
1431 1.1.4.2 thorpej fd->sc_type->sectrac = form_parms->nspt;
1432 1.1.4.2 thorpej if (form_parms->ntrk != 2 && form_parms->ntrk != 1)
1433 1.1.4.2 thorpej return EINVAL;
1434 1.1.4.2 thorpej fd->sc_type->heads = form_parms->ntrk;
1435 1.1.4.2 thorpej fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk;
1436 1.1.4.2 thorpej fd->sc_type->secsize = ffs(scratch)-1;
1437 1.1.4.2 thorpej fd->sc_type->gap2 = form_parms->gaplen;
1438 1.1.4.2 thorpej fd->sc_type->cyls = form_parms->ncyl;
1439 1.1.4.2 thorpej fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl *
1440 1.1.4.2 thorpej form_parms->nbps / DEV_BSIZE;
1441 1.1.4.2 thorpej fd->sc_type->step = form_parms->stepspercyl;
1442 1.1.4.2 thorpej fd->sc_type->fillbyte = form_parms->fillbyte;
1443 1.1.4.2 thorpej fd->sc_type->interleave = form_parms->interleave;
1444 1.1.4.2 thorpej return 0;
1445 1.1.4.2 thorpej
1446 1.1.4.2 thorpej case FDIOCFORMAT_TRACK:
1447 1.1.4.2 thorpej if((flag & FWRITE) == 0)
1448 1.1.4.2 thorpej return EBADF; /* must be opened for writing */
1449 1.1.4.2 thorpej form_cmd = (struct fdformat_cmd *)addr;
1450 1.1.4.2 thorpej if (form_cmd->formatcmd_version != FDFORMAT_VERSION)
1451 1.1.4.2 thorpej return EINVAL; /* wrong version of formatting prog */
1452 1.1.4.2 thorpej
1453 1.1.4.2 thorpej if (form_cmd->head >= fd->sc_type->heads ||
1454 1.1.4.2 thorpej form_cmd->cylinder >= fd->sc_type->cyls) {
1455 1.1.4.2 thorpej return EINVAL;
1456 1.1.4.2 thorpej }
1457 1.1.4.2 thorpej
1458 1.1.4.2 thorpej fd_formb = malloc(sizeof(struct ne7_fd_formb),
1459 1.1.4.2 thorpej M_TEMP, M_NOWAIT);
1460 1.1.4.2 thorpej if(fd_formb == 0)
1461 1.1.4.2 thorpej return ENOMEM;
1462 1.1.4.2 thorpej
1463 1.1.4.2 thorpej
1464 1.1.4.2 thorpej fd_formb->head = form_cmd->head;
1465 1.1.4.2 thorpej fd_formb->cyl = form_cmd->cylinder;
1466 1.1.4.2 thorpej fd_formb->transfer_rate = fd->sc_type->rate;
1467 1.1.4.2 thorpej fd_formb->fd_formb_secshift = fd->sc_type->secsize;
1468 1.1.4.2 thorpej fd_formb->fd_formb_nsecs = fd->sc_type->sectrac;
1469 1.1.4.2 thorpej fd_formb->fd_formb_gaplen = fd->sc_type->gap2;
1470 1.1.4.2 thorpej fd_formb->fd_formb_fillbyte = fd->sc_type->fillbyte;
1471 1.1.4.2 thorpej
1472 1.1.4.2 thorpej memset(il, 0, sizeof il);
1473 1.1.4.2 thorpej for (j = 0, i = 1; i <= fd_formb->fd_formb_nsecs; i++) {
1474 1.1.4.2 thorpej while (il[(j%fd_formb->fd_formb_nsecs)+1])
1475 1.1.4.2 thorpej j++;
1476 1.1.4.2 thorpej il[(j%fd_formb->fd_formb_nsecs)+1] = i;
1477 1.1.4.2 thorpej j += fd->sc_type->interleave;
1478 1.1.4.2 thorpej }
1479 1.1.4.2 thorpej for (i = 0; i < fd_formb->fd_formb_nsecs; i++) {
1480 1.1.4.2 thorpej fd_formb->fd_formb_cylno(i) = form_cmd->cylinder;
1481 1.1.4.2 thorpej fd_formb->fd_formb_headno(i) = form_cmd->head;
1482 1.1.4.2 thorpej fd_formb->fd_formb_secno(i) = il[i+1];
1483 1.1.4.2 thorpej fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize;
1484 1.1.4.2 thorpej }
1485 1.1.4.2 thorpej
1486 1.1.4.2 thorpej error = fdformat(dev, fd_formb, p);
1487 1.1.4.2 thorpej free(fd_formb, M_TEMP);
1488 1.1.4.2 thorpej return error;
1489 1.1.4.2 thorpej
1490 1.1.4.2 thorpej case FDIOCGETOPTS: /* get drive options */
1491 1.1.4.2 thorpej *(int *)addr = fd->sc_opts;
1492 1.1.4.2 thorpej return 0;
1493 1.1.4.2 thorpej
1494 1.1.4.2 thorpej case FDIOCSETOPTS: /* set drive options */
1495 1.1.4.2 thorpej fd->sc_opts = *(int *)addr;
1496 1.1.4.2 thorpej return 0;
1497 1.1.4.2 thorpej
1498 1.1.4.2 thorpej default:
1499 1.1.4.2 thorpej return ENOTTY;
1500 1.1.4.2 thorpej }
1501 1.1.4.2 thorpej
1502 1.1.4.2 thorpej #ifdef DIAGNOSTIC
1503 1.1.4.2 thorpej panic("fdioctl: impossible");
1504 1.1.4.2 thorpej #endif
1505 1.1.4.2 thorpej }
1506 1.1.4.2 thorpej
1507 1.1.4.2 thorpej int
1508 1.1.4.2 thorpej fdformat(dev, finfo, p)
1509 1.1.4.2 thorpej dev_t dev;
1510 1.1.4.2 thorpej struct ne7_fd_formb *finfo;
1511 1.1.4.2 thorpej struct proc *p;
1512 1.1.4.2 thorpej {
1513 1.1.4.2 thorpej int rv = 0, s;
1514 1.1.4.2 thorpej struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
1515 1.1.4.2 thorpej struct fd_type *type = fd->sc_type;
1516 1.1.4.2 thorpej struct buf *bp;
1517 1.1.4.2 thorpej
1518 1.1.4.2 thorpej /* set up a buffer header for fdstrategy() */
1519 1.1.4.2 thorpej bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
1520 1.1.4.2 thorpej if(bp == 0)
1521 1.1.4.2 thorpej return ENOBUFS;
1522 1.1.4.2 thorpej memset((void *)bp, 0, sizeof(struct buf));
1523 1.1.4.2 thorpej bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
1524 1.1.4.2 thorpej bp->b_proc = p;
1525 1.1.4.2 thorpej bp->b_dev = dev;
1526 1.1.4.2 thorpej
1527 1.1.4.2 thorpej /*
1528 1.1.4.2 thorpej * calculate a fake blkno, so fdstrategy() would initiate a
1529 1.1.4.2 thorpej * seek to the requested cylinder
1530 1.1.4.2 thorpej */
1531 1.1.4.2 thorpej bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads)
1532 1.1.4.2 thorpej + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE;
1533 1.1.4.2 thorpej
1534 1.1.4.2 thorpej bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
1535 1.1.4.2 thorpej bp->b_data = (caddr_t)finfo;
1536 1.1.4.2 thorpej
1537 1.1.4.2 thorpej #ifdef DEBUG
1538 1.1.4.2 thorpej printf("fdformat: blkno %x count %lx\n", bp->b_blkno, bp->b_bcount);
1539 1.1.4.2 thorpej #endif
1540 1.1.4.2 thorpej
1541 1.1.4.2 thorpej /* now do the format */
1542 1.1.4.2 thorpej fdstrategy(bp);
1543 1.1.4.2 thorpej
1544 1.1.4.2 thorpej /* ...and wait for it to complete */
1545 1.1.4.2 thorpej s = splbio();
1546 1.1.4.2 thorpej while(!(bp->b_flags & B_DONE)) {
1547 1.1.4.2 thorpej rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
1548 1.1.4.2 thorpej if (rv == EWOULDBLOCK)
1549 1.1.4.2 thorpej break;
1550 1.1.4.2 thorpej }
1551 1.1.4.2 thorpej splx(s);
1552 1.1.4.2 thorpej
1553 1.1.4.2 thorpej if (rv == EWOULDBLOCK) {
1554 1.1.4.2 thorpej /* timed out */
1555 1.1.4.2 thorpej rv = EIO;
1556 1.1.4.2 thorpej biodone(bp);
1557 1.1.4.2 thorpej }
1558 1.1.4.2 thorpej if(bp->b_flags & B_ERROR) {
1559 1.1.4.2 thorpej rv = bp->b_error;
1560 1.1.4.2 thorpej }
1561 1.1.4.2 thorpej free(bp, M_TEMP);
1562 1.1.4.2 thorpej return rv;
1563 1.1.4.2 thorpej }
1564 1.1.4.2 thorpej
1565 1.1.4.2 thorpej #include "md.h"
1566 1.1.4.2 thorpej #if NMD > 0
1567 1.1.4.2 thorpej
1568 1.1.4.2 thorpej #include <dev/md.h>
1569 1.1.4.2 thorpej
1570 1.1.4.2 thorpej int load_memory_disc_from_floppy __P((struct md_conf *md, dev_t dev));
1571 1.1.4.2 thorpej
1572 1.1.4.2 thorpej int
1573 1.1.4.2 thorpej load_memory_disc_from_floppy(md, dev)
1574 1.1.4.2 thorpej struct md_conf *md;
1575 1.1.4.2 thorpej dev_t dev;
1576 1.1.4.2 thorpej {
1577 1.1.4.2 thorpej struct buf *bp;
1578 1.1.4.2 thorpej int loop;
1579 1.1.4.2 thorpej int s;
1580 1.1.4.2 thorpej int type;
1581 1.1.4.2 thorpej int floppysize;
1582 1.1.4.2 thorpej
1583 1.1.4.6 nathanw if (bdevsw_lookup(dev) != &fd_bdevsw)
1584 1.1.4.2 thorpej return(EINVAL);
1585 1.1.4.2 thorpej
1586 1.1.4.2 thorpej if (md->md_type == MD_UNCONFIGURED || md->md_addr == 0)
1587 1.1.4.2 thorpej return(EBUSY);
1588 1.1.4.2 thorpej
1589 1.1.4.2 thorpej type = FDTYPE(dev) - 1;
1590 1.1.4.2 thorpej if (type < 0) type = 0;
1591 1.1.4.2 thorpej floppysize = fd_types[type].size << (fd_types[type].secsize + 7);
1592 1.1.4.2 thorpej
1593 1.1.4.2 thorpej if (md->md_size < floppysize) {
1594 1.1.4.2 thorpej printf("Memory disc is not big enough for floppy image\n");
1595 1.1.4.2 thorpej return(EINVAL);
1596 1.1.4.2 thorpej }
1597 1.1.4.2 thorpej
1598 1.1.4.2 thorpej /* We have the memory disk ! */
1599 1.1.4.2 thorpej
1600 1.1.4.2 thorpej printf("Loading memory disc : %4dK ", 0);
1601 1.1.4.2 thorpej
1602 1.1.4.2 thorpej /* obtain a buffer */
1603 1.1.4.2 thorpej
1604 1.1.4.2 thorpej bp = geteblk(fd_types[type].sectrac * DEV_BSIZE);
1605 1.1.4.2 thorpej
1606 1.1.4.2 thorpej /* request no partition relocation by driver on I/O operations */
1607 1.1.4.2 thorpej
1608 1.1.4.2 thorpej bp->b_dev = dev;
1609 1.1.4.2 thorpej
1610 1.1.4.2 thorpej s = spl0();
1611 1.1.4.2 thorpej
1612 1.1.4.4 nathanw if (fdopen(bp->b_dev, 0, 0, curproc) != 0) {
1613 1.1.4.2 thorpej brelse(bp);
1614 1.1.4.2 thorpej printf("Cannot open floppy device\n");
1615 1.1.4.2 thorpej return(EINVAL);
1616 1.1.4.2 thorpej }
1617 1.1.4.2 thorpej
1618 1.1.4.2 thorpej for (loop = 0;
1619 1.1.4.2 thorpej loop < (floppysize / DEV_BSIZE / fd_types[type].sectrac);
1620 1.1.4.2 thorpej ++loop) {
1621 1.1.4.2 thorpej printf("\x08\x08\x08\x08\x08\x08%4dK ",
1622 1.1.4.2 thorpej loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
1623 1.1.4.2 thorpej bp->b_blkno = loop * fd_types[type].sectrac;
1624 1.1.4.2 thorpej bp->b_bcount = fd_types[type].sectrac * DEV_BSIZE;
1625 1.1.4.2 thorpej bp->b_flags |= B_READ;
1626 1.1.4.2 thorpej bp->b_error = 0;
1627 1.1.4.2 thorpej bp->b_resid = 0;
1628 1.1.4.2 thorpej fdstrategy(bp);
1629 1.1.4.2 thorpej
1630 1.1.4.2 thorpej if (biowait(bp))
1631 1.1.4.2 thorpej panic("Cannot load floppy image\n");
1632 1.1.4.2 thorpej
1633 1.1.4.2 thorpej memcpy((caddr_t)md->md_addr + loop * fd_types[type].sectrac
1634 1.1.4.2 thorpej * DEV_BSIZE, (caddr_t)bp->b_data,
1635 1.1.4.2 thorpej fd_types[type].sectrac * DEV_BSIZE);
1636 1.1.4.2 thorpej }
1637 1.1.4.2 thorpej printf("\x08\x08\x08\x08\x08\x08%4dK done\n",
1638 1.1.4.2 thorpej loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
1639 1.1.4.2 thorpej
1640 1.1.4.4 nathanw fdclose(bp->b_dev, 0, 0, curproc);
1641 1.1.4.2 thorpej
1642 1.1.4.2 thorpej brelse(bp);
1643 1.1.4.2 thorpej
1644 1.1.4.2 thorpej splx(s);
1645 1.1.4.2 thorpej return(0);
1646 1.1.4.2 thorpej }
1647 1.1.4.2 thorpej
1648 1.1.4.2 thorpej #endif
1649