1 /* $NetBSD: fd.c,v 1.147 2009/12/19 10:34:18 tsutsui 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: fd.c,v 1.147 2009/12/19 10:34:18 tsutsui Exp $");
109 #include <sys/param.h>
110 #include <sys/systm.h>
111 #include <sys/callout.h>
112 #include <sys/kernel.h>
113 #include <sys/file.h>
114 #include <sys/ioctl.h>
115 #include <sys/device.h>
116 #include <sys/disklabel.h>
117 #include <sys/disk.h>
118 #include <sys/fdio.h>
120 #include <sys/bufq.h>
121 #include <sys/malloc.h>
122 #include <sys/proc.h>
124 #include <sys/stat.h>
125 #include <sys/syslog.h>
126 #include <sys/queue.h>
127 #include <sys/conf.h>
128 #include <sys/intr.h>
130 #include <dev/cons.h>
132 #include <uvm/uvm_extern.h>
134 #include <machine/autoconf.h>
136 #include <sparc/sparc/auxreg.h>
137 #include <sparc/dev/fdreg.h>
138 #include <sparc/dev/fdvar.h>
140 #define FDUNIT(dev) (minor(dev) / 8)
141 #define FDTYPE(dev) (minor(dev) % 8)
143 /* (mis)use device use flag to identify format operation */
144 #define B_FORMAT B_DEVPRIVATE
156 SEEKTIMEDOUT
, /* 4 */
157 SEEKCOMPLETE
, /* 5 */
161 IOCLEANUPWAIT
, /* 9 */
162 IOCLEANUPTIMEDOUT
,/*10 */
164 RESETCOMPLETE
, /* 12 */
165 RESETTIMEDOUT
, /* 13 */
168 RECALTIMEDOUT
, /* 16 */
169 RECALCOMPLETE
, /* 17 */
172 DSKCHGTIMEDOUT
, /* 20 */
175 /* software state, per controller */
177 struct device sc_dev
; /* boilerplate */
178 bus_space_tag_t sc_bustag
;
180 struct callout sc_timo_ch
; /* timeout callout */
181 struct callout sc_intr_ch
; /* pseudo-intr callout */
183 struct fd_softc
*sc_fd
[4]; /* pointers to children */
184 TAILQ_HEAD(drivehead
, fd_softc
) sc_drives
;
185 enum fdc_state sc_state
;
187 #define FDC_82077 0x01
188 #define FDC_NEEDHEADSETTLE 0x02
190 #define FDC_NEEDMOTORWAIT 0x08
191 int sc_errors
; /* number of retries so far */
192 int sc_overruns
; /* number of DMA overruns */
193 int sc_cfg
; /* current configuration */
195 #define sc_handle sc_io.fdcio_handle
196 #define sc_reg_msr sc_io.fdcio_reg_msr
197 #define sc_reg_fifo sc_io.fdcio_reg_fifo
198 #define sc_reg_dor sc_io.fdcio_reg_dor
199 #define sc_reg_dir sc_io.fdcio_reg_dir
200 #define sc_reg_drs sc_io.fdcio_reg_msr
201 #define sc_itask sc_io.fdcio_itask
202 #define sc_istatus sc_io.fdcio_istatus
203 #define sc_data sc_io.fdcio_data
204 #define sc_tc sc_io.fdcio_tc
205 #define sc_nstat sc_io.fdcio_nstat
206 #define sc_status sc_io.fdcio_status
207 #define sc_intrcnt sc_io.fdcio_intrcnt
209 void *sc_sicookie
; /* softintr(9) cookie */
212 extern struct fdcio
*fdciop
; /* I/O descriptor used in fdintr.s */
214 /* controller driver configuration */
215 int fdcmatch_mainbus(struct device
*, struct cfdata
*, void *);
216 int fdcmatch_obio(struct device
*, struct cfdata
*, void *);
217 void fdcattach_mainbus(struct device
*, struct device
*, void *);
218 void fdcattach_obio(struct device
*, struct device
*, void *);
220 int fdcattach(struct fdc_softc
*, int);
222 CFATTACH_DECL(fdc_mainbus
, sizeof(struct fdc_softc
),
223 fdcmatch_mainbus
, fdcattach_mainbus
, NULL
, NULL
);
225 CFATTACH_DECL(fdc_obio
, sizeof(struct fdc_softc
),
226 fdcmatch_obio
, fdcattach_obio
, NULL
, NULL
);
228 inline struct fd_type
*fd_dev_to_type(struct fd_softc
*, dev_t
);
231 * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
232 * we tell them apart.
235 int sectrac
; /* sectors per track */
236 int heads
; /* number of heads */
237 int seccyl
; /* sectors per cylinder */
238 int secsize
; /* size code for sectors */
239 int datalen
; /* data len when secsize = 0 */
240 int steprate
; /* step rate and head unload time */
241 int gap1
; /* gap len between sectors */
242 int gap2
; /* formatting gap */
243 int cylinders
; /* total num of cylinders */
244 int size
; /* size of disk in sectors */
245 int step
; /* steps per cylinder */
246 int rate
; /* transfer speed code */
247 int fillbyte
; /* format fill byte */
248 int interleave
; /* interleave factor (formatting) */
252 /* The order of entries in the following table is important -- BEWARE! */
253 struct fd_type fd_types
[] = {
254 { 18,2,36,2,0xff,0xcf,0x1b,0x54,80,2880,1,FDC_500KBPS
,0xf6,1, "1.44MB" }, /* 1.44MB diskette */
255 { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS
,0xf6,1, "720KB" }, /* 3.5" 720kB diskette */
256 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS
,0xf6,1, "360KB/x" }, /* 360kB in 720kB drive */
257 { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS
,0xf6,1, "1.2MB/NEC" } /* 1.2 MB japanese format */
260 /* software state, per disk (with up to 4 disks per ctlr) */
262 struct device sc_dv
; /* generic device info */
263 struct disk sc_dk
; /* generic disk info */
265 struct fd_type
*sc_deftype
; /* default type descriptor */
266 struct fd_type
*sc_type
; /* current type descriptor */
268 struct callout sc_motoron_ch
;
269 struct callout sc_motoroff_ch
;
271 daddr_t sc_blkno
; /* starting block number */
272 int sc_bcount
; /* byte count left */
273 int sc_skip
; /* bytes already transferred */
274 int sc_nblks
; /* number of blocks currently transferring */
275 int sc_nbytes
; /* number of bytes currently transferring */
277 int sc_drive
; /* physical unit number */
279 #define FD_OPEN 0x01 /* it's open */
280 #define FD_MOTOR 0x02 /* motor should be on */
281 #define FD_MOTOR_WAIT 0x04 /* motor coming up */
282 int sc_cylin
; /* where we think the head is */
283 int sc_opts
; /* user-set options */
285 TAILQ_ENTRY(fd_softc
) sc_drivechain
;
286 int sc_ops
; /* I/O ops since last switch */
287 struct bufq_state
*sc_q
;/* pending I/O requests */
288 int sc_active
; /* number of active I/O requests */
291 /* floppy driver configuration */
292 int fdmatch(struct device
*, struct cfdata
*, void *);
293 void fdattach(struct device
*, struct device
*, void *);
294 bool fdshutdown(device_t
, int);
295 bool fdsuspend(device_t
, pmf_qual_t
);
297 CFATTACH_DECL(fd
, sizeof(struct fd_softc
),
298 fdmatch
, fdattach
, NULL
, NULL
);
300 extern struct cfdriver fd_cd
;
302 dev_type_open(fdopen
);
303 dev_type_close(fdclose
);
304 dev_type_read(fdread
);
305 dev_type_write(fdwrite
);
306 dev_type_ioctl(fdioctl
);
307 dev_type_strategy(fdstrategy
);
309 const struct bdevsw fd_bdevsw
= {
310 fdopen
, fdclose
, fdstrategy
, fdioctl
, nodump
, nosize
, D_DISK
313 const struct cdevsw fd_cdevsw
= {
314 fdopen
, fdclose
, fdread
, fdwrite
, fdioctl
,
315 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_DISK
318 void fdgetdisklabel(dev_t
);
319 int fd_get_parms(struct fd_softc
*);
320 void fdstart(struct fd_softc
*);
321 int fdprint(void *, const char *);
323 struct dkdriver fddkdriver
= { fdstrategy
};
325 struct fd_type
*fd_nvtotype(char *, int, int);
326 void fd_set_motor(struct fdc_softc
*);
327 void fd_motor_off(void *);
328 void fd_motor_on(void *);
329 int fdcresult(struct fdc_softc
*);
330 int fdc_wrfifo(struct fdc_softc
*, uint8_t);
331 void fdcstart(struct fdc_softc
*);
332 void fdcstatus(struct fdc_softc
*, const char *);
333 void fdc_reset(struct fdc_softc
*);
334 int fdc_diskchange(struct fdc_softc
*);
335 void fdctimeout(void *);
336 void fdcpseudointr(void *);
337 int fdc_c_hwintr(void *);
338 void fdchwintr(void);
339 void fdcswintr(void *);
340 int fdcstate(struct fdc_softc
*);
341 void fdcretry(struct fdc_softc
*);
342 void fdfinish(struct fd_softc
*, struct buf
*);
343 int fdformat(dev_t
, struct ne7_fd_formb
*, struct proc
*);
344 void fd_do_eject(struct fd_softc
*);
345 void fd_mountroot_hook(struct device
*);
346 static int fdconf(struct fdc_softc
*);
347 static void establish_chip_type(
354 #ifdef MEMORY_DISK_HOOKS
355 int fd_read_md_image(size_t *, void **);
358 #define OBP_FDNAME (CPU_ISSUN4M ? "SUNW,fdtwo" : "fd")
361 fdcmatch_mainbus(struct device
*parent
, struct cfdata
*match
, void *aux
)
363 struct mainbus_attach_args
*ma
= aux
;
366 * Floppy controller is on mainbus on sun4c.
371 /* sun4c PROMs call the controller "fd" */
372 if (strcmp("fd", ma
->ma_name
) != 0)
375 return (bus_space_probe(ma
->ma_bustag
,
384 fdcmatch_obio(struct device
*parent
, struct cfdata
*match
, void *aux
)
386 union obio_attach_args
*uoba
= aux
;
387 struct sbus_attach_args
*sa
;
390 * Floppy controller is on obio on sun4m.
392 if (uoba
->uoba_isobio4
!= 0)
395 sa
= &uoba
->uoba_sbus
;
397 /* sun4m PROMs call the controller "SUNW,fdtwo" */
398 if (strcmp("SUNW,fdtwo", sa
->sa_name
) != 0)
401 return (bus_space_probe(sa
->sa_bustag
,
402 sbus_bus_addr(sa
->sa_bustag
,
403 sa
->sa_slot
, sa
->sa_offset
),
411 establish_chip_type(struct fdc_softc
*fdc
,
412 bus_space_tag_t tag
, bus_addr_t addr
, bus_size_t size
,
413 bus_space_handle_t handle
)
418 * This hack from Chris Torek: apparently DOR really
419 * addresses MSR/DRS on a 82072.
420 * We used to rely on the VERSION command to tell the
421 * difference (which did not work).
424 /* First, check the size of the register bank */
426 /* It isn't a 82077 */
429 /* Then probe the DOR register offset */
430 if (bus_space_probe(tag
, addr
,
432 FDREG77_DOR
, /* offset */
436 /* It isn't a 82077 */
440 v
= bus_space_read_1(tag
, handle
, FDREG77_DOR
);
443 * Value in DOR looks like it's really MSR
445 bus_space_write_1(tag
, handle
, FDREG77_DOR
, FDC_250KBPS
);
446 v
= bus_space_read_1(tag
, handle
, FDREG77_DOR
);
449 * The value in the DOR didn't stick;
456 fdc
->sc_flags
|= FDC_82077
;
460 * Arguments passed between fdcattach and fdprobe.
462 struct fdc_attach_args
{
464 struct fd_type
*fa_deftype
;
468 * Print the location of a disk drive (called just before attaching the
469 * the drive). If `fdc' is not NULL, the drive was found but was not
470 * in the system config file; print the drive name as well.
471 * Return QUIET (config_find ignores this if the device was configured) to
472 * avoid printing `fdN not configured' messages.
475 fdprint(void *aux
, const char *fdc
)
477 register struct fdc_attach_args
*fa
= aux
;
480 aprint_normal(" drive %d", fa
->fa_drive
);
485 * Configure several parameters and features on the FDC.
486 * Return 0 on success.
489 fdconf(struct fdc_softc
*fdc
)
493 if (fdc_wrfifo(fdc
, NE7CMD_DUMPREG
) || fdcresult(fdc
) != 10)
497 * dumpreg[7] seems to be a motor-off timeout; set it to whatever
498 * the PROM thinks is appropriate.
500 if ((vroom
= fdc
->sc_status
[7]) == 0)
503 /* Configure controller to use FIFO and Implied Seek */
504 if (fdc_wrfifo(fdc
, NE7CMD_CFG
) != 0)
506 if (fdc_wrfifo(fdc
, vroom
) != 0)
508 if (fdc_wrfifo(fdc
, fdc
->sc_cfg
) != 0)
510 if (fdc_wrfifo(fdc
, 0) != 0) /* PRETRK */
512 /* No result phase for the NE7CMD_CFG command */
514 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
515 /* Lock configuration across soft resets. */
516 if (fdc_wrfifo(fdc
, NE7CMD_LOCK
| CFG_LOCK
) != 0 ||
517 fdcresult(fdc
) != 1) {
519 printf("fdconf: CFGLOCK failed");
527 if (fdc_wrfifo(fdc
, NE7CMD_VERSION
) == 0 &&
528 fdcresult(fdc
) == 1 && fdc
->sc_status
[0] == 0x90) {
530 printf("[version cmd]");
536 fdcattach_mainbus(struct device
*parent
, struct device
*self
, void *aux
)
538 struct fdc_softc
*fdc
= device_private(self
);
539 struct mainbus_attach_args
*ma
= aux
;
541 fdc
->sc_bustag
= ma
->ma_bustag
;
547 BUS_SPACE_MAP_LINEAR
,
548 &fdc
->sc_handle
) != 0) {
549 printf("%s: cannot map registers\n", self
->dv_xname
);
553 establish_chip_type(fdc
,
559 if (fdcattach(fdc
, ma
->ma_pri
) != 0)
560 bus_space_unmap(ma
->ma_bustag
, fdc
->sc_handle
, ma
->ma_size
);
564 fdcattach_obio(struct device
*parent
, struct device
*self
, void *aux
)
566 struct fdc_softc
*fdc
= device_private(self
);
567 union obio_attach_args
*uoba
= aux
;
568 struct sbus_attach_args
*sa
= &uoba
->uoba_sbus
;
570 if (sa
->sa_nintr
== 0) {
571 printf(": no interrupt line configured\n");
575 fdc
->sc_bustag
= sa
->sa_bustag
;
577 if (sbus_bus_map(sa
->sa_bustag
,
578 sa
->sa_slot
, sa
->sa_offset
, sa
->sa_size
,
579 BUS_SPACE_MAP_LINEAR
, &fdc
->sc_handle
) != 0) {
580 printf("%s: cannot map control registers\n",
585 establish_chip_type(fdc
,
587 sbus_bus_addr(sa
->sa_bustag
, sa
->sa_slot
, sa
->sa_offset
),
591 if (strcmp(prom_getpropstring(sa
->sa_node
, "status"), "disabled") == 0) {
592 printf(": no drives attached\n");
596 if (fdcattach(fdc
, sa
->sa_pri
) != 0)
597 bus_space_unmap(sa
->sa_bustag
, fdc
->sc_handle
, sa
->sa_size
);
601 fdcattach(struct fdc_softc
*fdc
, int pri
)
603 struct fdc_attach_args fa
;
607 callout_init(&fdc
->sc_timo_ch
, 0);
608 callout_init(&fdc
->sc_intr_ch
, 0);
610 fdc
->sc_state
= DEVIDLE
;
611 fdc
->sc_itask
= FDC_ITASK_NONE
;
612 fdc
->sc_istatus
= FDC_ISTATUS_NONE
;
613 fdc
->sc_flags
|= FDC_EIS
;
614 TAILQ_INIT(&fdc
->sc_drives
);
616 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
617 fdc
->sc_reg_msr
= FDREG77_MSR
;
618 fdc
->sc_reg_fifo
= FDREG77_FIFO
;
619 fdc
->sc_reg_dor
= FDREG77_DOR
;
620 fdc
->sc_reg_dir
= FDREG77_DIR
;
622 fdc
->sc_flags
|= FDC_NEEDMOTORWAIT
;
624 fdc
->sc_reg_msr
= FDREG72_MSR
;
625 fdc
->sc_reg_fifo
= FDREG72_FIFO
;
631 * Configure controller; enable FIFO, Implied seek, no POLL mode?.
632 * Note: CFG_EFIFO is active-low, initial threshold value: 8
634 fdc
->sc_cfg
= CFG_EIS
|/*CFG_EFIFO|*/CFG_POLL
|(8 & CFG_THRHLD_MASK
);
635 if (fdconf(fdc
) != 0) {
636 printf(": no drives attached\n");
640 fdciop
= &fdc
->sc_io
;
641 if (bus_intr_establish2(fdc
->sc_bustag
, pri
, 0,
643 #ifdef notyet /* XXX bsd_fdintr.s needs to be fixed for MI softint(9) */
649 printf("\n%s: cannot register interrupt handler\n",
650 fdc
->sc_dev
.dv_xname
);
654 fdc
->sc_sicookie
= softint_establish(SOFTINT_BIO
, fdcswintr
, fdc
);
655 if (fdc
->sc_sicookie
== NULL
) {
656 printf("\n%s: cannot register soft interrupt handler\n",
657 fdc
->sc_dev
.dv_xname
);
660 printf(" softpri %d: chip 8207%c\n", IPL_SOFTFDC
, code
);
662 evcnt_attach_dynamic(&fdc
->sc_intrcnt
, EVCNT_TYPE_INTR
, NULL
,
663 fdc
->sc_dev
.dv_xname
, "intr");
665 /* physical limit: four drives per controller. */
667 for (fa
.fa_drive
= 0; fa
.fa_drive
< 4; fa
.fa_drive
++) {
668 fa
.fa_deftype
= NULL
; /* unknown */
669 fa
.fa_deftype
= &fd_types
[0]; /* XXX */
670 if (config_found(&fdc
->sc_dev
, (void *)&fa
, fdprint
) != NULL
)
674 if (drive_attached
== 0) {
675 /* XXX - dis-establish interrupts here */
683 fdmatch(struct device
*parent
, struct cfdata
*match
, void *aux
)
685 struct fdc_softc
*fdc
= device_private(parent
);
686 bus_space_tag_t t
= fdc
->sc_bustag
;
687 bus_space_handle_t h
= fdc
->sc_handle
;
688 struct fdc_attach_args
*fa
= aux
;
689 int drive
= fa
->fa_drive
;
693 /* XXX - for now, punt on more than one drive */
696 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
697 /* select drive and turn on motor */
698 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
,
699 drive
| FDO_FRST
| FDO_MOEN(drive
));
700 /* wait for motor to spin up */
703 auxregbisc(AUXIO4C_FDS
, 0);
706 fdc_wrfifo(fdc
, NE7CMD_RECAL
);
707 fdc_wrfifo(fdc
, drive
);
709 /* Wait for recalibration to complete */
710 for (n
= 0; n
< 10000; n
++) {
714 v
= bus_space_read_1(t
, h
, fdc
->sc_reg_msr
);
715 if ((v
& (NE7_RQM
|NE7_DIO
|NE7_CB
)) == NE7_RQM
) {
716 /* wait a bit longer till device *really* is ready */
718 if (fdc_wrfifo(fdc
, NE7CMD_SENSEI
))
720 if (fdcresult(fdc
) == 1 && fdc
->sc_status
[0] == 0x80)
722 * Got `invalid command'; we interpret it
723 * to mean that the re-calibrate hasn't in
734 printf("fdprobe: %d stati:", n
);
735 for (i
= 0; i
< n
; i
++)
736 printf(" 0x%x", fdc
->sc_status
[i
]);
740 ok
= (n
== 2 && (fdc
->sc_status
[0] & 0xf8) == 0x20) ? 1 : 0;
743 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
744 /* deselect drive and turn motor off */
745 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
, FDO_FRST
| FDO_DS
);
747 auxregbisc(0, AUXIO4C_FDS
);
754 * Controller is working, and drive responded. Attach it.
757 fdattach(struct device
*parent
, struct device
*self
, void *aux
)
759 struct fdc_softc
*fdc
= device_private(parent
);
760 struct fd_softc
*fd
= device_private(self
);
761 struct fdc_attach_args
*fa
= aux
;
762 struct fd_type
*type
= fa
->fa_deftype
;
763 int drive
= fa
->fa_drive
;
765 callout_init(&fd
->sc_motoron_ch
, 0);
766 callout_init(&fd
->sc_motoroff_ch
, 0);
768 /* XXX Allow `flags' to override device type? */
771 printf(": %s %d cyl, %d head, %d sec\n", type
->name
,
772 type
->cylinders
, type
->heads
, type
->sectrac
);
774 printf(": density unknown\n");
776 bufq_alloc(&fd
->sc_q
, "disksort", BUFQ_SORT_CYLINDER
);
778 fd
->sc_drive
= drive
;
779 fd
->sc_deftype
= type
;
780 fdc
->sc_fd
[drive
] = fd
;
782 fdc_wrfifo(fdc
, NE7CMD_SPECIFY
);
783 fdc_wrfifo(fdc
, type
->steprate
);
784 /* XXX head load time == 6ms */
785 fdc_wrfifo(fdc
, 6 | NE7_SPECIFY_NODMA
);
788 * Initialize and attach the disk structure.
790 disk_init(&fd
->sc_dk
, fd
->sc_dv
.dv_xname
, &fddkdriver
);
791 disk_attach(&fd
->sc_dk
);
794 * Establish a mountroot_hook anyway in case we booted
795 * with RB_ASKNAME and get selected as the boot device.
797 mountroothook_establish(fd_mountroot_hook
, &fd
->sc_dv
);
799 /* Make sure the drive motor gets turned off at shutdown time. */
800 if (!pmf_device_register1(self
, fdsuspend
, NULL
, fdshutdown
))
801 aprint_error_dev(self
, "couldn't establish power handler\n");
804 bool fdshutdown(device_t self
, int how
)
806 struct fd_softc
*fd
= device_private(self
);
812 bool fdsuspend(device_t self
, pmf_qual_t qual
)
815 return fdshutdown(self
, boothowto
);
819 inline struct fd_type
*
820 fd_dev_to_type(struct fd_softc
*fd
, dev_t dev
)
822 int type
= FDTYPE(dev
);
824 if (type
> (sizeof(fd_types
) / sizeof(fd_types
[0])))
826 return (type
? &fd_types
[type
- 1] : fd
->sc_deftype
);
830 fdstrategy(struct buf
*bp
)
833 int unit
= FDUNIT(bp
->b_dev
);
837 /* Valid unit, controller, and request? */
838 if ((fd
= device_lookup_private(&fd_cd
, unit
)) == 0 ||
840 (((bp
->b_bcount
% FD_BSIZE(fd
)) != 0 ||
841 (bp
->b_blkno
* DEV_BSIZE
) % FD_BSIZE(fd
) != 0) &&
842 (bp
->b_flags
& B_FORMAT
) == 0)) {
843 bp
->b_error
= EINVAL
;
847 /* If it's a null transfer, return immediately. */
848 if (bp
->b_bcount
== 0)
851 sz
= howmany(bp
->b_bcount
, DEV_BSIZE
);
853 if (bp
->b_blkno
+ sz
> (fd
->sc_type
->size
* DEV_BSIZE
) / FD_BSIZE(fd
)) {
854 sz
= (fd
->sc_type
->size
* DEV_BSIZE
) / FD_BSIZE(fd
)
857 /* If exactly at end of disk, return EOF. */
858 bp
->b_resid
= bp
->b_bcount
;
862 /* If past end of disk, return EINVAL. */
863 bp
->b_error
= EINVAL
;
866 /* Otherwise, truncate request. */
867 bp
->b_bcount
= sz
<< DEV_BSHIFT
;
870 bp
->b_rawblkno
= bp
->b_blkno
;
871 bp
->b_cylinder
= (bp
->b_blkno
* DEV_BSIZE
) /
872 (FD_BSIZE(fd
) * fd
->sc_type
->seccyl
);
876 printf("fdstrategy: b_blkno %lld b_bcount %d blkno %lld cylin %d\n",
877 (long long)bp
->b_blkno
, bp
->b_bcount
,
878 (long long)fd
->sc_blkno
, bp
->b_cylinder
);
881 /* Queue transfer on drive, activate drive and controller if idle. */
883 bufq_put(fd
->sc_q
, bp
);
884 callout_stop(&fd
->sc_motoroff_ch
); /* a good idea */
885 if (fd
->sc_active
== 0)
889 struct fdc_softc
*fdc
= (void *)device_parent(&fd
->sc_dv
);
890 if (fdc
->sc_state
== DEVIDLE
) {
891 printf("fdstrategy: controller inactive\n");
900 /* Toss transfer; we're done early. */
905 fdstart(struct fd_softc
*fd
)
907 struct fdc_softc
*fdc
= device_private(device_parent(&fd
->sc_dv
));
908 int active
= fdc
->sc_drives
.tqh_first
!= 0;
910 /* Link into controller queue. */
912 TAILQ_INSERT_TAIL(&fdc
->sc_drives
, fd
, sc_drivechain
);
914 /* If controller not already active, start it. */
920 fdfinish(struct fd_softc
*fd
, struct buf
*bp
)
922 struct fdc_softc
*fdc
= device_private(device_parent(&fd
->sc_dv
));
925 * Move this drive to the end of the queue to give others a `fair'
926 * chance. We only force a switch if N operations are completed while
927 * another drive is waiting to be serviced, since there is a long motor
928 * startup delay whenever we switch.
930 (void)bufq_get(fd
->sc_q
);
931 if (fd
->sc_drivechain
.tqe_next
&& ++fd
->sc_ops
>= 8) {
933 TAILQ_REMOVE(&fdc
->sc_drives
, fd
, sc_drivechain
);
934 if (bufq_peek(fd
->sc_q
) != NULL
) {
935 TAILQ_INSERT_TAIL(&fdc
->sc_drives
, fd
, sc_drivechain
);
939 bp
->b_resid
= fd
->sc_bcount
;
943 /* turn off motor 5s from now */
944 callout_reset(&fd
->sc_motoroff_ch
, 5 * hz
, fd_motor_off
, fd
);
945 fdc
->sc_state
= DEVIDLE
;
949 fdc_reset(struct fdc_softc
*fdc
)
951 bus_space_tag_t t
= fdc
->sc_bustag
;
952 bus_space_handle_t h
= fdc
->sc_handle
;
954 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
955 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
,
956 FDO_FDMAEN
| FDO_MOEN(0));
959 bus_space_write_1(t
, h
, fdc
->sc_reg_drs
, DRS_RESET
);
961 bus_space_write_1(t
, h
, fdc
->sc_reg_drs
, 0);
963 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
964 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
,
965 FDO_FRST
| FDO_FDMAEN
| FDO_DS
);
969 printf("fdc reset\n");
974 fd_set_motor(struct fdc_softc
*fdc
)
980 if ((fdc
->sc_flags
& FDC_82077
) != 0) {
981 status
= FDO_FRST
| FDO_FDMAEN
;
982 if ((fd
= fdc
->sc_drives
.tqh_first
) != NULL
)
983 status
|= fd
->sc_drive
;
985 for (n
= 0; n
< 4; n
++)
986 if ((fd
= fdc
->sc_fd
[n
]) && (fd
->sc_flags
& FD_MOTOR
))
987 status
|= FDO_MOEN(n
);
988 bus_space_write_1(fdc
->sc_bustag
, fdc
->sc_handle
,
989 fdc
->sc_reg_dor
, status
);
992 for (n
= 0; n
< 4; n
++) {
993 if ((fd
= fdc
->sc_fd
[n
]) != NULL
&&
994 (fd
->sc_flags
& FD_MOTOR
) != 0) {
995 auxregbisc(AUXIO4C_FDS
, 0);
999 auxregbisc(0, AUXIO4C_FDS
);
1004 fd_motor_off(void *arg
)
1006 struct fd_softc
*fd
= arg
;
1010 fd
->sc_flags
&= ~(FD_MOTOR
| FD_MOTOR_WAIT
);
1011 fd_set_motor((struct fdc_softc
*)device_parent(&fd
->sc_dv
));
1016 fd_motor_on(void *arg
)
1018 struct fd_softc
*fd
= arg
;
1019 struct fdc_softc
*fdc
= device_private(device_parent(&fd
->sc_dv
));
1023 fd
->sc_flags
&= ~FD_MOTOR_WAIT
;
1024 if ((fdc
->sc_drives
.tqh_first
== fd
) && (fdc
->sc_state
== MOTORWAIT
))
1025 (void) fdcstate(fdc
);
1030 * Get status bytes off the FDC after a command has finished
1031 * Returns the number of status bytes read; -1 on error.
1032 * The return value is also stored in `sc_nstat'.
1035 fdcresult(struct fdc_softc
*fdc
)
1037 bus_space_tag_t t
= fdc
->sc_bustag
;
1038 bus_space_handle_t h
= fdc
->sc_handle
;
1041 for (j
= 10000; j
; j
--) {
1042 uint8_t v
= bus_space_read_1(t
, h
, fdc
->sc_reg_msr
);
1043 v
&= (NE7_DIO
| NE7_RQM
| NE7_CB
);
1045 return (fdc
->sc_nstat
= n
);
1046 if (v
== (NE7_DIO
| NE7_RQM
| NE7_CB
)) {
1047 if (n
>= sizeof(fdc
->sc_status
)) {
1048 log(LOG_ERR
, "fdcresult: overrun\n");
1051 fdc
->sc_status
[n
++] =
1052 bus_space_read_1(t
, h
, fdc
->sc_reg_fifo
);
1057 log(LOG_ERR
, "fdcresult: timeout\n");
1058 return (fdc
->sc_nstat
= -1);
1062 * Write a command byte to the FDC.
1063 * Returns 0 on success; -1 on failure (i.e. timeout)
1066 fdc_wrfifo(struct fdc_softc
*fdc
, uint8_t x
)
1068 bus_space_tag_t t
= fdc
->sc_bustag
;
1069 bus_space_handle_t h
= fdc
->sc_handle
;
1072 for (i
= 100000; i
-- > 0;) {
1073 uint8_t v
= bus_space_read_1(t
, h
, fdc
->sc_reg_msr
);
1074 if ((v
& (NE7_DIO
|NE7_RQM
)) == NE7_RQM
) {
1075 /* The chip is ready */
1076 bus_space_write_1(t
, h
, fdc
->sc_reg_fifo
, x
);
1085 fdc_diskchange(struct fdc_softc
*fdc
)
1088 if (CPU_ISSUN4M
&& (fdc
->sc_flags
& FDC_82077
) != 0) {
1089 bus_space_tag_t t
= fdc
->sc_bustag
;
1090 bus_space_handle_t h
= fdc
->sc_handle
;
1091 uint8_t v
= bus_space_read_1(t
, h
, fdc
->sc_reg_dir
);
1092 return ((v
& FDI_DCHG
) != 0);
1093 } else if (CPU_ISSUN4C
) {
1094 return ((*AUXIO4C_REG
& AUXIO4C_FDC
) != 0);
1100 fdopen(dev_t dev
, int flags
, int fmt
, struct lwp
*l
)
1103 struct fd_softc
*fd
;
1104 struct fd_type
*type
;
1107 fd
= device_lookup_private(&fd_cd
, unit
);
1110 type
= fd_dev_to_type(fd
, dev
);
1114 if ((fd
->sc_flags
& FD_OPEN
) != 0 &&
1115 fd
->sc_type
!= type
)
1120 fd
->sc_flags
|= FD_OPEN
;
1123 * Only update the disklabel if we're not open anywhere else.
1125 if (fd
->sc_dk
.dk_openmask
== 0)
1126 fdgetdisklabel(dev
);
1128 pmask
= (1 << DISKPART(dev
));
1132 fd
->sc_dk
.dk_copenmask
|= pmask
;
1136 fd
->sc_dk
.dk_bopenmask
|= pmask
;
1139 fd
->sc_dk
.dk_openmask
=
1140 fd
->sc_dk
.dk_copenmask
| fd
->sc_dk
.dk_bopenmask
;
1146 fdclose(dev_t dev
, int flags
, int fmt
, struct lwp
*l
)
1148 struct fd_softc
*fd
= device_lookup_private(&fd_cd
, FDUNIT(dev
));
1149 int pmask
= (1 << DISKPART(dev
));
1151 fd
->sc_flags
&= ~FD_OPEN
;
1152 fd
->sc_opts
&= ~(FDOPT_NORETRY
|FDOPT_SILENT
);
1156 fd
->sc_dk
.dk_copenmask
&= ~pmask
;
1160 fd
->sc_dk
.dk_bopenmask
&= ~pmask
;
1163 fd
->sc_dk
.dk_openmask
=
1164 fd
->sc_dk
.dk_copenmask
| fd
->sc_dk
.dk_bopenmask
;
1170 fdread(dev_t dev
, struct uio
*uio
, int flag
)
1173 return (physio(fdstrategy
, NULL
, dev
, B_READ
, minphys
, uio
));
1177 fdwrite(dev_t dev
, struct uio
*uio
, int flag
)
1180 return (physio(fdstrategy
, NULL
, dev
, B_WRITE
, minphys
, uio
));
1184 fdcstart(struct fdc_softc
*fdc
)
1188 /* only got here if controller's drive queue was inactive; should
1190 if (fdc
->sc_state
!= DEVIDLE
) {
1191 printf("fdcstart: not idle\n");
1195 (void) fdcstate(fdc
);
1199 fdcpstatus(int n
, struct fdc_softc
*fdc
)
1208 snprintb(bits
, sizeof(bits
), NE7_ST0BITS
, fdc
->sc_status
[0]);
1209 printf(" (st0 %s cyl %d)\n", bits
, fdc
->sc_status
[1]);
1212 snprintb(bits
, sizeof(bits
), NE7_ST0BITS
, fdc
->sc_status
[0]);
1213 printf(" (st0 %s", bits
);
1214 snprintb(bits
, sizeof(bits
), NE7_ST1BITS
, fdc
->sc_status
[1]);
1215 printf(" st1 %s", bits
);
1216 snprintb(bits
, sizeof(bits
), NE7_ST2BITS
, fdc
->sc_status
[2]);
1217 printf(" st2 %s", bits
);
1218 printf(" cyl %d head %d sec %d)\n",
1219 fdc
->sc_status
[3], fdc
->sc_status
[4], fdc
->sc_status
[5]);
1223 printf("\nfdcstatus: weird size");
1230 fdcstatus(struct fdc_softc
*fdc
, const char *s
)
1232 struct fd_softc
*fd
= fdc
->sc_drives
.tqh_first
;
1235 /* Just print last status */
1240 * A 82072 seems to return <invalid command> on
1241 * gratuitous Sense Interrupt commands.
1243 if (n
== 0 && (fdc
->sc_flags
& FDC_82077
) != 0) {
1244 fdc_wrfifo(fdc
, NE7CMD_SENSEI
);
1245 (void) fdcresult(fdc
);
1250 printf("%s: %s: state %d",
1251 fd
? fd
->sc_dv
.dv_xname
: "fdc", s
, fdc
->sc_state
);
1257 fdctimeout(void *arg
)
1259 struct fdc_softc
*fdc
= arg
;
1260 struct fd_softc
*fd
;
1264 fd
= fdc
->sc_drives
.tqh_first
;
1266 printf("%s: timeout but no I/O pending: state %d, istatus=%d\n",
1267 fdc
->sc_dev
.dv_xname
,
1268 fdc
->sc_state
, fdc
->sc_istatus
);
1269 fdc
->sc_state
= DEVIDLE
;
1273 if (bufq_peek(fd
->sc_q
) != NULL
)
1276 fdc
->sc_state
= DEVIDLE
;
1278 (void) fdcstate(fdc
);
1285 fdcpseudointr(void *arg
)
1287 struct fdc_softc
*fdc
= arg
;
1290 /* Just ensure it has the right spl. */
1292 (void) fdcstate(fdc
);
1298 * hardware interrupt entry point: used only if no `fast trap' * (in-window)
1299 * handler is available. Unfortunately, we have no reliable way to
1300 * determine that the interrupt really came from the floppy controller;
1301 * just hope that the other devices that share this interrupt level
1305 fdc_c_hwintr(void *arg
)
1307 struct fdc_softc
*fdc
= arg
;
1308 bus_space_tag_t t
= fdc
->sc_bustag
;
1309 bus_space_handle_t h
= fdc
->sc_handle
;
1311 switch (fdc
->sc_itask
) {
1312 case FDC_ITASK_NONE
:
1314 case FDC_ITASK_SENSEI
:
1315 if (fdc_wrfifo(fdc
, NE7CMD_SENSEI
) != 0 || fdcresult(fdc
) == -1)
1316 fdc
->sc_istatus
= FDC_ISTATUS_ERROR
;
1318 fdc
->sc_istatus
= FDC_ISTATUS_DONE
;
1319 softint_schedule(fdc
->sc_sicookie
);
1321 case FDC_ITASK_RESULT
:
1322 if (fdcresult(fdc
) == -1)
1323 fdc
->sc_istatus
= FDC_ISTATUS_ERROR
;
1325 fdc
->sc_istatus
= FDC_ISTATUS_DONE
;
1326 softint_schedule(fdc
->sc_sicookie
);
1329 /* Proceed with pseudo-DMA below */
1332 printf("fdc: stray hard interrupt: itask=%d\n", fdc
->sc_itask
);
1333 fdc
->sc_istatus
= FDC_ISTATUS_SPURIOUS
;
1334 softint_schedule(fdc
->sc_sicookie
);
1339 * Pseudo DMA in progress
1344 msr
= bus_space_read_1(t
, h
, fdc
->sc_reg_msr
);
1346 if ((msr
& NE7_RQM
) == 0)
1347 /* That's all this round */
1350 if ((msr
& NE7_NDM
) == 0) {
1351 /* Execution phase finished, get result. */
1353 fdc
->sc_istatus
= FDC_ISTATUS_DONE
;
1354 softint_schedule(fdc
->sc_sicookie
);
1358 if (fdc
->sc_tc
== 0)
1359 /* For some reason the controller wants to transfer
1360 more data then what we want to transfer. */
1361 panic("fdc: overrun");
1363 /* Another byte can be transferred */
1364 if ((msr
& NE7_DIO
) != 0)
1366 bus_space_read_1(t
, h
, fdc
->sc_reg_fifo
);
1368 bus_space_write_1(t
, h
, fdc
->sc_reg_fifo
,
1372 if (--fdc
->sc_tc
== 0) {
1381 fdcswintr(void *arg
)
1383 struct fdc_softc
*fdc
= arg
;
1385 if (fdc
->sc_istatus
== FDC_ISTATUS_NONE
)
1386 /* This (software) interrupt is not for us */
1389 switch (fdc
->sc_istatus
) {
1390 case FDC_ISTATUS_ERROR
:
1391 printf("fdc: ierror status: state %d\n", fdc
->sc_state
);
1393 case FDC_ISTATUS_SPURIOUS
:
1394 printf("fdc: spurious interrupt: state %d\n", fdc
->sc_state
);
1403 fdcstate(struct fdc_softc
*fdc
)
1406 #define st0 fdc->sc_status[0]
1407 #define st1 fdc->sc_status[1]
1408 #define cyl fdc->sc_status[1]
1409 #define FDC_WRFIFO(fdc, c) do { \
1410 if (fdc_wrfifo(fdc, (c))) { \
1415 struct fd_softc
*fd
;
1417 int read
, head
, sec
, nblks
;
1418 struct fd_type
*type
;
1419 struct ne7_fd_formb
*finfo
= NULL
;
1421 if (fdc
->sc_istatus
== FDC_ISTATUS_ERROR
) {
1422 /* Prevent loop if the reset sequence produces errors */
1423 if (fdc
->sc_state
!= RESETCOMPLETE
&&
1424 fdc
->sc_state
!= RECALWAIT
&&
1425 fdc
->sc_state
!= RECALCOMPLETE
)
1426 fdc
->sc_state
= DORESET
;
1429 /* Clear I task/status field */
1430 fdc
->sc_istatus
= FDC_ISTATUS_NONE
;
1431 fdc
->sc_itask
= FDC_ITASK_NONE
;
1434 /* Is there a drive for the controller to do a transfer with? */
1435 fd
= fdc
->sc_drives
.tqh_first
;
1437 fdc
->sc_state
= DEVIDLE
;
1441 /* Is there a transfer to this drive? If not, deactivate drive. */
1442 bp
= bufq_peek(fd
->sc_q
);
1445 TAILQ_REMOVE(&fdc
->sc_drives
, fd
, sc_drivechain
);
1450 if (bp
->b_flags
& B_FORMAT
)
1451 finfo
= (struct ne7_fd_formb
*)bp
->b_data
;
1453 switch (fdc
->sc_state
) {
1457 fd
->sc_bcount
= bp
->b_bcount
;
1458 fd
->sc_blkno
= (bp
->b_blkno
* DEV_BSIZE
) / FD_BSIZE(fd
);
1459 callout_stop(&fd
->sc_motoroff_ch
);
1460 if ((fd
->sc_flags
& FD_MOTOR_WAIT
) != 0) {
1461 fdc
->sc_state
= MOTORWAIT
;
1464 if ((fd
->sc_flags
& FD_MOTOR
) == 0) {
1465 /* Turn on the motor, being careful about pairing. */
1466 struct fd_softc
*ofd
= fdc
->sc_fd
[fd
->sc_drive
^ 1];
1467 if (ofd
&& ofd
->sc_flags
& FD_MOTOR
) {
1468 callout_stop(&ofd
->sc_motoroff_ch
);
1469 ofd
->sc_flags
&= ~(FD_MOTOR
| FD_MOTOR_WAIT
);
1471 fd
->sc_flags
|= FD_MOTOR
| FD_MOTOR_WAIT
;
1473 fdc
->sc_state
= MOTORWAIT
;
1474 if ((fdc
->sc_flags
& FDC_NEEDMOTORWAIT
) != 0) { /*XXX*/
1475 /* Allow .25s for motor to stabilize. */
1476 callout_reset(&fd
->sc_motoron_ch
, hz
/ 4,
1479 fd
->sc_flags
&= ~FD_MOTOR_WAIT
;
1484 /* Make sure the right drive is selected. */
1487 if (fdc_diskchange(fdc
))
1493 if ((fdc
->sc_flags
& FDC_EIS
) &&
1494 (bp
->b_flags
& B_FORMAT
) == 0) {
1495 fd
->sc_cylin
= bp
->b_cylinder
;
1496 /* We use implied seek */
1500 if (fd
->sc_cylin
== bp
->b_cylinder
)
1504 fdc
->sc_state
= SEEKWAIT
;
1507 iostat_seek(fd
->sc_dk
.dk_stats
);
1509 disk_busy(&fd
->sc_dk
);
1510 callout_reset(&fdc
->sc_timo_ch
, 4 * hz
, fdctimeout
, fdc
);
1512 /* specify command */
1513 FDC_WRFIFO(fdc
, NE7CMD_SPECIFY
);
1514 FDC_WRFIFO(fdc
, fd
->sc_type
->steprate
);
1515 /* XXX head load time == 6ms */
1516 FDC_WRFIFO(fdc
, 6 | NE7_SPECIFY_NODMA
);
1518 fdc
->sc_itask
= FDC_ITASK_SENSEI
;
1520 FDC_WRFIFO(fdc
, NE7CMD_SEEK
);
1521 FDC_WRFIFO(fdc
, fd
->sc_drive
); /* drive number */
1522 FDC_WRFIFO(fdc
, bp
->b_cylinder
* fd
->sc_type
->step
);
1528 * Disk change: force a seek operation by going to cyl 1
1529 * followed by a recalibrate.
1531 disk_busy(&fd
->sc_dk
);
1532 callout_reset(&fdc
->sc_timo_ch
, 4 * hz
, fdctimeout
, fdc
);
1535 fdc
->sc_state
= DSKCHGWAIT
;
1537 fdc
->sc_itask
= FDC_ITASK_SENSEI
;
1539 FDC_WRFIFO(fdc
, NE7CMD_SEEK
);
1540 FDC_WRFIFO(fdc
, fd
->sc_drive
); /* drive number */
1541 FDC_WRFIFO(fdc
, 1 * fd
->sc_type
->step
);
1545 callout_stop(&fdc
->sc_timo_ch
);
1546 disk_unbusy(&fd
->sc_dk
, 0, 0);
1547 if (fdc
->sc_nstat
!= 2 || (st0
& 0xf8) != 0x20 ||
1548 cyl
!= 1 * fd
->sc_type
->step
) {
1549 fdcstatus(fdc
, "dskchg seek failed");
1550 fdc
->sc_state
= DORESET
;
1552 fdc
->sc_state
= DORECAL
;
1554 if (fdc_diskchange(fdc
)) {
1555 printf("%s: cannot clear disk change status\n",
1556 fdc
->sc_dev
.dv_xname
);
1557 fdc
->sc_state
= DORESET
;
1564 fd
->sc_skip
= (char *)&(finfo
->fd_formb_cylno(0)) -
1567 sec
= fd
->sc_blkno
% type
->seccyl
;
1568 nblks
= type
->seccyl
- sec
;
1569 nblks
= min(nblks
, fd
->sc_bcount
/ FD_BSIZE(fd
));
1570 nblks
= min(nblks
, FDC_MAXIOSIZE
/ FD_BSIZE(fd
));
1571 fd
->sc_nblks
= nblks
;
1572 fd
->sc_nbytes
= finfo
? bp
->b_bcount
: nblks
* FD_BSIZE(fd
);
1573 head
= sec
/ type
->sectrac
;
1574 sec
-= head
* type
->sectrac
;
1577 block
= (fd
->sc_cylin
* type
->heads
+ head
) * type
->sectrac
+ sec
;
1578 if (block
!= fd
->sc_blkno
) {
1579 printf("fdcintr: block %d != blkno %d\n", block
, (int)fd
->sc_blkno
);
1585 read
= bp
->b_flags
& B_READ
;
1587 /* Setup for pseudo DMA */
1588 fdc
->sc_data
= (char *)bp
->b_data
+ fd
->sc_skip
;
1589 fdc
->sc_tc
= fd
->sc_nbytes
;
1591 bus_space_write_1(fdc
->sc_bustag
, fdc
->sc_handle
,
1592 fdc
->sc_reg_drs
, type
->rate
);
1595 printf("fdcstate: doio: %s drive %d "
1596 "track %d head %d sec %d nblks %d\n",
1598 (read
? "read" : "write"),
1599 fd
->sc_drive
, fd
->sc_cylin
, head
, sec
, nblks
);
1601 fdc
->sc_state
= IOCOMPLETE
;
1602 fdc
->sc_itask
= FDC_ITASK_DMA
;
1605 disk_busy(&fd
->sc_dk
);
1607 /* allow 3 seconds for operation */
1608 callout_reset(&fdc
->sc_timo_ch
, 3 * hz
, fdctimeout
, fdc
);
1610 if (finfo
!= NULL
) {
1612 FDC_WRFIFO(fdc
, NE7CMD_FORMAT
);
1613 FDC_WRFIFO(fdc
, (head
<< 2) | fd
->sc_drive
);
1614 FDC_WRFIFO(fdc
, finfo
->fd_formb_secshift
);
1615 FDC_WRFIFO(fdc
, finfo
->fd_formb_nsecs
);
1616 FDC_WRFIFO(fdc
, finfo
->fd_formb_gaplen
);
1617 FDC_WRFIFO(fdc
, finfo
->fd_formb_fillbyte
);
1620 FDC_WRFIFO(fdc
, NE7CMD_READ
);
1622 FDC_WRFIFO(fdc
, NE7CMD_WRITE
);
1623 FDC_WRFIFO(fdc
, (head
<< 2) | fd
->sc_drive
);
1624 FDC_WRFIFO(fdc
, fd
->sc_cylin
); /*track*/
1625 FDC_WRFIFO(fdc
, head
);
1626 FDC_WRFIFO(fdc
, sec
+ 1); /*sector+1*/
1627 FDC_WRFIFO(fdc
, type
->secsize
);/*sector size*/
1628 FDC_WRFIFO(fdc
, type
->sectrac
);/*secs/track*/
1629 FDC_WRFIFO(fdc
, type
->gap1
); /*gap1 size*/
1630 FDC_WRFIFO(fdc
, type
->datalen
);/*data length*/
1633 return (1); /* will return later */
1636 callout_stop(&fdc
->sc_timo_ch
);
1637 fdc
->sc_state
= SEEKCOMPLETE
;
1638 if (fdc
->sc_flags
& FDC_NEEDHEADSETTLE
) {
1639 /* allow 1/50 second for heads to settle */
1640 callout_reset(&fdc
->sc_intr_ch
, hz
/ 50,
1641 fdcpseudointr
, fdc
);
1642 return (1); /* will return later */
1646 /* no data on seek */
1647 disk_unbusy(&fd
->sc_dk
, 0, 0);
1649 /* Make sure seek really happened. */
1650 if (fdc
->sc_nstat
!= 2 || (st0
& 0xf8) != 0x20 ||
1651 cyl
!= bp
->b_cylinder
* fd
->sc_type
->step
) {
1654 fdcstatus(fdc
, "seek failed");
1659 fd
->sc_cylin
= bp
->b_cylinder
;
1664 * Try to abort the I/O operation without resetting
1665 * the chip first. Poke TC and arrange to pick up
1666 * the timed out I/O command's status.
1668 fdc
->sc_itask
= FDC_ITASK_RESULT
;
1669 fdc
->sc_state
= IOCLEANUPWAIT
;
1671 /* 1/10 second should be enough */
1672 callout_reset(&fdc
->sc_timo_ch
, hz
/ 10, fdctimeout
, fdc
);
1676 case IOCLEANUPTIMEDOUT
:
1680 case DSKCHGTIMEDOUT
:
1681 fdcstatus(fdc
, "timeout");
1683 /* All other timeouts always roll through to a chip reset */
1686 /* Force reset, no matter what fdcretry() says */
1687 fdc
->sc_state
= DORESET
;
1690 case IOCLEANUPWAIT
: /* IO FAILED, cleanup succeeded */
1691 callout_stop(&fdc
->sc_timo_ch
);
1692 disk_unbusy(&fd
->sc_dk
, (bp
->b_bcount
- bp
->b_resid
),
1693 (bp
->b_flags
& B_READ
));
1697 case IOCOMPLETE
: /* IO DONE, post-analyze */
1698 callout_stop(&fdc
->sc_timo_ch
);
1700 disk_unbusy(&fd
->sc_dk
, (bp
->b_bcount
- bp
->b_resid
),
1701 (bp
->b_flags
& B_READ
));
1703 if (fdc
->sc_nstat
!= 7 || st1
!= 0 ||
1704 ((st0
& 0xf8) != 0 &&
1705 ((st0
& 0xf8) != 0x20 || (fdc
->sc_cfg
& CFG_EIS
) == 0))) {
1709 bp
->b_flags
& B_READ
1710 ? "read failed" : "write failed");
1711 printf("blkno %lld nblks %d nstat %d tc %d\n",
1712 (long long)fd
->sc_blkno
, fd
->sc_nblks
,
1713 fdc
->sc_nstat
, fdc
->sc_tc
);
1716 if (fdc
->sc_nstat
== 7 &&
1717 (st1
& ST1_OVERRUN
) == ST1_OVERRUN
) {
1720 * Silently retry overruns if no other
1721 * error bit is set. Adjust threshold.
1723 int thr
= fdc
->sc_cfg
& CFG_THRHLD_MASK
;
1726 fdc
->sc_cfg
&= ~CFG_THRHLD_MASK
;
1727 fdc
->sc_cfg
|= (thr
& CFG_THRHLD_MASK
);
1730 printf("fdc: %d -> threshold\n", thr
);
1733 fdc
->sc_overruns
= 0;
1735 if (++fdc
->sc_overruns
< 3) {
1736 fdc
->sc_state
= DOIO
;
1743 if (fdc
->sc_errors
) {
1744 diskerr(bp
, "fd", "soft error", LOG_PRINTF
,
1745 fd
->sc_skip
/ FD_BSIZE(fd
),
1746 (struct disklabel
*)NULL
);
1750 if (--fdc
->sc_overruns
< -20) {
1751 int thr
= fdc
->sc_cfg
& CFG_THRHLD_MASK
;
1754 fdc
->sc_cfg
&= ~CFG_THRHLD_MASK
;
1755 fdc
->sc_cfg
|= (thr
& CFG_THRHLD_MASK
);
1758 printf("fdc: %d -> threshold\n", thr
);
1762 fdc
->sc_overruns
= 0;
1765 fd
->sc_blkno
+= fd
->sc_nblks
;
1766 fd
->sc_skip
+= fd
->sc_nbytes
;
1767 fd
->sc_bcount
-= fd
->sc_nbytes
;
1768 if (finfo
== NULL
&& fd
->sc_bcount
> 0) {
1769 bp
->b_cylinder
= fd
->sc_blkno
/ fd
->sc_type
->seccyl
;
1776 /* try a reset, keep motor on */
1780 fdc
->sc_itask
= FDC_ITASK_SENSEI
;
1781 fdc
->sc_state
= RESETCOMPLETE
;
1782 callout_reset(&fdc
->sc_timo_ch
, hz
/ 2, fdctimeout
, fdc
);
1784 return (1); /* will return later */
1787 callout_stop(&fdc
->sc_timo_ch
);
1792 fdc
->sc_state
= RECALWAIT
;
1793 fdc
->sc_itask
= FDC_ITASK_SENSEI
;
1795 callout_reset(&fdc
->sc_timo_ch
, 5 * hz
, fdctimeout
, fdc
);
1796 /* recalibrate function */
1797 FDC_WRFIFO(fdc
, NE7CMD_RECAL
);
1798 FDC_WRFIFO(fdc
, fd
->sc_drive
);
1799 return (1); /* will return later */
1802 callout_stop(&fdc
->sc_timo_ch
);
1803 fdc
->sc_state
= RECALCOMPLETE
;
1804 if (fdc
->sc_flags
& FDC_NEEDHEADSETTLE
) {
1805 /* allow 1/30 second for heads to settle */
1806 callout_reset(&fdc
->sc_intr_ch
, hz
/ 30,
1807 fdcpseudointr
, fdc
);
1808 return (1); /* will return later */
1812 if (fdc
->sc_nstat
!= 2 || (st0
& 0xf8) != 0x20 || cyl
!= 0) {
1815 fdcstatus(fdc
, "recalibrate failed");
1824 if (fd
->sc_flags
& FD_MOTOR_WAIT
)
1825 return (1); /* time's not up yet */
1829 fdcstatus(fdc
, "stray interrupt");
1833 panic("fdcintr: impossible");
1838 * We get here if the chip locks up in FDC_WRFIFO()
1839 * Cancel any operation and schedule a reset
1841 callout_stop(&fdc
->sc_timo_ch
);
1843 (fdc
)->sc_state
= DORESET
;
1852 fdcretry(struct fdc_softc
*fdc
)
1854 struct fd_softc
*fd
;
1858 fd
= fdc
->sc_drives
.tqh_first
;
1859 bp
= bufq_peek(fd
->sc_q
);
1861 fdc
->sc_overruns
= 0;
1862 if (fd
->sc_opts
& FDOPT_NORETRY
)
1865 switch (fdc
->sc_errors
) {
1867 if (fdc
->sc_nstat
== 7 &&
1868 (fdc
->sc_status
[0] & 0xd8) == 0x40 &&
1869 (fdc
->sc_status
[1] & 0x2) == 0x2) {
1870 printf("%s: read-only medium\n", fd
->sc_dv
.dv_xname
);
1876 (fdc
->sc_flags
& FDC_EIS
) ? DOIO
: DOSEEK
;
1879 case 1: case 2: case 3:
1880 /* didn't work; try recalibrating */
1881 fdc
->sc_state
= DORECAL
;
1885 if (fdc
->sc_nstat
== 7 &&
1886 fdc
->sc_status
[0] == 0 &&
1887 fdc
->sc_status
[1] == 0 &&
1888 fdc
->sc_status
[2] == 0) {
1890 * We've retried a few times and we've got
1891 * valid status and all three status bytes
1892 * are zero. Assume this condition is the
1893 * result of no disk loaded into the drive.
1895 printf("%s: no medium?\n", fd
->sc_dv
.dv_xname
);
1900 /* still no go; reset the bastard */
1901 fdc
->sc_state
= DORESET
;
1906 if ((fd
->sc_opts
& FDOPT_SILENT
) == 0) {
1907 diskerr(bp
, "fd", "hard error", LOG_PRINTF
,
1908 fd
->sc_skip
/ FD_BSIZE(fd
),
1909 (struct disklabel
*)NULL
);
1911 fdcstatus(fdc
, "controller status");
1915 bp
->b_error
= error
;
1922 fdioctl(dev_t dev
, u_long cmd
, void *addr
, int flag
, struct lwp
*l
)
1924 struct fd_softc
*fd
;
1925 struct fdc_softc
*fdc
;
1926 struct fdformat_parms
*form_parms
;
1927 struct fdformat_cmd
*form_cmd
;
1928 struct ne7_fd_formb
*fd_formb
;
1929 int il
[FD_MAX_NSEC
+ 1];
1935 if (unit
>= fd_cd
.cd_ndevs
)
1938 fd
= device_lookup_private(&fd_cd
, FDUNIT(dev
));
1939 fdc
= device_private(device_parent(&fd
->sc_dv
));
1943 *(struct disklabel
*)addr
= *(fd
->sc_dk
.dk_label
);
1947 if ((flag
& FWRITE
) == 0)
1949 /* XXX do something */
1953 if ((flag
& FWRITE
) == 0)
1956 error
= setdisklabel(fd
->sc_dk
.dk_label
,
1957 (struct disklabel
*)addr
, 0,
1958 fd
->sc_dk
.dk_cpulabel
);
1962 error
= writedisklabel(dev
, fdstrategy
,
1964 fd
->sc_dk
.dk_cpulabel
);
1969 * Nothing to do here, really.
1974 if (*(int *)addr
== 0) {
1975 int part
= DISKPART(dev
);
1977 * Don't force eject: check that we are the only
1978 * partition open. If so, unlock it.
1980 if ((fd
->sc_dk
.dk_openmask
& ~(1 << part
)) != 0 ||
1981 fd
->sc_dk
.dk_bopenmask
+ fd
->sc_dk
.dk_copenmask
!=
1982 fd
->sc_dk
.dk_openmask
) {
1991 case FDIOCGETFORMAT
:
1992 form_parms
= (struct fdformat_parms
*)addr
;
1993 form_parms
->fdformat_version
= FDFORMAT_VERSION
;
1994 form_parms
->nbps
= 128 * (1 << fd
->sc_type
->secsize
);
1995 form_parms
->ncyl
= fd
->sc_type
->cylinders
;
1996 form_parms
->nspt
= fd
->sc_type
->sectrac
;
1997 form_parms
->ntrk
= fd
->sc_type
->heads
;
1998 form_parms
->stepspercyl
= fd
->sc_type
->step
;
1999 form_parms
->gaplen
= fd
->sc_type
->gap2
;
2000 form_parms
->fillbyte
= fd
->sc_type
->fillbyte
;
2001 form_parms
->interleave
= fd
->sc_type
->interleave
;
2002 switch (fd
->sc_type
->rate
) {
2004 form_parms
->xfer_rate
= 500 * 1024;
2007 form_parms
->xfer_rate
= 300 * 1024;
2010 form_parms
->xfer_rate
= 250 * 1024;
2017 case FDIOCSETFORMAT
:
2018 if ((flag
& FWRITE
) == 0)
2019 return (EBADF
); /* must be opened for writing */
2021 form_parms
= (struct fdformat_parms
*)addr
;
2022 if (form_parms
->fdformat_version
!= FDFORMAT_VERSION
)
2023 return (EINVAL
);/* wrong version of formatting prog */
2025 i
= form_parms
->nbps
>> 7;
2026 if ((form_parms
->nbps
& 0x7f) || ffs(i
) == 0 ||
2027 i
& ~(1 << (ffs(i
)-1)))
2028 /* not a power-of-two multiple of 128 */
2031 switch (form_parms
->xfer_rate
) {
2033 fd
->sc_type
->rate
= FDC_500KBPS
;
2036 fd
->sc_type
->rate
= FDC_300KBPS
;
2039 fd
->sc_type
->rate
= FDC_250KBPS
;
2045 if (form_parms
->nspt
> FD_MAX_NSEC
||
2046 form_parms
->fillbyte
> 0xff ||
2047 form_parms
->interleave
> 0xff)
2049 fd
->sc_type
->sectrac
= form_parms
->nspt
;
2050 if (form_parms
->ntrk
!= 2 && form_parms
->ntrk
!= 1)
2052 fd
->sc_type
->heads
= form_parms
->ntrk
;
2053 fd
->sc_type
->seccyl
= form_parms
->nspt
* form_parms
->ntrk
;
2054 fd
->sc_type
->secsize
= ffs(i
)-1;
2055 fd
->sc_type
->gap2
= form_parms
->gaplen
;
2056 fd
->sc_type
->cylinders
= form_parms
->ncyl
;
2057 fd
->sc_type
->size
= fd
->sc_type
->seccyl
* form_parms
->ncyl
*
2058 form_parms
->nbps
/ DEV_BSIZE
;
2059 fd
->sc_type
->step
= form_parms
->stepspercyl
;
2060 fd
->sc_type
->fillbyte
= form_parms
->fillbyte
;
2061 fd
->sc_type
->interleave
= form_parms
->interleave
;
2064 case FDIOCFORMAT_TRACK
:
2065 if((flag
& FWRITE
) == 0)
2066 /* must be opened for writing */
2068 form_cmd
= (struct fdformat_cmd
*)addr
;
2069 if (form_cmd
->formatcmd_version
!= FDFORMAT_VERSION
)
2070 /* wrong version of formatting prog */
2073 if (form_cmd
->head
>= fd
->sc_type
->heads
||
2074 form_cmd
->cylinder
>= fd
->sc_type
->cylinders
) {
2078 fd_formb
= malloc(sizeof(struct ne7_fd_formb
),
2083 fd_formb
->head
= form_cmd
->head
;
2084 fd_formb
->cyl
= form_cmd
->cylinder
;
2085 fd_formb
->transfer_rate
= fd
->sc_type
->rate
;
2086 fd_formb
->fd_formb_secshift
= fd
->sc_type
->secsize
;
2087 fd_formb
->fd_formb_nsecs
= fd
->sc_type
->sectrac
;
2088 fd_formb
->fd_formb_gaplen
= fd
->sc_type
->gap2
;
2089 fd_formb
->fd_formb_fillbyte
= fd
->sc_type
->fillbyte
;
2091 memset(il
, 0, sizeof il
);
2092 for (j
= 0, i
= 1; i
<= fd_formb
->fd_formb_nsecs
; i
++) {
2093 while (il
[(j
%fd_formb
->fd_formb_nsecs
) + 1])
2095 il
[(j
%fd_formb
->fd_formb_nsecs
) + 1] = i
;
2096 j
+= fd
->sc_type
->interleave
;
2098 for (i
= 0; i
< fd_formb
->fd_formb_nsecs
; i
++) {
2099 fd_formb
->fd_formb_cylno(i
) = form_cmd
->cylinder
;
2100 fd_formb
->fd_formb_headno(i
) = form_cmd
->head
;
2101 fd_formb
->fd_formb_secno(i
) = il
[i
+1];
2102 fd_formb
->fd_formb_secsize(i
) = fd
->sc_type
->secsize
;
2105 error
= fdformat(dev
, fd_formb
, l
->l_proc
);
2106 free(fd_formb
, M_TEMP
);
2109 case FDIOCGETOPTS
: /* get drive options */
2110 *(int *)addr
= fd
->sc_opts
;
2113 case FDIOCSETOPTS
: /* set drive options */
2114 fd
->sc_opts
= *(int *)addr
;
2119 fdc_wrfifo(fdc
, NE7CMD_DUMPREG
);
2121 printf("fdc: dumpreg(%d regs): <", fdc
->sc_nstat
);
2122 for (i
= 0; i
< fdc
->sc_nstat
; i
++)
2123 printf(" 0x%x", fdc
->sc_status
[i
]);
2127 case _IOW('f', 101, int):
2128 fdc
->sc_cfg
&= ~CFG_THRHLD_MASK
;
2129 fdc
->sc_cfg
|= (*(int *)addr
& CFG_THRHLD_MASK
);
2134 fdc_wrfifo(fdc
, NE7CMD_SENSEI
);
2136 printf("fdc: sensei(%d regs): <", fdc
->sc_nstat
);
2137 for (i
=0; i
< fdc
->sc_nstat
; i
++)
2138 printf(" 0x%x", fdc
->sc_status
[i
]);
2147 panic("fdioctl: impossible");
2152 fdformat(dev_t dev
, struct ne7_fd_formb
*finfo
, struct proc
*p
)
2155 struct fd_softc
*fd
= device_lookup_private(&fd_cd
, FDUNIT(dev
));
2156 struct fd_type
*type
= fd
->sc_type
;
2159 /* set up a buffer header for fdstrategy() */
2160 bp
= getiobuf(NULL
, false);
2165 bp
->b_cflags
= BC_BUSY
;
2166 bp
->b_flags
= B_PHYS
| B_FORMAT
;
2171 * Calculate a fake blkno, so fdstrategy() would initiate a
2172 * seek to the requested cylinder.
2174 bp
->b_blkno
= ((finfo
->cyl
* (type
->sectrac
* type
->heads
)
2175 + finfo
->head
* type
->sectrac
) * FD_BSIZE(fd
))
2178 bp
->b_bcount
= sizeof(struct fd_idfield_data
) * finfo
->fd_formb_nsecs
;
2179 bp
->b_data
= (void *)finfo
;
2185 printf("fdformat: blkno 0x%llx count %d\n",
2186 (unsigned long long)bp
->b_blkno
, bp
->b_bcount
);
2188 printf("\tcyl:\t%d\n", finfo
->cyl
);
2189 printf("\thead:\t%d\n", finfo
->head
);
2190 printf("\tnsecs:\t%d\n", finfo
->fd_formb_nsecs
);
2191 printf("\tsshft:\t%d\n", finfo
->fd_formb_secshift
);
2192 printf("\tgaplen:\t%d\n", finfo
->fd_formb_gaplen
);
2193 printf("\ttrack data:");
2194 for (i
= 0; i
< finfo
->fd_formb_nsecs
; i
++) {
2195 printf(" [c%d h%d s%d]",
2196 finfo
->fd_formb_cylno(i
),
2197 finfo
->fd_formb_headno(i
),
2198 finfo
->fd_formb_secno(i
) );
2199 if (finfo
->fd_formb_secsize(i
) != 2)
2200 printf("<sz:%d>", finfo
->fd_formb_secsize(i
));
2206 /* now do the format */
2209 /* ...and wait for it to complete */
2216 fdgetdisklabel(dev_t dev
)
2218 int unit
= FDUNIT(dev
), i
;
2219 struct fd_softc
*fd
= device_lookup_private(&fd_cd
, unit
);
2220 struct disklabel
*lp
= fd
->sc_dk
.dk_label
;
2221 struct cpu_disklabel
*clp
= fd
->sc_dk
.dk_cpulabel
;
2223 memset(lp
, 0, sizeof(struct disklabel
));
2224 memset(lp
, 0, sizeof(struct cpu_disklabel
));
2226 lp
->d_type
= DTYPE_FLOPPY
;
2227 lp
->d_secsize
= FD_BSIZE(fd
);
2228 lp
->d_secpercyl
= fd
->sc_type
->seccyl
;
2229 lp
->d_nsectors
= fd
->sc_type
->sectrac
;
2230 lp
->d_ncylinders
= fd
->sc_type
->cylinders
;
2231 lp
->d_ntracks
= fd
->sc_type
->heads
; /* Go figure... */
2232 lp
->d_secperunit
= lp
->d_secpercyl
* lp
->d_ncylinders
;
2233 lp
->d_rpm
= 3600; /* XXX like it matters... */
2235 strncpy(lp
->d_typename
, "floppy", sizeof(lp
->d_typename
));
2236 strncpy(lp
->d_packname
, "fictitious", sizeof(lp
->d_packname
));
2237 lp
->d_interleave
= 1;
2239 lp
->d_partitions
[RAW_PART
].p_offset
= 0;
2240 lp
->d_partitions
[RAW_PART
].p_size
= lp
->d_secpercyl
* lp
->d_ncylinders
;
2241 lp
->d_partitions
[RAW_PART
].p_fstype
= FS_UNUSED
;
2242 lp
->d_npartitions
= RAW_PART
+ 1;
2244 lp
->d_magic
= DISKMAGIC
;
2245 lp
->d_magic2
= DISKMAGIC
;
2246 lp
->d_checksum
= dkcksum(lp
);
2249 * Call the generic disklabel extraction routine. If there's
2250 * not a label there, fake it.
2252 if (readdisklabel(dev
, fdstrategy
, lp
, clp
) != NULL
) {
2253 strncpy(lp
->d_packname
, "default label",
2254 sizeof(lp
->d_packname
));
2256 * Reset the partition info; it might have gotten
2257 * trashed in readdisklabel().
2259 * XXX Why do we have to do this? readdisklabel()
2262 for (i
= 0; i
< MAXPARTITIONS
; ++i
) {
2263 lp
->d_partitions
[i
].p_offset
= 0;
2264 if (i
== RAW_PART
) {
2265 lp
->d_partitions
[i
].p_size
=
2266 lp
->d_secpercyl
* lp
->d_ncylinders
;
2267 lp
->d_partitions
[i
].p_fstype
= FS_BSDFFS
;
2269 lp
->d_partitions
[i
].p_size
= 0;
2270 lp
->d_partitions
[i
].p_fstype
= FS_UNUSED
;
2273 lp
->d_npartitions
= RAW_PART
+ 1;
2278 fd_do_eject(struct fd_softc
*fd
)
2280 struct fdc_softc
*fdc
= device_private(device_parent(&fd
->sc_dv
));
2283 auxregbisc(AUXIO4C_FDS
, AUXIO4C_FEJ
);
2285 auxregbisc(AUXIO4C_FEJ
, AUXIO4C_FDS
);
2288 if (CPU_ISSUN4M
&& (fdc
->sc_flags
& FDC_82077
) != 0) {
2289 bus_space_tag_t t
= fdc
->sc_bustag
;
2290 bus_space_handle_t h
= fdc
->sc_handle
;
2291 uint8_t dor
= FDO_FRST
| FDO_FDMAEN
| FDO_MOEN(0);
2293 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
, dor
| FDO_EJ
);
2295 bus_space_write_1(t
, h
, fdc
->sc_reg_dor
, FDO_FRST
| FDO_DS
);
2302 fd_mountroot_hook(struct device
*dev
)
2306 fd_do_eject(device_private(dev
));
2307 printf("Insert filesystem floppy and press return.");
2310 if ((c
== '\r') || (c
== '\n')) {
2317 #ifdef MEMORY_DISK_HOOKS
2319 #define FDMICROROOTSIZE ((2*18*80) << DEV_BSHIFT)
2322 fd_read_md_image(size_t *sizep
, void * *addrp
)
2324 struct buf buf
, *bp
= &buf
;
2329 dev
= makedev(54,0); /* XXX */
2331 addr
= malloc(FDMICROROOTSIZE
, M_DEVBUF
, M_WAITOK
);
2334 if (fdopen(dev
, 0, S_IFCHR
, NULL
))
2335 panic("fd: mountroot: fdopen");
2344 bp
->b_cflags
|= BC_BUSY
;
2345 bp
->b_flags
= B_PHYS
| B_RAW
| B_READ
;
2346 bp
->b_blkno
= btodb(offset
);
2347 bp
->b_bcount
= DEV_BSIZE
;
2352 panic("fd: mountroot: fdread error %d", bp
->b_error
);
2354 if (bp
->b_resid
!= 0)
2357 addr
= (char *)addr
+ DEV_BSIZE
;
2358 offset
+= DEV_BSIZE
;
2359 if (offset
+ DEV_BSIZE
> FDMICROROOTSIZE
)
2362 (void)fdclose(dev
, 0, S_IFCHR
, NULL
);
2364 fd_do_eject(device_lookup_private(&fd_cd
, FDUNIT(dev
)));
2367 #endif /* MEMORY_DISK_HOOKS */