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