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