1 /* $NetBSD: hdfd.c,v 1.70 2009/03/18 16:00:10 cegger Exp $ */
4 * Copyright (c) 1996 Leo Weppelman
5 * Copyright (c) 1990 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * @(#)fd.c 7.4 (Berkeley) 5/25/91
39 * Copyright (c) 1993, 1994, 1995, 1996
40 * Charles M. Hannum. All rights reserved.
42 * This code is derived from software contributed to Berkeley by
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 * must display the following acknowledgement:
55 * This product includes software developed by the University of
56 * California, Berkeley and its contributors.
57 * 4. Neither the name of the University nor the names of its contributors
58 * may be used to endorse or promote products derived from this software
59 * without specific prior written permission.
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * @(#)fd.c 7.4 (Berkeley) 5/25/91
77 * Floppy formatting facilities merged from FreeBSD fd.c driver:
78 * Id: fd.c,v 1.53 1995/03/12 22:40:56 joerg Exp
79 * which carries the same copyright/redistribution notice as shown above with
80 * the addition of the following statement before the "Redistribution and
83 * Copyright (c) 1993, 1994 by
84 * jc@irbs.UUCP (John Capo)
85 * vak@zebub.msk.su (Serge Vakulenko)
86 * ache@astral.msk.su (Andrew A. Chernov)
88 * Copyright (c) 1993, 1994, 1995 by
89 * joerg_wunsch@uriah.sax.de (Joerg Wunsch)
90 * dufault@hda.com (Peter Dufault)
93 #include <sys/cdefs.h>
94 __KERNEL_RCSID(0, "$NetBSD: hdfd.c,v 1.70 2009/03/18 16:00:10 cegger Exp $");
98 #include <sys/param.h>
99 #include <sys/systm.h>
100 #include <sys/callout.h>
101 #include <sys/kernel.h>
102 #include <sys/file.h>
103 #include <sys/ioctl.h>
104 #include <sys/device.h>
105 #include <sys/disklabel.h>
106 #include <sys/disk.h>
108 #include <sys/bufq.h>
109 #include <sys/malloc.h>
111 #include <sys/syslog.h>
112 #include <sys/queue.h>
113 #include <sys/proc.h>
114 #include <sys/fdio.h>
115 #include <sys/conf.h>
117 #include <uvm/uvm_extern.h>
119 #include <machine/cpu.h>
120 #include <machine/bus.h>
121 #include <machine/iomap.h>
122 #include <machine/mfp.h>
123 #include <machine/intr.h>
125 #include <atari/dev/hdfdreg.h>
126 #include <atari/atari/device.h>
128 #include "locators.h"
131 * {b,c}devsw[] function prototypes
133 dev_type_open(fdopen
);
134 dev_type_close(fdclose
);
135 dev_type_read(fdread
);
136 dev_type_write(fdwrite
);
137 dev_type_ioctl(fdioctl
);
138 dev_type_strategy(fdstrategy
);
140 volatile u_char
*fdio_addr
;
142 #define wrt_fdc_reg(reg, val) { fdio_addr[reg] = val; }
143 #define rd_fdc_reg(reg) ( fdio_addr[reg] )
145 #define fdc_ienable() MFP2->mf_ierb |= IB_DCHG;
148 * Interface to the pseudo-DMA handler
150 void fddma_intr(void);
151 void * fddmaaddr
= NULL
;
154 extern void mfp_hdfd_nf(void), mfp_hdfd_fifo(void);
157 * Argument to fdcintr.....
159 static void *intr_arg
= NULL
; /* XXX: arg. to intr_establish() */
163 #define FDUNIT(dev) (minor(dev) / 8)
164 #define FDTYPE(dev) (minor(dev) % 8)
166 /* (mis)use device use flag to identify format operation */
167 #define B_FORMAT B_DEVPRIVATE
188 /* software state, per controller */
190 struct device sc_dev
; /* boilerplate */
192 struct callout sc_timo_ch
; /* timeout callout */
193 struct callout sc_intr_ch
; /* pseudo-intr callout */
195 struct fd_softc
*sc_fd
[4]; /* pointers to children */
196 TAILQ_HEAD(drivehead
, fd_softc
) sc_drives
;
197 enum fdc_state sc_state
;
198 int sc_errors
; /* number of retries so far */
199 int sc_overruns
; /* number of overruns so far */
200 u_char sc_status
[7]; /* copy of registers */
203 /* controller driver configuration */
204 int fdcprobe(struct device
*, struct cfdata
*, void *);
205 int fdprint(void *, const char *);
206 void fdcattach(struct device
*, struct device
*, void *);
208 CFATTACH_DECL(fdc
, sizeof(struct fdc_softc
),
209 fdcprobe
, fdcattach
, NULL
, NULL
);
212 * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
213 * we tell them apart.
216 int sectrac
; /* sectors per track */
217 int heads
; /* number of heads */
218 int seccyl
; /* sectors per cylinder */
219 int secsize
; /* size code for sectors */
220 int datalen
; /* data len when secsize = 0 */
221 int steprate
; /* step rate and head unload time */
222 int gap1
; /* gap len between sectors */
223 int gap2
; /* formatting gap */
224 int tracks
; /* total num of tracks */
225 int size
; /* size of disk in sectors */
226 int step
; /* steps per cylinder */
227 int rate
; /* transfer speed code */
228 u_char fillbyte
; /* format fill byte */
229 u_char interleave
; /* interleave factor (formatting) */
234 * The order of entries in the following table is important -- BEWARE!
235 * The order of the types is the same as for the TT/Falcon....
237 struct fd_type fd_types
[] = {
238 /* 360kB in 720kB drive */
239 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_125KBPS
,0xf6,1,"360KB" },
240 /* 3.5" 720kB diskette */
241 { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_125KBPS
,0xf6,1,"720KB" },
242 /* 1.44MB diskette */
243 { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_250KBPS
,0xf6,1,"1.44MB" },
246 /* software state, per disk (with up to 4 disks per ctlr) */
248 struct device sc_dev
;
251 struct fd_type
*sc_deftype
; /* default type descriptor */
252 struct fd_type
*sc_type
; /* current type descriptor */
254 struct callout sc_motoron_ch
;
255 struct callout sc_motoroff_ch
;
257 daddr_t sc_blkno
; /* starting block number */
258 int sc_bcount
; /* byte count left */
259 int sc_opts
; /* user-set options */
260 int sc_skip
; /* bytes already transferred */
261 int sc_nblks
; /* #blocks currently transferring */
262 int sc_nbytes
; /* #bytes currently transferring */
264 int sc_drive
; /* physical unit number */
266 #define FD_OPEN 0x01 /* it's open */
267 #define FD_MOTOR 0x02 /* motor should be on */
268 #define FD_MOTOR_WAIT 0x04 /* motor coming up */
269 #define FD_HAVELAB 0x08 /* got a disklabel */
270 int sc_cylin
; /* where we think the head is */
272 void *sc_sdhook
; /* saved shutdown hook for drive. */
274 TAILQ_ENTRY(fd_softc
) sc_drivechain
;
275 int sc_ops
; /* I/O ops since last switch */
276 struct bufq_state
*sc_q
; /* pending I/O requests */
277 int sc_active
; /* number of active I/O operations */
280 /* floppy driver configuration */
281 int fdprobe(struct device
*, struct cfdata
*, void *);
282 void fdattach(struct device
*, struct device
*, void *);
284 CFATTACH_DECL(hdfd
, sizeof(struct fd_softc
),
285 fdprobe
, fdattach
, NULL
, NULL
);
287 extern struct cfdriver hdfd_cd
;
289 const struct bdevsw fd_bdevsw
= {
290 fdopen
, fdclose
, fdstrategy
, fdioctl
, nodump
, nosize
, D_DISK
293 const struct cdevsw fd_cdevsw
= {
294 fdopen
, fdclose
, fdread
, fdwrite
, fdioctl
,
295 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_DISK
298 void fdstart(struct fd_softc
*);
300 struct dkdriver fddkdriver
= { fdstrategy
};
302 void fd_set_motor(struct fdc_softc
*fdc
, int reset
);
303 void fd_motor_off(void *arg
);
304 void fd_motor_on(void *arg
);
305 int fdcresult(struct fdc_softc
*fdc
);
306 int out_fdc(u_char x
);
307 void fdc_ctrl_intr(struct clockframe
);
308 void fdcstart(struct fdc_softc
*fdc
);
309 void fdcstatus(struct device
*dv
, int n
, const char *s
);
310 void fdctimeout(void *arg
);
311 void fdcpseudointr(void *arg
);
313 void fdcretry(struct fdc_softc
*fdc
);
314 void fdfinish(struct fd_softc
*fd
, struct buf
*bp
);
315 int fdformat(dev_t
, struct ne7_fd_formb
*, struct proc
*);
317 static void fdgetdisklabel(struct fd_softc
*, dev_t
);
318 static void fdgetdefaultlabel(struct fd_softc
*, struct disklabel
*,
321 inline struct fd_type
*fd_dev_to_type(struct fd_softc
*, dev_t
);
324 fdcprobe(struct device
*parent
, struct cfdata
*cfp
, void *aux
)
326 static int fdc_matched
= 0;
327 bus_space_tag_t mb_tag
;
328 bus_space_handle_t handle
;
330 /* Match only once */
331 if(strcmp("fdc", aux
) || fdc_matched
)
334 if (!atari_realconfig
)
337 if ((mb_tag
= mb_alloc_bus_space_tag()) == NULL
)
340 if (bus_space_map(mb_tag
, FD_IOBASE
, FD_IOSIZE
, 0, &handle
)) {
341 printf("fdcprobe: cannot map io-area\n");
342 mb_free_bus_space_tag(mb_tag
);
345 fdio_addr
= bus_space_vaddr(mb_tag
, handle
); /* XXX */
348 printf("fdcprobe: I/O mapping done va: %p\n", fdio_addr
);
352 wrt_fdc_reg(fdout
, 0);
354 wrt_fdc_reg(fdout
, FDO_FRST
);
356 /* see if it can handle a command */
357 if (out_fdc(NE7CMD_SPECIFY
) < 0)
365 if (fdc_matched
== 0) {
366 bus_space_unmap(mb_tag
, handle
, FD_IOSIZE
);
367 mb_free_bus_space_tag(mb_tag
);
374 * Arguments passed between fdcattach and fdprobe.
376 struct fdc_attach_args
{
378 struct fd_type
*fa_deftype
;
382 * Print the location of a disk drive (called just before attaching the
383 * the drive). If `fdc' is not NULL, the drive was found but was not
384 * in the system config file; print the drive name as well.
385 * Return QUIET (config_find ignores this if the device was configured) to
386 * avoid printing `fdN not configured' messages.
389 fdprint(void *aux
, const char *fdc
)
391 register struct fdc_attach_args
*fa
= aux
;
394 aprint_normal(" drive %d", fa
->fa_drive
);
399 fdcattach(struct device
*parent
, struct device
*self
, void *aux
)
401 struct fdc_softc
*fdc
= (void *)self
;
402 struct fdc_attach_args fa
;
407 fdc
->sc_state
= DEVIDLE
;
408 TAILQ_INIT(&fdc
->sc_drives
);
410 out_fdc(NE7CMD_CONFIGURE
);
411 if (out_fdc(0) == 0) {
412 out_fdc(0x1a); /* No polling, fifo depth = 10 */
415 /* Retain configuration across resets */
416 out_fdc(NE7CMD_LOCK
);
417 (void)fdcresult(fdc
);
421 (void)rd_fdc_reg(fddata
);
427 callout_init(&fdc
->sc_timo_ch
, 0);
428 callout_init(&fdc
->sc_intr_ch
, 0);
430 if (intr_establish(22, USER_VEC
|FAST_VEC
, 0,
431 (hw_ifun_t
)(has_fifo
? mfp_hdfd_fifo
: mfp_hdfd_nf
),
433 printf("fdcattach: Can't establish interrupt\n");
438 * Setup the interrupt logic.
440 MFP2
->mf_iprb
= (u_int8_t
)~IB_DCHG
;
441 MFP2
->mf_imrb
|= IB_DCHG
;
442 MFP2
->mf_aer
|= 0x10; /* fdc int low->high */
444 /* physical limit: four drives per controller. */
445 for (fa
.fa_drive
= 0; fa
.fa_drive
< 4; fa
.fa_drive
++) {
447 * XXX: Choose something sensible as a default...
449 fa
.fa_deftype
= &fd_types
[2]; /* 1.44MB */
450 (void)config_found(self
, (void *)&fa
, fdprint
);
455 fdprobe(struct device
*parent
, struct cfdata
*cfp
, void *aux
)
457 struct fdc_softc
*fdc
= (void *)parent
;
458 struct fdc_attach_args
*fa
= aux
;
459 int drive
= fa
->fa_drive
;
462 if (cfp
->cf_loc
[FDCCF_UNIT
] != FDCCF_UNIT_DEFAULT
&&
463 cfp
->cf_loc
[FDCCF_UNIT
] != drive
)
467 * This is to work around some odd interactions between this driver
468 * and SMC Ethernet cards.
470 if (cfp
->cf_loc
[FDCCF_UNIT
] == FDCCF_UNIT_DEFAULT
&& drive
>= 2)
473 /* select drive and turn on motor */
474 wrt_fdc_reg(fdout
, drive
| FDO_FRST
| FDO_MOEN(drive
));
476 /* wait for motor to spin up */
478 out_fdc(NE7CMD_RECAL
);
481 /* wait for recalibrate */
483 out_fdc(NE7CMD_SENSEI
);
489 printf("fdprobe: status");
490 for (i
= 0; i
< n
; i
++)
491 printf(" %x", fdc
->sc_status
[i
]);
495 intr_arg
= (void*)fdc
;
496 if (n
!= 2 || (fdc
->sc_status
[0] & 0xf8) != 0x20)
499 wrt_fdc_reg(fdout
, FDO_FRST
);
505 * Controller is working, and drive responded. Attach it.
508 fdattach(struct device
*parent
, struct device
*self
, void *aux
)
510 struct fdc_softc
*fdc
= (void *)parent
;
511 struct fd_softc
*fd
= (void *)self
;
512 struct fdc_attach_args
*fa
= aux
;
513 struct fd_type
*type
= fa
->fa_deftype
;
514 int drive
= fa
->fa_drive
;
516 callout_init(&fd
->sc_motoron_ch
, 0);
517 callout_init(&fd
->sc_motoroff_ch
, 0);
519 /* XXX Allow `flags' to override device type? */
522 printf(": %s %d cyl, %d head, %d sec\n", type
->name
,
523 type
->tracks
, type
->heads
, type
->sectrac
);
525 printf(": density unknown\n");
527 bufq_alloc(&fd
->sc_q
, "disksort", BUFQ_SORT_CYLINDER
);
529 fd
->sc_drive
= drive
;
530 fd
->sc_deftype
= type
;
531 fdc
->sc_fd
[drive
] = fd
;
534 * Initialize and attach the disk structure.
536 disk_init(&fd
->sc_dk
, fd
->sc_dev
.dv_xname
, &fddkdriver
);
537 disk_attach(&fd
->sc_dk
);
539 /* Needed to power off if the motor is on when we halt. */
540 fd
->sc_sdhook
= shutdownhook_establish(fd_motor_off
, fd
);
544 * This is called from the assembly part of the interrupt handler
545 * when it is clear that the interrupt was not related to shoving
549 fdc_ctrl_intr(struct clockframe frame
)
554 * Disable further interrupts. The fdcintr() routine
555 * explicitly enables them when needed.
557 MFP2
->mf_ierb
&= ~IB_DCHG
;
560 * Set fddmalen to zero so no pseudo-DMA transfers will
565 if (!BASEPRI(frame
.cf_sr
)) {
567 * We don't want to stay on ipl6.....
569 add_sicallback((si_farg
)fdcpseudointr
, intr_arg
, 0);
573 (void) fdcintr(intr_arg
);
578 inline struct fd_type
*
579 fd_dev_to_type(struct fd_softc
*fd
, dev_t dev
)
581 int type
= FDTYPE(dev
);
583 if (type
> (sizeof(fd_types
) / sizeof(fd_types
[0])))
585 return type
? &fd_types
[type
- 1] : fd
->sc_deftype
;
589 fdstrategy(struct buf
*bp
)
591 struct fd_softc
*fd
= device_lookup_private(&hdfd_cd
, FDUNIT(bp
->b_dev
));
595 /* Valid unit, controller, and request? */
596 if (bp
->b_blkno
< 0 ||
597 ((bp
->b_bcount
% FDC_BSIZE
) != 0 &&
598 (bp
->b_flags
& B_FORMAT
) == 0)) {
599 bp
->b_error
= EINVAL
;
603 /* If it's a null transfer, return immediately. */
604 if (bp
->b_bcount
== 0)
607 sz
= howmany(bp
->b_bcount
, FDC_BSIZE
);
609 if (bp
->b_blkno
+ sz
> fd
->sc_type
->size
) {
610 sz
= fd
->sc_type
->size
- bp
->b_blkno
;
612 /* If exactly at end of disk, return EOF. */
616 /* If past end of disk, return EINVAL. */
617 bp
->b_error
= EINVAL
;
620 /* Otherwise, truncate request. */
621 bp
->b_bcount
= sz
<< DEV_BSHIFT
;
624 bp
->b_rawblkno
= bp
->b_blkno
;
625 bp
->b_cylinder
= bp
->b_blkno
/ (FDC_BSIZE
/DEV_BSIZE
) / fd
->sc_type
->seccyl
;
628 printf("fdstrategy: b_blkno %d b_bcount %ld blkno %qd cylin %ld sz"
629 " %d\n", bp
->b_blkno
, bp
->b_bcount
, (long)fd
->sc_blkno
,
633 /* Queue transfer on drive, activate drive and controller if idle. */
635 bufq_put(fd
->sc_q
, bp
);
636 callout_stop(&fd
->sc_motoroff_ch
); /* a good idea */
637 if (fd
->sc_active
== 0)
641 struct fdc_softc
*fdc
= (void *) device_parent(&fd
->sc_dev
);
642 if (fdc
->sc_state
== DEVIDLE
) {
643 printf("fdstrategy: controller inactive\n");
652 /* Toss transfer; we're done early. */
653 bp
->b_resid
= bp
->b_bcount
;
658 fdstart(struct fd_softc
*fd
)
660 struct fdc_softc
*fdc
= (void *) device_parent(&fd
->sc_dev
);
661 int active
= fdc
->sc_drives
.tqh_first
!= 0;
663 /* Link into controller queue. */
665 TAILQ_INSERT_TAIL(&fdc
->sc_drives
, fd
, sc_drivechain
);
667 /* If controller not already active, start it. */
673 fdfinish(struct fd_softc
*fd
, struct buf
*bp
)
675 struct fdc_softc
*fdc
= (void *) device_parent(&fd
->sc_dev
);
678 * Move this drive to the end of the queue to give others a `fair'
679 * chance. We only force a switch if N operations are completed while
680 * another drive is waiting to be serviced, since there is a long motor
681 * startup delay whenever we switch.
683 (void)bufq_get(fd
->sc_q
);
684 if (fd
->sc_drivechain
.tqe_next
&& ++fd
->sc_ops
>= 8) {
686 TAILQ_REMOVE(&fdc
->sc_drives
, fd
, sc_drivechain
);
687 if (bufq_peek(fd
->sc_q
) != NULL
)
688 TAILQ_INSERT_TAIL(&fdc
->sc_drives
, fd
, sc_drivechain
);
692 bp
->b_resid
= fd
->sc_bcount
;
696 /* turn off motor 5s from now */
697 callout_reset(&fd
->sc_motoroff_ch
, 5 * hz
, fd_motor_off
, fd
);
698 fdc
->sc_state
= DEVIDLE
;
702 fdread(dev_t dev
, struct uio
*uio
, int flags
)
704 return (physio(fdstrategy
, NULL
, dev
, B_READ
, minphys
, uio
));
708 fdwrite(dev_t dev
, struct uio
*uio
, int flags
)
710 return (physio(fdstrategy
, NULL
, dev
, B_WRITE
, minphys
, uio
));
714 fd_set_motor(struct fdc_softc
*fdc
, int reset
)
720 if ((fd
= fdc
->sc_drives
.tqh_first
) != NULL
)
721 status
= fd
->sc_drive
;
725 status
|= FDO_FRST
| FDO_FDMAEN
;
726 for (n
= 0; n
< 4; n
++)
727 if ((fd
= fdc
->sc_fd
[n
]) && (fd
->sc_flags
& FD_MOTOR
))
728 status
|= FDO_MOEN(n
);
729 wrt_fdc_reg(fdout
, status
);
733 fd_motor_off(void *arg
)
735 struct fd_softc
*fd
= arg
;
739 fd
->sc_flags
&= ~(FD_MOTOR
| FD_MOTOR_WAIT
);
740 fd_set_motor((struct fdc_softc
*) device_parent(&fd
->sc_dev
), 0);
745 fd_motor_on(void *arg
)
747 struct fd_softc
*fd
= arg
;
748 struct fdc_softc
*fdc
= (void *) device_parent(&fd
->sc_dev
);
752 fd
->sc_flags
&= ~FD_MOTOR_WAIT
;
753 if ((fdc
->sc_drives
.tqh_first
== fd
) && (fdc
->sc_state
== MOTORWAIT
))
759 fdcresult(struct fdc_softc
*fdc
)
766 i
= rd_fdc_reg(fdsts
) & (NE7_DIO
| NE7_RQM
| NE7_CB
);
769 if (i
== (NE7_DIO
| NE7_RQM
| NE7_CB
)) {
770 if (n
>= sizeof(fdc
->sc_status
)) {
771 log(LOG_ERR
, "fdcresult: overrun\n");
774 fdc
->sc_status
[n
++] = rd_fdc_reg(fddata
);
778 log(LOG_ERR
, "fdcresult: timeout\n");
787 while (((rd_fdc_reg(fdsts
) & (NE7_DIO
|NE7_RQM
)) != NE7_RQM
) && i
-- > 0)
791 wrt_fdc_reg(fddata
, x
);
796 fdopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
799 struct fd_type
*type
;
801 fd
= device_lookup_private(&hdfd_cd
, FDUNIT(dev
));
804 type
= fd_dev_to_type(fd
, dev
);
808 if ((fd
->sc_flags
& FD_OPEN
) != 0 &&
814 fd
->sc_flags
|= FD_OPEN
;
815 fdgetdisklabel(fd
, dev
);
821 fdclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
823 struct fd_softc
*fd
= device_lookup_private(&hdfd_cd
, FDUNIT(dev
));
825 fd
->sc_flags
&= ~(FD_OPEN
|FD_HAVELAB
);
826 fd
->sc_opts
&= ~(FDOPT_NORETRY
|FDOPT_SILENT
);
831 fdcstart(struct fdc_softc
*fdc
)
835 /* only got here if controller's drive queue was inactive; should
837 if (fdc
->sc_state
!= DEVIDLE
) {
838 printf("fdcstart: not idle\n");
846 fdcpstatus(struct fdc_softc
*fdc
)
850 snprintb(bits
, sizeof(bits
), NE7_ST0BITS
, fdc
->sc_status
[0]);
851 printf(" (st0 %s", bits
);
852 snprintb(bits
, sizeof(bits
), NE7_ST1BITS
, fdc
->sc_status
[1]);
853 printf(" st1 %s", bits
);
854 snprintb(bits
, sizeof(bits
), NE7_ST2BITS
, fdc
->sc_status
[2]);
855 printf(" st2 %s", bits
);
856 printf(" cyl %d head %d sec %d)\n",
857 fdc
->sc_status
[3], fdc
->sc_status
[4], fdc
->sc_status
[5]);
861 fdcstatus(struct device
*dv
, int n
, const char *s
)
863 struct fdc_softc
*fdc
= (void *) device_parent(dv
);
867 out_fdc(NE7CMD_SENSEI
);
868 (void) fdcresult(fdc
);
872 printf("%s: %s", dv
->dv_xname
, s
);
879 snprintb(bits
, sizeof(bits
), NE7_ST0BITS
, fdc
->sc_status
[0]);
880 printf(" (st0 %s cyl %d)\n", bits
, fdc
->sc_status
[1]);
887 printf("\nfdcstatus: weird size");
894 fdctimeout(void *arg
)
896 struct fdc_softc
*fdc
= arg
;
897 struct fd_softc
*fd
= fdc
->sc_drives
.tqh_first
;
901 fdcstatus(&fd
->sc_dev
, 0, "timeout");
903 if (bufq_peek(fd
->sc_q
) != NULL
)
906 fdc
->sc_state
= DEVIDLE
;
913 fdcpseudointr(void *arg
)
917 /* Just ensure it has the right spl. */
926 struct fdc_softc
*fdc
= arg
;
927 #define st0 fdc->sc_status[0]
928 #define st1 fdc->sc_status[1]
929 #define cyl fdc->sc_status[1]
933 int read
, head
, sec
, i
, nblks
;
934 struct fd_type
*type
;
935 struct ne7_fd_formb
*finfo
= NULL
;
938 /* Is there a drive for the controller to do a transfer with? */
939 fd
= fdc
->sc_drives
.tqh_first
;
941 fdc
->sc_state
= DEVIDLE
;
945 /* Is there a transfer to this drive? If not, deactivate drive. */
946 bp
= bufq_peek(fd
->sc_q
);
949 TAILQ_REMOVE(&fdc
->sc_drives
, fd
, sc_drivechain
);
954 if (bp
->b_flags
& B_FORMAT
)
955 finfo
= (struct ne7_fd_formb
*)bp
->b_data
;
957 switch (fdc
->sc_state
) {
960 fdc
->sc_overruns
= 0;
962 fd
->sc_bcount
= bp
->b_bcount
;
963 fd
->sc_blkno
= bp
->b_blkno
/ (FDC_BSIZE
/ DEV_BSIZE
);
964 callout_stop(&fd
->sc_motoroff_ch
);
965 if ((fd
->sc_flags
& FD_MOTOR_WAIT
) != 0) {
966 fdc
->sc_state
= MOTORWAIT
;
969 if ((fd
->sc_flags
& FD_MOTOR
) == 0) {
970 /* Turn on the motor, being careful about pairing. */
971 struct fd_softc
*ofd
= fdc
->sc_fd
[fd
->sc_drive
^ 1];
972 if (ofd
&& ofd
->sc_flags
& FD_MOTOR
) {
973 callout_stop(&ofd
->sc_motoroff_ch
);
974 ofd
->sc_flags
&= ~(FD_MOTOR
| FD_MOTOR_WAIT
);
976 fd
->sc_flags
|= FD_MOTOR
| FD_MOTOR_WAIT
;
977 fd_set_motor(fdc
, 0);
978 fdc
->sc_state
= MOTORWAIT
;
979 /* Allow .25s for motor to stabilize. */
980 callout_reset(&fd
->sc_motoron_ch
, hz
/ 4,
984 /* Make sure the right drive is selected. */
985 fd_set_motor(fdc
, 0);
990 if (fd
->sc_cylin
== bp
->b_cylinder
)
993 out_fdc(NE7CMD_SPECIFY
);/* specify command */
994 out_fdc(fd
->sc_type
->steprate
);
995 out_fdc(0x7); /* XXX head load time == 6ms - non-DMA */
999 out_fdc(NE7CMD_SEEK
); /* seek function */
1000 out_fdc(fd
->sc_drive
); /* drive number */
1001 out_fdc(bp
->b_cylinder
* fd
->sc_type
->step
);
1004 fdc
->sc_state
= SEEKWAIT
;
1006 iostat_seek(fd
->sc_dk
.dk_stats
);
1007 disk_busy(&fd
->sc_dk
);
1009 callout_reset(&fdc
->sc_timo_ch
, 4 * hz
, fdctimeout
, fdc
);
1015 fd
->sc_skip
= (char *)&(finfo
->fd_formb_cylno(0)) -
1019 sec
= fd
->sc_blkno
% type
->seccyl
;
1020 head
= sec
/ type
->sectrac
;
1021 sec
-= head
* type
->sectrac
;
1022 nblks
= type
->sectrac
- sec
;
1023 nblks
= min(nblks
, fd
->sc_bcount
/ FDC_BSIZE
);
1024 nblks
= min(nblks
, FDC_MAXIOSIZE
/ FDC_BSIZE
);
1025 fd
->sc_nblks
= nblks
;
1026 fd
->sc_nbytes
= finfo
? bp
->b_bcount
: nblks
* FDC_BSIZE
;
1031 block
= (fd
->sc_cylin
* type
->heads
+ head
)
1032 * type
->sectrac
+ sec
;
1033 if (block
!= fd
->sc_blkno
) {
1034 printf("fdcintr: block %d != blkno %qd\n",
1035 block
, fd
->sc_blkno
);
1042 read
= bp
->b_flags
& B_READ
? 1 : 0;
1045 * Setup pseudo-DMA address & count
1047 fddmaaddr
= (char *)bp
->b_data
+ fd
->sc_skip
;
1048 fddmalen
= fd
->sc_nbytes
;
1050 wrt_fdc_reg(fdctl
, type
->rate
);
1052 printf("fdcintr: %s drive %d track %d head %d sec %d"
1053 " nblks %d\n", read
? "read" : "write",
1054 fd
->sc_drive
, fd
->sc_cylin
, head
, sec
, nblks
);
1060 if (out_fdc(NE7CMD_FORMAT
) < 0) {
1065 out_fdc((head
<< 2) | fd
->sc_drive
);
1066 out_fdc(finfo
->fd_formb_secshift
);
1067 out_fdc(finfo
->fd_formb_nsecs
);
1068 out_fdc(finfo
->fd_formb_gaplen
);
1069 out_fdc(finfo
->fd_formb_fillbyte
);
1072 out_fdc(NE7CMD_READ
); /* READ */
1074 out_fdc(NE7CMD_WRITE
); /* WRITE */
1075 out_fdc((head
<< 2) | fd
->sc_drive
);
1076 out_fdc(fd
->sc_cylin
); /* track */
1077 out_fdc(head
); /* head */
1078 out_fdc(sec
+ 1); /* sector +1 */
1079 out_fdc(type
->secsize
); /* sector size */
1080 out_fdc(sec
+ nblks
); /* last sectors */
1081 out_fdc(type
->gap1
); /* gap1 size */
1082 out_fdc(type
->datalen
); /* data length */
1084 fdc
->sc_state
= IOCOMPLETE
;
1086 disk_busy(&fd
->sc_dk
);
1088 /* allow 2 seconds for operation */
1089 callout_reset(&fdc
->sc_timo_ch
, 2 * hz
, fdctimeout
, fdc
);
1090 return 1; /* will return later */
1093 callout_stop(&fdc
->sc_timo_ch
);
1094 fdc
->sc_state
= SEEKCOMPLETE
;
1095 /* allow 1/50 second for heads to settle */
1096 callout_reset(&fdc
->sc_intr_ch
, hz
/ 50, fdcpseudointr
, fdc
);
1100 /* no data on seek */
1101 disk_unbusy(&fd
->sc_dk
, 0, 0);
1103 /* Make sure seek really happened. */
1104 out_fdc(NE7CMD_SENSEI
);
1105 if (fdcresult(fdc
) != 2 || (st0
& 0xf8) != 0x20 ||
1106 cyl
!= bp
->b_cylinder
* fd
->sc_type
->step
) {
1108 fdcstatus(&fd
->sc_dev
, 2, "seek failed");
1113 fd
->sc_cylin
= bp
->b_cylinder
;
1123 case IOCOMPLETE
: /* IO DONE, post-analyze */
1124 callout_stop(&fdc
->sc_timo_ch
);
1126 disk_unbusy(&fd
->sc_dk
, (bp
->b_bcount
- bp
->b_resid
),
1127 (bp
->b_flags
& B_READ
));
1129 if (fdcresult(fdc
) != 7 || (st1
& 0x37) != 0) {
1131 * As the damn chip doesn't seem to have a FIFO,
1132 * accept a few overruns as a fact of life *sigh*
1134 if ((st1
& 0x10) && (++fdc
->sc_overruns
< 4)) {
1135 fdc
->sc_state
= DOSEEK
;
1139 fdcstatus(&fd
->sc_dev
, 7, bp
->b_flags
& B_READ
?
1140 "read failed" : "write failed");
1141 printf("blkno %qd nblks %d\n",
1142 fd
->sc_blkno
, fd
->sc_nblks
);
1147 if (fdc
->sc_errors
) {
1148 diskerr(bp
, "fd", "soft error", LOG_PRINTF
,
1149 fd
->sc_skip
/ FDC_BSIZE
, (struct disklabel
*)NULL
);
1153 fdc
->sc_overruns
= 0;
1154 fd
->sc_blkno
+= fd
->sc_nblks
;
1155 fd
->sc_skip
+= fd
->sc_nbytes
;
1156 fd
->sc_bcount
-= fd
->sc_nbytes
;
1157 if (!finfo
&& fd
->sc_bcount
> 0) {
1158 bp
->b_cylinder
= fd
->sc_blkno
/ fd
->sc_type
->seccyl
;
1165 /* try a reset, keep motor on */
1166 fd_set_motor(fdc
, 1);
1168 fd_set_motor(fdc
, 0);
1169 fdc
->sc_state
= RESETCOMPLETE
;
1170 callout_reset(&fdc
->sc_timo_ch
, hz
/ 2, fdctimeout
, fdc
);
1171 return 1; /* will return later */
1174 callout_stop(&fdc
->sc_timo_ch
);
1175 /* clear the controller output buffer */
1176 for (i
= 0; i
< 4; i
++) {
1177 out_fdc(NE7CMD_SENSEI
);
1178 (void) fdcresult(fdc
);
1185 out_fdc(NE7CMD_RECAL
); /* recalibrate function */
1186 out_fdc(fd
->sc_drive
);
1187 fdc
->sc_state
= RECALWAIT
;
1188 callout_reset(&fdc
->sc_timo_ch
, 5 * hz
, fdctimeout
, fdc
);
1189 return 1; /* will return later */
1192 callout_stop(&fdc
->sc_timo_ch
);
1193 fdc
->sc_state
= RECALCOMPLETE
;
1194 /* allow 1/30 second for heads to settle */
1195 callout_reset(&fdc
->sc_intr_ch
, hz
/ 30, fdcpseudointr
, fdc
);
1196 return 1; /* will return later */
1199 out_fdc(NE7CMD_SENSEI
);
1200 if (fdcresult(fdc
) != 2 || (st0
& 0xf8) != 0x20 || cyl
!= 0) {
1202 fdcstatus(&fd
->sc_dev
, 2, "recalibrate failed");
1211 if (fd
->sc_flags
& FD_MOTOR_WAIT
)
1212 return 1; /* time's not up yet */
1216 fdcstatus(&fd
->sc_dev
, 0, "stray interrupt");
1220 panic("fdcintr: impossible");
1228 fdcretry(struct fdc_softc
*fdc
)
1230 struct fd_softc
*fd
;
1233 fd
= fdc
->sc_drives
.tqh_first
;
1234 bp
= bufq_peek(fd
->sc_q
);
1236 if (fd
->sc_opts
& FDOPT_NORETRY
)
1239 switch (fdc
->sc_errors
) {
1242 fdc
->sc_state
= DOSEEK
;
1245 case 1: case 2: case 3:
1246 /* didn't work; try recalibrating */
1247 fdc
->sc_state
= DORECAL
;
1251 /* still no go; reset the bastard */
1252 fdc
->sc_state
= DORESET
;
1257 if ((fd
->sc_opts
& FDOPT_SILENT
) == 0) {
1258 diskerr(bp
, "fd", "hard error", LOG_PRINTF
,
1259 fd
->sc_skip
/ FDC_BSIZE
,
1260 (struct disklabel
*)NULL
);
1270 fdioctl(dev_t dev
, u_long cmd
, void *addr
, int flag
, struct lwp
*l
)
1272 struct fd_softc
*fd
;
1273 struct disklabel buffer
;
1275 struct fdformat_parms
*form_parms
;
1276 struct fdformat_cmd
*form_cmd
;
1277 struct ne7_fd_formb
*fd_formb
;
1278 unsigned int scratch
;
1279 int il
[FD_MAX_NSEC
+ 1];
1282 fd
= device_lookup_private(&hdfd_cd
, FDUNIT(dev
));
1286 fdgetdisklabel(fd
, dev
);
1287 *(struct disklabel
*)addr
= *(fd
->sc_dk
.dk_label
);
1291 fdgetdisklabel(fd
, dev
);
1292 ((struct partinfo
*)addr
)->disklab
= fd
->sc_dk
.dk_label
;
1293 ((struct partinfo
*)addr
)->part
=
1294 &fd
->sc_dk
.dk_label
->d_partitions
[RAW_PART
];
1298 if ((flag
& FWRITE
) == 0)
1300 /* XXX do something */
1305 if ((flag
& FWRITE
) == 0)
1308 fd
->sc_flags
&= ~FD_HAVELAB
; /* Invalid */
1309 error
= setdisklabel(&buffer
, (struct disklabel
*)addr
, 0,NULL
);
1313 if (cmd
== DIOCWDINFO
)
1314 error
= writedisklabel(dev
, fdstrategy
, &buffer
, NULL
);
1317 case FDIOCGETFORMAT
:
1318 form_parms
= (struct fdformat_parms
*)addr
;
1319 form_parms
->fdformat_version
= FDFORMAT_VERSION
;
1320 form_parms
->nbps
= 128 * (1 << fd
->sc_type
->secsize
);
1321 form_parms
->ncyl
= fd
->sc_type
->tracks
;
1322 form_parms
->nspt
= fd
->sc_type
->sectrac
;
1323 form_parms
->ntrk
= fd
->sc_type
->heads
;
1324 form_parms
->stepspercyl
= fd
->sc_type
->step
;
1325 form_parms
->gaplen
= fd
->sc_type
->gap2
;
1326 form_parms
->fillbyte
= fd
->sc_type
->fillbyte
;
1327 form_parms
->interleave
= fd
->sc_type
->interleave
;
1328 switch (fd
->sc_type
->rate
) {
1330 form_parms
->xfer_rate
= 500 * 1024;
1333 form_parms
->xfer_rate
= 300 * 1024;
1336 form_parms
->xfer_rate
= 250 * 1024;
1339 form_parms
->xfer_rate
= 125 * 1024;
1346 case FDIOCSETFORMAT
:
1347 if((flag
& FWRITE
) == 0)
1348 return EBADF
; /* must be opened for writing */
1349 form_parms
= (struct fdformat_parms
*)addr
;
1350 if (form_parms
->fdformat_version
!= FDFORMAT_VERSION
)
1351 return EINVAL
; /* wrong version of formatting prog */
1353 scratch
= form_parms
->nbps
>> 7;
1354 if ((form_parms
->nbps
& 0x7f) || ffs(scratch
) == 0 ||
1355 scratch
& ~(1 << (ffs(scratch
)-1)))
1356 /* not a power-of-two multiple of 128 */
1359 switch (form_parms
->xfer_rate
) {
1361 fd
->sc_type
->rate
= FDC_500KBPS
;
1364 fd
->sc_type
->rate
= FDC_300KBPS
;
1367 fd
->sc_type
->rate
= FDC_250KBPS
;
1370 fd
->sc_type
->rate
= FDC_125KBPS
;
1376 if (form_parms
->nspt
> FD_MAX_NSEC
||
1377 form_parms
->fillbyte
> 0xff ||
1378 form_parms
->interleave
> 0xff)
1380 fd
->sc_type
->sectrac
= form_parms
->nspt
;
1381 if (form_parms
->ntrk
!= 2 && form_parms
->ntrk
!= 1)
1383 fd
->sc_type
->heads
= form_parms
->ntrk
;
1384 fd
->sc_type
->seccyl
= form_parms
->nspt
* form_parms
->ntrk
;
1385 fd
->sc_type
->secsize
= ffs(scratch
)-1;
1386 fd
->sc_type
->gap2
= form_parms
->gaplen
;
1387 fd
->sc_type
->tracks
= form_parms
->ncyl
;
1388 fd
->sc_type
->size
= fd
->sc_type
->seccyl
* form_parms
->ncyl
*
1389 form_parms
->nbps
/ DEV_BSIZE
;
1390 fd
->sc_type
->step
= form_parms
->stepspercyl
;
1391 fd
->sc_type
->fillbyte
= form_parms
->fillbyte
;
1392 fd
->sc_type
->interleave
= form_parms
->interleave
;
1395 case FDIOCFORMAT_TRACK
:
1396 if((flag
& FWRITE
) == 0)
1397 return EBADF
; /* must be opened for writing */
1398 form_cmd
= (struct fdformat_cmd
*)addr
;
1399 if (form_cmd
->formatcmd_version
!= FDFORMAT_VERSION
)
1400 return EINVAL
; /* wrong version of formatting prog */
1402 if (form_cmd
->head
>= fd
->sc_type
->heads
||
1403 form_cmd
->cylinder
>= fd
->sc_type
->tracks
) {
1407 fd_formb
= malloc(sizeof(struct ne7_fd_formb
),
1412 fd_formb
->head
= form_cmd
->head
;
1413 fd_formb
->cyl
= form_cmd
->cylinder
;
1414 fd_formb
->transfer_rate
= fd
->sc_type
->rate
;
1415 fd_formb
->fd_formb_secshift
= fd
->sc_type
->secsize
;
1416 fd_formb
->fd_formb_nsecs
= fd
->sc_type
->sectrac
;
1417 fd_formb
->fd_formb_gaplen
= fd
->sc_type
->gap2
;
1418 fd_formb
->fd_formb_fillbyte
= fd
->sc_type
->fillbyte
;
1420 memset(il
, 0,sizeof il
);
1421 for (j
= 0, i
= 1; i
<= fd_formb
->fd_formb_nsecs
; i
++) {
1422 while (il
[(j
%fd_formb
->fd_formb_nsecs
)+1])
1424 il
[(j
%fd_formb
->fd_formb_nsecs
)+1] = i
;
1425 j
+= fd
->sc_type
->interleave
;
1427 for (i
= 0; i
< fd_formb
->fd_formb_nsecs
; i
++) {
1428 fd_formb
->fd_formb_cylno(i
) = form_cmd
->cylinder
;
1429 fd_formb
->fd_formb_headno(i
) = form_cmd
->head
;
1430 fd_formb
->fd_formb_secno(i
) = il
[i
+1];
1431 fd_formb
->fd_formb_secsize(i
) = fd
->sc_type
->secsize
;
1434 error
= fdformat(dev
, fd_formb
, l
->l_proc
);
1435 free(fd_formb
, M_TEMP
);
1438 case FDIOCGETOPTS
: /* get drive options */
1439 *(int *)addr
= fd
->sc_opts
;
1442 case FDIOCSETOPTS
: /* set drive options */
1443 fd
->sc_opts
= *(int *)addr
;
1452 panic("fdioctl: impossible");
1457 fdformat(dev_t dev
, struct ne7_fd_formb
*finfo
, struct proc
*p
)
1460 struct fd_softc
*fd
= device_lookup_private(&hdfd_cd
, FDUNIT(dev
));
1461 struct fd_type
*type
= fd
->sc_type
;
1464 /* set up a buffer header for fdstrategy() */
1465 bp
= getiobuf(NULL
, false);
1468 memset((void *)bp
, 0, sizeof(struct buf
));
1469 bp
->b_flags
= B_PHYS
| B_FORMAT
;
1470 bp
->b_cflags
|= BC_BUSY
;
1475 * calculate a fake blkno, so fdstrategy() would initiate a
1476 * seek to the requested cylinder
1478 bp
->b_blkno
= (finfo
->cyl
* (type
->sectrac
* type
->heads
)
1479 + finfo
->head
* type
->sectrac
) * FDC_BSIZE
/ DEV_BSIZE
;
1481 bp
->b_bcount
= sizeof(struct fd_idfield_data
) * finfo
->fd_formb_nsecs
;
1482 bp
->b_data
= (void *)finfo
;
1485 printf("fdformat: blkno %x count %lx\n", bp
->b_blkno
, bp
->b_bcount
);
1488 /* now do the format */
1491 /* ...and wait for it to complete */
1492 mutex_enter(bp
->b_objlock
);
1493 while(!(bp
->b_oflags
& BO_DONE
)) {
1494 rv
= cv_timedwait(&bp
->b_done
, bp
->b_objlock
, 20 * hz
);
1495 if (rv
== EWOULDBLOCK
)
1498 mutex_exit(bp
->b_objlock
);
1500 if (rv
== EWOULDBLOCK
) {
1504 } else if (bp
->b_error
!= 0) {
1513 * Obtain a disklabel. Either a real one from the disk or, if there
1514 * is none, a fake one.
1517 fdgetdisklabel(struct fd_softc
*fd
, dev_t dev
)
1519 struct disklabel
*lp
;
1520 struct cpu_disklabel cpulab
;
1522 if (fd
->sc_flags
& FD_HAVELAB
)
1523 return; /* Already got one */
1525 lp
= fd
->sc_dk
.dk_label
;
1527 memset(lp
, 0, sizeof(*lp
));
1528 memset(&cpulab
, 0, sizeof(cpulab
));
1530 lp
->d_secpercyl
= fd
->sc_type
->seccyl
;
1531 lp
->d_type
= DTYPE_FLOPPY
;
1532 lp
->d_secsize
= FDC_BSIZE
;
1533 lp
->d_secperunit
= fd
->sc_type
->size
;
1536 * If there is no label on the disk: fake one
1538 if (readdisklabel(dev
, fdstrategy
, lp
, &cpulab
) != NULL
)
1539 fdgetdefaultlabel(fd
, lp
, RAW_PART
);
1540 fd
->sc_flags
|= FD_HAVELAB
;
1542 if ((FDC_BSIZE
* fd
->sc_type
->size
)
1543 < (lp
->d_secsize
* lp
->d_secperunit
)) {
1545 * XXX: Ignore these fields. If you drop a vnddisk
1546 * on more than one floppy, you'll get disturbing
1549 lp
->d_secpercyl
= fd
->sc_type
->seccyl
;
1550 lp
->d_type
= DTYPE_FLOPPY
;
1551 lp
->d_secsize
= FDC_BSIZE
;
1552 lp
->d_secperunit
= fd
->sc_type
->size
;
1557 * Build defaultdisk label. For now we only create a label from what we
1561 fdgetdefaultlabel(struct fd_softc
*fd
, struct disklabel
*lp
, int part
)
1563 memset(lp
, 0, sizeof(struct disklabel
));
1565 lp
->d_secsize
= 128 * (1 << fd
->sc_type
->secsize
);
1566 lp
->d_ntracks
= fd
->sc_type
->heads
;
1567 lp
->d_nsectors
= fd
->sc_type
->sectrac
;
1568 lp
->d_secpercyl
= lp
->d_ntracks
* lp
->d_nsectors
;
1569 lp
->d_ncylinders
= fd
->sc_type
->size
/ lp
->d_secpercyl
;
1570 lp
->d_secperunit
= fd
->sc_type
->size
;
1572 lp
->d_type
= DTYPE_FLOPPY
;
1573 lp
->d_rpm
= 300; /* good guess I suppose. */
1574 lp
->d_interleave
= 1; /* FIXME: is this OK? */
1577 lp
->d_npartitions
= part
+ 1;
1578 lp
->d_trkseek
= 6000; /* Who cares... */
1579 lp
->d_magic
= DISKMAGIC
;
1580 lp
->d_magic2
= DISKMAGIC
;
1581 lp
->d_checksum
= dkcksum(lp
);
1582 lp
->d_partitions
[part
].p_size
= lp
->d_secperunit
;
1583 lp
->d_partitions
[part
].p_fstype
= FS_UNUSED
;
1584 lp
->d_partitions
[part
].p_fsize
= 1024;
1585 lp
->d_partitions
[part
].p_frag
= 8;