Home | History | Annotate | Line # | Download | only in mca
ed_mca.c revision 1.7.2.2
      1  1.7.2.2  nathanw /*	$NetBSD: ed_mca.c,v 1.7.2.2 2001/06/21 20:03:59 nathanw Exp $	*/
      2  1.7.2.2  nathanw 
      3  1.7.2.2  nathanw /*
      4  1.7.2.2  nathanw  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  1.7.2.2  nathanw  *
      6  1.7.2.2  nathanw  * This code is derived from software contributed to The NetBSD Foundation
      7  1.7.2.2  nathanw  * by Jaromir Dolecek.
      8  1.7.2.2  nathanw  *
      9  1.7.2.2  nathanw  * Redistribution and use in source and binary forms, with or without
     10  1.7.2.2  nathanw  * modification, are permitted provided that the following conditions
     11  1.7.2.2  nathanw  * are met:
     12  1.7.2.2  nathanw  * 1. Redistributions of source code must retain the above copyright
     13  1.7.2.2  nathanw  *    notice, this list of conditions and the following disclaimer.
     14  1.7.2.2  nathanw  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.7.2.2  nathanw  *    notice, this list of conditions and the following disclaimer in the
     16  1.7.2.2  nathanw  *    documentation and/or other materials provided with the distribution.
     17  1.7.2.2  nathanw  * 3. All advertising materials mentioning features or use of this software
     18  1.7.2.2  nathanw  *    must display the following acknowledgement:
     19  1.7.2.2  nathanw  *        This product includes software developed by the NetBSD
     20  1.7.2.2  nathanw  *        Foundation, Inc. and its contributors.
     21  1.7.2.2  nathanw  * 4. The name of the author may not be used to endorse or promote products
     22  1.7.2.2  nathanw  *    derived from this software without specific prior written permission.
     23  1.7.2.2  nathanw  *
     24  1.7.2.2  nathanw  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     25  1.7.2.2  nathanw  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     26  1.7.2.2  nathanw  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     27  1.7.2.2  nathanw  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     28  1.7.2.2  nathanw  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     29  1.7.2.2  nathanw  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     30  1.7.2.2  nathanw  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     31  1.7.2.2  nathanw  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     32  1.7.2.2  nathanw  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     33  1.7.2.2  nathanw  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34  1.7.2.2  nathanw  */
     35  1.7.2.2  nathanw 
     36  1.7.2.2  nathanw /*
     37  1.7.2.2  nathanw  * Disk goo for MCA ESDI controller driver.
     38  1.7.2.2  nathanw  */
     39  1.7.2.2  nathanw 
     40  1.7.2.2  nathanw #include "rnd.h"
     41  1.7.2.2  nathanw 
     42  1.7.2.2  nathanw #include <sys/param.h>
     43  1.7.2.2  nathanw #include <sys/systm.h>
     44  1.7.2.2  nathanw #include <sys/kernel.h>
     45  1.7.2.2  nathanw #include <sys/conf.h>
     46  1.7.2.2  nathanw #include <sys/file.h>
     47  1.7.2.2  nathanw #include <sys/stat.h>
     48  1.7.2.2  nathanw #include <sys/ioctl.h>
     49  1.7.2.2  nathanw #include <sys/buf.h>
     50  1.7.2.2  nathanw #include <sys/uio.h>
     51  1.7.2.2  nathanw #include <sys/malloc.h>
     52  1.7.2.2  nathanw #include <sys/device.h>
     53  1.7.2.2  nathanw #include <sys/disklabel.h>
     54  1.7.2.2  nathanw #include <sys/disk.h>
     55  1.7.2.2  nathanw #include <sys/syslog.h>
     56  1.7.2.2  nathanw #include <sys/proc.h>
     57  1.7.2.2  nathanw #include <sys/vnode.h>
     58  1.7.2.2  nathanw #include <sys/kthread.h>
     59  1.7.2.2  nathanw #if NRND > 0
     60  1.7.2.2  nathanw #include <sys/rnd.h>
     61  1.7.2.2  nathanw #endif
     62  1.7.2.2  nathanw 
     63  1.7.2.2  nathanw #include <machine/intr.h>
     64  1.7.2.2  nathanw #include <machine/bus.h>
     65  1.7.2.2  nathanw 
     66  1.7.2.2  nathanw #include <dev/mca/mcavar.h>
     67  1.7.2.2  nathanw 
     68  1.7.2.2  nathanw #include <dev/mca/edcreg.h>
     69  1.7.2.2  nathanw #include <dev/mca/edvar.h>
     70  1.7.2.2  nathanw #include <dev/mca/edcvar.h>
     71  1.7.2.2  nathanw 
     72  1.7.2.2  nathanw /* #define WDCDEBUG */
     73  1.7.2.2  nathanw 
     74  1.7.2.2  nathanw #ifdef WDCDEBUG
     75  1.7.2.2  nathanw #define WDCDEBUG_PRINT(args, level)  printf args
     76  1.7.2.2  nathanw #else
     77  1.7.2.2  nathanw #define WDCDEBUG_PRINT(args, level)
     78  1.7.2.2  nathanw #endif
     79  1.7.2.2  nathanw 
     80  1.7.2.2  nathanw #define	EDLABELDEV(dev) (MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART))
     81  1.7.2.2  nathanw 
     82  1.7.2.2  nathanw /* XXX: these should go elsewhere */
     83  1.7.2.2  nathanw cdev_decl(edmca);
     84  1.7.2.2  nathanw bdev_decl(edmca);
     85  1.7.2.2  nathanw 
     86  1.7.2.2  nathanw static int     ed_mca_probe   __P((struct device *, struct cfdata *, void *));
     87  1.7.2.2  nathanw static void    ed_mca_attach  __P((struct device *, struct device *, void *));
     88  1.7.2.2  nathanw 
     89  1.7.2.2  nathanw struct cfattach ed_mca_ca = {
     90  1.7.2.2  nathanw 	sizeof(struct ed_softc), ed_mca_probe, ed_mca_attach
     91  1.7.2.2  nathanw };
     92  1.7.2.2  nathanw 
     93  1.7.2.2  nathanw extern struct cfdriver ed_cd;
     94  1.7.2.2  nathanw 
     95  1.7.2.2  nathanw static int	ed_get_params __P((struct ed_softc *));
     96  1.7.2.2  nathanw static int	ed_lock	__P((struct ed_softc *));
     97  1.7.2.2  nathanw static void	ed_unlock	__P((struct ed_softc *));
     98  1.7.2.2  nathanw static void	edgetdisklabel	__P((struct ed_softc *));
     99  1.7.2.2  nathanw static void	edgetdefaultlabel __P((struct ed_softc *, struct disklabel *));
    100  1.7.2.2  nathanw static void	ed_shutdown __P((void*));
    101  1.7.2.2  nathanw static void	__edstart __P((struct ed_softc*, struct buf *));
    102  1.7.2.2  nathanw static void	bad144intern __P((struct ed_softc *));
    103  1.7.2.2  nathanw static void	edworker __P((void *));
    104  1.7.2.2  nathanw static void	ed_spawn_worker __P((void *));
    105  1.7.2.2  nathanw static void	edmcadone __P((struct ed_softc *, struct buf *));
    106  1.7.2.2  nathanw static void	ed_bio __P((struct ed_softc *, int, int));
    107  1.7.2.2  nathanw static void	ed_bio_done __P((struct ed_softc *));
    108  1.7.2.2  nathanw 
    109  1.7.2.2  nathanw static struct dkdriver eddkdriver = { edmcastrategy };
    110  1.7.2.2  nathanw 
    111  1.7.2.2  nathanw /*
    112  1.7.2.2  nathanw  * Just check if it's possible to identify the disk.
    113  1.7.2.2  nathanw  */
    114  1.7.2.2  nathanw static int
    115  1.7.2.2  nathanw ed_mca_probe(parent, match, aux)
    116  1.7.2.2  nathanw 	struct device *parent;
    117  1.7.2.2  nathanw 	struct cfdata *match;
    118  1.7.2.2  nathanw 	void *aux;
    119  1.7.2.2  nathanw {
    120  1.7.2.2  nathanw 	u_int16_t cmd_args[2];
    121  1.7.2.2  nathanw 	struct edc_mca_softc *sc = (void *) parent;
    122  1.7.2.2  nathanw 	struct ed_attach_args *eda = (void *) aux;
    123  1.7.2.2  nathanw 	int found = 1;
    124  1.7.2.2  nathanw 
    125  1.7.2.2  nathanw 	/*
    126  1.7.2.2  nathanw 	 * Get Device Configuration (09).
    127  1.7.2.2  nathanw 	 */
    128  1.7.2.2  nathanw 	cmd_args[0] = 14;	/* Options: 00s110, s: 0=Physical 1=Pseudo */
    129  1.7.2.2  nathanw 	cmd_args[1] = 0;
    130  1.7.2.2  nathanw 	if (edc_run_cmd(sc, CMD_GET_DEV_CONF, eda->sc_devno, cmd_args, 2, 0, 1))
    131  1.7.2.2  nathanw 		found = 0;
    132  1.7.2.2  nathanw 
    133  1.7.2.2  nathanw 	return (found);
    134  1.7.2.2  nathanw }
    135  1.7.2.2  nathanw 
    136  1.7.2.2  nathanw static void
    137  1.7.2.2  nathanw ed_mca_attach(parent, self, aux)
    138  1.7.2.2  nathanw 	struct device *parent, *self;
    139  1.7.2.2  nathanw 	void *aux;
    140  1.7.2.2  nathanw {
    141  1.7.2.2  nathanw 	struct ed_softc *ed = (void *) self;
    142  1.7.2.2  nathanw 	struct edc_mca_softc *sc = (void *) parent;
    143  1.7.2.2  nathanw 	struct ed_attach_args *eda = (void *) aux;
    144  1.7.2.2  nathanw 	char pbuf[8];
    145  1.7.2.2  nathanw 	int error, nsegs;
    146  1.7.2.2  nathanw 
    147  1.7.2.2  nathanw 	ed->edc_softc = sc;
    148  1.7.2.2  nathanw 	ed->sc_dmat = eda->sc_dmat;
    149  1.7.2.2  nathanw 	ed->sc_devno = eda->sc_devno;
    150  1.7.2.2  nathanw 	edc_add_disk(sc, ed, eda->sc_devno);
    151  1.7.2.2  nathanw 
    152  1.7.2.2  nathanw 	BUFQ_INIT(&ed->sc_q);
    153  1.7.2.2  nathanw 	spinlockinit(&ed->sc_q_lock, "edbqlock", 0);
    154  1.7.2.2  nathanw 	lockinit(&ed->sc_lock, PRIBIO | PCATCH, "edlck", 0, 0);
    155  1.7.2.2  nathanw 
    156  1.7.2.2  nathanw 	if (ed_get_params(ed)) {
    157  1.7.2.2  nathanw 		printf(": IDENTIFY failed, no disk found\n");
    158  1.7.2.2  nathanw 		return;
    159  1.7.2.2  nathanw 	}
    160  1.7.2.2  nathanw 
    161  1.7.2.2  nathanw 	format_bytes(pbuf, sizeof(pbuf),
    162  1.7.2.2  nathanw 		(u_int64_t) ed->sc_capacity * DEV_BSIZE);
    163  1.7.2.2  nathanw 	printf(": %s, %u cyl, %u head, %u sec, 512 bytes/sect x %u sectors\n",
    164  1.7.2.2  nathanw 		pbuf,
    165  1.7.2.2  nathanw 		ed->cyl, ed->heads, ed->sectors,
    166  1.7.2.2  nathanw 		ed->sc_capacity);
    167  1.7.2.2  nathanw 
    168  1.7.2.2  nathanw 	printf("%s: %u spares/cyl, %s, %s, %s, %s, %s\n",
    169  1.7.2.2  nathanw 		ed->sc_dev.dv_xname, ed->spares,
    170  1.7.2.2  nathanw 		(ed->drv_flags & (1 << 0)) ? "NoRetries" : "Retries",
    171  1.7.2.2  nathanw 		(ed->drv_flags & (1 << 1)) ? "Removable" : "Fixed",
    172  1.7.2.2  nathanw 		(ed->drv_flags & (1 << 2)) ? "SkewedFormat" : "NoSkew",
    173  1.7.2.2  nathanw 		(ed->drv_flags & (1 << 3)) ? "ZeroDefect" : "Defects",
    174  1.7.2.2  nathanw 		(ed->drv_flags & (1 << 4)) ? "InvalidSecondary" : "SecondaryOK"
    175  1.7.2.2  nathanw 		);
    176  1.7.2.2  nathanw 
    177  1.7.2.2  nathanw 	/* Create a DMA map for mapping individual transfer bufs */
    178  1.7.2.2  nathanw 	if ((error = bus_dmamap_create(ed->sc_dmat, 65536, 1,
    179  1.7.2.2  nathanw 		65536, 65536, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
    180  1.7.2.2  nathanw 		&ed->dmamap_xfer)) != 0) {
    181  1.7.2.2  nathanw 		printf("%s: unable to create xfer DMA map, error=%d\n",
    182  1.7.2.2  nathanw 			ed->sc_dev.dv_xname, error);
    183  1.7.2.2  nathanw 		return;
    184  1.7.2.2  nathanw 	}
    185  1.7.2.2  nathanw 
    186  1.7.2.2  nathanw 	/*
    187  1.7.2.2  nathanw 	 * Allocate DMA memory used in case where passed buf isn't
    188  1.7.2.2  nathanw 	 * physically contiguous.
    189  1.7.2.2  nathanw 	 */
    190  1.7.2.2  nathanw 	ed->sc_dmam_sz = MAXPHYS;
    191  1.7.2.2  nathanw 	if ((error = bus_dmamem_alloc(ed->sc_dmat, ed->sc_dmam_sz,
    192  1.7.2.2  nathanw 		ed->sc_dmam_sz, 65536, ed->sc_dmam, 1, &nsegs,
    193  1.7.2.2  nathanw 		BUS_DMA_WAITOK|BUS_DMA_STREAMING)) != 0) {
    194  1.7.2.2  nathanw 		printf("%s: unable to allocate DMA memory for xfer, errno=%d\n",
    195  1.7.2.2  nathanw 				ed->sc_dev.dv_xname, error);
    196  1.7.2.2  nathanw 		bus_dmamap_destroy(ed->sc_dmat, ed->dmamap_xfer);
    197  1.7.2.2  nathanw 		return;
    198  1.7.2.2  nathanw 	}
    199  1.7.2.2  nathanw 	/*
    200  1.7.2.2  nathanw 	 * Map the memory.
    201  1.7.2.2  nathanw 	 */
    202  1.7.2.2  nathanw 	if ((error = bus_dmamem_map(ed->sc_dmat, ed->sc_dmam, 1,
    203  1.7.2.2  nathanw 		ed->sc_dmam_sz, &ed->sc_dmamkva, BUS_DMA_WAITOK)) != 0) {
    204  1.7.2.2  nathanw 		printf("%s: unable to map DMA memory, error=%d\n",
    205  1.7.2.2  nathanw 			ed->sc_dev.dv_xname, error);
    206  1.7.2.2  nathanw 		bus_dmamem_free(ed->sc_dmat, ed->sc_dmam, 1);
    207  1.7.2.2  nathanw 		bus_dmamap_destroy(ed->sc_dmat, ed->dmamap_xfer);
    208  1.7.2.2  nathanw 		return;
    209  1.7.2.2  nathanw 	}
    210  1.7.2.2  nathanw 
    211  1.7.2.2  nathanw 
    212  1.7.2.2  nathanw 	/*
    213  1.7.2.2  nathanw 	 * Initialize and attach the disk structure.
    214  1.7.2.2  nathanw 	 */
    215  1.7.2.2  nathanw 	ed->sc_dk.dk_driver = &eddkdriver;
    216  1.7.2.2  nathanw 	ed->sc_dk.dk_name = ed->sc_dev.dv_xname;
    217  1.7.2.2  nathanw 	disk_attach(&ed->sc_dk);
    218  1.7.2.2  nathanw #if 0
    219  1.7.2.2  nathanw 	wd->sc_wdc_bio.lp = wd->sc_dk.dk_label;
    220  1.7.2.2  nathanw #endif
    221  1.7.2.2  nathanw 	ed->sc_sdhook = shutdownhook_establish(ed_shutdown, ed);
    222  1.7.2.2  nathanw 	if (ed->sc_sdhook == NULL)
    223  1.7.2.2  nathanw 		printf("%s: WARNING: unable to establish shutdown hook\n",
    224  1.7.2.2  nathanw 		    ed->sc_dev.dv_xname);
    225  1.7.2.2  nathanw #if NRND > 0
    226  1.7.2.2  nathanw 	rnd_attach_source(&ed->rnd_source, ed->sc_dev.dv_xname,
    227  1.7.2.2  nathanw 			  RND_TYPE_DISK, 0);
    228  1.7.2.2  nathanw #endif
    229  1.7.2.2  nathanw 
    230  1.7.2.2  nathanw 	config_pending_incr();
    231  1.7.2.2  nathanw 	kthread_create(ed_spawn_worker, (void *) ed);
    232  1.7.2.2  nathanw 
    233  1.7.2.2  nathanw 	ed->sc_flags |= EDF_INIT;
    234  1.7.2.2  nathanw }
    235  1.7.2.2  nathanw 
    236  1.7.2.2  nathanw void
    237  1.7.2.2  nathanw ed_spawn_worker(arg)
    238  1.7.2.2  nathanw 	void *arg;
    239  1.7.2.2  nathanw {
    240  1.7.2.2  nathanw 	struct ed_softc *ed = (struct ed_softc *) arg;
    241  1.7.2.2  nathanw 	int error;
    242  1.7.2.2  nathanw 
    243  1.7.2.2  nathanw 	/* Now, everything is ready, start a kthread */
    244  1.7.2.2  nathanw 	if ((error = kthread_create1(edworker, ed, &ed->sc_worker,
    245  1.7.2.2  nathanw 			"%s", ed->sc_dev.dv_xname))) {
    246  1.7.2.2  nathanw 		printf("%s: cannot spawn worker thread: errno=%d\n",
    247  1.7.2.2  nathanw 			ed->sc_dev.dv_xname, error);
    248  1.7.2.2  nathanw 		panic("ed_spawn_worker");
    249  1.7.2.2  nathanw 	}
    250  1.7.2.2  nathanw }
    251  1.7.2.2  nathanw 
    252  1.7.2.2  nathanw /*
    253  1.7.2.2  nathanw  * Read/write routine for a buffer.  Validates the arguments and schedules the
    254  1.7.2.2  nathanw  * transfer.  Does not wait for the transfer to complete.
    255  1.7.2.2  nathanw  */
    256  1.7.2.2  nathanw void
    257  1.7.2.2  nathanw edmcastrategy(bp)
    258  1.7.2.2  nathanw 	struct buf *bp;
    259  1.7.2.2  nathanw {
    260  1.7.2.2  nathanw 	struct ed_softc *wd = device_lookup(&ed_cd, DISKUNIT(bp->b_dev));
    261  1.7.2.2  nathanw 	struct disklabel *lp = wd->sc_dk.dk_label;
    262  1.7.2.2  nathanw 	daddr_t blkno;
    263  1.7.2.2  nathanw 	int s;
    264  1.7.2.2  nathanw 
    265  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("edmcastrategy (%s)\n", wd->sc_dev.dv_xname),
    266  1.7.2.2  nathanw 	    DEBUG_XFERS);
    267  1.7.2.2  nathanw 
    268  1.7.2.2  nathanw 	/* Valid request?  */
    269  1.7.2.2  nathanw 	if (bp->b_blkno < 0 ||
    270  1.7.2.2  nathanw 	    (bp->b_bcount % lp->d_secsize) != 0 ||
    271  1.7.2.2  nathanw 	    (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) {
    272  1.7.2.2  nathanw 		bp->b_error = EINVAL;
    273  1.7.2.2  nathanw 		goto bad;
    274  1.7.2.2  nathanw 	}
    275  1.7.2.2  nathanw 
    276  1.7.2.2  nathanw 	/* If device invalidated (e.g. media change, door open), error. */
    277  1.7.2.2  nathanw 	if ((wd->sc_flags & WDF_LOADED) == 0) {
    278  1.7.2.2  nathanw 		bp->b_error = EIO;
    279  1.7.2.2  nathanw 		goto bad;
    280  1.7.2.2  nathanw 	}
    281  1.7.2.2  nathanw 
    282  1.7.2.2  nathanw 	/* If it's a null transfer, return immediately. */
    283  1.7.2.2  nathanw 	if (bp->b_bcount == 0)
    284  1.7.2.2  nathanw 		goto done;
    285  1.7.2.2  nathanw 
    286  1.7.2.2  nathanw 	/*
    287  1.7.2.2  nathanw 	 * Do bounds checking, adjust transfer. if error, process.
    288  1.7.2.2  nathanw 	 * If end of partition, just return.
    289  1.7.2.2  nathanw 	 */
    290  1.7.2.2  nathanw 	if (DISKPART(bp->b_dev) != RAW_PART &&
    291  1.7.2.2  nathanw 	    bounds_check_with_label(bp, wd->sc_dk.dk_label,
    292  1.7.2.2  nathanw 	    (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
    293  1.7.2.2  nathanw 		goto done;
    294  1.7.2.2  nathanw 
    295  1.7.2.2  nathanw 	/*
    296  1.7.2.2  nathanw 	 * Now convert the block number to absolute and put it in
    297  1.7.2.2  nathanw 	 * terms of the device's logical block size.
    298  1.7.2.2  nathanw 	 */
    299  1.7.2.2  nathanw 	if (lp->d_secsize >= DEV_BSIZE)
    300  1.7.2.2  nathanw 		blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
    301  1.7.2.2  nathanw 	else
    302  1.7.2.2  nathanw 		blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
    303  1.7.2.2  nathanw 
    304  1.7.2.2  nathanw 	if (DISKPART(bp->b_dev) != RAW_PART)
    305  1.7.2.2  nathanw 		blkno += lp->d_partitions[DISKPART(bp->b_dev)].p_offset;
    306  1.7.2.2  nathanw 
    307  1.7.2.2  nathanw 	bp->b_rawblkno = blkno;
    308  1.7.2.2  nathanw 
    309  1.7.2.2  nathanw 	/* Queue transfer on drive, activate drive and controller if idle. */
    310  1.7.2.2  nathanw 	s = splbio();
    311  1.7.2.2  nathanw 	simple_lock(&wd->sc_q_lock);
    312  1.7.2.2  nathanw 	disksort_blkno(&wd->sc_q, bp);
    313  1.7.2.2  nathanw 	simple_unlock(&wd->sc_q_lock);
    314  1.7.2.2  nathanw 
    315  1.7.2.2  nathanw 	/* Ring the worker thread */
    316  1.7.2.2  nathanw 	wd->sc_flags |= EDF_PROCESS_QUEUE;
    317  1.7.2.2  nathanw 	wakeup_one(&wd->sc_q);
    318  1.7.2.2  nathanw 
    319  1.7.2.2  nathanw 	splx(s);
    320  1.7.2.2  nathanw 	return;
    321  1.7.2.2  nathanw bad:
    322  1.7.2.2  nathanw 	bp->b_flags |= B_ERROR;
    323  1.7.2.2  nathanw done:
    324  1.7.2.2  nathanw 	/* Toss transfer; we're done early. */
    325  1.7.2.2  nathanw 	bp->b_resid = bp->b_bcount;
    326  1.7.2.2  nathanw 	biodone(bp);
    327  1.7.2.2  nathanw }
    328  1.7.2.2  nathanw 
    329  1.7.2.2  nathanw static void
    330  1.7.2.2  nathanw ed_bio(struct ed_softc *ed, int async, int poll)
    331  1.7.2.2  nathanw {
    332  1.7.2.2  nathanw 	u_int16_t cmd_args[4];
    333  1.7.2.2  nathanw 	int error=0;
    334  1.7.2.2  nathanw 	u_int16_t track;
    335  1.7.2.2  nathanw 	u_int16_t cyl;
    336  1.7.2.2  nathanw 	u_int8_t head;
    337  1.7.2.2  nathanw 	u_int8_t sector;
    338  1.7.2.2  nathanw 
    339  1.7.2.2  nathanw 	/* Get physical bus mapping for buf. */
    340  1.7.2.2  nathanw 	if (bus_dmamap_load(ed->sc_dmat, ed->dmamap_xfer,
    341  1.7.2.2  nathanw 			ed->sc_data, ed->sc_bcount, NULL,
    342  1.7.2.2  nathanw 			BUS_DMA_WAITOK|BUS_DMA_STREAMING) != 0) {
    343  1.7.2.2  nathanw 
    344  1.7.2.2  nathanw 		/*
    345  1.7.2.2  nathanw 		 * Use our DMA safe memory to get data to/from device.
    346  1.7.2.2  nathanw 		 */
    347  1.7.2.2  nathanw 		if ((error = bus_dmamap_load(ed->sc_dmat, ed->dmamap_xfer,
    348  1.7.2.2  nathanw 			ed->sc_dmamkva, ed->sc_bcount, NULL,
    349  1.7.2.2  nathanw 			BUS_DMA_WAITOK|BUS_DMA_STREAMING)) != 0) {
    350  1.7.2.2  nathanw 			printf("%s: unable to load raw data for xfer, errno=%d\n",
    351  1.7.2.2  nathanw 				ed->sc_dev.dv_xname, error);
    352  1.7.2.2  nathanw 			goto out;
    353  1.7.2.2  nathanw 		}
    354  1.7.2.2  nathanw 		ed->sc_flags |= EDF_BOUNCEBUF;
    355  1.7.2.2  nathanw 
    356  1.7.2.2  nathanw 		/* If data write, copy the data to our bounce buffer. */
    357  1.7.2.2  nathanw 		if (!ed->sc_read)
    358  1.7.2.2  nathanw 			memcpy(ed->sc_dmamkva, ed->sc_data, ed->sc_bcount);
    359  1.7.2.2  nathanw 	}
    360  1.7.2.2  nathanw 
    361  1.7.2.2  nathanw 	ed->sc_flags |= EDF_DMAMAP_LOADED;
    362  1.7.2.2  nathanw 
    363  1.7.2.2  nathanw 	track = ed->sc_rawblkno / ed->sectors;
    364  1.7.2.2  nathanw 	head = track % ed->heads;
    365  1.7.2.2  nathanw 	cyl = track / ed->heads;
    366  1.7.2.2  nathanw 	sector = ed->sc_rawblkno % ed->sectors;
    367  1.7.2.2  nathanw 
    368  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("__edstart %s: map: %u %u %u\n", ed->sc_dev.dv_xname,
    369  1.7.2.2  nathanw 		cyl, sector, head),
    370  1.7.2.2  nathanw 	    DEBUG_XFERS);
    371  1.7.2.2  nathanw 
    372  1.7.2.2  nathanw 	mca_disk_busy();
    373  1.7.2.2  nathanw 
    374  1.7.2.2  nathanw 	/* Read or Write Data command */
    375  1.7.2.2  nathanw 	cmd_args[0] = 2;	/* Options 0000010 */
    376  1.7.2.2  nathanw 	cmd_args[1] = ed->sc_bcount / DEV_BSIZE;
    377  1.7.2.2  nathanw 	cmd_args[2] = ((cyl & 0x1f) << 11) | (head << 5) | sector;
    378  1.7.2.2  nathanw 	cmd_args[3] = ((cyl & 0x3E0) >> 5);
    379  1.7.2.2  nathanw 	if (edc_run_cmd(ed->edc_softc,
    380  1.7.2.2  nathanw 			(ed->sc_read) ? CMD_READ_DATA : CMD_WRITE_DATA,
    381  1.7.2.2  nathanw 			ed->sc_devno, cmd_args, 4, async, poll)) {
    382  1.7.2.2  nathanw 		printf("%s: data i/o command failed\n", ed->sc_dev.dv_xname);
    383  1.7.2.2  nathanw 		mca_disk_unbusy();
    384  1.7.2.2  nathanw 		error = EIO;
    385  1.7.2.2  nathanw 	}
    386  1.7.2.2  nathanw 
    387  1.7.2.2  nathanw     out:
    388  1.7.2.2  nathanw 	if (error)
    389  1.7.2.2  nathanw 		ed->sc_error = error;
    390  1.7.2.2  nathanw }
    391  1.7.2.2  nathanw 
    392  1.7.2.2  nathanw static void
    393  1.7.2.2  nathanw __edstart(ed, bp)
    394  1.7.2.2  nathanw 	struct ed_softc *ed;
    395  1.7.2.2  nathanw 	struct buf *bp;
    396  1.7.2.2  nathanw {
    397  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("__edstart %s (%s): %lu %lu %u\n", ed->sc_dev.dv_xname,
    398  1.7.2.2  nathanw 		(bp->b_flags & B_READ) ? "read" : "write",
    399  1.7.2.2  nathanw 		bp->b_bcount, bp->b_resid, bp->b_rawblkno),
    400  1.7.2.2  nathanw 	    DEBUG_XFERS);
    401  1.7.2.2  nathanw 
    402  1.7.2.2  nathanw 	/* Instrumentation. */
    403  1.7.2.2  nathanw 	disk_busy(&ed->sc_dk);
    404  1.7.2.2  nathanw 	ed->sc_flags |= EDF_DK_BUSY;
    405  1.7.2.2  nathanw 
    406  1.7.2.2  nathanw 	ed->sc_data = bp->b_data;
    407  1.7.2.2  nathanw 	ed->sc_rawblkno = bp->b_rawblkno;
    408  1.7.2.2  nathanw 	ed->sc_bcount = bp->b_bcount;
    409  1.7.2.2  nathanw 	ed->sc_read = bp->b_flags & B_READ;
    410  1.7.2.2  nathanw 	ed_bio(ed, 1, 0);
    411  1.7.2.2  nathanw }
    412  1.7.2.2  nathanw 
    413  1.7.2.2  nathanw static void
    414  1.7.2.2  nathanw ed_bio_done(ed)
    415  1.7.2.2  nathanw 	struct ed_softc *ed;
    416  1.7.2.2  nathanw {
    417  1.7.2.2  nathanw 	/*
    418  1.7.2.2  nathanw 	 * If read transfer finished without error and using a bounce
    419  1.7.2.2  nathanw 	 * buffer, copy the data to buf.
    420  1.7.2.2  nathanw 	 */
    421  1.7.2.2  nathanw 	if (ed->sc_error == 0 && (ed->sc_flags & EDF_BOUNCEBUF) && ed->sc_read)
    422  1.7.2.2  nathanw 		memcpy(ed->sc_data, ed->sc_dmamkva, ed->sc_bcount);
    423  1.7.2.2  nathanw 	ed->sc_flags &= ~EDF_BOUNCEBUF;
    424  1.7.2.2  nathanw 
    425  1.7.2.2  nathanw 	/* Unload buf from DMA map */
    426  1.7.2.2  nathanw 	if (ed->sc_flags & EDF_DMAMAP_LOADED) {
    427  1.7.2.2  nathanw 		bus_dmamap_unload(ed->sc_dmat, ed->dmamap_xfer);
    428  1.7.2.2  nathanw 		ed->sc_flags &= ~EDF_DMAMAP_LOADED;
    429  1.7.2.2  nathanw 	}
    430  1.7.2.2  nathanw 
    431  1.7.2.2  nathanw 	mca_disk_unbusy();
    432  1.7.2.2  nathanw }
    433  1.7.2.2  nathanw 
    434  1.7.2.2  nathanw static void
    435  1.7.2.2  nathanw edmcadone(ed, bp)
    436  1.7.2.2  nathanw 	struct ed_softc *ed;
    437  1.7.2.2  nathanw 	struct buf *bp;
    438  1.7.2.2  nathanw {
    439  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("eddone %s\n", ed->sc_dev.dv_xname),
    440  1.7.2.2  nathanw 	    DEBUG_XFERS);
    441  1.7.2.2  nathanw 
    442  1.7.2.2  nathanw 	if (ed->sc_error) {
    443  1.7.2.2  nathanw 		bp->b_error = ed->sc_error;
    444  1.7.2.2  nathanw 		bp->b_flags |= B_ERROR;
    445  1.7.2.2  nathanw 	} else {
    446  1.7.2.2  nathanw 		/* Set resid, most commonly to zero. */
    447  1.7.2.2  nathanw 		bp->b_resid = ed->sc_status_block[SB_RESBLKCNT_IDX] * DEV_BSIZE;
    448  1.7.2.2  nathanw 	}
    449  1.7.2.2  nathanw 
    450  1.7.2.2  nathanw 	ed_bio_done(ed);
    451  1.7.2.2  nathanw 
    452  1.7.2.2  nathanw 	/* If disk was busied, unbusy it now */
    453  1.7.2.2  nathanw 	if (ed->sc_flags & EDF_DK_BUSY) {
    454  1.7.2.2  nathanw 		disk_unbusy(&ed->sc_dk, (bp->b_bcount - bp->b_resid));
    455  1.7.2.2  nathanw 		ed->sc_flags &= ~EDF_DK_BUSY;
    456  1.7.2.2  nathanw 	}
    457  1.7.2.2  nathanw 
    458  1.7.2.2  nathanw #if NRND > 0
    459  1.7.2.2  nathanw 	rnd_add_uint32(&ed->rnd_source, bp->b_blkno);
    460  1.7.2.2  nathanw #endif
    461  1.7.2.2  nathanw 	biodone(bp);
    462  1.7.2.2  nathanw }
    463  1.7.2.2  nathanw 
    464  1.7.2.2  nathanw int
    465  1.7.2.2  nathanw edmcaread(dev, uio, flags)
    466  1.7.2.2  nathanw 	dev_t dev;
    467  1.7.2.2  nathanw 	struct uio *uio;
    468  1.7.2.2  nathanw 	int flags;
    469  1.7.2.2  nathanw {
    470  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("edread\n"), DEBUG_XFERS);
    471  1.7.2.2  nathanw 	return (physio(edmcastrategy, NULL, dev, B_READ, minphys, uio));
    472  1.7.2.2  nathanw }
    473  1.7.2.2  nathanw 
    474  1.7.2.2  nathanw int
    475  1.7.2.2  nathanw edmcawrite(dev, uio, flags)
    476  1.7.2.2  nathanw 	dev_t dev;
    477  1.7.2.2  nathanw 	struct uio *uio;
    478  1.7.2.2  nathanw 	int flags;
    479  1.7.2.2  nathanw {
    480  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("edwrite\n"), DEBUG_XFERS);
    481  1.7.2.2  nathanw 	return (physio(edmcastrategy, NULL, dev, B_WRITE, minphys, uio));
    482  1.7.2.2  nathanw }
    483  1.7.2.2  nathanw 
    484  1.7.2.2  nathanw /*
    485  1.7.2.2  nathanw  * Wait interruptibly for an exclusive lock.
    486  1.7.2.2  nathanw  */
    487  1.7.2.2  nathanw static int
    488  1.7.2.2  nathanw ed_lock(ed)
    489  1.7.2.2  nathanw 	struct ed_softc *ed;
    490  1.7.2.2  nathanw {
    491  1.7.2.2  nathanw 	int error;
    492  1.7.2.2  nathanw 	int s;
    493  1.7.2.2  nathanw 
    494  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("ed_lock\n"), DEBUG_FUNCS);
    495  1.7.2.2  nathanw 
    496  1.7.2.2  nathanw 	s = splbio();
    497  1.7.2.2  nathanw 	error = lockmgr(&ed->sc_lock, LK_EXCLUSIVE, NULL);
    498  1.7.2.2  nathanw 	splx(s);
    499  1.7.2.2  nathanw 
    500  1.7.2.2  nathanw 	return (error);
    501  1.7.2.2  nathanw }
    502  1.7.2.2  nathanw 
    503  1.7.2.2  nathanw /*
    504  1.7.2.2  nathanw  * Unlock and wake up any waiters.
    505  1.7.2.2  nathanw  */
    506  1.7.2.2  nathanw static void
    507  1.7.2.2  nathanw ed_unlock(ed)
    508  1.7.2.2  nathanw 	struct ed_softc *ed;
    509  1.7.2.2  nathanw {
    510  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("ed_unlock\n"), DEBUG_FUNCS);
    511  1.7.2.2  nathanw 
    512  1.7.2.2  nathanw 	(void) lockmgr(&ed->sc_lock, LK_RELEASE, NULL);
    513  1.7.2.2  nathanw }
    514  1.7.2.2  nathanw 
    515  1.7.2.2  nathanw int
    516  1.7.2.2  nathanw edmcaopen(dev, flag, fmt, p)
    517  1.7.2.2  nathanw 	dev_t dev;
    518  1.7.2.2  nathanw 	int flag, fmt;
    519  1.7.2.2  nathanw 	struct proc *p;
    520  1.7.2.2  nathanw {
    521  1.7.2.2  nathanw 	struct ed_softc *wd;
    522  1.7.2.2  nathanw 	int part, error;
    523  1.7.2.2  nathanw 
    524  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("edopen\n"), DEBUG_FUNCS);
    525  1.7.2.2  nathanw 	wd = device_lookup(&ed_cd, DISKUNIT(dev));
    526  1.7.2.2  nathanw 	if (wd == NULL || (wd->sc_flags & EDF_INIT) == 0)
    527  1.7.2.2  nathanw 		return (ENXIO);
    528  1.7.2.2  nathanw 
    529  1.7.2.2  nathanw 	if ((error = ed_lock(wd)) != 0)
    530  1.7.2.2  nathanw 		goto bad4;
    531  1.7.2.2  nathanw 
    532  1.7.2.2  nathanw 	if (wd->sc_dk.dk_openmask != 0) {
    533  1.7.2.2  nathanw 		/*
    534  1.7.2.2  nathanw 		 * If any partition is open, but the disk has been invalidated,
    535  1.7.2.2  nathanw 		 * disallow further opens.
    536  1.7.2.2  nathanw 		 */
    537  1.7.2.2  nathanw 		if ((wd->sc_flags & WDF_LOADED) == 0) {
    538  1.7.2.2  nathanw 			error = EIO;
    539  1.7.2.2  nathanw 			goto bad3;
    540  1.7.2.2  nathanw 		}
    541  1.7.2.2  nathanw 	} else {
    542  1.7.2.2  nathanw 		if ((wd->sc_flags & WDF_LOADED) == 0) {
    543  1.7.2.2  nathanw 			wd->sc_flags |= WDF_LOADED;
    544  1.7.2.2  nathanw 
    545  1.7.2.2  nathanw 			/* Load the physical device parameters. */
    546  1.7.2.2  nathanw 			ed_get_params(wd);
    547  1.7.2.2  nathanw 
    548  1.7.2.2  nathanw 			/* Load the partition info if not already loaded. */
    549  1.7.2.2  nathanw 			edgetdisklabel(wd);
    550  1.7.2.2  nathanw 		}
    551  1.7.2.2  nathanw 	}
    552  1.7.2.2  nathanw 
    553  1.7.2.2  nathanw 	part = DISKPART(dev);
    554  1.7.2.2  nathanw 
    555  1.7.2.2  nathanw 	/* Check that the partition exists. */
    556  1.7.2.2  nathanw 	if (part != RAW_PART &&
    557  1.7.2.2  nathanw 	    (part >= wd->sc_dk.dk_label->d_npartitions ||
    558  1.7.2.2  nathanw 	     wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
    559  1.7.2.2  nathanw 		error = ENXIO;
    560  1.7.2.2  nathanw 		goto bad;
    561  1.7.2.2  nathanw 	}
    562  1.7.2.2  nathanw 
    563  1.7.2.2  nathanw 	/* Insure only one open at a time. */
    564  1.7.2.2  nathanw 	switch (fmt) {
    565  1.7.2.2  nathanw 	case S_IFCHR:
    566  1.7.2.2  nathanw 		wd->sc_dk.dk_copenmask |= (1 << part);
    567  1.7.2.2  nathanw 		break;
    568  1.7.2.2  nathanw 	case S_IFBLK:
    569  1.7.2.2  nathanw 		wd->sc_dk.dk_bopenmask |= (1 << part);
    570  1.7.2.2  nathanw 		break;
    571  1.7.2.2  nathanw 	}
    572  1.7.2.2  nathanw 	wd->sc_dk.dk_openmask =
    573  1.7.2.2  nathanw 	    wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
    574  1.7.2.2  nathanw 
    575  1.7.2.2  nathanw 	ed_unlock(wd);
    576  1.7.2.2  nathanw 	return 0;
    577  1.7.2.2  nathanw 
    578  1.7.2.2  nathanw bad:
    579  1.7.2.2  nathanw 	if (wd->sc_dk.dk_openmask == 0) {
    580  1.7.2.2  nathanw 	}
    581  1.7.2.2  nathanw 
    582  1.7.2.2  nathanw bad3:
    583  1.7.2.2  nathanw 	ed_unlock(wd);
    584  1.7.2.2  nathanw bad4:
    585  1.7.2.2  nathanw 	return (error);
    586  1.7.2.2  nathanw }
    587  1.7.2.2  nathanw 
    588  1.7.2.2  nathanw int
    589  1.7.2.2  nathanw edmcaclose(dev, flag, fmt, p)
    590  1.7.2.2  nathanw 	dev_t dev;
    591  1.7.2.2  nathanw 	int flag, fmt;
    592  1.7.2.2  nathanw 	struct proc *p;
    593  1.7.2.2  nathanw {
    594  1.7.2.2  nathanw 	struct ed_softc *wd = device_lookup(&ed_cd, DISKUNIT(dev));
    595  1.7.2.2  nathanw 	int part = DISKPART(dev);
    596  1.7.2.2  nathanw 	int error;
    597  1.7.2.2  nathanw 
    598  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("edmcaclose\n"), DEBUG_FUNCS);
    599  1.7.2.2  nathanw 	if ((error = ed_lock(wd)) != 0)
    600  1.7.2.2  nathanw 		return error;
    601  1.7.2.2  nathanw 
    602  1.7.2.2  nathanw 	switch (fmt) {
    603  1.7.2.2  nathanw 	case S_IFCHR:
    604  1.7.2.2  nathanw 		wd->sc_dk.dk_copenmask &= ~(1 << part);
    605  1.7.2.2  nathanw 		break;
    606  1.7.2.2  nathanw 	case S_IFBLK:
    607  1.7.2.2  nathanw 		wd->sc_dk.dk_bopenmask &= ~(1 << part);
    608  1.7.2.2  nathanw 		break;
    609  1.7.2.2  nathanw 	}
    610  1.7.2.2  nathanw 	wd->sc_dk.dk_openmask =
    611  1.7.2.2  nathanw 	    wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
    612  1.7.2.2  nathanw 
    613  1.7.2.2  nathanw 	if (wd->sc_dk.dk_openmask == 0) {
    614  1.7.2.2  nathanw #if 0
    615  1.7.2.2  nathanw 		wd_flushcache(wd, AT_WAIT);
    616  1.7.2.2  nathanw #endif
    617  1.7.2.2  nathanw 		/* XXXX Must wait for I/O to complete! */
    618  1.7.2.2  nathanw 
    619  1.7.2.2  nathanw 		if (! (wd->sc_flags & WDF_KLABEL))
    620  1.7.2.2  nathanw 			wd->sc_flags &= ~WDF_LOADED;
    621  1.7.2.2  nathanw 	}
    622  1.7.2.2  nathanw 
    623  1.7.2.2  nathanw 	ed_unlock(wd);
    624  1.7.2.2  nathanw 
    625  1.7.2.2  nathanw 	return 0;
    626  1.7.2.2  nathanw }
    627  1.7.2.2  nathanw 
    628  1.7.2.2  nathanw static void
    629  1.7.2.2  nathanw edgetdefaultlabel(wd, lp)
    630  1.7.2.2  nathanw 	struct ed_softc *wd;
    631  1.7.2.2  nathanw 	struct disklabel *lp;
    632  1.7.2.2  nathanw {
    633  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("edgetdefaultlabel\n"), DEBUG_FUNCS);
    634  1.7.2.2  nathanw 	memset(lp, 0, sizeof(struct disklabel));
    635  1.7.2.2  nathanw 
    636  1.7.2.2  nathanw 	lp->d_secsize = DEV_BSIZE;
    637  1.7.2.2  nathanw 	lp->d_ntracks = wd->heads;
    638  1.7.2.2  nathanw 	lp->d_nsectors = wd->sectors;
    639  1.7.2.2  nathanw 	lp->d_ncylinders = wd->cyl;
    640  1.7.2.2  nathanw 	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
    641  1.7.2.2  nathanw 
    642  1.7.2.2  nathanw 	lp->d_type = DTYPE_ESDI;
    643  1.7.2.2  nathanw 
    644  1.7.2.2  nathanw 	strncpy(lp->d_typename, "ESDI", 16);
    645  1.7.2.2  nathanw 	strncpy(lp->d_packname, "fictitious", 16);
    646  1.7.2.2  nathanw 	lp->d_secperunit = wd->sc_capacity;
    647  1.7.2.2  nathanw 	lp->d_rpm = 3600;
    648  1.7.2.2  nathanw 	lp->d_interleave = 1;
    649  1.7.2.2  nathanw 	lp->d_flags = 0;
    650  1.7.2.2  nathanw 
    651  1.7.2.2  nathanw 	lp->d_partitions[RAW_PART].p_offset = 0;
    652  1.7.2.2  nathanw 	lp->d_partitions[RAW_PART].p_size =
    653  1.7.2.2  nathanw 	lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
    654  1.7.2.2  nathanw 	lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
    655  1.7.2.2  nathanw 	lp->d_npartitions = RAW_PART + 1;
    656  1.7.2.2  nathanw 
    657  1.7.2.2  nathanw 	lp->d_magic = DISKMAGIC;
    658  1.7.2.2  nathanw 	lp->d_magic2 = DISKMAGIC;
    659  1.7.2.2  nathanw 	lp->d_checksum = dkcksum(lp);
    660  1.7.2.2  nathanw }
    661  1.7.2.2  nathanw 
    662  1.7.2.2  nathanw /*
    663  1.7.2.2  nathanw  * Fabricate a default disk label, and try to read the correct one.
    664  1.7.2.2  nathanw  */
    665  1.7.2.2  nathanw static void
    666  1.7.2.2  nathanw edgetdisklabel(wd)
    667  1.7.2.2  nathanw 	struct ed_softc *wd;
    668  1.7.2.2  nathanw {
    669  1.7.2.2  nathanw 	struct disklabel *lp = wd->sc_dk.dk_label;
    670  1.7.2.2  nathanw 	char *errstring;
    671  1.7.2.2  nathanw 
    672  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("edgetdisklabel\n"), DEBUG_FUNCS);
    673  1.7.2.2  nathanw 
    674  1.7.2.2  nathanw 	memset(wd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
    675  1.7.2.2  nathanw 
    676  1.7.2.2  nathanw 	edgetdefaultlabel(wd, lp);
    677  1.7.2.2  nathanw 
    678  1.7.2.2  nathanw #if 0
    679  1.7.2.2  nathanw 	wd->sc_badsect[0] = -1;
    680  1.7.2.2  nathanw 
    681  1.7.2.2  nathanw 	if (wd->drvp->state > RECAL)
    682  1.7.2.2  nathanw 		wd->drvp->drive_flags |= DRIVE_RESET;
    683  1.7.2.2  nathanw #endif
    684  1.7.2.2  nathanw 	errstring = readdisklabel(MAKEDISKDEV(0, wd->sc_dev.dv_unit, RAW_PART),
    685  1.7.2.2  nathanw 	    edmcastrategy, lp, wd->sc_dk.dk_cpulabel);
    686  1.7.2.2  nathanw 	if (errstring) {
    687  1.7.2.2  nathanw 		/*
    688  1.7.2.2  nathanw 		 * This probably happened because the drive's default
    689  1.7.2.2  nathanw 		 * geometry doesn't match the DOS geometry.  We
    690  1.7.2.2  nathanw 		 * assume the DOS geometry is now in the label and try
    691  1.7.2.2  nathanw 		 * again.  XXX This is a kluge.
    692  1.7.2.2  nathanw 		 */
    693  1.7.2.2  nathanw #if 0
    694  1.7.2.2  nathanw 		if (wd->drvp->state > RECAL)
    695  1.7.2.2  nathanw 			wd->drvp->drive_flags |= DRIVE_RESET;
    696  1.7.2.2  nathanw #endif
    697  1.7.2.2  nathanw 		errstring = readdisklabel(MAKEDISKDEV(0, wd->sc_dev.dv_unit,
    698  1.7.2.2  nathanw 		    RAW_PART), edmcastrategy, lp, wd->sc_dk.dk_cpulabel);
    699  1.7.2.2  nathanw 	}
    700  1.7.2.2  nathanw 	if (errstring) {
    701  1.7.2.2  nathanw 		printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);
    702  1.7.2.2  nathanw 		return;
    703  1.7.2.2  nathanw 	}
    704  1.7.2.2  nathanw 
    705  1.7.2.2  nathanw #if 0
    706  1.7.2.2  nathanw 	if (wd->drvp->state > RECAL)
    707  1.7.2.2  nathanw 		wd->drvp->drive_flags |= DRIVE_RESET;
    708  1.7.2.2  nathanw #endif
    709  1.7.2.2  nathanw #ifdef HAS_BAD144_HANDLING
    710  1.7.2.2  nathanw 	if ((lp->d_flags & D_BADSECT) != 0)
    711  1.7.2.2  nathanw 		bad144intern(wd);
    712  1.7.2.2  nathanw #endif
    713  1.7.2.2  nathanw }
    714  1.7.2.2  nathanw 
    715  1.7.2.2  nathanw int
    716  1.7.2.2  nathanw edmcaioctl(dev, xfer, addr, flag, p)
    717  1.7.2.2  nathanw 	dev_t dev;
    718  1.7.2.2  nathanw 	u_long xfer;
    719  1.7.2.2  nathanw 	caddr_t addr;
    720  1.7.2.2  nathanw 	int flag;
    721  1.7.2.2  nathanw 	struct proc *p;
    722  1.7.2.2  nathanw {
    723  1.7.2.2  nathanw 	struct ed_softc *wd = device_lookup(&ed_cd, DISKUNIT(dev));
    724  1.7.2.2  nathanw 	int error;
    725  1.7.2.2  nathanw #ifdef __HAVE_OLD_DISKLABEL
    726  1.7.2.2  nathanw 	struct disklabel newlabel;
    727  1.7.2.2  nathanw #endif
    728  1.7.2.2  nathanw 
    729  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("edioctl\n"), DEBUG_FUNCS);
    730  1.7.2.2  nathanw 
    731  1.7.2.2  nathanw 	if ((wd->sc_flags & WDF_LOADED) == 0)
    732  1.7.2.2  nathanw 		return EIO;
    733  1.7.2.2  nathanw 
    734  1.7.2.2  nathanw 	switch (xfer) {
    735  1.7.2.2  nathanw #ifdef HAS_BAD144_HANDLING
    736  1.7.2.2  nathanw 	case DIOCSBAD:
    737  1.7.2.2  nathanw 		if ((flag & FWRITE) == 0)
    738  1.7.2.2  nathanw 			return EBADF;
    739  1.7.2.2  nathanw 		wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
    740  1.7.2.2  nathanw 		wd->sc_dk.dk_label->d_flags |= D_BADSECT;
    741  1.7.2.2  nathanw 		bad144intern(wd);
    742  1.7.2.2  nathanw 		return 0;
    743  1.7.2.2  nathanw #endif
    744  1.7.2.2  nathanw 
    745  1.7.2.2  nathanw 	case DIOCGDINFO:
    746  1.7.2.2  nathanw 		*(struct disklabel *)addr = *(wd->sc_dk.dk_label);
    747  1.7.2.2  nathanw 		return 0;
    748  1.7.2.2  nathanw #ifdef __HAVE_OLD_DISKLABEL
    749  1.7.2.2  nathanw 	case ODIOCGDINFO:
    750  1.7.2.2  nathanw 		newlabel = *(wd->sc_dk.dk_label);
    751  1.7.2.2  nathanw 		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
    752  1.7.2.2  nathanw 			return ENOTTY;
    753  1.7.2.2  nathanw 		memcpy(addr, &newlabel, sizeof (struct olddisklabel));
    754  1.7.2.2  nathanw 		return 0;
    755  1.7.2.2  nathanw #endif
    756  1.7.2.2  nathanw 
    757  1.7.2.2  nathanw 	case DIOCGPART:
    758  1.7.2.2  nathanw 		((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
    759  1.7.2.2  nathanw 		((struct partinfo *)addr)->part =
    760  1.7.2.2  nathanw 		    &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)];
    761  1.7.2.2  nathanw 		return 0;
    762  1.7.2.2  nathanw 
    763  1.7.2.2  nathanw 	case DIOCWDINFO:
    764  1.7.2.2  nathanw 	case DIOCSDINFO:
    765  1.7.2.2  nathanw #ifdef __HAVE_OLD_DISKLABEL
    766  1.7.2.2  nathanw 	case ODIOCWDINFO:
    767  1.7.2.2  nathanw 	case ODIOCSDINFO:
    768  1.7.2.2  nathanw #endif
    769  1.7.2.2  nathanw 	{
    770  1.7.2.2  nathanw 		struct disklabel *lp;
    771  1.7.2.2  nathanw 
    772  1.7.2.2  nathanw #ifdef __HAVE_OLD_DISKLABEL
    773  1.7.2.2  nathanw 		if (xfer == ODIOCSDINFO || xfer == ODIOCWDINFO) {
    774  1.7.2.2  nathanw 			memset(&newlabel, 0, sizeof newlabel);
    775  1.7.2.2  nathanw 			memcpy(&newlabel, addr, sizeof (struct olddisklabel));
    776  1.7.2.2  nathanw 			lp = &newlabel;
    777  1.7.2.2  nathanw 		} else
    778  1.7.2.2  nathanw #endif
    779  1.7.2.2  nathanw 		lp = (struct disklabel *)addr;
    780  1.7.2.2  nathanw 
    781  1.7.2.2  nathanw 		if ((flag & FWRITE) == 0)
    782  1.7.2.2  nathanw 			return EBADF;
    783  1.7.2.2  nathanw 
    784  1.7.2.2  nathanw 		if ((error = ed_lock(wd)) != 0)
    785  1.7.2.2  nathanw 			return error;
    786  1.7.2.2  nathanw 		wd->sc_flags |= WDF_LABELLING;
    787  1.7.2.2  nathanw 
    788  1.7.2.2  nathanw 		error = setdisklabel(wd->sc_dk.dk_label,
    789  1.7.2.2  nathanw 		    lp, /*wd->sc_dk.dk_openmask : */0,
    790  1.7.2.2  nathanw 		    wd->sc_dk.dk_cpulabel);
    791  1.7.2.2  nathanw 		if (error == 0) {
    792  1.7.2.2  nathanw #if 0
    793  1.7.2.2  nathanw 			if (wd->drvp->state > RECAL)
    794  1.7.2.2  nathanw 				wd->drvp->drive_flags |= DRIVE_RESET;
    795  1.7.2.2  nathanw #endif
    796  1.7.2.2  nathanw 			if (xfer == DIOCWDINFO
    797  1.7.2.2  nathanw #ifdef __HAVE_OLD_DISKLABEL
    798  1.7.2.2  nathanw 			    || xfer == ODIOCWDINFO
    799  1.7.2.2  nathanw #endif
    800  1.7.2.2  nathanw 			    )
    801  1.7.2.2  nathanw 				error = writedisklabel(EDLABELDEV(dev),
    802  1.7.2.2  nathanw 				    edmcastrategy, wd->sc_dk.dk_label,
    803  1.7.2.2  nathanw 				    wd->sc_dk.dk_cpulabel);
    804  1.7.2.2  nathanw 		}
    805  1.7.2.2  nathanw 
    806  1.7.2.2  nathanw 		wd->sc_flags &= ~WDF_LABELLING;
    807  1.7.2.2  nathanw 		ed_unlock(wd);
    808  1.7.2.2  nathanw 		return error;
    809  1.7.2.2  nathanw 	}
    810  1.7.2.2  nathanw 
    811  1.7.2.2  nathanw 	case DIOCKLABEL:
    812  1.7.2.2  nathanw 		if (*(int *)addr)
    813  1.7.2.2  nathanw 			wd->sc_flags |= WDF_KLABEL;
    814  1.7.2.2  nathanw 		else
    815  1.7.2.2  nathanw 			wd->sc_flags &= ~WDF_KLABEL;
    816  1.7.2.2  nathanw 		return 0;
    817  1.7.2.2  nathanw 
    818  1.7.2.2  nathanw 	case DIOCWLABEL:
    819  1.7.2.2  nathanw 		if ((flag & FWRITE) == 0)
    820  1.7.2.2  nathanw 			return EBADF;
    821  1.7.2.2  nathanw 		if (*(int *)addr)
    822  1.7.2.2  nathanw 			wd->sc_flags |= WDF_WLABEL;
    823  1.7.2.2  nathanw 		else
    824  1.7.2.2  nathanw 			wd->sc_flags &= ~WDF_WLABEL;
    825  1.7.2.2  nathanw 		return 0;
    826  1.7.2.2  nathanw 
    827  1.7.2.2  nathanw 	case DIOCGDEFLABEL:
    828  1.7.2.2  nathanw 		edgetdefaultlabel(wd, (struct disklabel *)addr);
    829  1.7.2.2  nathanw 		return 0;
    830  1.7.2.2  nathanw #ifdef __HAVE_OLD_DISKLABEL
    831  1.7.2.2  nathanw 	case ODIOCGDEFLABEL:
    832  1.7.2.2  nathanw 		edgetdefaultlabel(wd, &newlabel);
    833  1.7.2.2  nathanw 		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
    834  1.7.2.2  nathanw 			return ENOTTY;
    835  1.7.2.2  nathanw 		memcpy(addr, &newlabel, sizeof (struct olddisklabel));
    836  1.7.2.2  nathanw 		return 0;
    837  1.7.2.2  nathanw #endif
    838  1.7.2.2  nathanw 
    839  1.7.2.2  nathanw #ifdef notyet
    840  1.7.2.2  nathanw 	case DIOCWFORMAT:
    841  1.7.2.2  nathanw 		if ((flag & FWRITE) == 0)
    842  1.7.2.2  nathanw 			return EBADF;
    843  1.7.2.2  nathanw 		{
    844  1.7.2.2  nathanw 		register struct format_op *fop;
    845  1.7.2.2  nathanw 		struct iovec aiov;
    846  1.7.2.2  nathanw 		struct uio auio;
    847  1.7.2.2  nathanw 
    848  1.7.2.2  nathanw 		fop = (struct format_op *)addr;
    849  1.7.2.2  nathanw 		aiov.iov_base = fop->df_buf;
    850  1.7.2.2  nathanw 		aiov.iov_len = fop->df_count;
    851  1.7.2.2  nathanw 		auio.uio_iov = &aiov;
    852  1.7.2.2  nathanw 		auio.uio_iovcnt = 1;
    853  1.7.2.2  nathanw 		auio.uio_resid = fop->df_count;
    854  1.7.2.2  nathanw 		auio.uio_segflg = 0;
    855  1.7.2.2  nathanw 		auio.uio_offset =
    856  1.7.2.2  nathanw 			fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
    857  1.7.2.2  nathanw 		auio.uio_procp = p;
    858  1.7.2.2  nathanw 		error = physio(wdformat, NULL, dev, B_WRITE, minphys,
    859  1.7.2.2  nathanw 		    &auio);
    860  1.7.2.2  nathanw 		fop->df_count -= auio.uio_resid;
    861  1.7.2.2  nathanw 		fop->df_reg[0] = wdc->sc_status;
    862  1.7.2.2  nathanw 		fop->df_reg[1] = wdc->sc_error;
    863  1.7.2.2  nathanw 		return error;
    864  1.7.2.2  nathanw 		}
    865  1.7.2.2  nathanw #endif
    866  1.7.2.2  nathanw 
    867  1.7.2.2  nathanw 	default:
    868  1.7.2.2  nathanw 		return ENOTTY;
    869  1.7.2.2  nathanw 	}
    870  1.7.2.2  nathanw 
    871  1.7.2.2  nathanw #ifdef DIAGNOSTIC
    872  1.7.2.2  nathanw 	panic("edioctl: impossible");
    873  1.7.2.2  nathanw #endif
    874  1.7.2.2  nathanw }
    875  1.7.2.2  nathanw 
    876  1.7.2.2  nathanw #if 0
    877  1.7.2.2  nathanw #ifdef B_FORMAT
    878  1.7.2.2  nathanw int
    879  1.7.2.2  nathanw edmcaformat(struct buf *bp)
    880  1.7.2.2  nathanw {
    881  1.7.2.2  nathanw 
    882  1.7.2.2  nathanw 	bp->b_flags |= B_FORMAT;
    883  1.7.2.2  nathanw 	return edmcastrategy(bp);
    884  1.7.2.2  nathanw }
    885  1.7.2.2  nathanw #endif
    886  1.7.2.2  nathanw #endif
    887  1.7.2.2  nathanw 
    888  1.7.2.2  nathanw int
    889  1.7.2.2  nathanw edmcasize(dev)
    890  1.7.2.2  nathanw 	dev_t dev;
    891  1.7.2.2  nathanw {
    892  1.7.2.2  nathanw 	struct ed_softc *wd;
    893  1.7.2.2  nathanw 	int part, omask;
    894  1.7.2.2  nathanw 	int size;
    895  1.7.2.2  nathanw 
    896  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("edsize\n"), DEBUG_FUNCS);
    897  1.7.2.2  nathanw 
    898  1.7.2.2  nathanw 	wd = device_lookup(&ed_cd, DISKUNIT(dev));
    899  1.7.2.2  nathanw 	if (wd == NULL)
    900  1.7.2.2  nathanw 		return (-1);
    901  1.7.2.2  nathanw 
    902  1.7.2.2  nathanw 	part = DISKPART(dev);
    903  1.7.2.2  nathanw 	omask = wd->sc_dk.dk_openmask & (1 << part);
    904  1.7.2.2  nathanw 
    905  1.7.2.2  nathanw 	if (omask == 0 && edmcaopen(dev, 0, S_IFBLK, NULL) != 0)
    906  1.7.2.2  nathanw 		return (-1);
    907  1.7.2.2  nathanw 	if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
    908  1.7.2.2  nathanw 		size = -1;
    909  1.7.2.2  nathanw 	else
    910  1.7.2.2  nathanw 		size = wd->sc_dk.dk_label->d_partitions[part].p_size *
    911  1.7.2.2  nathanw 		    (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
    912  1.7.2.2  nathanw 	if (omask == 0 && edmcaclose(dev, 0, S_IFBLK, NULL) != 0)
    913  1.7.2.2  nathanw 		return (-1);
    914  1.7.2.2  nathanw 	return (size);
    915  1.7.2.2  nathanw }
    916  1.7.2.2  nathanw 
    917  1.7.2.2  nathanw /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
    918  1.7.2.2  nathanw static int eddoingadump = 0;
    919  1.7.2.2  nathanw static int eddumprecalibrated = 0;
    920  1.7.2.2  nathanw static int eddumpmulti = 1;
    921  1.7.2.2  nathanw 
    922  1.7.2.2  nathanw /*
    923  1.7.2.2  nathanw  * Dump core after a system crash.
    924  1.7.2.2  nathanw  */
    925  1.7.2.2  nathanw int
    926  1.7.2.2  nathanw edmcadump(dev, blkno, va, size)
    927  1.7.2.2  nathanw 	dev_t dev;
    928  1.7.2.2  nathanw 	daddr_t blkno;
    929  1.7.2.2  nathanw 	caddr_t va;
    930  1.7.2.2  nathanw 	size_t size;
    931  1.7.2.2  nathanw {
    932  1.7.2.2  nathanw 	struct ed_softc *ed;	/* disk unit to do the I/O */
    933  1.7.2.2  nathanw 	struct disklabel *lp;   /* disk's disklabel */
    934  1.7.2.2  nathanw 	int part;
    935  1.7.2.2  nathanw 	int nblks;	/* total number of sectors left to write */
    936  1.7.2.2  nathanw 
    937  1.7.2.2  nathanw 	/* Check if recursive dump; if so, punt. */
    938  1.7.2.2  nathanw 	if (eddoingadump)
    939  1.7.2.2  nathanw 		return EFAULT;
    940  1.7.2.2  nathanw 	eddoingadump = 1;
    941  1.7.2.2  nathanw 
    942  1.7.2.2  nathanw 	ed = device_lookup(&ed_cd, DISKUNIT(dev));
    943  1.7.2.2  nathanw 	if (ed == NULL)
    944  1.7.2.2  nathanw 		return (ENXIO);
    945  1.7.2.2  nathanw 
    946  1.7.2.2  nathanw 	part = DISKPART(dev);
    947  1.7.2.2  nathanw 
    948  1.7.2.2  nathanw 	/* Make sure it was initialized. */
    949  1.7.2.2  nathanw 	if ((ed->sc_flags & EDF_INIT) == 0)
    950  1.7.2.2  nathanw 		return ENXIO;
    951  1.7.2.2  nathanw 
    952  1.7.2.2  nathanw 	/* Convert to disk sectors.  Request must be a multiple of size. */
    953  1.7.2.2  nathanw 	lp = ed->sc_dk.dk_label;
    954  1.7.2.2  nathanw 	if ((size % lp->d_secsize) != 0)
    955  1.7.2.2  nathanw 		return EFAULT;
    956  1.7.2.2  nathanw 	nblks = size / lp->d_secsize;
    957  1.7.2.2  nathanw 	blkno = blkno / (lp->d_secsize / DEV_BSIZE);
    958  1.7.2.2  nathanw 
    959  1.7.2.2  nathanw 	/* Check transfer bounds against partition size. */
    960  1.7.2.2  nathanw 	if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
    961  1.7.2.2  nathanw 		return EINVAL;
    962  1.7.2.2  nathanw 
    963  1.7.2.2  nathanw 	/* Offset block number to start of partition. */
    964  1.7.2.2  nathanw 	blkno += lp->d_partitions[part].p_offset;
    965  1.7.2.2  nathanw 
    966  1.7.2.2  nathanw 	/* Recalibrate, if first dump transfer. */
    967  1.7.2.2  nathanw 	if (eddumprecalibrated == 0) {
    968  1.7.2.2  nathanw 		eddumprecalibrated = 1;
    969  1.7.2.2  nathanw 		eddumpmulti = 8;
    970  1.7.2.2  nathanw #if 0
    971  1.7.2.2  nathanw 		wd->drvp->state = RESET;
    972  1.7.2.2  nathanw #endif
    973  1.7.2.2  nathanw 	}
    974  1.7.2.2  nathanw 
    975  1.7.2.2  nathanw 	while (nblks > 0) {
    976  1.7.2.2  nathanw 		ed->sc_data = va;
    977  1.7.2.2  nathanw 		ed->sc_rawblkno = blkno;
    978  1.7.2.2  nathanw 		ed->sc_bcount = min(nblks, eddumpmulti) * lp->d_secsize;
    979  1.7.2.2  nathanw 		ed->sc_read = 0;
    980  1.7.2.2  nathanw 
    981  1.7.2.2  nathanw 		ed_bio(ed, 0, 1);
    982  1.7.2.2  nathanw 		if (ed->sc_error)
    983  1.7.2.2  nathanw 			return (ed->sc_error);
    984  1.7.2.2  nathanw 
    985  1.7.2.2  nathanw 		ed_bio_done(ed);
    986  1.7.2.2  nathanw 
    987  1.7.2.2  nathanw 		/* update block count */
    988  1.7.2.2  nathanw 		nblks -= min(nblks, eddumpmulti);
    989  1.7.2.2  nathanw 		blkno += min(nblks, eddumpmulti);
    990  1.7.2.2  nathanw 		va += min(nblks, eddumpmulti) * lp->d_secsize;
    991  1.7.2.2  nathanw 	}
    992  1.7.2.2  nathanw 
    993  1.7.2.2  nathanw 	eddoingadump = 0;
    994  1.7.2.2  nathanw 	return (0);
    995  1.7.2.2  nathanw }
    996  1.7.2.2  nathanw 
    997  1.7.2.2  nathanw #ifdef HAS_BAD144_HANDLING
    998  1.7.2.2  nathanw /*
    999  1.7.2.2  nathanw  * Internalize the bad sector table.
   1000  1.7.2.2  nathanw  */
   1001  1.7.2.2  nathanw static void
   1002  1.7.2.2  nathanw bad144intern(wd)
   1003  1.7.2.2  nathanw 	struct ed_softc *wd;
   1004  1.7.2.2  nathanw {
   1005  1.7.2.2  nathanw 	struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
   1006  1.7.2.2  nathanw 	struct disklabel *lp = wd->sc_dk.dk_label;
   1007  1.7.2.2  nathanw 	int i = 0;
   1008  1.7.2.2  nathanw 
   1009  1.7.2.2  nathanw 	WDCDEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS);
   1010  1.7.2.2  nathanw 
   1011  1.7.2.2  nathanw 	for (; i < NBT_BAD; i++) {
   1012  1.7.2.2  nathanw 		if (bt->bt_bad[i].bt_cyl == 0xffff)
   1013  1.7.2.2  nathanw 			break;
   1014  1.7.2.2  nathanw 		wd->sc_badsect[i] =
   1015  1.7.2.2  nathanw 		    bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
   1016  1.7.2.2  nathanw 		    (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
   1017  1.7.2.2  nathanw 		    (bt->bt_bad[i].bt_trksec & 0xff);
   1018  1.7.2.2  nathanw 	}
   1019  1.7.2.2  nathanw 	for (; i < NBT_BAD+1; i++)
   1020  1.7.2.2  nathanw 		wd->sc_badsect[i] = -1;
   1021  1.7.2.2  nathanw }
   1022  1.7.2.2  nathanw #endif
   1023  1.7.2.2  nathanw 
   1024  1.7.2.2  nathanw static int
   1025  1.7.2.2  nathanw ed_get_params(ed)
   1026  1.7.2.2  nathanw 	struct ed_softc *ed;
   1027  1.7.2.2  nathanw {
   1028  1.7.2.2  nathanw 	u_int16_t cmd_args[2];
   1029  1.7.2.2  nathanw 
   1030  1.7.2.2  nathanw 	/*
   1031  1.7.2.2  nathanw 	 * Get Device Configuration (09).
   1032  1.7.2.2  nathanw 	 */
   1033  1.7.2.2  nathanw 	cmd_args[0] = 14;	/* Options: 00s110, s: 0=Physical 1=Pseudo */
   1034  1.7.2.2  nathanw 	cmd_args[1] = 0;
   1035  1.7.2.2  nathanw 	if (edc_run_cmd(ed->edc_softc, CMD_GET_DEV_CONF, ed->sc_devno,
   1036  1.7.2.2  nathanw 	    cmd_args, 2, 0, 1))
   1037  1.7.2.2  nathanw 		return (1);
   1038  1.7.2.2  nathanw 
   1039  1.7.2.2  nathanw 	ed->spares = ed->sc_status_block[1] >> 8;
   1040  1.7.2.2  nathanw 	ed->drv_flags = ed->sc_status_block[1] & 0x1f;
   1041  1.7.2.2  nathanw 	ed->rba = ed->sc_status_block[2] |
   1042  1.7.2.2  nathanw 		(ed->sc_status_block[3] << 16);
   1043  1.7.2.2  nathanw 	/* Instead of using:
   1044  1.7.2.2  nathanw 		ed->cyl = ed->sc_status_block[4];
   1045  1.7.2.2  nathanw 		ed->heads = ed->sc_status_block[5] & 0xff;
   1046  1.7.2.2  nathanw 		ed->sectors = ed->sc_status_block[5] >> 8;
   1047  1.7.2.2  nathanw 	 * we fabricate the numbers from RBA count, so that
   1048  1.7.2.2  nathanw 	 * number of sectors is 32 and heads 64. This seems
   1049  1.7.2.2  nathanw 	 * to be necessary for integrated ESDI controller.
   1050  1.7.2.2  nathanw 	 */
   1051  1.7.2.2  nathanw 	ed->sectors = 32;
   1052  1.7.2.2  nathanw 	ed->heads = 64;
   1053  1.7.2.2  nathanw 	ed->cyl = ed->rba / (ed->heads * ed->sectors);
   1054  1.7.2.2  nathanw 	ed->sc_capacity = ed->rba;
   1055  1.7.2.2  nathanw 
   1056  1.7.2.2  nathanw 	return (0);
   1057  1.7.2.2  nathanw }
   1058  1.7.2.2  nathanw 
   1059  1.7.2.2  nathanw /*
   1060  1.7.2.2  nathanw  * Our shutdown hook. We attempt to park disk's head only.
   1061  1.7.2.2  nathanw  */
   1062  1.7.2.2  nathanw void
   1063  1.7.2.2  nathanw ed_shutdown(arg)
   1064  1.7.2.2  nathanw 	void *arg;
   1065  1.7.2.2  nathanw {
   1066  1.7.2.2  nathanw #if 0
   1067  1.7.2.2  nathanw 	struct ed_softc *ed = arg;
   1068  1.7.2.2  nathanw 	u_int16_t cmd_args[2];
   1069  1.7.2.2  nathanw 
   1070  1.7.2.2  nathanw 	/* Issue Park Head command */
   1071  1.7.2.2  nathanw 	cmd_args[0] = 6;	/* Options: 000110 */
   1072  1.7.2.2  nathanw 	cmd_args[1] = 0;
   1073  1.7.2.2  nathanw 	(void) edc_run_cmd(ed->edc_softc, CMD_PARK_HEAD, ed->sc_devno,
   1074  1.7.2.2  nathanw 			cmd_args, 2, 0);
   1075  1.7.2.2  nathanw #endif
   1076  1.7.2.2  nathanw }
   1077  1.7.2.2  nathanw 
   1078  1.7.2.2  nathanw /*
   1079  1.7.2.2  nathanw  * Main worker thread function.
   1080  1.7.2.2  nathanw  */
   1081  1.7.2.2  nathanw void
   1082  1.7.2.2  nathanw edworker(arg)
   1083  1.7.2.2  nathanw 	void *arg;
   1084  1.7.2.2  nathanw {
   1085  1.7.2.2  nathanw 	struct ed_softc *ed = (struct ed_softc *) arg;
   1086  1.7.2.2  nathanw 	struct buf *bp;
   1087  1.7.2.2  nathanw 	int s;
   1088  1.7.2.2  nathanw 
   1089  1.7.2.2  nathanw 	config_pending_decr();
   1090  1.7.2.2  nathanw 
   1091  1.7.2.2  nathanw 	for(;;) {
   1092  1.7.2.2  nathanw 		/* Wait until awakened */
   1093  1.7.2.2  nathanw 		(void) tsleep(&ed->sc_q, PRIBIO, "edidle", 0);
   1094  1.7.2.2  nathanw 
   1095  1.7.2.2  nathanw 		if ((ed->sc_flags & EDF_PROCESS_QUEUE) == 0)
   1096  1.7.2.2  nathanw 			panic("edworker: expecting process queue");
   1097  1.7.2.2  nathanw 		ed->sc_flags &= ~EDF_PROCESS_QUEUE;
   1098  1.7.2.2  nathanw 
   1099  1.7.2.2  nathanw 		for(;;) {
   1100  1.7.2.2  nathanw 			/* Is there a buf for us ? */
   1101  1.7.2.2  nathanw 			simple_lock(&ed->sc_q_lock);
   1102  1.7.2.2  nathanw 			if ((bp = BUFQ_FIRST(&ed->sc_q)) == NULL) {
   1103  1.7.2.2  nathanw 				simple_unlock(&ed->sc_q_lock);
   1104  1.7.2.2  nathanw 				break;
   1105  1.7.2.2  nathanw 			}
   1106  1.7.2.2  nathanw 			BUFQ_REMOVE(&ed->sc_q, bp);
   1107  1.7.2.2  nathanw 			simple_unlock(&ed->sc_q_lock);
   1108  1.7.2.2  nathanw 
   1109  1.7.2.2  nathanw 			/* Schedule i/o operation */
   1110  1.7.2.2  nathanw 			ed->sc_error = 0;
   1111  1.7.2.2  nathanw 			s = splbio();
   1112  1.7.2.2  nathanw 			__edstart(ed, bp);
   1113  1.7.2.2  nathanw 
   1114  1.7.2.2  nathanw 			/*
   1115  1.7.2.2  nathanw 			 * Wait until the command executes; edc_intr() wakes
   1116  1.7.2.2  nathanw 			 * us up.
   1117  1.7.2.2  nathanw 			 */
   1118  1.7.2.2  nathanw 			if (ed->sc_error == 0)
   1119  1.7.2.2  nathanw 				(void)tsleep(&ed->edc_softc, PRIBIO, "edwrk",0);
   1120  1.7.2.2  nathanw 
   1121  1.7.2.2  nathanw 			/* Handle i/o results */
   1122  1.7.2.2  nathanw 			edmcadone(ed, bp);
   1123  1.7.2.2  nathanw 			splx(s);
   1124  1.7.2.2  nathanw 		}
   1125  1.7.2.2  nathanw 	}
   1126  1.7.2.2  nathanw }
   1127