diff options
Diffstat (limited to 'sys/dev/aac/aac_disk.c')
-rw-r--r-- | sys/dev/aac/aac_disk.c | 413 |
1 files changed, 213 insertions, 200 deletions
diff --git a/sys/dev/aac/aac_disk.c b/sys/dev/aac/aac_disk.c index a5a70da..3917fa1 100644 --- a/sys/dev/aac/aac_disk.c +++ b/sys/dev/aac/aac_disk.c @@ -71,21 +71,21 @@ static d_dump_t aac_disk_dump; #define AAC_DISK_CDEV_MAJOR 151 static struct cdevsw aac_disk_cdevsw = { - /* open */ aac_disk_open, - /* close */ aac_disk_close, - /* read */ physread, - /* write */ physwrite, - /* ioctl */ noioctl, - /* poll */ nopoll, - /* mmap */ nommap, - /* strategy */ aac_disk_strategy, - /* name */ "aacd", - /* maj */ AAC_DISK_CDEV_MAJOR, - /* dump */ aac_disk_dump, - /* psize */ nopsize, - /* flags */ D_DISK, + /* open */ aac_disk_open, + /* close */ aac_disk_close, + /* read */ physread, + /* write */ physwrite, + /* ioctl */ noioctl, + /* poll */ nopoll, + /* mmap */ nommap, + /* strategy */ aac_disk_strategy, + /* name */ "aacd", + /* maj */ AAC_DISK_CDEV_MAJOR, + /* dump */ aac_disk_dump, + /* psize */ nopsize, + /* flags */ D_DISK, #if __FreeBSD_version < 500005 - /* bmaj */ -1 + /* bmaj */ -1 #endif }; @@ -96,16 +96,16 @@ static int disks_registered = 0; #endif static device_method_t aac_disk_methods[] = { - DEVMETHOD(device_probe, aac_disk_probe), - DEVMETHOD(device_attach, aac_disk_attach), - DEVMETHOD(device_detach, aac_disk_detach), - { 0, 0 } + DEVMETHOD(device_probe, aac_disk_probe), + DEVMETHOD(device_attach, aac_disk_attach), + DEVMETHOD(device_detach, aac_disk_detach), + { 0, 0 } }; static driver_t aac_disk_driver = { - "aacd", - aac_disk_methods, - sizeof(struct aac_disk) + "aacd", + aac_disk_methods, + sizeof(struct aac_disk) }; DRIVER_MODULE(aacd, aac, aac_disk_driver, aac_disk_devclass, 0, 0); @@ -120,7 +120,7 @@ SYSCTL_UINT(_hw_aac, OID_AUTO, iosize_max, CTLFLAG_RD, &aac_iosize_max, 0, #define AAC_MAXIO 65536 -/****************************************************************************** +/* * Handle open from generic layer. * * This is called by the diskslice code on first open in order to get the @@ -129,84 +129,90 @@ SYSCTL_UINT(_hw_aac, OID_AUTO, iosize_max, CTLFLAG_RD, &aac_iosize_max, 0, static int aac_disk_open(dev_t dev, int flags, int fmt, struct proc *p) { - struct aac_disk *sc = (struct aac_disk *)dev->si_drv1; - struct disklabel *label; + struct aac_disk *sc; + struct disklabel *label; + + debug_called(4); - debug_called(4); + sc = (struct aac_disk *)dev->si_drv1; - if (sc == NULL) - return (ENXIO); - - /* check that the controller is up and running */ - if (sc->ad_controller->aac_state & AAC_STATE_SUSPEND) - return(ENXIO); - - /* build synthetic label */ - label = &sc->ad_disk.d_label; - bzero(label, sizeof(*label)); - label->d_type = DTYPE_ESDI; - label->d_secsize = AAC_BLOCK_SIZE; - label->d_nsectors = sc->ad_sectors; - label->d_ntracks = sc->ad_heads; - label->d_ncylinders = sc->ad_cylinders; - label->d_secpercyl = sc->ad_sectors * sc->ad_heads; - label->d_secperunit = sc->ad_size; - - sc->ad_flags |= AAC_DISK_OPEN; - return (0); + if (sc == NULL) + return (ENXIO); + + /* check that the controller is up and running */ + if (sc->ad_controller->aac_state & AAC_STATE_SUSPEND) + return(ENXIO); + + /* build synthetic label */ + label = &sc->ad_disk.d_label; + bzero(label, sizeof(*label)); + label->d_type = DTYPE_ESDI; + label->d_secsize = AAC_BLOCK_SIZE; + label->d_nsectors = sc->ad_sectors; + label->d_ntracks = sc->ad_heads; + label->d_ncylinders = sc->ad_cylinders; + label->d_secpercyl = sc->ad_sectors * sc->ad_heads; + label->d_secperunit = sc->ad_size; + + sc->ad_flags |= AAC_DISK_OPEN; + return (0); } -/****************************************************************************** +/* * Handle last close of the disk device. */ static int aac_disk_close(dev_t dev, int flags, int fmt, struct proc *p) { - struct aac_disk *sc = (struct aac_disk *)dev->si_drv1; + struct aac_disk *sc; - debug_called(4); + debug_called(4); + + sc = (struct aac_disk *)dev->si_drv1; - if (sc == NULL) - return (ENXIO); + if (sc == NULL) + return (ENXIO); - sc->ad_flags &= ~AAC_DISK_OPEN; - return (0); + sc->ad_flags &= ~AAC_DISK_OPEN; + return (0); } -/****************************************************************************** +/* * Handle an I/O request. */ static void aac_disk_strategy(struct bio *bp) { - struct aac_disk *sc = (struct aac_disk *)bp->bio_dev->si_drv1; + struct aac_disk *sc; - debug_called(4); + debug_called(4); - /* bogus disk? */ - if (sc == NULL) { - bp->bio_flags |= BIO_ERROR; - bp->bio_error = EINVAL; - biodone(bp); - return; - } + sc = (struct aac_disk *)bp->bio_dev->si_drv1; - /* do-nothing operation? */ - if (bp->bio_bcount == 0) { - bp->bio_resid = bp->bio_bcount; - biodone(bp); - return; - } + /* bogus disk? */ + if (sc == NULL) { + bp->bio_flags |= BIO_ERROR; + bp->bio_error = EINVAL; + biodone(bp); + return; + } + + /* do-nothing operation? */ + if (bp->bio_bcount == 0) { + bp->bio_resid = bp->bio_bcount; + biodone(bp); + return; + } - /* perform accounting */ - devstat_start_transaction(&sc->ad_stats); + /* perform accounting */ + devstat_start_transaction(&sc->ad_stats); - /* pass the bio to the controller - it can work out who we are */ - aac_submit_bio(bp); - return; + /* pass the bio to the controller - it can work out who we are */ + aac_submit_bio(bp); + return; } -/****************************************************************************** +/* * Dump memory out to an array * * This queues blocks of memory of size AAC_MAXIO to the controller and waits @@ -215,186 +221,193 @@ aac_disk_strategy(struct bio *bp) static int aac_disk_dump(dev_t dev) { - struct aac_disk *ad = dev->si_drv1; - struct aac_softc *sc; - vm_offset_t addr = 0; - long blkcnt; - unsigned int count, blkno, secsize; - int dumppages = AAC_MAXIO / PAGE_SIZE; - int i, error; + struct aac_disk *ad; + struct aac_softc *sc; + vm_offset_t addr; + long blkcnt; + unsigned int count, blkno, secsize; + int dumppages; + int i, error; - if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize))) - return (error); + ad = dev->si_drv1; + addr = 0; + dumppages = AAC_MAXIO / PAGE_SIZE; - if (ad == NULL) - return (ENXIO); + if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize))) + return (error); - sc= ad->ad_controller; + if (ad == NULL) + return (ENXIO); - blkcnt = howmany(PAGE_SIZE, secsize); + sc= ad->ad_controller; - while (count > 0) { - caddr_t va = NULL; + blkcnt = howmany(PAGE_SIZE, secsize); - if ((count / blkcnt) < dumppages) - dumppages = count / blkcnt; + while (count > 0) { + caddr_t va = NULL; - for (i = 0; i < dumppages; ++i) { - vm_offset_t a = addr + (i * PAGE_SIZE); - if (is_physical_memory(a)) { - va = pmap_kenter_temporary(trunc_page(a), i); - } else { - va = pmap_kenter_temporary(trunc_page(0), i); - } - } + if ((count / blkcnt) < dumppages) + dumppages = count / blkcnt; + + for (i = 0; i < dumppages; ++i) { + vm_offset_t a = addr + (i * PAGE_SIZE); + if (is_physical_memory(a)) { + va = pmap_kenter_temporary(trunc_page(a), i); + } else { + va = pmap_kenter_temporary(trunc_page(0), i); + } + } retry: - /* - * Queue the block to the controller. If the queue is full, EBUSY - * will be returned. - */ - error = aac_dump_enqueue(ad, blkno, va, dumppages); - if (error && (error != EBUSY)) - return (error); - - if (!error) { - if (dumpstatus(addr, (long)(count * DEV_BSIZE)) < 0) - return (EINTR); - - blkno += blkcnt * dumppages; - count -= blkcnt * dumppages; - addr += PAGE_SIZE * dumppages; - if (count > 0) - continue; + /* + * Queue the block to the controller. If the queue is full, + * EBUSY will be returned. + */ + error = aac_dump_enqueue(ad, blkno, va, dumppages); + if (error && (error != EBUSY)) + return (error); + + if (!error) { + if (dumpstatus(addr, (long)(count * DEV_BSIZE)) < 0) + return (EINTR); + + blkno += blkcnt * dumppages; + count -= blkcnt * dumppages; + addr += PAGE_SIZE * dumppages; + if (count > 0) + continue; + } + + /* + * Either the queue was full on the last attemp, or we have no + * more data to dump. Let the queue drain out and retry the + * block if the queue was full. + */ + aac_dump_complete(sc); + + if (error == EBUSY) + goto retry; } - /* - * Either the queue was full on the last attemp, or we have no more - * data to dump. Let the queue drain out and retry the block if - * the queue was full. - */ - aac_dump_complete(sc); - - if (error == EBUSY) - goto retry; - } - - return (0); + return (0); } -/****************************************************************************** +/* * Handle completion of an I/O request. */ void aac_biodone(struct bio *bp) { - struct aac_disk *sc = (struct aac_disk *)bp->bio_dev->si_drv1; + struct aac_disk *sc; + int blkno; - debug_called(4); + debug_called(4); - devstat_end_transaction_bio(&sc->ad_stats, bp); - if (bp->bio_flags & BIO_ERROR) { - /* - * XXX For some reason, the disklabel seems to get zero'd out. This - * will cause diskerr to panic unless we pass in -1 as the blkno. - */ - int blkno = (sc->ad_label.d_nsectors) ? 0 : -1; + sc = (struct aac_disk *)bp->bio_dev->si_drv1; + + devstat_end_transaction_bio(&sc->ad_stats, bp); + if (bp->bio_flags & BIO_ERROR) { + blkno = (sc->ad_label.d_nsectors) ? 0 : -1; #if __FreeBSD_version > 500005 - diskerr(bp, (char *)bp->bio_driver1, blkno, &sc->ad_label); + diskerr(bp, (char *)bp->bio_driver1, blkno, &sc->ad_label); #else - diskerr(bp, (char *)bp->bio_driver1, 0, blkno, &sc->ad_label); + diskerr(bp, (char *)bp->bio_driver1, 0, blkno, &sc->ad_label); #endif - } - biodone(bp); + } + biodone(bp); } -/****************************************************************************** +/* * Stub only. */ static int aac_disk_probe(device_t dev) { - debug_called(2); + debug_called(2); - return (0); + return (0); } -/****************************************************************************** +/* * Attach a unit to the controller. */ static int aac_disk_attach(device_t dev) { - struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev); - - debug_called(1); - - /* initialise our softc */ - sc->ad_controller = - (struct aac_softc *)device_get_softc(device_get_parent(dev)); - sc->ad_container = device_get_ivars(dev); - sc->ad_dev = dev; - - /* - * require that extended translation be enabled - other drivers read the - * disk! - */ - sc->ad_size = sc->ad_container->co_mntobj.Capacity; - if (sc->ad_size >= (2 * 1024 * 1024)) { /* 2GB */ - sc->ad_heads = 255; - sc->ad_sectors = 63; - } else if (sc->ad_size >= (1 * 1024 * 1024)) { /* 1GB */ - sc->ad_heads = 128; - sc->ad_sectors = 32; - } else { - sc->ad_heads = 64; - sc->ad_sectors = 32; - } - sc->ad_cylinders = (sc->ad_size / (sc->ad_heads * sc->ad_sectors)); - - device_printf(dev, "%uMB (%u sectors)\n", - sc->ad_size / ((1024 * 1024) / AAC_BLOCK_SIZE), sc->ad_size); - - devstat_add_entry(&sc->ad_stats, "aacd", device_get_unit(dev), - AAC_BLOCK_SIZE, DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_STORARRAY | DEVSTAT_TYPE_IF_OTHER, - DEVSTAT_PRIORITY_ARRAY); - - /* attach a generic disk device to ourselves */ - sc->ad_dev_t = disk_create(device_get_unit(dev), &sc->ad_disk, 0, - &aac_disk_cdevsw, &aac_disk_disk_cdevsw); - sc->ad_dev_t->si_drv1 = sc; + struct aac_disk *sc; + + debug_called(1); + + sc = (struct aac_disk *)device_get_softc(dev); + + /* initialise our softc */ + sc->ad_controller = + (struct aac_softc *)device_get_softc(device_get_parent(dev)); + sc->ad_container = device_get_ivars(dev); + sc->ad_dev = dev; + + /* + * require that extended translation be enabled - other drivers read the + * disk! + */ + sc->ad_size = sc->ad_container->co_mntobj.Capacity; + if (sc->ad_size >= (2 * 1024 * 1024)) { /* 2GB */ + sc->ad_heads = 255; + sc->ad_sectors = 63; + } else if (sc->ad_size >= (1 * 1024 * 1024)) { /* 1GB */ + sc->ad_heads = 128; + sc->ad_sectors = 32; + } else { + sc->ad_heads = 64; + sc->ad_sectors = 32; + } + sc->ad_cylinders = (sc->ad_size / (sc->ad_heads * sc->ad_sectors)); + + device_printf(dev, "%uMB (%u sectors)\n", + sc->ad_size / ((1024 * 1024) / AAC_BLOCK_SIZE), + sc->ad_size); + + devstat_add_entry(&sc->ad_stats, "aacd", device_get_unit(dev), + AAC_BLOCK_SIZE, DEVSTAT_NO_ORDERED_TAGS, + DEVSTAT_TYPE_STORARRAY | DEVSTAT_TYPE_IF_OTHER, + DEVSTAT_PRIORITY_ARRAY); + + /* attach a generic disk device to ourselves */ + sc->ad_dev_t = disk_create(device_get_unit(dev), &sc->ad_disk, 0, + &aac_disk_cdevsw, &aac_disk_disk_cdevsw); + sc->ad_dev_t->si_drv1 = sc; #ifdef FREEBSD_4 - disks_registered++; + disks_registered++; #endif - sc->ad_dev_t->si_iosize_max = aac_iosize_max; - sc->unit = device_get_unit(dev); + sc->ad_dev_t->si_iosize_max = aac_iosize_max; + sc->unit = device_get_unit(dev); - return (0); + return (0); } -/****************************************************************************** +/* * Disconnect ourselves from the system. */ static int aac_disk_detach(device_t dev) { - struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev); + struct aac_disk *sc; - debug_called(2); + debug_called(2); - if (sc->ad_flags & AAC_DISK_OPEN) - return(EBUSY); + sc = (struct aac_disk *)device_get_softc(dev); - devstat_remove_entry(&sc->ad_stats); - disk_destroy(sc->ad_dev_t); + if (sc->ad_flags & AAC_DISK_OPEN) + return(EBUSY); + + devstat_remove_entry(&sc->ad_stats); + disk_destroy(sc->ad_dev_t); #ifdef FREEBSD_4 - if (--disks_registered == 0) - cdevsw_remove(&aac_disk_cdevsw); + if (--disks_registered == 0) + cdevsw_remove(&aac_disk_cdevsw); #endif - return(0); + return(0); } - |