1 /* $NetBSD: fdc.c,v 1.31 2009/05/15 20:52:22 jnemeth Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1990 The Regents of the University of California.
34 * All rights reserved.
36 * This code is derived from software contributed to Berkeley by
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
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
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
63 * @(#)fd.c 7.4 (Berkeley) 5/25/91
67 * Copyright (c) 1993, 1994, 1995 Charles M. Hannum.
69 * This code is derived from software contributed to Berkeley by
72 * Redistribution and use in source and binary forms, with or without
73 * modification, are permitted provided that the following conditions
75 * 1. Redistributions of source code must retain the above copyright
76 * notice, this list of conditions and the following disclaimer.
77 * 2. Redistributions in binary form must reproduce the above copyright
78 * notice, this list of conditions and the following disclaimer in the
79 * documentation and/or other materials provided with the distribution.
80 * 3. All advertising materials mentioning features or use of this software
81 * must display the following acknowledgement:
82 * This product includes software developed by the University of
83 * California, Berkeley and its contributors.
84 * 4. Neither the name of the University nor the names of its contributors
85 * may be used to endorse or promote products derived from this software
86 * without specific prior written permission.
88 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
89 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
90 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
91 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
92 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
93 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
94 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
95 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
96 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
97 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
100 * @(#)fd.c 7.4 (Berkeley) 5/25/91
103 #include <sys/cdefs.h>
104 __KERNEL_RCSID(0, "$NetBSD: fdc.c,v 1.31 2009/05/15 20:52:22 jnemeth Exp $");
109 #include <sys/param.h>
110 #include <sys/types.h>
111 #include <sys/systm.h>
112 #include <sys/callout.h>
113 #include <sys/kernel.h>
114 #include <sys/file.h>
115 #include <sys/ioctl.h>
116 #include <sys/device.h>
117 #include <sys/disklabel.h>
118 #include <sys/disk.h>
119 #include <sys/fdio.h>
121 #include <sys/bufq.h>
122 #include <sys/malloc.h>
123 #include <sys/proc.h>
125 #include <sys/stat.h>
126 #include <sys/syslog.h>
127 #include <sys/queue.h>
128 #include <sys/conf.h>
129 #include <sys/intr.h>
131 #include <dev/cons.h>
133 #include <uvm/uvm_extern.h>
135 #include <machine/autoconf.h>
138 #include <sparc/sparc/auxreg.h>
139 #include <sparc/dev/fdreg.h>
140 #include <sparc/dev/fdvar.h>
142 #include <dev/ebus/ebusreg.h>
143 #include <dev/ebus/ebusvar.h>
144 /* #include <sparc/sparc/auxreg.h> */
145 #include <sparc64/dev/auxioreg.h>
146 #include <sparc64/dev/auxiovar.h>
147 #include <sparc64/dev/fdcreg.h>
148 #include <sparc64/dev/fdcvar.h>
151 #include <prop/proplib.h>
153 #define FDUNIT(dev) (minor(dev) / 8)
154 #define FDTYPE(dev) (minor(dev) % 8)
156 /* (mis)use device use flag to identify format operation */
157 #define B_FORMAT B_DEVPRIVATE
169 SEEKTIMEDOUT
, /* 4 */
170 SEEKCOMPLETE
, /* 5 */
174 IOCLEANUPWAIT
, /* 9 */
175 IOCLEANUPTIMEDOUT
,/*10 */
177 RESETCOMPLETE
, /* 12 */
178 RESETTIMEDOUT
, /* 13 */
181 RECALTIMEDOUT
, /* 16 */
182 RECALCOMPLETE
, /* 17 */
185 DSKCHGTIMEDOUT
, /* 20 */
188 /* software state, per controller */
190 struct device sc_dev
; /* boilerplate */
191 bus_space_tag_t sc_bustag
;
193 struct callout sc_timo_ch
; /* timeout callout */
194 struct callout sc_intr_ch
; /* pseudo-intr callout */
196 struct fd_softc
*sc_fd
[4]; /* pointers to children */
197 TAILQ_HEAD(drivehead
, fd_softc
) sc_drives
;
198 enum fdc_state sc_state
;
200 #define FDC_82077 0x01
201 #define FDC_NEEDHEADSETTLE 0x02
203 #define FDC_NEEDMOTORWAIT 0x08
204 #define FDC_NOEJECT 0x10
205 #define FDC_EBUS 0x20
206 int sc_errors
; /* number of retries so far */
207 int sc_overruns
; /* number of DMA overruns */
208 int sc_cfg
; /* current configuration */
210 #define sc_handle sc_io.fdcio_handle
211 #define sc_reg_msr sc_io.fdcio_reg_msr
212 #define sc_reg_fifo sc_io.fdcio_reg_fifo
213 #define sc_reg_dor sc_io.fdcio_reg_dor
214 #define sc_reg_dir sc_io.fdcio_reg_dir
215 #define sc_reg_drs sc_io.fdcio_reg_msr
216 #define sc_itask sc_io.fdcio_itask
217 #define sc_istatus sc_io.fdcio_istatus
218 #define sc_data sc_io.fdcio_data
219 #define sc_tc sc_io.fdcio_tc
220 #define sc_nstat sc_io.fdcio_nstat
221 #define sc_status sc_io.fdcio_status
222 #define sc_intrcnt sc_io.fdcio_intrcnt
224 void *sc_sicookie
; /* softint(9) cookie */
228 extern struct fdcio
*fdciop
; /* I/O descriptor used in fdintr.s */
231 /* controller driver configuration */
233 int fdcmatch_mainbus(struct device
*, struct cfdata
*, void*);
234 int fdcmatch_obio(struct device
*, struct cfdata
*, void *);
235 void fdcattach_mainbus(struct device
*, struct device
*, void *);
236 void fdcattach_obio(struct device
*, struct device
*, void *);
238 int fdcmatch_sbus(struct device
*, struct cfdata
*, void *);
239 int fdcmatch_ebus(struct device
*, struct cfdata
*, void *);
240 void fdcattach_sbus(struct device
*, struct device
*, void *);
241 void fdcattach_ebus(struct device
*, struct device
*, void *);
244 int fdcattach(struct fdc_softc
*, int);
247 CFATTACH_DECL(fdc_mainbus
, sizeof(struct fdc_softc
),
248 fdcmatch_mainbus
, fdcattach_mainbus
, NULL
, NULL
);
250 CFATTACH_DECL(fdc_obio
, sizeof(struct fdc_softc
),
251 fdcmatch_obio
, fdcattach_obio
, NULL
, NULL
);
253 CFATTACH_DECL(fdc_sbus
, sizeof(struct fdc_softc
),
254 fdcmatch_sbus
, fdcattach_sbus
, NULL
, NULL
);
256 CFATTACH_DECL(fdc_ebus
, sizeof(struct fdc_softc
),
257 fdcmatch_ebus
, fdcattach_ebus
, NULL
, NULL
);
260 inline struct fd_type
*fd_dev_to_type(struct fd_softc
*, dev_t
);
263 * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
264 * we tell them apart.
267 int sectrac
; /* sectors per track */
268 int heads
; /* number of heads */
269 int seccyl
; /* sectors per cylinder */
270 int secsize
; /* size code for sectors */
271 int datalen
; /* data len when secsize = 0 */
272 int steprate
; /* step rate and head unload time */
273 int gap1
; /* gap len between sectors */
274 int gap2
; /* formatting gap */
275 int cylinders
; /* total num of cylinders */
276 int size
; /* size of disk in sectors */
277 int step
; /* steps per cylinder */
278 int rate
; /* transfer speed code */
279 int fillbyte
; /* format fill byte */
280 int interleave
; /* interleave factor (formatting) */
284 /* The order of entries in the following table is important -- BEWARE! */
285 struct fd_type fd_types
[] = {
286 { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS
,0xf6,1, "1.44MB" }, /* 1.44MB diskette */
287 { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS
,0xf6,1, "720KB" }, /* 3.5" 720kB diskette */
288 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS
,0xf6,1, "360KB/x" }, /* 360kB in 720kB drive */
289 { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS
,0xf6,1, "1.2MB/NEC" } /* 1.2 MB japanese format */
292 /* software state, per disk (with up to 4 disks per ctlr) */
294 struct device sc_dv
; /* generic device info */
295 struct disk sc_dk
; /* generic disk info */
297 struct fd_type
*sc_deftype
; /* default type descriptor */
298 struct fd_type
*sc_type
; /* current type descriptor */
300 struct callout sc_motoron_ch
;
301 struct callout sc_motoroff_ch
;
303 daddr_t sc_blkno
; /* starting block number */
304 int sc_bcount
; /* byte count left */
305 int sc_skip
; /* bytes already transferred */
306 int sc_nblks
; /* number of blocks currently transferring */
307 int sc_nbytes
; /* number of bytes currently transferring */
309 int sc_drive
; /* physical unit number */
311 #define FD_OPEN 0x01 /* it's open */
312 #define FD_MOTOR 0x02 /* motor should be on */
313 #define FD_MOTOR_WAIT 0x04 /* motor coming up */
314 int sc_cylin
; /* where we think the head is */
315 int sc_opts
; /* user-set options */
317 TAILQ_ENTRY(fd_softc
) sc_drivechain
;
318 int sc_ops
; /* I/O ops since last switch */
319 struct bufq_state
*sc_q
;/* pending I/O requests */
320 int sc_active
; /* number of active I/O requests */
323 /* floppy driver configuration */
324 int fdmatch(struct device
*, struct cfdata
*, void *);
325 void fdattach(struct device
*, struct device
*, void *);
326 bool fdshutdown(device_t
, int);
327 bool fdsuspend(device_t
, pmf_qual_t
);
329 CFATTACH_DECL(fd
, sizeof(struct fd_softc
),
330 fdmatch
, fdattach
, NULL
, NULL
);
332 extern struct cfdriver fd_cd
;
334 dev_type_open(fdopen
);
335 dev_type_close(fdclose
);
336 dev_type_read(fdread
);
337 dev_type_write(fdwrite
);
338 dev_type_ioctl(fdioctl
);
339 dev_type_strategy(fdstrategy
);
341 const struct bdevsw fd_bdevsw
= {
342 fdopen
, fdclose
, fdstrategy
, fdioctl
, nodump
, nosize
, D_DISK
345 const struct cdevsw fd_cdevsw
= {
346 fdopen
, fdclose
, fdread
, fdwrite
, fdioctl
,
347 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_DISK
350 void fdgetdisklabel(dev_t
);
351 int fd_get_parms(struct fd_softc
*);
352 void fdstrategy(struct buf
*);
353 void fdstart(struct fd_softc
*);
354 int fdprint(void *, const char *);
356 struct dkdriver fddkdriver
= { fdstrategy
, NULL
};
358 struct fd_type
*fd_nvtotype(char *, int, int);
359 void fd_set_motor(struct fdc_softc
*);
360 void fd_motor_off(void *);
361 void fd_motor_on(void *);
362 int fdcresult(struct fdc_softc
*);
363 int fdc_wrfifo(struct fdc_softc
*, uint8_t);
364 void fdcstart(struct fdc_softc
*);
365 void fdcstatus(struct fdc_softc
*, const char *);
366 void fdc_reset(struct fdc_softc
*);
367 int fdc_diskchange(struct fdc_softc
*);
368 void fdctimeout(void *);
369 void fdcpseudointr(void *);
370 int fdc_c_hwintr(void *);
371 void fdchwintr(void);
372 void fdcswintr(void *);
373 int fdcstate(struct fdc_softc
*);
374 void fdcretry(struct fdc_softc
*);
375 void fdfinish(struct fd_softc
*, struct buf
*);
376 int fdformat(dev_t
, struct ne7_fd_formb
*, struct proc
*);
377 void fd_do_eject(struct fd_softc
*);
378 void fd_mountroot_hook(struct device
*);
379 static int fdconf(struct fdc_softc
*);
380 static void establish_chip_type(
386 static void fd_set_properties(struct fd_softc
*);
388 #ifdef MEMORY_DISK_HOOKS
389 int fd_read_md_image(size_t *, void **);
393 #define OBP_FDNAME (CPU_ISSUN4M ? "SUNW,fdtwo" : "fd")
396 fdcmatch_mainbus(struct device
*parent
, struct cfdata
*match
, void *aux
)
398 struct mainbus_attach_args
*ma
= aux
;
401 * Floppy controller is on mainbus on sun4c.
406 /* sun4c PROMs call the controller "fd" */
407 if (strcmp("fd", ma
->ma_name
) != 0)
410 return bus_space_probe(ma
->ma_bustag
,
419 fdcmatch_obio(struct device
*parent
, struct cfdata
*match
, void *aux
)
421 union obio_attach_args
*uoba
= aux
;
422 struct sbus_attach_args
*sa
;
425 * Floppy controller is on obio on sun4m.
427 if (uoba
->uoba_isobio4
!= 0)
430 sa
= &uoba
->uoba_sbus
;
432 /* sun4m PROMs call the controller "SUNW,fdtwo" */
433 if (strcmp("SUNW,fdtwo", sa
->sa_name
) != 0)
436 return bus_space_probe(sa
->sa_bustag
,
437 sbus_bus_addr(sa
->sa_bustag
,
438 sa
->sa_slot
, sa
->sa_offset
),
448 fdcmatch_sbus(struct device
*parent
, struct cfdata
*match
, void *aux
)
450 struct sbus_attach_args
*sa
= aux
;
452 return strcmp("SUNW,fdtwo", sa
->sa_name
) == 0;
456 fdcmatch_ebus(struct device
*parent
, struct cfdata
*match
, void *aux
)
458 struct ebus_attach_args
*ea
= aux
;
460 return strcmp("fdthree", ea
->ea_name
) == 0;
465 establish_chip_type(struct fdc_softc
*fdc
,
466 bus_space_tag_t tag
, bus_addr_t addr
, bus_size_t size
,
467 bus_space_handle_t handle
)
472 * This hack from Chris Torek: apparently DOR really
473 * addresses MSR/DRS on a 82072.
474 * We used to rely on the VERSION command to tell the
475 * difference (which did not work).
478 /* First, check the size of the register bank */
480 /* It isn't a 82077 */
484 /* Then probe the DOR register offset */
485 if (bus_space_probe(tag
, addr
,
487 FDREG77_DOR
, /* offset */
491 /* It isn't a 82077 */
496 v
= bus_space_read_1(tag
, handle
, FDREG77_DOR
);
499 * Value in DOR looks like it's really MSR
501 bus_space_write_1(tag
, handle
, FDREG77_DOR
, FDC_250KBPS
);
502 v
= bus_space_read_1(tag
, handle
, FDREG77_DOR
);
505 * The value in the DOR didn't stick;
512 fdc
->sc_flags
|= FDC_82077
;
516 * Arguments passed between fdcattach and fdprobe.
518 struct fdc_attach_args
{
520 struct fd_type
*fa_deftype
;
524 * Print the location of a disk drive (called just before attaching the
525 * the drive). If `fdc' is not NULL, the drive was found but was not
526 * in the system config file; print the drive name as well.
527 * Return QUIET (config_find ignores this if the device was configured) to
528 * avoid printing `fdN not configured' messages.
531 fdprint(void *aux
, const char *fdc
)
533 register struct fdc_attach_args
*fa
= aux
;
536 aprint_normal(" drive %d", fa
->fa_drive
);
541 * Configure several parameters and features on the FDC.
542 * Return 0 on success.
545 fdconf(struct fdc_softc
*fdc
)
549 if (fdc_wrfifo(fdc
, NE7CMD_DUMPREG
) || fdcresult(fdc
) != 10)
553 * dumpreg[7] seems to be a motor-off timeout; set it to whatever
554 * the PROM thinks is appropriate.
556 if ((vroom
= fdc
->sc_status
[7]) == 0)
559 /* Configure controller to use FIFO and Implied Seek */
560 if (fdc_wrfifo(fdc
, NE7CMD_CFG
) != 0)
562 if (fdc_wrfifo(fdc
, vroom
) != 0)
564 if (fdc_wrfifo(fdc
, fdc
->sc_cfg
) != 0)
566 if (fdc_wrfifo(fdc
, 0) != 0) /* PRETRK */
568 /* No result phase for the NE7CMD_CFG command */
570 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
571 /* Lock configuration across soft resets. */
572 if (fdc_wrfifo(fdc
, NE7CMD_LOCK
| CFG_LOCK
) != 0 ||
573 fdcresult(fdc
) != 1) {
575 printf("fdconf: CFGLOCK failed");
583 if (fdc_wrfifo(fdc
, NE7CMD_VERSION
) == 0 &&
584 fdcresult(fdc
) == 1 && fdc
->sc_status
[0] == 0x90) {
586 printf("[version cmd]");
593 fdcattach_mainbus(struct device
*parent
, struct device
*self
, void *aux
)
595 struct fdc_softc
*fdc
= (void *)self
;
596 struct mainbus_attach_args
*ma
= aux
;
598 fdc
->sc_bustag
= ma
->ma_bustag
;
604 BUS_SPACE_MAP_LINEAR
,
605 &fdc
->sc_handle
) != 0) {
606 aprint_error_dev(self
, "cannot map registers\n");
610 establish_chip_type(fdc
,
616 if (fdcattach(fdc
, ma
->ma_pri
) != 0)
617 bus_space_unmap(ma
->ma_bustag
, fdc
->sc_handle
, ma
->ma_size
);
621 fdcattach_obio(struct device
*parent
, struct device
*self
, void *aux
)
623 struct fdc_softc
*fdc
= (void *)self
;
624 union obio_attach_args
*uoba
= aux
;
625 struct sbus_attach_args
*sa
= &uoba
->uoba_sbus
;
627 if (sa
->sa_nintr
== 0) {
628 printf(": no interrupt line configured\n");
632 fdc
->sc_bustag
= sa
->sa_bustag
;
634 if (sbus_bus_map(sa
->sa_bustag
,
635 sa
->sa_slot
, sa
->sa_offset
, sa
->sa_size
,
636 BUS_SPACE_MAP_LINEAR
, &fdc
->sc_handle
) != 0) {
637 aprint_error_dev(self
, "cannot map control registers\n");
641 establish_chip_type(fdc
,
643 sbus_bus_addr(sa
->sa_bustag
, sa
->sa_slot
, sa
->sa_offset
),
647 if (strcmp(prom_getpropstring(sa
->sa_node
, "status"), "disabled") == 0) {
648 printf(": no drives attached\n");
652 if (fdcattach(fdc
, sa
->sa_pri
) != 0)
653 bus_space_unmap(sa
->sa_bustag
, fdc
->sc_handle
, sa
->sa_size
);
659 fdcattach_sbus(struct device
*parent
, struct device
*self
, void *aux
)
661 struct fdc_softc
*fdc
= (void *)self
;
662 struct sbus_attach_args
*sa
= aux
;
664 if (sa
->sa_nintr
== 0) {
665 printf(": no interrupt line configured\n");
669 if (auxio_fd_control(0) != 0) {
670 printf(": can't attach before auxio\n");
674 fdc
->sc_bustag
= sa
->sa_bustag
;
676 if (bus_space_map(sa
->sa_bustag
, BUS_ADDR(sa
->sa_slot
, sa
->sa_offset
),
677 sa
->sa_size
, 0, &fdc
->sc_handle
) != 0) {
678 printf(": cannot map control registers\n");
682 establish_chip_type(fdc
,
684 BUS_ADDR(sa
->sa_slot
, sa
->sa_offset
),
688 if (strcmp(prom_getpropstring(sa
->sa_node
, "status"), "disabled") == 0) {
689 printf(": no drives attached\n");
693 if (prom_getproplen(sa
->sa_node
, "manual") >= 0)
694 fdc
->sc_flags
|= FDC_NOEJECT
;
697 if (fdcattach(fdc
, sa
->sa_pri
) != 0)
698 bus_space_unmap(sa
->sa_bustag
, fdc
->sc_handle
, sa
->sa_size
);
702 fdcattach_ebus(struct device
*parent
, struct device
*self
, void *aux
)
704 struct fdc_softc
*fdc
= (void *)self
;
705 struct ebus_attach_args
*ea
= aux
;
708 if (ea
->ea_nintr
== 0) {
709 printf(": no interrupt line configured\n");
713 if (ea
->ea_nreg
< 3) {
714 printf(": expected 3 registers, only got %d\n",
719 fdc
->sc_bustag
= ea
->ea_bustag
;
721 if (ea
->ea_nvaddr
> 0) {
722 sparc_promaddr_to_handle(ea
->ea_bustag
,
723 ea
->ea_vaddr
[0], &fdc
->sc_handle
);
725 } else if (bus_space_map(fdc
->sc_bustag
,
726 EBUS_ADDR_FROM_REG(&ea
->ea_reg
[0]),
727 ea
->ea_reg
[0].size
, 0, &fdc
->sc_handle
) == 0) {
730 printf(": can't map control registers\n");
734 establish_chip_type(fdc
,
736 map_vaddr
? ea
->ea_vaddr
[0] :
737 EBUS_ADDR_FROM_REG(&ea
->ea_reg
[0]),
741 fdc
->sc_flags
|= FDC_EBUS
;
743 if (prom_getproplen(ea
->ea_node
, "manual") >= 0)
744 fdc
->sc_flags
|= FDC_NOEJECT
;
746 if (fdcattach(fdc
, ea
->ea_intr
[0]) != 0)
748 bus_space_unmap(ea
->ea_bustag
, fdc
->sc_handle
,
754 fdcattach(struct fdc_softc
*fdc
, int pri
)
756 struct fdc_attach_args fa
;
760 callout_init(&fdc
->sc_timo_ch
, 0);
761 callout_init(&fdc
->sc_intr_ch
, 0);
763 fdc
->sc_state
= DEVIDLE
;
764 fdc
->sc_itask
= FDC_ITASK_NONE
;
765 fdc
->sc_istatus
= FDC_ISTATUS_NONE
;
766 fdc
->sc_flags
|= FDC_EIS
;
767 TAILQ_INIT(&fdc
->sc_drives
);
769 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
770 fdc
->sc_reg_msr
= FDREG77_MSR
;
771 fdc
->sc_reg_fifo
= FDREG77_FIFO
;
772 fdc
->sc_reg_dor
= FDREG77_DOR
;
773 fdc
->sc_reg_dir
= FDREG77_DIR
;
775 fdc
->sc_flags
|= FDC_NEEDMOTORWAIT
;
777 fdc
->sc_reg_msr
= FDREG72_MSR
;
778 fdc
->sc_reg_fifo
= FDREG72_FIFO
;
784 * Configure controller; enable FIFO, Implied seek, no POLL mode?.
785 * Note: CFG_EFIFO is active-low, initial threshold value: 8
787 fdc
->sc_cfg
= CFG_EIS
|/*CFG_EFIFO|*/CFG_POLL
|(8 & CFG_THRHLD_MASK
);
788 if (fdconf(fdc
) != 0) {
789 printf(": no drives attached\n");
793 fdc
->sc_sicookie
= softint_establish(SOFTINT_BIO
, fdcswintr
, fdc
);
794 if (fdc
->sc_sicookie
== NULL
) {
796 aprint_error_dev(&fdc
->sc_dev
, "cannot register soft interrupt handler\n");
797 callout_stop(&fdc
->sc_timo_ch
);
798 callout_stop(&fdc
->sc_intr_ch
);
802 printf(" softpri %d: chip 8207%c\n", IPL_SOFTFDC
, code
);
804 printf(" softpri %d: chip 8207%c", PIL_FDSOFT
, code
);
805 if (fdc
->sc_flags
& FDC_NOEJECT
)
806 printf(": manual eject");
811 fdciop
= &fdc
->sc_io
;
812 if (bus_intr_establish2(fdc
->sc_bustag
, pri
, 0,
813 fdc_c_hwintr
, fdc
, fdchwintr
) == NULL
) {
815 if (bus_intr_establish(fdc
->sc_bustag
, pri
, IPL_BIO
,
816 fdc_c_hwintr
, fdc
) == NULL
) {
819 aprint_error_dev(&fdc
->sc_dev
, "cannot register interrupt handler\n");
820 callout_stop(&fdc
->sc_timo_ch
);
821 callout_stop(&fdc
->sc_intr_ch
);
822 softint_disestablish(fdc
->sc_sicookie
);
826 evcnt_attach_dynamic(&fdc
->sc_intrcnt
, EVCNT_TYPE_INTR
, NULL
,
827 device_xname(&fdc
->sc_dev
), "intr");
829 /* physical limit: four drives per controller. */
831 for (fa
.fa_drive
= 0; fa
.fa_drive
< 4; fa
.fa_drive
++) {
832 fa
.fa_deftype
= NULL
; /* unknown */
833 fa
.fa_deftype
= &fd_types
[0]; /* XXX */
834 if (config_found(&fdc
->sc_dev
, (void *)&fa
, fdprint
) != NULL
)
838 if (drive_attached
== 0) {
839 /* XXX - dis-establish interrupts here */
847 fdmatch(struct device
*parent
, struct cfdata
*match
, void *aux
)
849 struct fdc_softc
*fdc
= (void *)parent
;
850 bus_space_tag_t t
= fdc
->sc_bustag
;
851 bus_space_handle_t h
= fdc
->sc_handle
;
852 struct fdc_attach_args
*fa
= aux
;
853 int drive
= fa
->fa_drive
;
857 /* XXX - for now, punt on more than one drive */
860 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
861 /* select drive and turn on motor */
862 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
,
863 drive
| FDO_FRST
| FDO_MOEN(drive
));
864 /* wait for motor to spin up */
868 auxregbisc(AUXIO4C_FDS
, 0);
872 fdc_wrfifo(fdc
, NE7CMD_RECAL
);
873 fdc_wrfifo(fdc
, drive
);
875 /* Wait for recalibration to complete */
876 for (n
= 0; n
< 10000; n
++) {
880 v
= bus_space_read_1(t
, h
, fdc
->sc_reg_msr
);
881 if ((v
& (NE7_RQM
|NE7_DIO
|NE7_CB
)) == NE7_RQM
) {
882 /* wait a bit longer till device *really* is ready */
884 if (fdc_wrfifo(fdc
, NE7CMD_SENSEI
))
886 if (fdcresult(fdc
) == 1 && fdc
->sc_status
[0] == 0x80)
888 * Got `invalid command'; we interpret it
889 * to mean that the re-calibrate hasn't in
900 printf("fdprobe: %d stati:", n
);
901 for (i
= 0; i
< n
; i
++)
902 printf(" 0x%x", fdc
->sc_status
[i
]);
906 ok
= (n
== 2 && (fdc
->sc_status
[0] & 0xf8) == 0x20) ? 1 : 0;
909 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
910 /* deselect drive and turn motor off */
911 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
, FDO_FRST
| FDO_DS
);
914 auxregbisc(0, AUXIO4C_FDS
);
922 * Controller is working, and drive responded. Attach it.
925 fdattach(struct device
*parent
, struct device
*self
, void *aux
)
927 struct fdc_softc
*fdc
= (void *)parent
;
928 struct fd_softc
*fd
= (void *)self
;
929 struct fdc_attach_args
*fa
= aux
;
930 struct fd_type
*type
= fa
->fa_deftype
;
931 int drive
= fa
->fa_drive
;
933 callout_init(&fd
->sc_motoron_ch
, 0);
934 callout_init(&fd
->sc_motoroff_ch
, 0);
936 /* XXX Allow `flags' to override device type? */
939 printf(": %s %d cyl, %d head, %d sec\n", type
->name
,
940 type
->cylinders
, type
->heads
, type
->sectrac
);
942 printf(": density unknown\n");
944 bufq_alloc(&fd
->sc_q
, "disksort", BUFQ_SORT_CYLINDER
);
946 fd
->sc_drive
= drive
;
947 fd
->sc_deftype
= type
;
948 fdc
->sc_fd
[drive
] = fd
;
950 fdc_wrfifo(fdc
, NE7CMD_SPECIFY
);
951 fdc_wrfifo(fdc
, type
->steprate
);
952 /* XXX head load time == 6ms */
953 fdc_wrfifo(fdc
, 6 | NE7_SPECIFY_NODMA
);
956 * Initialize and attach the disk structure.
958 disk_init(&fd
->sc_dk
, device_xname(&fd
->sc_dv
), &fddkdriver
);
959 disk_attach(&fd
->sc_dk
);
962 * Establish a mountroot_hook anyway in case we booted
963 * with RB_ASKNAME and get selected as the boot device.
965 mountroothook_establish(fd_mountroot_hook
, &fd
->sc_dv
);
967 fd_set_properties(fd
);
969 /* Make sure the drive motor gets turned off at shutdown time. */
970 if (!pmf_device_register1(self
, fdsuspend
, NULL
, fdshutdown
))
971 aprint_error_dev(self
, "couldn't establish power handler\n");
974 bool fdshutdown(device_t self
, int how
)
976 struct fd_softc
*fd
= device_private(self
);
982 bool fdsuspend(device_t self
, pmf_qual_t qual
)
985 return fdshutdown(self
, boothowto
);
989 inline struct fd_type
*
990 fd_dev_to_type(struct fd_softc
*fd
, dev_t dev
)
992 int type
= FDTYPE(dev
);
994 if (type
> (sizeof(fd_types
) / sizeof(fd_types
[0])))
996 return type
? &fd_types
[type
- 1] : fd
->sc_deftype
;
1000 fdstrategy(struct buf
*bp
)
1002 struct fd_softc
*fd
;
1006 /* Valid unit, controller, and request? */
1007 fd
= device_lookup_private(&fd_cd
, FDUNIT(bp
->b_dev
));
1009 bp
->b_error
= EINVAL
;
1013 if (bp
->b_blkno
< 0 ||
1014 (((bp
->b_bcount
% FD_BSIZE(fd
)) != 0 ||
1015 (bp
->b_blkno
* DEV_BSIZE
) % FD_BSIZE(fd
) != 0) &&
1016 (bp
->b_flags
& B_FORMAT
) == 0)) {
1017 bp
->b_error
= EINVAL
;
1021 /* If it's a null transfer, return immediately. */
1022 if (bp
->b_bcount
== 0)
1025 sz
= howmany(bp
->b_bcount
, DEV_BSIZE
);
1027 if (bp
->b_blkno
+ sz
> (fd
->sc_type
->size
* DEV_BSIZE
) / FD_BSIZE(fd
)) {
1028 sz
= (fd
->sc_type
->size
* DEV_BSIZE
) / FD_BSIZE(fd
)
1031 /* If exactly at end of disk, return EOF. */
1032 bp
->b_resid
= bp
->b_bcount
;
1036 /* If past end of disk, return EINVAL. */
1037 bp
->b_error
= EINVAL
;
1040 /* Otherwise, truncate request. */
1041 bp
->b_bcount
= sz
<< DEV_BSHIFT
;
1044 bp
->b_rawblkno
= bp
->b_blkno
;
1045 bp
->b_cylinder
= (bp
->b_blkno
* DEV_BSIZE
) /
1046 (FD_BSIZE(fd
) * fd
->sc_type
->seccyl
);
1050 printf("fdstrategy: b_blkno %lld b_bcount %d blkno %lld cylin %d sz %d\n",
1051 (long long)bp
->b_blkno
, bp
->b_bcount
,
1052 (long long)fd
->sc_blkno
, bp
->b_cylinder
, sz
);
1055 /* Queue transfer on drive, activate drive and controller if idle. */
1057 bufq_put(fd
->sc_q
, bp
);
1058 callout_stop(&fd
->sc_motoroff_ch
); /* a good idea */
1059 if (fd
->sc_active
== 0)
1063 struct fdc_softc
*fdc
= (void *)device_parent(&fd
->sc_dv
);
1064 if (fdc
->sc_state
== DEVIDLE
) {
1065 printf("fdstrategy: controller inactive\n");
1074 /* Toss transfer; we're done early. */
1079 fdstart(struct fd_softc
*fd
)
1081 struct fdc_softc
*fdc
= (void *)device_parent(&fd
->sc_dv
);
1082 int active
= fdc
->sc_drives
.tqh_first
!= 0;
1084 /* Link into controller queue. */
1086 TAILQ_INSERT_TAIL(&fdc
->sc_drives
, fd
, sc_drivechain
);
1088 /* If controller not already active, start it. */
1094 fdfinish(struct fd_softc
*fd
, struct buf
*bp
)
1096 struct fdc_softc
*fdc
= (void *)device_parent(&fd
->sc_dv
);
1099 * Move this drive to the end of the queue to give others a `fair'
1100 * chance. We only force a switch if N operations are completed while
1101 * another drive is waiting to be serviced, since there is a long motor
1102 * startup delay whenever we switch.
1104 (void)bufq_get(fd
->sc_q
);
1105 if (fd
->sc_drivechain
.tqe_next
&& ++fd
->sc_ops
>= 8) {
1107 TAILQ_REMOVE(&fdc
->sc_drives
, fd
, sc_drivechain
);
1108 if (bufq_peek(fd
->sc_q
) != NULL
) {
1109 TAILQ_INSERT_TAIL(&fdc
->sc_drives
, fd
, sc_drivechain
);
1113 bp
->b_resid
= fd
->sc_bcount
;
1117 /* turn off motor 5s from now */
1118 callout_reset(&fd
->sc_motoroff_ch
, 5 * hz
, fd_motor_off
, fd
);
1119 fdc
->sc_state
= DEVIDLE
;
1123 fdc_reset(struct fdc_softc
*fdc
)
1125 bus_space_tag_t t
= fdc
->sc_bustag
;
1126 bus_space_handle_t h
= fdc
->sc_handle
;
1128 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
1129 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
,
1130 FDO_FDMAEN
| FDO_MOEN(0));
1133 bus_space_write_1(t
, h
, fdc
->sc_reg_drs
, DRS_RESET
);
1135 bus_space_write_1(t
, h
, fdc
->sc_reg_drs
, 0);
1137 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
1138 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
,
1139 FDO_FRST
| FDO_FDMAEN
| FDO_DS
);
1143 printf("fdc reset\n");
1148 fd_set_motor(struct fdc_softc
*fdc
)
1150 struct fd_softc
*fd
;
1154 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
1155 status
= FDO_FRST
| FDO_FDMAEN
;
1156 if ((fd
= fdc
->sc_drives
.tqh_first
) != NULL
)
1157 status
|= fd
->sc_drive
;
1159 for (n
= 0; n
< 4; n
++)
1160 if ((fd
= fdc
->sc_fd
[n
]) && (fd
->sc_flags
& FD_MOTOR
))
1161 status
|= FDO_MOEN(n
);
1162 bus_space_write_1(fdc
->sc_bustag
, fdc
->sc_handle
,
1163 fdc
->sc_reg_dor
, status
);
1167 for (n
= 0; n
< 4; n
++) {
1168 if ((fd
= fdc
->sc_fd
[n
]) != NULL
&&
1169 (fd
->sc_flags
& FD_MOTOR
) != 0) {
1170 auxregbisc(AUXIO4C_FDS
, 0);
1174 auxregbisc(0, AUXIO4C_FDS
);
1180 fd_motor_off(void *arg
)
1182 struct fd_softc
*fd
= arg
;
1186 fd
->sc_flags
&= ~(FD_MOTOR
| FD_MOTOR_WAIT
);
1187 fd_set_motor((struct fdc_softc
*)device_parent(&fd
->sc_dv
));
1192 fd_motor_on(void *arg
)
1194 struct fd_softc
*fd
= arg
;
1195 struct fdc_softc
*fdc
= (void *)device_parent(&fd
->sc_dv
);
1199 fd
->sc_flags
&= ~FD_MOTOR_WAIT
;
1200 if ((fdc
->sc_drives
.tqh_first
== fd
) && (fdc
->sc_state
== MOTORWAIT
))
1201 (void)fdcstate(fdc
);
1206 * Get status bytes off the FDC after a command has finished
1207 * Returns the number of status bytes read; -1 on error.
1208 * The return value is also stored in `sc_nstat'.
1211 fdcresult(struct fdc_softc
*fdc
)
1213 bus_space_tag_t t
= fdc
->sc_bustag
;
1214 bus_space_handle_t h
= fdc
->sc_handle
;
1217 for (j
= 10000; j
; j
--) {
1218 uint8_t v
= bus_space_read_1(t
, h
, fdc
->sc_reg_msr
);
1219 v
&= (NE7_DIO
| NE7_RQM
| NE7_CB
);
1221 return fdc
->sc_nstat
= n
;
1222 if (v
== (NE7_DIO
| NE7_RQM
| NE7_CB
)) {
1223 if (n
>= sizeof(fdc
->sc_status
)) {
1224 log(LOG_ERR
, "fdcresult: overrun\n");
1227 fdc
->sc_status
[n
++] =
1228 bus_space_read_1(t
, h
, fdc
->sc_reg_fifo
);
1233 log(LOG_ERR
, "fdcresult: timeout\n");
1234 return fdc
->sc_nstat
= -1;
1238 * Write a command byte to the FDC.
1239 * Returns 0 on success; -1 on failure (i.e. timeout)
1242 fdc_wrfifo(struct fdc_softc
*fdc
, uint8_t x
)
1244 bus_space_tag_t t
= fdc
->sc_bustag
;
1245 bus_space_handle_t h
= fdc
->sc_handle
;
1248 for (i
= 100000; i
-- > 0;) {
1249 uint8_t v
= bus_space_read_1(t
, h
, fdc
->sc_reg_msr
);
1250 if ((v
& (NE7_DIO
|NE7_RQM
)) == NE7_RQM
) {
1251 /* The chip is ready */
1252 bus_space_write_1(t
, h
, fdc
->sc_reg_fifo
, x
);
1261 fdc_diskchange(struct fdc_softc
*fdc
)
1265 if (CPU_ISSUN4M
&& (fdc
->sc_flags
& FDC_82077
) != 0) {
1267 bus_space_tag_t t
= fdc
->sc_bustag
;
1268 bus_space_handle_t h
= fdc
->sc_handle
;
1269 uint8_t v
= bus_space_read_1(t
, h
, fdc
->sc_reg_dir
);
1270 return (v
& FDI_DCHG
) != 0;
1272 } else if (CPU_ISSUN4C
) {
1273 return (*AUXIO4C_REG
& AUXIO4C_FDC
) != 0;
1280 fdopen(dev_t dev
, int flags
, int fmt
, struct lwp
*l
)
1283 struct fd_softc
*fd
;
1284 struct fd_type
*type
;
1286 fd
= device_lookup_private(&fd_cd
, FDUNIT(dev
));
1289 type
= fd_dev_to_type(fd
, dev
);
1293 if ((fd
->sc_flags
& FD_OPEN
) != 0 &&
1294 fd
->sc_type
!= type
)
1299 fd
->sc_flags
|= FD_OPEN
;
1302 * Only update the disklabel if we're not open anywhere else.
1304 if (fd
->sc_dk
.dk_openmask
== 0)
1305 fdgetdisklabel(dev
);
1307 pmask
= (1 << DISKPART(dev
));
1311 fd
->sc_dk
.dk_copenmask
|= pmask
;
1315 fd
->sc_dk
.dk_bopenmask
|= pmask
;
1318 fd
->sc_dk
.dk_openmask
=
1319 fd
->sc_dk
.dk_copenmask
| fd
->sc_dk
.dk_bopenmask
;
1325 fdclose(dev_t dev
, int flags
, int fmt
, struct lwp
*l
)
1327 struct fd_softc
*fd
= device_lookup_private(&fd_cd
, FDUNIT(dev
));
1328 int pmask
= (1 << DISKPART(dev
));
1330 fd
->sc_flags
&= ~FD_OPEN
;
1331 fd
->sc_opts
&= ~(FDOPT_NORETRY
|FDOPT_SILENT
);
1335 fd
->sc_dk
.dk_copenmask
&= ~pmask
;
1339 fd
->sc_dk
.dk_bopenmask
&= ~pmask
;
1342 fd
->sc_dk
.dk_openmask
=
1343 fd
->sc_dk
.dk_copenmask
| fd
->sc_dk
.dk_bopenmask
;
1349 fdread(dev_t dev
, struct uio
*uio
, int flag
)
1352 return physio(fdstrategy
, NULL
, dev
, B_READ
, minphys
, uio
);
1356 fdwrite(dev_t dev
, struct uio
*uio
, int flag
)
1359 return physio(fdstrategy
, NULL
, dev
, B_WRITE
, minphys
, uio
);
1363 fdcstart(struct fdc_softc
*fdc
)
1367 /* only got here if controller's drive queue was inactive; should
1369 if (fdc
->sc_state
!= DEVIDLE
) {
1370 printf("fdcstart: not idle\n");
1374 (void)fdcstate(fdc
);
1378 fdcpstatus(struct fdc_softc
*fdc
)
1382 snprintb(bits
, sizeof(bits
), NE7_ST0BITS
, fdc
->sc_status
[0]);
1383 printf(" (st0 %s", bits
);
1384 snprintb(bits
, sizeof(bits
), NE7_ST1BITS
, fdc
->sc_status
[1]);
1385 printf(" st1 %s", bits
);
1386 snprintb(bits
, sizeof(bits
), NE7_ST2BITS
, fdc
->sc_status
[2]);
1387 printf(" st2 %s", bits
);
1388 printf(" cyl %d head %d sec %d)\n",
1389 fdc
->sc_status
[3], fdc
->sc_status
[4], fdc
->sc_status
[5]);
1393 fdcstatus(struct fdc_softc
*fdc
, const char *s
)
1395 struct fd_softc
*fd
= fdc
->sc_drives
.tqh_first
;
1399 /* Just print last status */
1404 * A 82072 seems to return <invalid command> on
1405 * gratuitous Sense Interrupt commands.
1407 if (n
== 0 && (fdc
->sc_flags
& FDC_82077
) != 0) {
1408 fdc_wrfifo(fdc
, NE7CMD_SENSEI
);
1409 (void)fdcresult(fdc
);
1414 printf("%s: %s: state %d",
1415 fd
? device_xname(&fd
->sc_dv
) : "fdc", s
, fdc
->sc_state
);
1422 snprintb(bits
, sizeof(bits
), NE7_ST0BITS
, fdc
->sc_status
[0]);
1423 printf(" (st0 %s cyl %d)\n", bits
, fdc
->sc_status
[1]);
1430 printf(" fdcstatus: weird size: %d\n", n
);
1437 fdctimeout(void *arg
)
1439 struct fdc_softc
*fdc
= arg
;
1440 struct fd_softc
*fd
;
1444 fd
= fdc
->sc_drives
.tqh_first
;
1446 aprint_error_dev(&fdc
->sc_dev
, "timeout but no I/O pending: state %d, istatus=%d\n",
1447 fdc
->sc_state
, fdc
->sc_istatus
);
1448 fdc
->sc_state
= DEVIDLE
;
1452 if (bufq_peek(fd
->sc_q
) != NULL
)
1455 fdc
->sc_state
= DEVIDLE
;
1457 (void)fdcstate(fdc
);
1464 fdcpseudointr(void *arg
)
1466 struct fdc_softc
*fdc
= arg
;
1469 /* Just ensure it has the right spl. */
1471 (void)fdcstate(fdc
);
1477 * hardware interrupt entry point: used only if no `fast trap' * (in-window)
1478 * handler is available. Unfortunately, we have no reliable way to
1479 * determine that the interrupt really came from the floppy controller;
1480 * just hope that the other devices that share this interrupt level
1484 fdc_c_hwintr(void *arg
)
1486 struct fdc_softc
*fdc
= arg
;
1487 bus_space_tag_t t
= fdc
->sc_bustag
;
1488 bus_space_handle_t h
= fdc
->sc_handle
;
1490 switch (fdc
->sc_itask
) {
1491 case FDC_ITASK_NONE
:
1493 case FDC_ITASK_SENSEI
:
1494 if (fdc_wrfifo(fdc
, NE7CMD_SENSEI
) != 0 || fdcresult(fdc
) == -1)
1495 fdc
->sc_istatus
= FDC_ISTATUS_ERROR
;
1497 fdc
->sc_istatus
= FDC_ISTATUS_DONE
;
1498 softint_schedule(fdc
->sc_sicookie
);
1500 case FDC_ITASK_RESULT
:
1501 if (fdcresult(fdc
) == -1)
1502 fdc
->sc_istatus
= FDC_ISTATUS_ERROR
;
1504 fdc
->sc_istatus
= FDC_ISTATUS_DONE
;
1505 softint_schedule(fdc
->sc_sicookie
);
1508 /* Proceed with pseudo-DMA below */
1511 printf("fdc: stray hard interrupt: itask=%d\n", fdc
->sc_itask
);
1512 fdc
->sc_istatus
= FDC_ISTATUS_SPURIOUS
;
1513 softint_schedule(fdc
->sc_sicookie
);
1518 * Pseudo DMA in progress
1523 msr
= bus_space_read_1(t
, h
, fdc
->sc_reg_msr
);
1525 if ((msr
& NE7_RQM
) == 0)
1526 /* That's all this round. */
1529 if ((msr
& NE7_NDM
) == 0) {
1530 /* Execution phase finished, get result. */
1532 fdc
->sc_istatus
= FDC_ISTATUS_DONE
;
1533 softint_schedule(fdc
->sc_sicookie
);
1537 if (fdc
->sc_tc
== 0)
1538 /* For some reason the controller wants to transfer
1539 more data then what we want to transfer. */
1540 panic("fdc: overrun");
1542 /* Another byte can be transferred */
1543 if ((msr
& NE7_DIO
) != 0)
1545 bus_space_read_1(t
, h
, fdc
->sc_reg_fifo
);
1547 bus_space_write_1(t
, h
, fdc
->sc_reg_fifo
,
1551 if (--fdc
->sc_tc
== 0) {
1560 fdcswintr(void *arg
)
1562 struct fdc_softc
*fdc
= arg
;
1564 if (fdc
->sc_istatus
== FDC_ISTATUS_NONE
)
1565 /* This (software) interrupt is not for us */
1568 switch (fdc
->sc_istatus
) {
1569 case FDC_ISTATUS_ERROR
:
1570 printf("fdc: ierror status: state %d\n", fdc
->sc_state
);
1572 case FDC_ISTATUS_SPURIOUS
:
1573 printf("fdc: spurious interrupt: state %d\n", fdc
->sc_state
);
1582 fdcstate(struct fdc_softc
*fdc
)
1585 #define st0 fdc->sc_status[0]
1586 #define st1 fdc->sc_status[1]
1587 #define cyl fdc->sc_status[1]
1588 #define FDC_WRFIFO(fdc, c) do { \
1589 if (fdc_wrfifo(fdc, (c))) { \
1594 struct fd_softc
*fd
;
1596 int read
, head
, sec
, nblks
;
1597 struct fd_type
*type
;
1598 struct ne7_fd_formb
*finfo
= NULL
;
1600 if (fdc
->sc_istatus
== FDC_ISTATUS_ERROR
) {
1601 /* Prevent loop if the reset sequence produces errors */
1602 if (fdc
->sc_state
!= RESETCOMPLETE
&&
1603 fdc
->sc_state
!= RECALWAIT
&&
1604 fdc
->sc_state
!= RECALCOMPLETE
)
1605 fdc
->sc_state
= DORESET
;
1608 /* Clear I task/status field */
1609 fdc
->sc_istatus
= FDC_ISTATUS_NONE
;
1610 fdc
->sc_itask
= FDC_ITASK_NONE
;
1613 /* Is there a drive for the controller to do a transfer with? */
1614 fd
= fdc
->sc_drives
.tqh_first
;
1616 fdc
->sc_state
= DEVIDLE
;
1620 /* Is there a transfer to this drive? If not, deactivate drive. */
1621 bp
= bufq_peek(fd
->sc_q
);
1624 TAILQ_REMOVE(&fdc
->sc_drives
, fd
, sc_drivechain
);
1629 if (bp
->b_flags
& B_FORMAT
)
1630 finfo
= (struct ne7_fd_formb
*)bp
->b_data
;
1632 switch (fdc
->sc_state
) {
1636 fd
->sc_bcount
= bp
->b_bcount
;
1637 fd
->sc_blkno
= (bp
->b_blkno
* DEV_BSIZE
) / FD_BSIZE(fd
);
1638 callout_stop(&fd
->sc_motoroff_ch
);
1639 if ((fd
->sc_flags
& FD_MOTOR_WAIT
) != 0) {
1640 fdc
->sc_state
= MOTORWAIT
;
1643 if ((fd
->sc_flags
& FD_MOTOR
) == 0) {
1644 /* Turn on the motor, being careful about pairing. */
1645 struct fd_softc
*ofd
= fdc
->sc_fd
[fd
->sc_drive
^ 1];
1646 if (ofd
&& ofd
->sc_flags
& FD_MOTOR
) {
1647 callout_stop(&ofd
->sc_motoroff_ch
);
1648 ofd
->sc_flags
&= ~(FD_MOTOR
| FD_MOTOR_WAIT
);
1650 fd
->sc_flags
|= FD_MOTOR
| FD_MOTOR_WAIT
;
1652 fdc
->sc_state
= MOTORWAIT
;
1653 if ((fdc
->sc_flags
& FDC_NEEDMOTORWAIT
) != 0) { /*XXX*/
1654 /* Allow .25s for motor to stabilize. */
1655 callout_reset(&fd
->sc_motoron_ch
, hz
/ 4,
1658 fd
->sc_flags
&= ~FD_MOTOR_WAIT
;
1663 /* Make sure the right drive is selected. */
1666 if (fdc_diskchange(fdc
))
1672 if ((fdc
->sc_flags
& FDC_EIS
) &&
1673 (bp
->b_flags
& B_FORMAT
) == 0) {
1674 fd
->sc_cylin
= bp
->b_cylinder
;
1675 /* We use implied seek */
1679 if (fd
->sc_cylin
== bp
->b_cylinder
)
1683 fdc
->sc_state
= SEEKWAIT
;
1686 iostat_seek(fd
->sc_dk
.dk_stats
);
1688 disk_busy(&fd
->sc_dk
);
1689 callout_reset(&fdc
->sc_timo_ch
, 4 * hz
, fdctimeout
, fdc
);
1691 /* specify command */
1692 FDC_WRFIFO(fdc
, NE7CMD_SPECIFY
);
1693 FDC_WRFIFO(fdc
, fd
->sc_type
->steprate
);
1694 /* XXX head load time == 6ms */
1695 FDC_WRFIFO(fdc
, 6 | NE7_SPECIFY_NODMA
);
1697 fdc
->sc_itask
= FDC_ITASK_SENSEI
;
1699 FDC_WRFIFO(fdc
, NE7CMD_SEEK
);
1700 FDC_WRFIFO(fdc
, fd
->sc_drive
); /* drive number */
1701 FDC_WRFIFO(fdc
, bp
->b_cylinder
* fd
->sc_type
->step
);
1707 * Disk change: force a seek operation by going to cyl 1
1708 * followed by a recalibrate.
1710 disk_busy(&fd
->sc_dk
);
1711 callout_reset(&fdc
->sc_timo_ch
, 4 * hz
, fdctimeout
, fdc
);
1714 fdc
->sc_state
= DSKCHGWAIT
;
1716 fdc
->sc_itask
= FDC_ITASK_SENSEI
;
1718 FDC_WRFIFO(fdc
, NE7CMD_SEEK
);
1719 FDC_WRFIFO(fdc
, fd
->sc_drive
); /* drive number */
1720 FDC_WRFIFO(fdc
, 1 * fd
->sc_type
->step
);
1724 callout_stop(&fdc
->sc_timo_ch
);
1725 disk_unbusy(&fd
->sc_dk
, 0, 0);
1726 if (fdc
->sc_nstat
!= 2 || (st0
& 0xf8) != 0x20 ||
1727 cyl
!= 1 * fd
->sc_type
->step
) {
1728 fdcstatus(fdc
, "dskchg seek failed");
1729 fdc
->sc_state
= DORESET
;
1731 fdc
->sc_state
= DORECAL
;
1733 if (fdc_diskchange(fdc
)) {
1734 aprint_error_dev(&fdc
->sc_dev
, "cannot clear disk change status\n");
1735 fdc
->sc_state
= DORESET
;
1742 fd
->sc_skip
= (char *)&(finfo
->fd_formb_cylno(0)) -
1745 sec
= fd
->sc_blkno
% type
->seccyl
;
1746 nblks
= type
->seccyl
- sec
;
1747 nblks
= min(nblks
, fd
->sc_bcount
/ FD_BSIZE(fd
));
1748 nblks
= min(nblks
, FDC_MAXIOSIZE
/ FD_BSIZE(fd
));
1749 fd
->sc_nblks
= nblks
;
1750 fd
->sc_nbytes
= finfo
? bp
->b_bcount
: nblks
* FD_BSIZE(fd
);
1751 head
= sec
/ type
->sectrac
;
1752 sec
-= head
* type
->sectrac
;
1755 block
= (fd
->sc_cylin
* type
->heads
+ head
) * type
->sectrac
+
1757 if (block
!= fd
->sc_blkno
) {
1758 printf("fdcintr: block %d != blkno %d\n", block
,
1765 read
= bp
->b_flags
& B_READ
;
1767 /* Setup for pseudo DMA */
1768 fdc
->sc_data
= (char *)bp
->b_data
+ fd
->sc_skip
;
1769 fdc
->sc_tc
= fd
->sc_nbytes
;
1771 bus_space_write_1(fdc
->sc_bustag
, fdc
->sc_handle
,
1772 fdc
->sc_reg_drs
, type
->rate
);
1775 printf("fdcstate: doio: %s drive %d "
1776 "track %d head %d sec %d nblks %d\n",
1778 (read
? "read" : "write"),
1779 fd
->sc_drive
, fd
->sc_cylin
, head
, sec
, nblks
);
1781 fdc
->sc_state
= IOCOMPLETE
;
1782 fdc
->sc_itask
= FDC_ITASK_DMA
;
1785 disk_busy(&fd
->sc_dk
);
1787 /* allow 3 seconds for operation */
1788 callout_reset(&fdc
->sc_timo_ch
, 3 * hz
, fdctimeout
, fdc
);
1790 if (finfo
!= NULL
) {
1792 FDC_WRFIFO(fdc
, NE7CMD_FORMAT
);
1793 FDC_WRFIFO(fdc
, (head
<< 2) | fd
->sc_drive
);
1794 FDC_WRFIFO(fdc
, finfo
->fd_formb_secshift
);
1795 FDC_WRFIFO(fdc
, finfo
->fd_formb_nsecs
);
1796 FDC_WRFIFO(fdc
, finfo
->fd_formb_gaplen
);
1797 FDC_WRFIFO(fdc
, finfo
->fd_formb_fillbyte
);
1800 FDC_WRFIFO(fdc
, NE7CMD_READ
);
1802 FDC_WRFIFO(fdc
, NE7CMD_WRITE
);
1803 FDC_WRFIFO(fdc
, (head
<< 2) | fd
->sc_drive
);
1804 FDC_WRFIFO(fdc
, fd
->sc_cylin
); /*track*/
1805 FDC_WRFIFO(fdc
, head
);
1806 FDC_WRFIFO(fdc
, sec
+ 1); /*sector+1*/
1807 FDC_WRFIFO(fdc
, type
->secsize
); /*sector size*/
1808 FDC_WRFIFO(fdc
, type
->sectrac
); /*secs/track*/
1809 FDC_WRFIFO(fdc
, type
->gap1
); /*gap1 size*/
1810 FDC_WRFIFO(fdc
, type
->datalen
); /*data length*/
1813 return 1; /* will return later */
1816 callout_stop(&fdc
->sc_timo_ch
);
1817 fdc
->sc_state
= SEEKCOMPLETE
;
1818 if (fdc
->sc_flags
& FDC_NEEDHEADSETTLE
) {
1819 /* allow 1/50 second for heads to settle */
1820 callout_reset(&fdc
->sc_intr_ch
, hz
/ 50,
1821 fdcpseudointr
, fdc
);
1822 return 1; /* will return later */
1826 /* no data on seek */
1827 disk_unbusy(&fd
->sc_dk
, 0, 0);
1829 /* Make sure seek really happened. */
1830 if (fdc
->sc_nstat
!= 2 || (st0
& 0xf8) != 0x20 ||
1831 cyl
!= bp
->b_cylinder
* fd
->sc_type
->step
) {
1834 fdcstatus(fdc
, "seek failed");
1839 fd
->sc_cylin
= bp
->b_cylinder
;
1844 * Try to abort the I/O operation without resetting
1845 * the chip first. Poke TC and arrange to pick up
1846 * the timed out I/O command's status.
1848 fdc
->sc_itask
= FDC_ITASK_RESULT
;
1849 fdc
->sc_state
= IOCLEANUPWAIT
;
1851 /* 1/10 second should be enough */
1852 callout_reset(&fdc
->sc_timo_ch
, hz
/ 10, fdctimeout
, fdc
);
1856 case IOCLEANUPTIMEDOUT
:
1860 case DSKCHGTIMEDOUT
:
1861 fdcstatus(fdc
, "timeout");
1863 /* All other timeouts always roll through to a chip reset */
1866 /* Force reset, no matter what fdcretry() says */
1867 fdc
->sc_state
= DORESET
;
1870 case IOCLEANUPWAIT
: /* IO FAILED, cleanup succeeded */
1871 callout_stop(&fdc
->sc_timo_ch
);
1872 disk_unbusy(&fd
->sc_dk
, (bp
->b_bcount
- bp
->b_resid
),
1873 (bp
->b_flags
& B_READ
));
1877 case IOCOMPLETE
: /* IO DONE, post-analyze */
1878 callout_stop(&fdc
->sc_timo_ch
);
1880 disk_unbusy(&fd
->sc_dk
, (bp
->b_bcount
- bp
->b_resid
),
1881 (bp
->b_flags
& B_READ
));
1883 if (fdc
->sc_nstat
!= 7 || st1
!= 0 ||
1884 ((st0
& 0xf8) != 0 &&
1885 ((st0
& 0xf8) != 0x20 || (fdc
->sc_cfg
& CFG_EIS
) == 0))) {
1888 fdcstatus(fdc
, bp
->b_flags
& B_READ
?
1889 "read failed" : "write failed");
1890 printf("blkno %lld nblks %d nstat %d tc %d\n",
1891 (long long)fd
->sc_blkno
, fd
->sc_nblks
,
1892 fdc
->sc_nstat
, fdc
->sc_tc
);
1895 if (fdc
->sc_nstat
== 7 &&
1896 (st1
& ST1_OVERRUN
) == ST1_OVERRUN
) {
1899 * Silently retry overruns if no other
1900 * error bit is set. Adjust threshold.
1902 int thr
= fdc
->sc_cfg
& CFG_THRHLD_MASK
;
1905 fdc
->sc_cfg
&= ~CFG_THRHLD_MASK
;
1906 fdc
->sc_cfg
|= (thr
& CFG_THRHLD_MASK
);
1909 printf("fdc: %d -> threshold\n",
1913 fdc
->sc_overruns
= 0;
1915 if (++fdc
->sc_overruns
< 3) {
1916 fdc
->sc_state
= DOIO
;
1923 if (fdc
->sc_errors
) {
1924 diskerr(bp
, "fd", "soft error", LOG_PRINTF
,
1925 fd
->sc_skip
/ FD_BSIZE(fd
),
1926 (struct disklabel
*)NULL
);
1930 if (--fdc
->sc_overruns
< -20) {
1931 int thr
= fdc
->sc_cfg
& CFG_THRHLD_MASK
;
1934 fdc
->sc_cfg
&= ~CFG_THRHLD_MASK
;
1935 fdc
->sc_cfg
|= (thr
& CFG_THRHLD_MASK
);
1938 printf("fdc: %d -> threshold\n",
1943 fdc
->sc_overruns
= 0;
1946 fd
->sc_blkno
+= fd
->sc_nblks
;
1947 fd
->sc_skip
+= fd
->sc_nbytes
;
1948 fd
->sc_bcount
-= fd
->sc_nbytes
;
1949 if (finfo
== NULL
&& fd
->sc_bcount
> 0) {
1950 bp
->b_cylinder
= fd
->sc_blkno
/ fd
->sc_type
->seccyl
;
1957 /* try a reset, keep motor on */
1961 fdc
->sc_itask
= FDC_ITASK_SENSEI
;
1962 fdc
->sc_state
= RESETCOMPLETE
;
1963 callout_reset(&fdc
->sc_timo_ch
, hz
/ 2, fdctimeout
, fdc
);
1965 return 1; /* will return later */
1968 callout_stop(&fdc
->sc_timo_ch
);
1973 fdc
->sc_state
= RECALWAIT
;
1974 fdc
->sc_itask
= FDC_ITASK_SENSEI
;
1976 callout_reset(&fdc
->sc_timo_ch
, 5 * hz
, fdctimeout
, fdc
);
1977 /* recalibrate function */
1978 FDC_WRFIFO(fdc
, NE7CMD_RECAL
);
1979 FDC_WRFIFO(fdc
, fd
->sc_drive
);
1980 return 1; /* will return later */
1983 callout_stop(&fdc
->sc_timo_ch
);
1984 fdc
->sc_state
= RECALCOMPLETE
;
1985 if (fdc
->sc_flags
& FDC_NEEDHEADSETTLE
) {
1986 /* allow 1/30 second for heads to settle */
1987 callout_reset(&fdc
->sc_intr_ch
, hz
/ 30,
1988 fdcpseudointr
, fdc
);
1989 return 1; /* will return later */
1993 if (fdc
->sc_nstat
!= 2 || (st0
& 0xf8) != 0x20 || cyl
!= 0) {
1996 fdcstatus(fdc
, "recalibrate failed");
2005 if (fd
->sc_flags
& FD_MOTOR_WAIT
)
2006 return 1; /* time's not up yet */
2010 fdcstatus(fdc
, "stray interrupt");
2014 panic("fdcintr: impossible");
2019 * We get here if the chip locks up in FDC_WRFIFO()
2020 * Cancel any operation and schedule a reset
2022 callout_stop(&fdc
->sc_timo_ch
);
2024 fdc
->sc_state
= DORESET
;
2033 fdcretry(struct fdc_softc
*fdc
)
2035 struct fd_softc
*fd
;
2039 fd
= fdc
->sc_drives
.tqh_first
;
2040 bp
= bufq_peek(fd
->sc_q
);
2042 fdc
->sc_overruns
= 0;
2043 if (fd
->sc_opts
& FDOPT_NORETRY
)
2046 switch (fdc
->sc_errors
) {
2048 if (fdc
->sc_nstat
== 7 &&
2049 (fdc
->sc_status
[0] & 0xd8) == 0x40 &&
2050 (fdc
->sc_status
[1] & 0x2) == 0x2) {
2051 aprint_error_dev(&fdc
->sc_dev
, "read-only medium\n");
2057 (fdc
->sc_flags
& FDC_EIS
) ? DOIO
: DOSEEK
;
2060 case 1: case 2: case 3:
2061 /* didn't work; try recalibrating */
2062 fdc
->sc_state
= DORECAL
;
2066 if (fdc
->sc_nstat
== 7 &&
2067 fdc
->sc_status
[0] == 0 &&
2068 fdc
->sc_status
[1] == 0 &&
2069 fdc
->sc_status
[2] == 0) {
2071 * We've retried a few times and we've got
2072 * valid status and all three status bytes
2073 * are zero. Assume this condition is the
2074 * result of no disk loaded into the drive.
2076 aprint_error_dev(&fdc
->sc_dev
, "no medium?\n");
2081 /* still no go; reset the bastard */
2082 fdc
->sc_state
= DORESET
;
2087 if ((fd
->sc_opts
& FDOPT_SILENT
) == 0) {
2088 diskerr(bp
, "fd", "hard error", LOG_PRINTF
,
2089 fd
->sc_skip
/ FD_BSIZE(fd
),
2090 (struct disklabel
*)NULL
);
2092 fdcstatus(fdc
, "controller status");
2096 bp
->b_error
= error
;
2103 fdioctl(dev_t dev
, u_long cmd
, void *addr
, int flag
, struct lwp
*l
)
2105 struct fd_softc
*fd
;
2106 struct fdc_softc
*fdc
;
2107 struct fdformat_parms
*form_parms
;
2108 struct fdformat_cmd
*form_cmd
;
2109 struct ne7_fd_formb
*fd_formb
;
2110 int il
[FD_MAX_NSEC
+ 1];
2116 if (unit
>= fd_cd
.cd_ndevs
)
2119 fd
= device_lookup_private(&fd_cd
, FDUNIT(dev
));
2120 fdc
= device_private(device_parent(&fd
->sc_dv
));
2124 *(struct disklabel
*)addr
= *(fd
->sc_dk
.dk_label
);
2128 if ((flag
& FWRITE
) == 0)
2130 /* XXX do something */
2134 if ((flag
& FWRITE
) == 0)
2137 error
= setdisklabel(fd
->sc_dk
.dk_label
,
2138 (struct disklabel
*)addr
, 0,
2139 fd
->sc_dk
.dk_cpulabel
);
2143 error
= writedisklabel(dev
, fdstrategy
,
2145 fd
->sc_dk
.dk_cpulabel
);
2150 * Nothing to do here, really.
2155 if (*(int *)addr
== 0) {
2156 int part
= DISKPART(dev
);
2158 * Don't force eject: check that we are the only
2159 * partition open. If so, unlock it.
2161 if ((fd
->sc_dk
.dk_openmask
& ~(1 << part
)) != 0 ||
2162 fd
->sc_dk
.dk_bopenmask
+ fd
->sc_dk
.dk_copenmask
!=
2163 fd
->sc_dk
.dk_openmask
) {
2169 if (fdc
->sc_flags
& FDC_NOEJECT
)
2174 case FDIOCGETFORMAT
:
2175 form_parms
= (struct fdformat_parms
*)addr
;
2176 form_parms
->fdformat_version
= FDFORMAT_VERSION
;
2177 form_parms
->nbps
= 128 * (1 << fd
->sc_type
->secsize
);
2178 form_parms
->ncyl
= fd
->sc_type
->cylinders
;
2179 form_parms
->nspt
= fd
->sc_type
->sectrac
;
2180 form_parms
->ntrk
= fd
->sc_type
->heads
;
2181 form_parms
->stepspercyl
= fd
->sc_type
->step
;
2182 form_parms
->gaplen
= fd
->sc_type
->gap2
;
2183 form_parms
->fillbyte
= fd
->sc_type
->fillbyte
;
2184 form_parms
->interleave
= fd
->sc_type
->interleave
;
2185 switch (fd
->sc_type
->rate
) {
2187 form_parms
->xfer_rate
= 500 * 1024;
2190 form_parms
->xfer_rate
= 300 * 1024;
2193 form_parms
->xfer_rate
= 250 * 1024;
2200 case FDIOCSETFORMAT
:
2201 if ((flag
& FWRITE
) == 0)
2202 return EBADF
; /* must be opened for writing */
2204 form_parms
= (struct fdformat_parms
*)addr
;
2205 if (form_parms
->fdformat_version
!= FDFORMAT_VERSION
)
2206 return EINVAL
;/* wrong version of formatting prog */
2208 i
= form_parms
->nbps
>> 7;
2209 if ((form_parms
->nbps
& 0x7f) || ffs(i
) == 0 ||
2210 i
& ~(1 << (ffs(i
)-1)))
2211 /* not a power-of-two multiple of 128 */
2214 switch (form_parms
->xfer_rate
) {
2216 fd
->sc_type
->rate
= FDC_500KBPS
;
2219 fd
->sc_type
->rate
= FDC_300KBPS
;
2222 fd
->sc_type
->rate
= FDC_250KBPS
;
2228 if (form_parms
->nspt
> FD_MAX_NSEC
||
2229 form_parms
->fillbyte
> 0xff ||
2230 form_parms
->interleave
> 0xff)
2232 fd
->sc_type
->sectrac
= form_parms
->nspt
;
2233 if (form_parms
->ntrk
!= 2 && form_parms
->ntrk
!= 1)
2235 fd
->sc_type
->heads
= form_parms
->ntrk
;
2236 fd
->sc_type
->seccyl
= form_parms
->nspt
* form_parms
->ntrk
;
2237 fd
->sc_type
->secsize
= ffs(i
)-1;
2238 fd
->sc_type
->gap2
= form_parms
->gaplen
;
2239 fd
->sc_type
->cylinders
= form_parms
->ncyl
;
2240 fd
->sc_type
->size
= fd
->sc_type
->seccyl
* form_parms
->ncyl
*
2241 form_parms
->nbps
/ DEV_BSIZE
;
2242 fd
->sc_type
->step
= form_parms
->stepspercyl
;
2243 fd
->sc_type
->fillbyte
= form_parms
->fillbyte
;
2244 fd
->sc_type
->interleave
= form_parms
->interleave
;
2247 case FDIOCFORMAT_TRACK
:
2248 if((flag
& FWRITE
) == 0)
2249 /* must be opened for writing */
2251 form_cmd
= (struct fdformat_cmd
*)addr
;
2252 if (form_cmd
->formatcmd_version
!= FDFORMAT_VERSION
)
2253 /* wrong version of formatting prog */
2256 if (form_cmd
->head
>= fd
->sc_type
->heads
||
2257 form_cmd
->cylinder
>= fd
->sc_type
->cylinders
) {
2261 fd_formb
= malloc(sizeof(struct ne7_fd_formb
),
2266 fd_formb
->head
= form_cmd
->head
;
2267 fd_formb
->cyl
= form_cmd
->cylinder
;
2268 fd_formb
->transfer_rate
= fd
->sc_type
->rate
;
2269 fd_formb
->fd_formb_secshift
= fd
->sc_type
->secsize
;
2270 fd_formb
->fd_formb_nsecs
= fd
->sc_type
->sectrac
;
2271 fd_formb
->fd_formb_gaplen
= fd
->sc_type
->gap2
;
2272 fd_formb
->fd_formb_fillbyte
= fd
->sc_type
->fillbyte
;
2274 memset(il
, 0, sizeof il
);
2275 for (j
= 0, i
= 1; i
<= fd_formb
->fd_formb_nsecs
; i
++) {
2276 while (il
[(j
% fd_formb
->fd_formb_nsecs
) + 1])
2278 il
[(j
% fd_formb
->fd_formb_nsecs
) + 1] = i
;
2279 j
+= fd
->sc_type
->interleave
;
2281 for (i
= 0; i
< fd_formb
->fd_formb_nsecs
; i
++) {
2282 fd_formb
->fd_formb_cylno(i
) = form_cmd
->cylinder
;
2283 fd_formb
->fd_formb_headno(i
) = form_cmd
->head
;
2284 fd_formb
->fd_formb_secno(i
) = il
[i
+ 1];
2285 fd_formb
->fd_formb_secsize(i
) = fd
->sc_type
->secsize
;
2288 error
= fdformat(dev
, fd_formb
, l
->l_proc
);
2289 free(fd_formb
, M_TEMP
);
2292 case FDIOCGETOPTS
: /* get drive options */
2293 *(int *)addr
= fd
->sc_opts
;
2296 case FDIOCSETOPTS
: /* set drive options */
2297 fd
->sc_opts
= *(int *)addr
;
2302 fdc_wrfifo(fdc
, NE7CMD_DUMPREG
);
2304 printf("fdc: dumpreg(%d regs): <", fdc
->sc_nstat
);
2305 for (i
= 0; i
< fdc
->sc_nstat
; i
++)
2306 printf(" 0x%x", fdc
->sc_status
[i
]);
2310 case _IOW('f', 101, int):
2311 fdc
->sc_cfg
&= ~CFG_THRHLD_MASK
;
2312 fdc
->sc_cfg
|= (*(int *)addr
& CFG_THRHLD_MASK
);
2317 fdc_wrfifo(fdc
, NE7CMD_SENSEI
);
2319 printf("fdc: sensei(%d regs): <", fdc
->sc_nstat
);
2320 for (i
=0; i
< fdc
->sc_nstat
; i
++)
2321 printf(" 0x%x", fdc
->sc_status
[i
]);
2330 panic("fdioctl: impossible");
2335 fdformat(dev_t dev
, struct ne7_fd_formb
*finfo
, struct proc
*p
)
2338 struct fd_softc
*fd
= device_lookup_private(&fd_cd
, FDUNIT(dev
));
2339 struct fd_type
*type
= fd
->sc_type
;
2342 /* set up a buffer header for fdstrategy() */
2343 bp
= getiobuf(NULL
, false);
2348 bp
->b_cflags
= BC_BUSY
;
2349 bp
->b_flags
= B_PHYS
| B_FORMAT
;
2354 * Calculate a fake blkno, so fdstrategy() would initiate a
2355 * seek to the requested cylinder.
2357 bp
->b_blkno
= ((finfo
->cyl
* (type
->sectrac
* type
->heads
)
2358 + finfo
->head
* type
->sectrac
) * FD_BSIZE(fd
))
2361 bp
->b_bcount
= sizeof(struct fd_idfield_data
) * finfo
->fd_formb_nsecs
;
2362 bp
->b_data
= (void *)finfo
;
2368 printf("fdformat: blkno 0x%llx count %d\n",
2369 (unsigned long long)bp
->b_blkno
, bp
->b_bcount
);
2371 printf("\tcyl:\t%d\n", finfo
->cyl
);
2372 printf("\thead:\t%d\n", finfo
->head
);
2373 printf("\tnsecs:\t%d\n", finfo
->fd_formb_nsecs
);
2374 printf("\tsshft:\t%d\n", finfo
->fd_formb_secshift
);
2375 printf("\tgaplen:\t%d\n", finfo
->fd_formb_gaplen
);
2376 printf("\ttrack data:");
2377 for (i
= 0; i
< finfo
->fd_formb_nsecs
; i
++) {
2378 printf(" [c%d h%d s%d]",
2379 finfo
->fd_formb_cylno(i
),
2380 finfo
->fd_formb_headno(i
),
2381 finfo
->fd_formb_secno(i
) );
2382 if (finfo
->fd_formb_secsize(i
) != 2)
2383 printf("<sz:%d>", finfo
->fd_formb_secsize(i
));
2389 /* now do the format */
2392 /* ...and wait for it to complete */
2399 fdgetdisklabel(dev_t dev
)
2402 struct fd_softc
*fd
= device_lookup_private(&fd_cd
, FDUNIT(dev
));
2403 struct disklabel
*lp
= fd
->sc_dk
.dk_label
;
2404 struct cpu_disklabel
*clp
= fd
->sc_dk
.dk_cpulabel
;
2406 memset(lp
, 0, sizeof(struct disklabel
));
2407 memset(lp
, 0, sizeof(struct cpu_disklabel
));
2409 lp
->d_type
= DTYPE_FLOPPY
;
2410 lp
->d_secsize
= FD_BSIZE(fd
);
2411 lp
->d_secpercyl
= fd
->sc_type
->seccyl
;
2412 lp
->d_nsectors
= fd
->sc_type
->sectrac
;
2413 lp
->d_ncylinders
= fd
->sc_type
->cylinders
;
2414 lp
->d_ntracks
= fd
->sc_type
->heads
; /* Go figure... */
2415 lp
->d_secperunit
= lp
->d_secpercyl
* lp
->d_ncylinders
;
2416 lp
->d_rpm
= 300; /* XXX like it matters... */
2418 strncpy(lp
->d_typename
, "floppy disk", sizeof(lp
->d_typename
));
2419 strncpy(lp
->d_packname
, "fictitious", sizeof(lp
->d_packname
));
2420 lp
->d_interleave
= 1;
2421 lp
->d_flags
= D_REMOVABLE
;
2423 lp
->d_partitions
[RAW_PART
].p_offset
= 0;
2424 lp
->d_partitions
[RAW_PART
].p_size
= lp
->d_secpercyl
* lp
->d_ncylinders
;
2425 lp
->d_partitions
[RAW_PART
].p_fstype
= FS_UNUSED
;
2426 lp
->d_npartitions
= RAW_PART
+ 1;
2428 lp
->d_magic
= DISKMAGIC
;
2429 lp
->d_magic2
= DISKMAGIC
;
2430 lp
->d_checksum
= dkcksum(lp
);
2433 * Call the generic disklabel extraction routine. If there's
2434 * not a label there, fake it.
2436 if (readdisklabel(dev
, fdstrategy
, lp
, clp
) != NULL
) {
2437 strncpy(lp
->d_packname
, "default label",
2438 sizeof(lp
->d_packname
));
2440 * Reset the partition info; it might have gotten
2441 * trashed in readdisklabel().
2443 * XXX Why do we have to do this? readdisklabel()
2446 for (i
= 0; i
< MAXPARTITIONS
; ++i
) {
2447 lp
->d_partitions
[i
].p_offset
= 0;
2448 if (i
== RAW_PART
) {
2449 lp
->d_partitions
[i
].p_size
=
2450 lp
->d_secpercyl
* lp
->d_ncylinders
;
2451 lp
->d_partitions
[i
].p_fstype
= FS_BSDFFS
;
2453 lp
->d_partitions
[i
].p_size
= 0;
2454 lp
->d_partitions
[i
].p_fstype
= FS_UNUSED
;
2457 lp
->d_npartitions
= RAW_PART
+ 1;
2462 fd_do_eject(struct fd_softc
*fd
)
2464 struct fdc_softc
*fdc
= (void *)device_parent(&fd
->sc_dv
);
2468 auxregbisc(AUXIO4C_FDS
, AUXIO4C_FEJ
);
2470 auxregbisc(AUXIO4C_FEJ
, AUXIO4C_FDS
);
2473 if (CPU_ISSUN4M
&& (fdc
->sc_flags
& FDC_82077
) != 0) {
2475 bus_space_tag_t t
= fdc
->sc_bustag
;
2476 bus_space_handle_t h
= fdc
->sc_handle
;
2477 uint8_t dor
= FDO_FRST
| FDO_FDMAEN
| FDO_MOEN(0);
2479 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
, dor
| FDO_EJ
);
2481 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
, FDO_FRST
| FDO_DS
);
2490 fd_mountroot_hook(struct device
*dev
)
2494 fd_do_eject((struct fd_softc
*)dev
);
2495 printf("Insert filesystem floppy and press return.");
2498 if ((c
== '\r') || (c
== '\n')) {
2505 #ifdef MEMORY_DISK_HOOKS
2507 #define FDMICROROOTSIZE ((2*18*80) << DEV_BSHIFT)
2510 fd_read_md_image(size_t *sizep
, void **addrp
)
2512 struct buf buf
, *bp
= &buf
;
2517 dev
= makedev(54,0); /* XXX */
2519 addr
= malloc(FDMICROROOTSIZE
, M_DEVBUF
, M_WAITOK
);
2522 if (fdopen(dev
, 0, S_IFCHR
, NULL
))
2523 panic("fd: mountroot: fdopen");
2532 bp
->b_cflags
= BC_BUSY
;
2533 bp
->b_flags
= B_PHYS
| B_RAW
| B_READ
;
2534 bp
->b_blkno
= btodb(offset
);
2535 bp
->b_bcount
= DEV_BSIZE
;
2540 panic("fd: mountroot: fdread error %d", bp
->b_error
);
2542 if (bp
->b_resid
!= 0)
2546 offset
+= DEV_BSIZE
;
2547 if (offset
+ DEV_BSIZE
> FDMICROROOTSIZE
)
2550 (void)fdclose(dev
, 0, S_IFCHR
, NULL
);
2552 fd_do_eject(device_lookup_private(&fd_cd
, FDUNIT(dev
)));
2555 #endif /* MEMORY_DISK_HOOKS */
2558 fd_set_properties(struct fd_softc
*fd
)
2560 prop_dictionary_t disk_info
, odisk_info
, geom
;
2561 struct fd_type
*fdt
;
2564 fdt
= fd
->sc_deftype
;
2566 disk_info
= prop_dictionary_create();
2568 geom
= prop_dictionary_create();
2570 prop_dictionary_set_uint64(geom
, "sectors-per-unit",
2573 switch (fdt
->secsize
) {
2584 prop_dictionary_set_uint32(geom
, "sector-size",
2587 prop_dictionary_set_uint16(geom
, "sectors-per-track",
2590 prop_dictionary_set_uint16(geom
, "tracks-per-cylinder",
2593 prop_dictionary_set_uint64(geom
, "cylinders-per-unit",
2596 prop_dictionary_set(disk_info
, "geometry", geom
);
2597 prop_object_release(geom
);
2599 prop_dictionary_set(device_properties(&fd
->sc_dv
),
2600 "disk-info", disk_info
);
2603 * Don't release disk_info here; we keep a reference to it.
2604 * disk_detach() will release it when we go away.
2607 odisk_info
= fd
->sc_dk
.dk_info
;
2608 fd
->sc_dk
.dk_info
= disk_info
;
2610 prop_object_release(odisk_info
);