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