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