| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: fd.c,v 1.126 2022/05/23 16:58:37 tsutsui Exp $ */ | | 1 | /* $NetBSD: fd.c,v 1.127 2022/05/26 14:27:43 tsutsui Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Charles M. Hannum and Minoura Makoto. | | 8 | * by Charles M. Hannum and Minoura Makoto. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -54,27 +54,27 @@ | | | @@ -54,27 +54,27 @@ |
54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
61 | * SUCH DAMAGE. | | 61 | * SUCH DAMAGE. |
62 | * | | 62 | * |
63 | * @(#)fd.c 7.4 (Berkeley) 5/25/91 | | 63 | * @(#)fd.c 7.4 (Berkeley) 5/25/91 |
64 | */ | | 64 | */ |
65 | | | 65 | |
66 | #include <sys/cdefs.h> | | 66 | #include <sys/cdefs.h> |
67 | __KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.126 2022/05/23 16:58:37 tsutsui Exp $"); | | 67 | __KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.127 2022/05/26 14:27:43 tsutsui Exp $"); |
68 | | | 68 | |
69 | #include "opt_ddb.h" | | 69 | #include "opt_ddb.h" |
70 | #include "opt_m68k_arch.h" | | 70 | #include "opt_m68k_arch.h" |
71 | | | 71 | |
72 | #include <sys/param.h> | | 72 | #include <sys/param.h> |
73 | #include <sys/systm.h> | | 73 | #include <sys/systm.h> |
74 | #include <sys/bus.h> | | 74 | #include <sys/bus.h> |
75 | #include <sys/callout.h> | | 75 | #include <sys/callout.h> |
76 | #include <sys/kernel.h> | | 76 | #include <sys/kernel.h> |
77 | #include <sys/conf.h> | | 77 | #include <sys/conf.h> |
78 | #include <sys/file.h> | | 78 | #include <sys/file.h> |
79 | #include <sys/stat.h> | | 79 | #include <sys/stat.h> |
80 | #include <sys/ioctl.h> | | 80 | #include <sys/ioctl.h> |
| @@ -150,33 +150,33 @@ struct fdc_softc { | | | @@ -150,33 +150,33 @@ struct fdc_softc { |
150 | bus_dmamap_t sc_dmamap; /* DMA map */ | | 150 | bus_dmamap_t sc_dmamap; /* DMA map */ |
151 | uint8_t *sc_addr; /* physical address */ | | 151 | uint8_t *sc_addr; /* physical address */ |
152 | struct dmac_channel_stat *sc_dmachan; /* intio DMA channel */ | | 152 | struct dmac_channel_stat *sc_dmachan; /* intio DMA channel */ |
153 | struct dmac_dma_xfer *sc_xfer; /* DMA transfer */ | | 153 | struct dmac_dma_xfer *sc_xfer; /* DMA transfer */ |
154 | int sc_read; | | 154 | int sc_read; |
155 | | | 155 | |
156 | struct fd_softc *sc_fd[4]; /* pointers to children */ | | 156 | struct fd_softc *sc_fd[4]; /* pointers to children */ |
157 | TAILQ_HEAD(drivehead, fd_softc) sc_drives; | | 157 | TAILQ_HEAD(drivehead, fd_softc) sc_drives; |
158 | enum fdc_state sc_state; | | 158 | enum fdc_state sc_state; |
159 | int sc_errors; /* number of retries so far */ | | 159 | int sc_errors; /* number of retries so far */ |
160 | uint8_t sc_status[7]; /* copy of registers */ | | 160 | uint8_t sc_status[7]; /* copy of registers */ |
161 | }; | | 161 | }; |
162 | | | 162 | |
163 | int fdcintr(void *); | | 163 | static int fdcintr(void *); |
164 | void fdcreset(struct fdc_softc *); | | 164 | static void fdcreset(struct fdc_softc *); |
165 | | | 165 | |
166 | /* controller driver configuration */ | | 166 | /* controller driver configuration */ |
167 | int fdcprobe(device_t, cfdata_t, void *); | | 167 | static int fdcprobe(device_t, cfdata_t, void *); |
168 | void fdcattach(device_t, device_t, void *); | | 168 | static void fdcattach(device_t, device_t, void *); |
169 | int fdprint(void *, const char *); | | 169 | static int fdprint(void *, const char *); |
170 | | | 170 | |
171 | CFATTACH_DECL_NEW(fdc, sizeof(struct fdc_softc), | | 171 | CFATTACH_DECL_NEW(fdc, sizeof(struct fdc_softc), |
172 | fdcprobe, fdcattach, NULL, NULL); | | 172 | fdcprobe, fdcattach, NULL, NULL); |
173 | | | 173 | |
174 | /* | | 174 | /* |
175 | * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how | | 175 | * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how |
176 | * we tell them apart. | | 176 | * we tell them apart. |
177 | */ | | 177 | */ |
178 | struct fd_type { | | 178 | struct fd_type { |
179 | int sectrac; /* sectors per track */ | | 179 | int sectrac; /* sectors per track */ |
180 | int heads; /* number of heads */ | | 180 | int heads; /* number of heads */ |
181 | int seccyl; /* sectors per cylinder */ | | 181 | int seccyl; /* sectors per cylinder */ |
182 | int secsize; /* size code for sectors */ | | 182 | int secsize; /* size code for sectors */ |
| @@ -184,27 +184,27 @@ struct fd_type { | | | @@ -184,27 +184,27 @@ struct fd_type { |
184 | int steprate; /* step rate and head unload time */ | | 184 | int steprate; /* step rate and head unload time */ |
185 | int gap1; /* gap len between sectors */ | | 185 | int gap1; /* gap len between sectors */ |
186 | int gap2; /* formatting gap */ | | 186 | int gap2; /* formatting gap */ |
187 | int cyls; /* total num of cylinders */ | | 187 | int cyls; /* total num of cylinders */ |
188 | int size; /* size of disk in sectors */ | | 188 | int size; /* size of disk in sectors */ |
189 | int step; /* steps per cylinder */ | | 189 | int step; /* steps per cylinder */ |
190 | int rate; /* transfer speed code */ | | 190 | int rate; /* transfer speed code */ |
191 | uint8_t fillbyte; /* format fill byte */ | | 191 | uint8_t fillbyte; /* format fill byte */ |
192 | uint8_t interleave; /* interleave factor (formatting) */ | | 192 | uint8_t interleave; /* interleave factor (formatting) */ |
193 | const char *name; | | 193 | const char *name; |
194 | }; | | 194 | }; |
195 | | | 195 | |
196 | /* The order of entries in the following table is important -- BEWARE! */ | | 196 | /* The order of entries in the following table is important -- BEWARE! */ |
197 | struct fd_type fd_types[] = { | | 197 | static struct fd_type fd_types[] = { |
198 | { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS, 0xf6, 1, | | 198 | { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS, 0xf6, 1, |
199 | "1.2MB/[1024bytes/sector]" }, /* 1.2 MB japanese format */ | | 199 | "1.2MB/[1024bytes/sector]" }, /* 1.2 MB japanese format */ |
200 | { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS, 0xf6, 1, | | 200 | { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS, 0xf6, 1, |
201 | "1.44MB" }, /* 1.44MB diskette */ | | 201 | "1.44MB" }, /* 1.44MB diskette */ |
202 | { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, 0xf6, 1, | | 202 | { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, 0xf6, 1, |
203 | "1.2MB" }, /* 1.2 MB AT-diskettes */ | | 203 | "1.2MB" }, /* 1.2 MB AT-diskettes */ |
204 | { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, 0xf6, 1, | | 204 | { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, 0xf6, 1, |
205 | "360KB/AT" }, /* 360kB in 1.2MB drive */ | | 205 | "360KB/AT" }, /* 360kB in 1.2MB drive */ |
206 | { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, 0xf6, 1, | | 206 | { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, 0xf6, 1, |
207 | "360KB/PC" }, /* 360kB PC diskettes */ | | 207 | "360KB/PC" }, /* 360kB PC diskettes */ |
208 | { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, 0xf6, 1, | | 208 | { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, 0xf6, 1, |
209 | "720KB" }, /* 3.5" 720kB diskette */ | | 209 | "720KB" }, /* 3.5" 720kB diskette */ |
210 | { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, 0xf6, 1, | | 210 | { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, 0xf6, 1, |
| @@ -247,38 +247,38 @@ struct fd_softc { | | | @@ -247,38 +247,38 @@ struct fd_softc { |
247 | int sc_ops; /* I/O ops since last switch */ | | 247 | int sc_ops; /* I/O ops since last switch */ |
248 | struct bufq_state *sc_q;/* pending I/O requests */ | | 248 | struct bufq_state *sc_q;/* pending I/O requests */ |
249 | int sc_active; /* number of active I/O operations */ | | 249 | int sc_active; /* number of active I/O operations */ |
250 | uint8_t *sc_copybuf; /* for secsize >=3 */ | | 250 | uint8_t *sc_copybuf; /* for secsize >=3 */ |
251 | uint8_t sc_part; /* for secsize >=3 */ | | 251 | uint8_t sc_part; /* for secsize >=3 */ |
252 | #define SEC_P10 0x02 /* first part */ | | 252 | #define SEC_P10 0x02 /* first part */ |
253 | #define SEC_P01 0x01 /* second part */ | | 253 | #define SEC_P01 0x01 /* second part */ |
254 | #define SEC_P11 0x03 /* both part */ | | 254 | #define SEC_P11 0x03 /* both part */ |
255 | | | 255 | |
256 | krndsource_t rnd_source; | | 256 | krndsource_t rnd_source; |
257 | }; | | 257 | }; |
258 | | | 258 | |
259 | /* floppy driver configuration */ | | 259 | /* floppy driver configuration */ |
260 | int fdprobe(device_t, cfdata_t, void *); | | 260 | static int fdprobe(device_t, cfdata_t, void *); |
261 | void fdattach(device_t, device_t, void *); | | 261 | static void fdattach(device_t, device_t, void *); |
262 | | | 262 | |
263 | CFATTACH_DECL_NEW(fd, sizeof(struct fd_softc), | | 263 | CFATTACH_DECL_NEW(fd, sizeof(struct fd_softc), |
264 | fdprobe, fdattach, NULL, NULL); | | 264 | fdprobe, fdattach, NULL, NULL); |
265 | | | 265 | |
266 | dev_type_open(fdopen); | | 266 | static dev_type_open(fdopen); |
267 | dev_type_close(fdclose); | | 267 | static dev_type_close(fdclose); |
268 | dev_type_read(fdread); | | 268 | static dev_type_read(fdread); |
269 | dev_type_write(fdwrite); | | 269 | static dev_type_write(fdwrite); |
270 | dev_type_ioctl(fdioctl); | | 270 | static dev_type_ioctl(fdioctl); |
271 | dev_type_strategy(fdstrategy); | | 271 | static dev_type_strategy(fdstrategy); |
272 | | | 272 | |
273 | const struct bdevsw fd_bdevsw = { | | 273 | const struct bdevsw fd_bdevsw = { |
274 | .d_open = fdopen, | | 274 | .d_open = fdopen, |
275 | .d_close = fdclose, | | 275 | .d_close = fdclose, |
276 | .d_strategy = fdstrategy, | | 276 | .d_strategy = fdstrategy, |
277 | .d_ioctl = fdioctl, | | 277 | .d_ioctl = fdioctl, |
278 | .d_dump = nodump, | | 278 | .d_dump = nodump, |
279 | .d_psize = nosize, | | 279 | .d_psize = nosize, |
280 | .d_discard = nodiscard, | | 280 | .d_discard = nodiscard, |
281 | .d_flag = D_DISK | | 281 | .d_flag = D_DISK |
282 | }; | | 282 | }; |
283 | | | 283 | |
284 | const struct cdevsw fd_cdevsw = { | | 284 | const struct cdevsw fd_cdevsw = { |
| @@ -286,52 +286,54 @@ const struct cdevsw fd_cdevsw = { | | | @@ -286,52 +286,54 @@ const struct cdevsw fd_cdevsw = { |
286 | .d_close = fdclose, | | 286 | .d_close = fdclose, |
287 | .d_read = fdread, | | 287 | .d_read = fdread, |
288 | .d_write = fdwrite, | | 288 | .d_write = fdwrite, |
289 | .d_ioctl = fdioctl, | | 289 | .d_ioctl = fdioctl, |
290 | .d_stop = nostop, | | 290 | .d_stop = nostop, |
291 | .d_tty = notty, | | 291 | .d_tty = notty, |
292 | .d_poll = nopoll, | | 292 | .d_poll = nopoll, |
293 | .d_mmap = nommap, | | 293 | .d_mmap = nommap, |
294 | .d_kqfilter = nokqfilter, | | 294 | .d_kqfilter = nokqfilter, |
295 | .d_discard = nodiscard, | | 295 | .d_discard = nodiscard, |
296 | .d_flag = D_DISK | | 296 | .d_flag = D_DISK |
297 | }; | | 297 | }; |
298 | | | 298 | |
299 | void fdstart(struct fd_softc *); | | 299 | static void fdstart(struct fd_softc *); |
300 | | | 300 | |
301 | struct dkdriver fddkdriver = { | | 301 | struct dkdriver fddkdriver = { |
302 | .d_strategy = fdstrategy | | 302 | .d_strategy = fdstrategy |
303 | }; | | 303 | }; |
304 | | | 304 | |
305 | void fd_set_motor(struct fdc_softc *, int); | | 305 | static void fd_set_motor(struct fdc_softc *, int); |
306 | void fd_motor_off(void *); | | 306 | static void fd_motor_off(void *); |
307 | #if 0 | | 307 | #if 0 |
308 | void fd_motor_on(void *); | | 308 | static void fd_motor_on(void *); |
309 | #endif | | 309 | #endif |
310 | int fdcresult(struct fdc_softc *); | | 310 | static int fdcresult(struct fdc_softc *); |
311 | int out_fdc(bus_space_tag_t, bus_space_handle_t, uint8_t); | | 311 | static int out_fdc(bus_space_tag_t, bus_space_handle_t, uint8_t); |
312 | void fdcstart(struct fdc_softc *); | | 312 | static void fdcstart(struct fdc_softc *); |
313 | void fdcstatus(device_t, int, const char *); | | 313 | static void fdcstatus(device_t, int, const char *); |
314 | void fdctimeout(void *); | | 314 | static void fdctimeout(void *); |
315 | void fdcpseudointr(void *); | | 315 | #if 0 |
316 | void fdcretry(struct fdc_softc *); | | 316 | static void fdcpseudointr(void *); |
317 | void fdfinish(struct fd_softc *, struct buf *); | | 317 | #endif |
| | | 318 | static void fdcretry(struct fdc_softc *); |
| | | 319 | static void fdfinish(struct fd_softc *, struct buf *); |
318 | static struct fd_type *fd_dev_to_type(struct fd_softc *, dev_t); | | 320 | static struct fd_type *fd_dev_to_type(struct fd_softc *, dev_t); |
319 | int fdformat(dev_t, struct ne7_fd_formb *, struct lwp *); | | 321 | static int fdformat(dev_t, struct ne7_fd_formb *, struct lwp *); |
320 | static int fdcpoll(struct fdc_softc *); | | 322 | static int fdcpoll(struct fdc_softc *); |
321 | static int fdgetdisklabel(struct fd_softc *, dev_t); | | 323 | static int fdgetdisklabel(struct fd_softc *, dev_t); |
322 | static void fd_do_eject(struct fdc_softc *, int); | | 324 | static void fd_do_eject(struct fdc_softc *, int); |
323 | | | 325 | |
324 | void fd_mountroot_hook(device_t); | | 326 | static void fd_mountroot_hook(device_t); |
325 | | | 327 | |
326 | /* DMA transfer routines */ | | 328 | /* DMA transfer routines */ |
327 | inline static void fdc_dmastart(struct fdc_softc *, int, void *, vsize_t); | | 329 | inline static void fdc_dmastart(struct fdc_softc *, int, void *, vsize_t); |
328 | inline static void fdc_dmaabort(struct fdc_softc *); | | 330 | inline static void fdc_dmaabort(struct fdc_softc *); |
329 | static int fdcdmaintr(void *); | | 331 | static int fdcdmaintr(void *); |
330 | static int fdcdmaerrintr(void *); | | 332 | static int fdcdmaerrintr(void *); |
331 | | | 333 | |
332 | inline static void | | 334 | inline static void |
333 | fdc_dmastart(struct fdc_softc *fdc, int read, void *addr, vsize_t count) | | 335 | fdc_dmastart(struct fdc_softc *fdc, int read, void *addr, vsize_t count) |
334 | { | | 336 | { |
335 | int error; | | 337 | int error; |
336 | | | 338 | |
337 | DPRINTF(("fdc_dmastart: %s, addr = %p, count = %ld\n", | | 339 | DPRINTF(("fdc_dmastart: %s, addr = %p, count = %ld\n", |
| @@ -390,27 +392,27 @@ fdcdmaintr(void *arg) | | | @@ -390,27 +392,27 @@ fdcdmaintr(void *arg) |
390 | return 0; | | 392 | return 0; |
391 | } | | 393 | } |
392 | | | 394 | |
393 | static int | | 395 | static int |
394 | fdcdmaerrintr(void *dummy) | | 396 | fdcdmaerrintr(void *dummy) |
395 | { | | 397 | { |
396 | | | 398 | |
397 | DPRINTF(("fdcdmaerrintr\n")); | | 399 | DPRINTF(("fdcdmaerrintr\n")); |
398 | | | 400 | |
399 | return 0; | | 401 | return 0; |
400 | } | | 402 | } |
401 | | | 403 | |
402 | /* ARGSUSED */ | | 404 | /* ARGSUSED */ |
403 | int | | 405 | static int |
404 | fdcprobe(device_t parent, cfdata_t cf, void *aux) | | 406 | fdcprobe(device_t parent, cfdata_t cf, void *aux) |
405 | { | | 407 | { |
406 | struct intio_attach_args *ia = aux; | | 408 | struct intio_attach_args *ia = aux; |
407 | | | 409 | |
408 | if (strcmp(ia->ia_name, "fdc") != 0) | | 410 | if (strcmp(ia->ia_name, "fdc") != 0) |
409 | return 0; | | 411 | return 0; |
410 | | | 412 | |
411 | if (ia->ia_addr == INTIOCF_ADDR_DEFAULT) | | 413 | if (ia->ia_addr == INTIOCF_ADDR_DEFAULT) |
412 | ia->ia_addr = FDC_ADDR; | | 414 | ia->ia_addr = FDC_ADDR; |
413 | if (ia->ia_intr == INTIOCF_INTR_DEFAULT) | | 415 | if (ia->ia_intr == INTIOCF_INTR_DEFAULT) |
414 | ia->ia_intr = FDC_INTR; | | 416 | ia->ia_intr = FDC_INTR; |
415 | if (ia->ia_dma == INTIOCF_DMA_DEFAULT) | | 417 | if (ia->ia_dma == INTIOCF_DMA_DEFAULT) |
416 | ia->ia_dma = FDC_DMA; | | 418 | ia->ia_dma = FDC_DMA; |
| @@ -433,37 +435,37 @@ fdcprobe(device_t parent, cfdata_t cf, v | | | @@ -433,37 +435,37 @@ fdcprobe(device_t parent, cfdata_t cf, v |
433 | */ | | 435 | */ |
434 | struct fdc_attach_args { | | 436 | struct fdc_attach_args { |
435 | int fa_drive; | | 437 | int fa_drive; |
436 | struct fd_type *fa_deftype; | | 438 | struct fd_type *fa_deftype; |
437 | }; | | 439 | }; |
438 | | | 440 | |
439 | /* | | 441 | /* |
440 | * Print the location of a disk drive (called just before attaching the | | 442 | * Print the location of a disk drive (called just before attaching the |
441 | * the drive). If `fdc' is not NULL, the drive was found but was not | | 443 | * the drive). If `fdc' is not NULL, the drive was found but was not |
442 | * in the system config file; print the drive name as well. | | 444 | * in the system config file; print the drive name as well. |
443 | * Return QUIET (config_find ignores this if the device was configured) to | | 445 | * Return QUIET (config_find ignores this if the device was configured) to |
444 | * avoid printing `fdN not configured' messages. | | 446 | * avoid printing `fdN not configured' messages. |
445 | */ | | 447 | */ |
446 | int | | 448 | static int |
447 | fdprint(void *aux, const char *fdc) | | 449 | fdprint(void *aux, const char *fdc) |
448 | { | | 450 | { |
449 | struct fdc_attach_args *fa = aux; | | 451 | struct fdc_attach_args *fa = aux; |
450 | | | 452 | |
451 | if (fdc == NULL) | | 453 | if (fdc == NULL) |
452 | aprint_normal(" drive %d", fa->fa_drive); | | 454 | aprint_normal(" drive %d", fa->fa_drive); |
453 | return QUIET; | | 455 | return QUIET; |
454 | } | | 456 | } |
455 | | | 457 | |
456 | void | | 458 | static void |
457 | fdcattach(device_t parent, device_t self, void *aux) | | 459 | fdcattach(device_t parent, device_t self, void *aux) |
458 | { | | 460 | { |
459 | struct fdc_softc *fdc = device_private(self); | | 461 | struct fdc_softc *fdc = device_private(self); |
460 | bus_space_tag_t iot; | | 462 | bus_space_tag_t iot; |
461 | bus_space_handle_t ioh; | | 463 | bus_space_handle_t ioh; |
462 | struct intio_attach_args *ia = aux; | | 464 | struct intio_attach_args *ia = aux; |
463 | struct fdc_attach_args fa; | | 465 | struct fdc_attach_args fa; |
464 | | | 466 | |
465 | iot = ia->ia_bst; | | 467 | iot = ia->ia_bst; |
466 | | | 468 | |
467 | aprint_normal("\n"); | | 469 | aprint_normal("\n"); |
468 | | | 470 | |
469 | /* Re-map the I/O space. */ | | 471 | /* Re-map the I/O space. */ |
| @@ -510,50 +512,50 @@ fdcattach(device_t parent, device_t self | | | @@ -510,50 +512,50 @@ fdcattach(device_t parent, device_t self |
510 | aprint_normal_dev(self, "uPD72065 FDC\n"); | | 512 | aprint_normal_dev(self, "uPD72065 FDC\n"); |
511 | out_fdc(iot, ioh, NE7CMD_SPECIFY); /* specify command */ | | 513 | out_fdc(iot, ioh, NE7CMD_SPECIFY); /* specify command */ |
512 | out_fdc(iot, ioh, 0xd0); | | 514 | out_fdc(iot, ioh, 0xd0); |
513 | out_fdc(iot, ioh, 0x10); | | 515 | out_fdc(iot, ioh, 0x10); |
514 | | | 516 | |
515 | /* physical limit: four drives per controller. */ | | 517 | /* physical limit: four drives per controller. */ |
516 | for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) { | | 518 | for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) { |
517 | (void)config_found(self, (void *)&fa, fdprint, CFARGS_NONE); | | 519 | (void)config_found(self, (void *)&fa, fdprint, CFARGS_NONE); |
518 | } | | 520 | } |
519 | | | 521 | |
520 | intio_enable_intr(SICILIAN_INTR_FDC); | | 522 | intio_enable_intr(SICILIAN_INTR_FDC); |
521 | } | | 523 | } |
522 | | | 524 | |
523 | void | | 525 | static void |
524 | fdcreset(struct fdc_softc *fdc) | | 526 | fdcreset(struct fdc_softc *fdc) |
525 | { | | 527 | { |
526 | | | 528 | |
527 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdsts, NE7CMD_RESET); | | 529 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdsts, NE7CMD_RESET); |
528 | } | | 530 | } |
529 | | | 531 | |
530 | static int | | 532 | static int |
531 | fdcpoll(struct fdc_softc *fdc) | | 533 | fdcpoll(struct fdc_softc *fdc) |
532 | { | | 534 | { |
533 | int i = 25000; | | 535 | int i = 25000; |
534 | | | 536 | |
535 | while (--i > 0) { | | 537 | while (--i > 0) { |
536 | if ((intio_get_sicilian_intr() & SICILIAN_STAT_FDC) != 0) { | | 538 | if ((intio_get_sicilian_intr() & SICILIAN_STAT_FDC) != 0) { |
537 | out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI); | | 539 | out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI); |
538 | fdcresult(fdc); | | 540 | fdcresult(fdc); |
539 | break; | | 541 | break; |
540 | } | | 542 | } |
541 | DELAY(100); | | 543 | DELAY(100); |
542 | } | | 544 | } |
543 | return i; | | 545 | return i; |
544 | } | | 546 | } |
545 | | | 547 | |
546 | int | | 548 | static int |
547 | fdprobe(device_t parent, cfdata_t cf, void *aux) | | 549 | fdprobe(device_t parent, cfdata_t cf, void *aux) |
548 | { | | 550 | { |
549 | struct fdc_softc *fdc = device_private(parent); | | 551 | struct fdc_softc *fdc = device_private(parent); |
550 | struct fd_type *type; | | 552 | struct fd_type *type; |
551 | struct fdc_attach_args *fa = aux; | | 553 | struct fdc_attach_args *fa = aux; |
552 | int drive = fa->fa_drive; | | 554 | int drive = fa->fa_drive; |
553 | bus_space_tag_t iot = fdc->sc_iot; | | 555 | bus_space_tag_t iot = fdc->sc_iot; |
554 | bus_space_handle_t ioh = fdc->sc_ioh; | | 556 | bus_space_handle_t ioh = fdc->sc_ioh; |
555 | int n = 0; | | 557 | int n = 0; |
556 | int found = 0; | | 558 | int found = 0; |
557 | int i; | | 559 | int i; |
558 | | | 560 | |
559 | if (cf->cf_loc[FDCCF_UNIT] != FDCCF_UNIT_DEFAULT && | | 561 | if (cf->cf_loc[FDCCF_UNIT] != FDCCF_UNIT_DEFAULT && |
| @@ -610,27 +612,27 @@ fdprobe(device_t parent, cfdata_t cf, vo | | | @@ -610,27 +612,27 @@ fdprobe(device_t parent, cfdata_t cf, vo |
610 | fdctl, (type->rate << 4) | drive); | | 612 | fdctl, (type->rate << 4) | drive); |
611 | fdc_force_ready(FDCSTBY); | | 613 | fdc_force_ready(FDCSTBY); |
612 | if (!found) { | | 614 | if (!found) { |
613 | intio_enable_intr(SICILIAN_INTR_FDC); | | 615 | intio_enable_intr(SICILIAN_INTR_FDC); |
614 | return 0; | | 616 | return 0; |
615 | } | | 617 | } |
616 | | | 618 | |
617 | return 1; | | 619 | return 1; |
618 | } | | 620 | } |
619 | | | 621 | |
620 | /* | | 622 | /* |
621 | * Controller is working, and drive responded. Attach it. | | 623 | * Controller is working, and drive responded. Attach it. |
622 | */ | | 624 | */ |
623 | void | | 625 | static void |
624 | fdattach(device_t parent, device_t self, void *aux) | | 626 | fdattach(device_t parent, device_t self, void *aux) |
625 | { | | 627 | { |
626 | struct fdc_softc *fdc = device_private(parent); | | 628 | struct fdc_softc *fdc = device_private(parent); |
627 | struct fd_softc *fd = device_private(self); | | 629 | struct fd_softc *fd = device_private(self); |
628 | struct fdc_attach_args *fa = aux; | | 630 | struct fdc_attach_args *fa = aux; |
629 | struct fd_type *type = &fd_types[0]; /* XXX 1.2MB */ | | 631 | struct fd_type *type = &fd_types[0]; /* XXX 1.2MB */ |
630 | int drive = fa->fa_drive; | | 632 | int drive = fa->fa_drive; |
631 | | | 633 | |
632 | #if 0 | | 634 | #if 0 |
633 | callout_init(&fd->sc_motoron_ch, 0); | | 635 | callout_init(&fd->sc_motoron_ch, 0); |
634 | #endif | | 636 | #endif |
635 | callout_init(&fd->sc_motoroff_ch, 0); | | 637 | callout_init(&fd->sc_motoroff_ch, 0); |
636 | | | 638 | |
| @@ -670,27 +672,27 @@ fdattach(device_t parent, device_t self, | | | @@ -670,27 +672,27 @@ fdattach(device_t parent, device_t self, |
670 | RND_TYPE_DISK, RND_FLAG_DEFAULT); | | 672 | RND_TYPE_DISK, RND_FLAG_DEFAULT); |
671 | } | | 673 | } |
672 | | | 674 | |
673 | static struct fd_type * | | 675 | static struct fd_type * |
674 | fd_dev_to_type(struct fd_softc *fd, dev_t dev) | | 676 | fd_dev_to_type(struct fd_softc *fd, dev_t dev) |
675 | { | | 677 | { |
676 | size_t type = FDTYPE(dev); | | 678 | size_t type = FDTYPE(dev); |
677 | | | 679 | |
678 | if (type >= __arraycount(fd_types)) | | 680 | if (type >= __arraycount(fd_types)) |
679 | return NULL; | | 681 | return NULL; |
680 | return &fd_types[type]; | | 682 | return &fd_types[type]; |
681 | } | | 683 | } |
682 | | | 684 | |
683 | void | | 685 | static void |
684 | fdstrategy(struct buf *bp) | | 686 | fdstrategy(struct buf *bp) |
685 | { | | 687 | { |
686 | struct fd_softc *fd; | | 688 | struct fd_softc *fd; |
687 | int unit; | | 689 | int unit; |
688 | int sz; | | 690 | int sz; |
689 | int s; | | 691 | int s; |
690 | | | 692 | |
691 | unit = FDUNIT(bp->b_dev); | | 693 | unit = FDUNIT(bp->b_dev); |
692 | fd = device_lookup_private(&fd_cd, unit); | | 694 | fd = device_lookup_private(&fd_cd, unit); |
693 | if (fd == NULL) { | | 695 | if (fd == NULL) { |
694 | bp->b_error = EINVAL; | | 696 | bp->b_error = EINVAL; |
695 | goto done; | | 697 | goto done; |
696 | } | | 698 | } |
| @@ -751,42 +753,42 @@ fdstrategy(struct buf *bp) | | | @@ -751,42 +753,42 @@ fdstrategy(struct buf *bp) |
751 | printf("fdstrategy: controller inactive\n"); | | 753 | printf("fdstrategy: controller inactive\n"); |
752 | fdcstart(fdc); | | 754 | fdcstart(fdc); |
753 | } | | 755 | } |
754 | } | | 756 | } |
755 | #endif | | 757 | #endif |
756 | splx(s); | | 758 | splx(s); |
757 | return; | | 759 | return; |
758 | | | 760 | |
759 | done: | | 761 | done: |
760 | /* Toss transfer; we're done early. */ | | 762 | /* Toss transfer; we're done early. */ |
761 | biodone(bp); | | 763 | biodone(bp); |
762 | } | | 764 | } |
763 | | | 765 | |
764 | void | | 766 | static void |
765 | fdstart(struct fd_softc *fd) | | 767 | fdstart(struct fd_softc *fd) |
766 | { | | 768 | { |
767 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); | | 769 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); |
768 | int active = !TAILQ_EMPTY(&fdc->sc_drives); | | 770 | int active = !TAILQ_EMPTY(&fdc->sc_drives); |
769 | | | 771 | |
770 | /* Link into controller queue. */ | | 772 | /* Link into controller queue. */ |
771 | fd->sc_active = 1; | | 773 | fd->sc_active = 1; |
772 | TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); | | 774 | TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); |
773 | | | 775 | |
774 | /* If controller not already active, start it. */ | | 776 | /* If controller not already active, start it. */ |
775 | if (!active) | | 777 | if (!active) |
776 | fdcstart(fdc); | | 778 | fdcstart(fdc); |
777 | } | | 779 | } |
778 | | | 780 | |
779 | void | | 781 | static void |
780 | fdfinish(struct fd_softc *fd, struct buf *bp) | | 782 | fdfinish(struct fd_softc *fd, struct buf *bp) |
781 | { | | 783 | { |
782 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); | | 784 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); |
783 | | | 785 | |
784 | /* | | 786 | /* |
785 | * Move this drive to the end of the queue to give others a `fair' | | 787 | * Move this drive to the end of the queue to give others a `fair' |
786 | * chance. We only force a switch if N operations are completed while | | 788 | * chance. We only force a switch if N operations are completed while |
787 | * another drive is waiting to be serviced, since there is a long motor | | 789 | * another drive is waiting to be serviced, since there is a long motor |
788 | * startup delay whenever we switch. | | 790 | * startup delay whenever we switch. |
789 | */ | | 791 | */ |
790 | (void)bufq_get(fd->sc_q); | | 792 | (void)bufq_get(fd->sc_q); |
791 | if (TAILQ_NEXT(fd, sc_drivechain) && ++fd->sc_ops >= 8) { | | 793 | if (TAILQ_NEXT(fd, sc_drivechain) && ++fd->sc_ops >= 8) { |
792 | fd->sc_ops = 0; | | 794 | fd->sc_ops = 0; |
| @@ -797,94 +799,94 @@ fdfinish(struct fd_softc *fd, struct buf | | | @@ -797,94 +799,94 @@ fdfinish(struct fd_softc *fd, struct buf |
797 | fd->sc_active = 0; | | 799 | fd->sc_active = 0; |
798 | } | | 800 | } |
799 | bp->b_resid = fd->sc_bcount; | | 801 | bp->b_resid = fd->sc_bcount; |
800 | fd->sc_skip = 0; | | 802 | fd->sc_skip = 0; |
801 | | | 803 | |
802 | rnd_add_uint32(&fd->rnd_source, bp->b_blkno); | | 804 | rnd_add_uint32(&fd->rnd_source, bp->b_blkno); |
803 | | | 805 | |
804 | biodone(bp); | | 806 | biodone(bp); |
805 | /* turn off motor 5s from now */ | | 807 | /* turn off motor 5s from now */ |
806 | callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd); | | 808 | callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd); |
807 | fdc->sc_state = DEVIDLE; | | 809 | fdc->sc_state = DEVIDLE; |
808 | } | | 810 | } |
809 | | | 811 | |
810 | int | | 812 | static int |
811 | fdread(dev_t dev, struct uio *uio, int flags) | | 813 | fdread(dev_t dev, struct uio *uio, int flags) |
812 | { | | 814 | { |
813 | | | 815 | |
814 | return physio(fdstrategy, NULL, dev, B_READ, minphys, uio); | | 816 | return physio(fdstrategy, NULL, dev, B_READ, minphys, uio); |
815 | } | | 817 | } |
816 | | | 818 | |
817 | int | | 819 | static int |
818 | fdwrite(dev_t dev, struct uio *uio, int flags) | | 820 | fdwrite(dev_t dev, struct uio *uio, int flags) |
819 | { | | 821 | { |
820 | | | 822 | |
821 | return physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio); | | 823 | return physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio); |
822 | } | | 824 | } |
823 | | | 825 | |
824 | void | | 826 | static void |
825 | fd_set_motor(struct fdc_softc *fdc, int reset) | | 827 | fd_set_motor(struct fdc_softc *fdc, int reset) |
826 | { | | 828 | { |
827 | struct fd_softc *fd; | | 829 | struct fd_softc *fd; |
828 | int n; | | 830 | int n; |
829 | | | 831 | |
830 | DPRINTF(("fd_set_motor:\n")); | | 832 | DPRINTF(("fd_set_motor:\n")); |
831 | for (n = 0; n < 4; n++) { | | 833 | for (n = 0; n < 4; n++) { |
832 | fd = fdc->sc_fd[n]; | | 834 | fd = fdc->sc_fd[n]; |
833 | if (fd != NULL && (fd->sc_flags & FD_MOTOR) != 0) | | 835 | if (fd != NULL && (fd->sc_flags & FD_MOTOR) != 0) |
834 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdctl, | | 836 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdctl, |
835 | 0x80 | (fd->sc_type->rate << 4)| n); | | 837 | 0x80 | (fd->sc_type->rate << 4)| n); |
836 | } | | 838 | } |
837 | } | | 839 | } |
838 | | | 840 | |
839 | void | | 841 | static void |
840 | fd_motor_off(void *arg) | | 842 | fd_motor_off(void *arg) |
841 | { | | 843 | { |
842 | struct fd_softc *fd = arg; | | 844 | struct fd_softc *fd = arg; |
843 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); | | 845 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); |
844 | int s; | | 846 | int s; |
845 | | | 847 | |
846 | DPRINTF(("fd_motor_off:\n")); | | 848 | DPRINTF(("fd_motor_off:\n")); |
847 | | | 849 | |
848 | s = splbio(); | | 850 | s = splbio(); |
849 | fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); | | 851 | fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); |
850 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdctl, | | 852 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdctl, |
851 | (fd->sc_type->rate << 4) | fd->sc_drive); | | 853 | (fd->sc_type->rate << 4) | fd->sc_drive); |
852 | #if 0 | | 854 | #if 0 |
853 | fd_set_motor(fdc, 0); /* XXX */ | | 855 | fd_set_motor(fdc, 0); /* XXX */ |
854 | #endif | | 856 | #endif |
855 | splx(s); | | 857 | splx(s); |
856 | } | | 858 | } |
857 | | | 859 | |
858 | #if 0 /* on x68k motor on triggers interrupts by state change of ready line. */ | | 860 | #if 0 /* on x68k motor on triggers interrupts by state change of ready line. */ |
859 | void | | 861 | static void |
860 | fd_motor_on(void *arg) | | 862 | fd_motor_on(void *arg) |
861 | { | | 863 | { |
862 | struct fd_softc *fd = arg; | | 864 | struct fd_softc *fd = arg; |
863 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); | | 865 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); |
864 | int s; | | 866 | int s; |
865 | | | 867 | |
866 | DPRINTF(("fd_motor_on:\n")); | | 868 | DPRINTF(("fd_motor_on:\n")); |
867 | | | 869 | |
868 | s = splbio(); | | 870 | s = splbio(); |
869 | fd->sc_flags &= ~FD_MOTOR_WAIT; | | 871 | fd->sc_flags &= ~FD_MOTOR_WAIT; |
870 | if ((TAILQ_FIRST(&fdc->sc_drives) == fd) && | | 872 | if ((TAILQ_FIRST(&fdc->sc_drives) == fd) && |
871 | (fdc->sc_state == MOTORWAIT)) | | 873 | (fdc->sc_state == MOTORWAIT)) |
872 | (void)fdcintr(fdc); | | 874 | (void)fdcintr(fdc); |
873 | splx(s); | | 875 | splx(s); |
874 | } | | 876 | } |
875 | #endif | | 877 | #endif |
876 | | | 878 | |
877 | int | | 879 | static int |
878 | fdcresult(struct fdc_softc *fdc) | | 880 | fdcresult(struct fdc_softc *fdc) |
879 | { | | 881 | { |
880 | bus_space_tag_t iot = fdc->sc_iot; | | 882 | bus_space_tag_t iot = fdc->sc_iot; |
881 | bus_space_handle_t ioh = fdc->sc_ioh; | | 883 | bus_space_handle_t ioh = fdc->sc_ioh; |
882 | uint8_t i; | | 884 | uint8_t i; |
883 | int j, n; | | 885 | int j, n; |
884 | | | 886 | |
885 | n = 0; | | 887 | n = 0; |
886 | for (j = 100000; j != 0; j--) { | | 888 | for (j = 100000; j != 0; j--) { |
887 | i = bus_space_read_1(iot, ioh, fdsts) & | | 889 | i = bus_space_read_1(iot, ioh, fdsts) & |
888 | (NE7_DIO | NE7_RQM | NE7_CB); | | 890 | (NE7_DIO | NE7_RQM | NE7_CB); |
889 | | | 891 | |
890 | if (i == NE7_RQM) | | 892 | if (i == NE7_RQM) |
| @@ -893,42 +895,42 @@ fdcresult(struct fdc_softc *fdc) | | | @@ -893,42 +895,42 @@ fdcresult(struct fdc_softc *fdc) |
893 | if (n >= sizeof(fdc->sc_status)) { | | 895 | if (n >= sizeof(fdc->sc_status)) { |
894 | log(LOG_ERR, "fdcresult: overrun\n"); | | 896 | log(LOG_ERR, "fdcresult: overrun\n"); |
895 | return -1; | | 897 | return -1; |
896 | } | | 898 | } |
897 | fdc->sc_status[n++] = | | 899 | fdc->sc_status[n++] = |
898 | bus_space_read_1(iot, ioh, fddata); | | 900 | bus_space_read_1(iot, ioh, fddata); |
899 | } | | 901 | } |
900 | delay(10); | | 902 | delay(10); |
901 | } | | 903 | } |
902 | log(LOG_ERR, "fdcresult: timeout\n"); | | 904 | log(LOG_ERR, "fdcresult: timeout\n"); |
903 | return -1; | | 905 | return -1; |
904 | } | | 906 | } |
905 | | | 907 | |
906 | int | | 908 | static int |
907 | out_fdc(bus_space_tag_t iot, bus_space_handle_t ioh, uint8_t x) | | 909 | out_fdc(bus_space_tag_t iot, bus_space_handle_t ioh, uint8_t x) |
908 | { | | 910 | { |
909 | int i = 100000; | | 911 | int i = 100000; |
910 | | | 912 | |
911 | while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0); | | 913 | while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0); |
912 | if (i <= 0) | | 914 | if (i <= 0) |
913 | return -1; | | 915 | return -1; |
914 | while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0); | | 916 | while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0); |
915 | if (i <= 0) | | 917 | if (i <= 0) |
916 | return -1; | | 918 | return -1; |
917 | bus_space_write_1(iot, ioh, fddata, x); | | 919 | bus_space_write_1(iot, ioh, fddata, x); |
918 | return 0; | | 920 | return 0; |
919 | } | | 921 | } |
920 | | | 922 | |
921 | int | | 923 | static int |
922 | fdopen(dev_t dev, int flags, int mode, struct lwp *l) | | 924 | fdopen(dev_t dev, int flags, int mode, struct lwp *l) |
923 | { | | 925 | { |
924 | int unit; | | 926 | int unit; |
925 | struct fd_softc *fd; | | 927 | struct fd_softc *fd; |
926 | struct fd_type *type; | | 928 | struct fd_type *type; |
927 | struct fdc_softc *fdc; | | 929 | struct fdc_softc *fdc; |
928 | | | 930 | |
929 | unit = FDUNIT(dev); | | 931 | unit = FDUNIT(dev); |
930 | fd = device_lookup_private(&fd_cd, unit); | | 932 | fd = device_lookup_private(&fd_cd, unit); |
931 | if (fd == NULL) | | 933 | if (fd == NULL) |
932 | return ENXIO; | | 934 | return ENXIO; |
933 | type = fd_dev_to_type(fd, dev); | | 935 | type = fd_dev_to_type(fd, dev); |
934 | if (type == NULL) | | 936 | if (type == NULL) |
| @@ -953,27 +955,27 @@ fdopen(dev_t dev, int flags, int mode, s | | | @@ -953,27 +955,27 @@ fdopen(dev_t dev, int flags, int mode, s |
953 | case S_IFCHR: | | 955 | case S_IFCHR: |
954 | fd->sc_flags |= FD_COPEN; | | 956 | fd->sc_flags |= FD_COPEN; |
955 | break; | | 957 | break; |
956 | case S_IFBLK: | | 958 | case S_IFBLK: |
957 | fd->sc_flags |= FD_BOPEN; | | 959 | fd->sc_flags |= FD_BOPEN; |
958 | break; | | 960 | break; |
959 | } | | 961 | } |
960 | | | 962 | |
961 | fdgetdisklabel(fd, dev); | | 963 | fdgetdisklabel(fd, dev); |
962 | | | 964 | |
963 | return 0; | | 965 | return 0; |
964 | } | | 966 | } |
965 | | | 967 | |
966 | int | | 968 | static int |
967 | fdclose(dev_t dev, int flags, int mode, struct lwp *l) | | 969 | fdclose(dev_t dev, int flags, int mode, struct lwp *l) |
968 | { | | 970 | { |
969 | int unit = FDUNIT(dev); | | 971 | int unit = FDUNIT(dev); |
970 | struct fd_softc *fd = device_lookup_private(&fd_cd, unit); | | 972 | struct fd_softc *fd = device_lookup_private(&fd_cd, unit); |
971 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); | | 973 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); |
972 | | | 974 | |
973 | DPRINTF(("fdclose %d\n", unit)); | | 975 | DPRINTF(("fdclose %d\n", unit)); |
974 | | | 976 | |
975 | switch (mode) { | | 977 | switch (mode) { |
976 | case S_IFCHR: | | 978 | case S_IFCHR: |
977 | fd->sc_flags &= ~FD_COPEN; | | 979 | fd->sc_flags &= ~FD_COPEN; |
978 | break; | | 980 | break; |
979 | case S_IFBLK: | | 981 | case S_IFBLK: |
| @@ -982,27 +984,27 @@ fdclose(dev_t dev, int flags, int mode, | | | @@ -982,27 +984,27 @@ fdclose(dev_t dev, int flags, int mode, |
982 | } | | 984 | } |
983 | | | 985 | |
984 | /* clear flags */ | | 986 | /* clear flags */ |
985 | fd->sc_opts &= ~(FDOPT_NORETRY | FDOPT_SILENT); | | 987 | fd->sc_opts &= ~(FDOPT_NORETRY | FDOPT_SILENT); |
986 | | | 988 | |
987 | if ((fd->sc_flags & FD_OPEN) == 0) { | | 989 | if ((fd->sc_flags & FD_OPEN) == 0) { |
988 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, | | 990 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, |
989 | (1 << unit)); | | 991 | (1 << unit)); |
990 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, 0); | | 992 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, 0); |
991 | } | | 993 | } |
992 | return 0; | | 994 | return 0; |
993 | } | | 995 | } |
994 | | | 996 | |
995 | void | | 997 | static void |
996 | fdcstart(struct fdc_softc *fdc) | | 998 | fdcstart(struct fdc_softc *fdc) |
997 | { | | 999 | { |
998 | | | 1000 | |
999 | #ifdef DIAGNOSTIC | | 1001 | #ifdef DIAGNOSTIC |
1000 | /* | | 1002 | /* |
1001 | * only got here if controller's drive queue was inactive; should | | 1003 | * only got here if controller's drive queue was inactive; should |
1002 | * be in idle state | | 1004 | * be in idle state |
1003 | */ | | 1005 | */ |
1004 | if (fdc->sc_state != DEVIDLE) { | | 1006 | if (fdc->sc_state != DEVIDLE) { |
1005 | printf("fdcstart: not idle\n"); | | 1007 | printf("fdcstart: not idle\n"); |
1006 | return; | | 1008 | return; |
1007 | } | | 1009 | } |
1008 | #endif | | 1010 | #endif |
| @@ -1031,75 +1033,75 @@ fdcpstatus(int n, struct fdc_softc *fdc) | | | @@ -1031,75 +1033,75 @@ fdcpstatus(int n, struct fdc_softc *fdc) |
1031 | snprintb(bits, sizeof(bits), NE7_ST2BITS, fdc->sc_status[2]); | | 1033 | snprintb(bits, sizeof(bits), NE7_ST2BITS, fdc->sc_status[2]); |
1032 | printf(" st2 %s", bits); | | 1034 | printf(" st2 %s", bits); |
1033 | printf(" cyl %d head %d sec %d)\n", | | 1035 | printf(" cyl %d head %d sec %d)\n", |
1034 | fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]); | | 1036 | fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]); |
1035 | break; | | 1037 | break; |
1036 | #ifdef DIAGNOSTIC | | 1038 | #ifdef DIAGNOSTIC |
1037 | default: | | 1039 | default: |
1038 | printf("\nfdcstatus: weird size"); | | 1040 | printf("\nfdcstatus: weird size"); |
1039 | break; | | 1041 | break; |
1040 | #endif | | 1042 | #endif |
1041 | } | | 1043 | } |
1042 | } | | 1044 | } |
1043 | | | 1045 | |
1044 | void | | 1046 | static void |
1045 | fdcstatus(device_t dv, int n, const char *s) | | 1047 | fdcstatus(device_t dv, int n, const char *s) |
1046 | { | | 1048 | { |
1047 | struct fdc_softc *fdc = device_private(device_parent(dv)); | | 1049 | struct fdc_softc *fdc = device_private(device_parent(dv)); |
1048 | | | 1050 | |
1049 | if (n == 0) { | | 1051 | if (n == 0) { |
1050 | out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI); | | 1052 | out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI); |
1051 | (void)fdcresult(fdc); | | 1053 | (void)fdcresult(fdc); |
1052 | n = 2; | | 1054 | n = 2; |
1053 | } | | 1055 | } |
1054 | | | 1056 | |
1055 | printf("%s: %s: state %d", device_xname(dv), s, fdc->sc_state); | | 1057 | printf("%s: %s: state %d", device_xname(dv), s, fdc->sc_state); |
1056 | fdcpstatus(n, fdc); | | 1058 | fdcpstatus(n, fdc); |
1057 | } | | 1059 | } |
1058 | | | 1060 | |
1059 | void | | 1061 | static void |
1060 | fdctimeout(void *arg) | | 1062 | fdctimeout(void *arg) |
1061 | { | | 1063 | { |
1062 | struct fdc_softc *fdc = arg; | | 1064 | struct fdc_softc *fdc = arg; |
1063 | struct fd_softc *fd = TAILQ_FIRST(&fdc->sc_drives); | | 1065 | struct fd_softc *fd = TAILQ_FIRST(&fdc->sc_drives); |
1064 | int s; | | 1066 | int s; |
1065 | | | 1067 | |
1066 | s = splbio(); | | 1068 | s = splbio(); |
1067 | fdcstatus(fd->sc_dev, 0, "timeout"); | | 1069 | fdcstatus(fd->sc_dev, 0, "timeout"); |
1068 | | | 1070 | |
1069 | if (bufq_peek(fd->sc_q) != NULL) | | 1071 | if (bufq_peek(fd->sc_q) != NULL) |
1070 | fdc->sc_state++; | | 1072 | fdc->sc_state++; |
1071 | else | | 1073 | else |
1072 | fdc->sc_state = DEVIDLE; | | 1074 | fdc->sc_state = DEVIDLE; |
1073 | | | 1075 | |
1074 | (void)fdcintr(fdc); | | 1076 | (void)fdcintr(fdc); |
1075 | splx(s); | | 1077 | splx(s); |
1076 | } | | 1078 | } |
1077 | | | 1079 | |
1078 | #if 0 | | 1080 | #if 0 |
1079 | void | | 1081 | static void |
1080 | fdcpseudointr(void *arg) | | 1082 | fdcpseudointr(void *arg) |
1081 | { | | 1083 | { |
1082 | int s; | | 1084 | int s; |
1083 | struct fdc_softc *fdc = arg; | | 1085 | struct fdc_softc *fdc = arg; |
1084 | | | 1086 | |
1085 | /* just ensure it has the right spl */ | | 1087 | /* just ensure it has the right spl */ |
1086 | s = splbio(); | | 1088 | s = splbio(); |
1087 | (void)fdcintr(fdc); | | 1089 | (void)fdcintr(fdc); |
1088 | splx(s); | | 1090 | splx(s); |
1089 | } | | 1091 | } |
1090 | #endif | | 1092 | #endif |
1091 | | | 1093 | |
1092 | int | | 1094 | static int |
1093 | fdcintr(void *arg) | | 1095 | fdcintr(void *arg) |
1094 | { | | 1096 | { |
1095 | struct fdc_softc *fdc = arg; | | 1097 | struct fdc_softc *fdc = arg; |
1096 | #define st0 fdc->sc_status[0] | | 1098 | #define st0 fdc->sc_status[0] |
1097 | #define cyl fdc->sc_status[1] | | 1099 | #define cyl fdc->sc_status[1] |
1098 | struct fd_softc *fd; | | 1100 | struct fd_softc *fd; |
1099 | struct buf *bp; | | 1101 | struct buf *bp; |
1100 | bus_space_tag_t iot = fdc->sc_iot; | | 1102 | bus_space_tag_t iot = fdc->sc_iot; |
1101 | bus_space_handle_t ioh = fdc->sc_ioh; | | 1103 | bus_space_handle_t ioh = fdc->sc_ioh; |
1102 | int read, head, sec, pos, i, sectrac, nblks; | | 1104 | int read, head, sec, pos, i, sectrac, nblks; |
1103 | int tmp; | | 1105 | int tmp; |
1104 | struct fd_type *type; | | 1106 | struct fd_type *type; |
1105 | struct ne7_fd_formb *finfo = NULL; | | 1107 | struct ne7_fd_formb *finfo = NULL; |
| @@ -1550,27 +1552,27 @@ fdcintr(void *arg) | | | @@ -1550,27 +1552,27 @@ fdcintr(void *arg) |
1550 | goto doseek; | | 1552 | goto doseek; |
1551 | | | 1553 | |
1552 | default: | | 1554 | default: |
1553 | fdcstatus(fd->sc_dev, 0, "stray interrupt"); | | 1555 | fdcstatus(fd->sc_dev, 0, "stray interrupt"); |
1554 | return 1; | | 1556 | return 1; |
1555 | } | | 1557 | } |
1556 | #ifdef DIAGNOSTIC | | 1558 | #ifdef DIAGNOSTIC |
1557 | panic("fdcintr: impossible"); | | 1559 | panic("fdcintr: impossible"); |
1558 | #endif | | 1560 | #endif |
1559 | #undef st0 | | 1561 | #undef st0 |
1560 | #undef cyl | | 1562 | #undef cyl |
1561 | } | | 1563 | } |
1562 | | | 1564 | |
1563 | void | | 1565 | static void |
1564 | fdcretry(struct fdc_softc *fdc) | | 1566 | fdcretry(struct fdc_softc *fdc) |
1565 | { | | 1567 | { |
1566 | struct fd_softc *fd; | | 1568 | struct fd_softc *fd; |
1567 | struct buf *bp; | | 1569 | struct buf *bp; |
1568 | | | 1570 | |
1569 | DPRINTF(("fdcretry:\n")); | | 1571 | DPRINTF(("fdcretry:\n")); |
1570 | fd = TAILQ_FIRST(&fdc->sc_drives); | | 1572 | fd = TAILQ_FIRST(&fdc->sc_drives); |
1571 | bp = bufq_peek(fd->sc_q); | | 1573 | bp = bufq_peek(fd->sc_q); |
1572 | | | 1574 | |
1573 | if (fd->sc_opts & FDOPT_NORETRY) | | 1575 | if (fd->sc_opts & FDOPT_NORETRY) |
1574 | goto fail; | | 1576 | goto fail; |
1575 | | | 1577 | |
1576 | switch (fdc->sc_errors) { | | 1578 | switch (fdc->sc_errors) { |
| @@ -1595,27 +1597,27 @@ fdcretry(struct fdc_softc *fdc) | | | @@ -1595,27 +1597,27 @@ fdcretry(struct fdc_softc *fdc) |
1595 | fail: | | 1597 | fail: |
1596 | if ((fd->sc_opts & FDOPT_SILENT) == 0) { | | 1598 | if ((fd->sc_opts & FDOPT_SILENT) == 0) { |
1597 | diskerr(bp, "fd", "hard error", LOG_PRINTF, | | 1599 | diskerr(bp, "fd", "hard error", LOG_PRINTF, |
1598 | fd->sc_skip, (struct disklabel *)NULL); | | 1600 | fd->sc_skip, (struct disklabel *)NULL); |
1599 | fdcpstatus(7, fdc); | | 1601 | fdcpstatus(7, fdc); |
1600 | } | | 1602 | } |
1601 | | | 1603 | |
1602 | bp->b_error = EIO; | | 1604 | bp->b_error = EIO; |
1603 | fdfinish(fd, bp); | | 1605 | fdfinish(fd, bp); |
1604 | } | | 1606 | } |
1605 | fdc->sc_errors++; | | 1607 | fdc->sc_errors++; |
1606 | } | | 1608 | } |
1607 | | | 1609 | |
1608 | int | | 1610 | static int |
1609 | fdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) | | 1611 | fdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) |
1610 | { | | 1612 | { |
1611 | struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev)); | | 1613 | struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev)); |
1612 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); | | 1614 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); |
1613 | struct fdformat_parms *form_parms; | | 1615 | struct fdformat_parms *form_parms; |
1614 | struct fdformat_cmd *form_cmd; | | 1616 | struct fdformat_cmd *form_cmd; |
1615 | struct ne7_fd_formb *fd_formb; | | 1617 | struct ne7_fd_formb *fd_formb; |
1616 | int part = DISKPART(dev); | | 1618 | int part = DISKPART(dev); |
1617 | struct disklabel buffer; | | 1619 | struct disklabel buffer; |
1618 | int error; | | 1620 | int error; |
1619 | unsigned int scratch; | | 1621 | unsigned int scratch; |
1620 | int il[FD_MAX_NSEC + 1]; | | 1622 | int il[FD_MAX_NSEC + 1]; |
1621 | int i, j; | | 1623 | int i, j; |
| @@ -1795,27 +1797,27 @@ fdioctl(dev_t dev, u_long cmd, void *add | | | @@ -1795,27 +1797,27 @@ fdioctl(dev_t dev, u_long cmd, void *add |
1795 | DPRINTF(("ODIOCEJECT\n")); | | 1797 | DPRINTF(("ODIOCEJECT\n")); |
1796 | fd_do_eject(fdc, FDUNIT(dev)); | | 1798 | fd_do_eject(fdc, FDUNIT(dev)); |
1797 | return 0; | | 1799 | return 0; |
1798 | | | 1800 | |
1799 | default: | | 1801 | default: |
1800 | return ENOTTY; | | 1802 | return ENOTTY; |
1801 | } | | 1803 | } |
1802 | | | 1804 | |
1803 | #ifdef DIAGNOSTIC | | 1805 | #ifdef DIAGNOSTIC |
1804 | panic("fdioctl: impossible"); | | 1806 | panic("fdioctl: impossible"); |
1805 | #endif | | 1807 | #endif |
1806 | } | | 1808 | } |
1807 | | | 1809 | |
1808 | int | | 1810 | static int |
1809 | fdformat(dev_t dev, struct ne7_fd_formb *finfo, struct lwp *l) | | 1811 | fdformat(dev_t dev, struct ne7_fd_formb *finfo, struct lwp *l) |
1810 | { | | 1812 | { |
1811 | int rv = 0; | | 1813 | int rv = 0; |
1812 | struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev)); | | 1814 | struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev)); |
1813 | struct fd_type *type = fd->sc_type; | | 1815 | struct fd_type *type = fd->sc_type; |
1814 | struct buf *bp; | | 1816 | struct buf *bp; |
1815 | | | 1817 | |
1816 | /* set up a buffer header for fdstrategy() */ | | 1818 | /* set up a buffer header for fdstrategy() */ |
1817 | bp = getiobuf(NULL, false); | | 1819 | bp = getiobuf(NULL, false); |
1818 | if (bp == NULL) | | 1820 | if (bp == NULL) |
1819 | return ENOBUFS; | | 1821 | return ENOBUFS; |
1820 | | | 1822 | |
1821 | bp->b_cflags = BC_BUSY; | | 1823 | bp->b_cflags = BC_BUSY; |
| @@ -1837,27 +1839,27 @@ fdformat(dev_t dev, struct ne7_fd_formb | | | @@ -1837,27 +1839,27 @@ fdformat(dev_t dev, struct ne7_fd_formb |
1837 | printf("fdformat: blkno %" PRIx64 " count %x\n", | | 1839 | printf("fdformat: blkno %" PRIx64 " count %x\n", |
1838 | bp->b_blkno, bp->b_bcount); | | 1840 | bp->b_blkno, bp->b_bcount); |
1839 | #endif | | 1841 | #endif |
1840 | | | 1842 | |
1841 | /* now do the format */ | | 1843 | /* now do the format */ |
1842 | fdstrategy(bp); | | 1844 | fdstrategy(bp); |
1843 | | | 1845 | |
1844 | /* ...and wait for it to complete */ | | 1846 | /* ...and wait for it to complete */ |
1845 | rv = biowait(bp); | | 1847 | rv = biowait(bp); |
1846 | putiobuf(bp); | | 1848 | putiobuf(bp); |
1847 | return rv; | | 1849 | return rv; |
1848 | } | | 1850 | } |
1849 | | | 1851 | |
1850 | void | | 1852 | static void |
1851 | fd_do_eject(struct fdc_softc *fdc, int unit) | | 1853 | fd_do_eject(struct fdc_softc *fdc, int unit) |
1852 | { | | 1854 | { |
1853 | | | 1855 | |
1854 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, 0x20 | (1 << unit)); | | 1856 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, 0x20 | (1 << unit)); |
1855 | DELAY(1); /* XXX */ | | 1857 | DELAY(1); /* XXX */ |
1856 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, 0x20); | | 1858 | bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, 0x20); |
1857 | } | | 1859 | } |
1858 | | | 1860 | |
1859 | /* | | 1861 | /* |
1860 | * Build disk label. For now we only create a label from what we know | | 1862 | * Build disk label. For now we only create a label from what we know |
1861 | * from 'sc'. | | 1863 | * from 'sc'. |
1862 | */ | | 1864 | */ |
1863 | static int | | 1865 | static int |
| @@ -1892,27 +1894,27 @@ fdgetdisklabel(struct fd_softc *sc, dev_ | | | @@ -1892,27 +1894,27 @@ fdgetdisklabel(struct fd_softc *sc, dev_ |
1892 | lp->d_checksum = dkcksum(lp); | | 1894 | lp->d_checksum = dkcksum(lp); |
1893 | lp->d_partitions[part].p_size = lp->d_secperunit; | | 1895 | lp->d_partitions[part].p_size = lp->d_secperunit; |
1894 | lp->d_partitions[part].p_fstype = FS_UNUSED; | | 1896 | lp->d_partitions[part].p_fstype = FS_UNUSED; |
1895 | lp->d_partitions[part].p_fsize = 1024; | | 1897 | lp->d_partitions[part].p_fsize = 1024; |
1896 | lp->d_partitions[part].p_frag = 8; | | 1898 | lp->d_partitions[part].p_frag = 8; |
1897 | | | 1899 | |
1898 | return 0; | | 1900 | return 0; |
1899 | } | | 1901 | } |
1900 | | | 1902 | |
1901 | /* | | 1903 | /* |
1902 | * Mountroot hook: prompt the user to enter the root file system | | 1904 | * Mountroot hook: prompt the user to enter the root file system |
1903 | * floppy. | | 1905 | * floppy. |
1904 | */ | | 1906 | */ |
1905 | void | | 1907 | static void |
1906 | fd_mountroot_hook(device_t dev) | | 1908 | fd_mountroot_hook(device_t dev) |
1907 | { | | 1909 | { |
1908 | struct fd_softc *fd = device_private(dev); | | 1910 | struct fd_softc *fd = device_private(dev); |
1909 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); | | 1911 | struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev)); |
1910 | int c; | | 1912 | int c; |
1911 | | | 1913 | |
1912 | /* XXX device_unit() abuse */ | | 1914 | /* XXX device_unit() abuse */ |
1913 | fd_do_eject(fdc, device_unit(dev)); | | 1915 | fd_do_eject(fdc, device_unit(dev)); |
1914 | printf("Insert filesystem floppy and press return."); | | 1916 | printf("Insert filesystem floppy and press return."); |
1915 | for (;;) { | | 1917 | for (;;) { |
1916 | c = cngetc(); | | 1918 | c = cngetc(); |
1917 | if ((c == '\r') || (c == '\n')) { | | 1919 | if ((c == '\r') || (c == '\n')) { |
1918 | printf("\n"); | | 1920 | printf("\n"); |