amr_disk.c revision 111249
151974Smsmith/*- 251974Smsmith * Copyright (c) 1999 Jonathan Lemon 365245Smsmith * Copyright (c) 1999, 2000 Michael Smith 465245Smsmith * Copyright (c) 2000 BSDi 551974Smsmith * All rights reserved. 651974Smsmith * 751974Smsmith * Redistribution and use in source and binary forms, with or without 851974Smsmith * modification, are permitted provided that the following conditions 951974Smsmith * are met: 1051974Smsmith * 1. Redistributions of source code must retain the above copyright 1151974Smsmith * notice, this list of conditions and the following disclaimer. 1251974Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1351974Smsmith * notice, this list of conditions and the following disclaimer in the 1451974Smsmith * documentation and/or other materials provided with the distribution. 1551974Smsmith * 1651974Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1751974Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1851974Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1951974Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2051974Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2151974Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2251974Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2351974Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2451974Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2551974Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2651974Smsmith * SUCH DAMAGE. 2751974Smsmith * 28106225Semoore * Copyright (c) 2002 Eric Moore 29106225Semoore * Copyright (c) 2002 LSI Logic Corporation 30106225Semoore * All rights reserved. 31106225Semoore * 32106225Semoore * Redistribution and use in source and binary forms, with or without 33106225Semoore * modification, are permitted provided that the following conditions 34106225Semoore * are met: 35106225Semoore * 1. Redistributions of source code must retain the above copyright 36106225Semoore * notice, this list of conditions and the following disclaimer. 37106225Semoore * 2. Redistributions in binary form must reproduce the above copyright 38106225Semoore * notice, this list of conditions and the following disclaimer in the 39106225Semoore * documentation and/or other materials provided with the distribution. 40105419Semoore * 3. The party using or redistributing the source code and binary forms 41106225Semoore * agrees to the disclaimer below and the terms and conditions set forth 42105419Semoore * herein. 43105419Semoore * 44106225Semoore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 45106225Semoore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46106225Semoore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47106225Semoore * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 48106225Semoore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49106225Semoore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50106225Semoore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51106225Semoore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52106225Semoore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53106225Semoore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54106225Semoore * SUCH DAMAGE. 55105419Semoore * 56106225Semoore * 5751974Smsmith * $FreeBSD: head/sys/dev/amr/amr_disk.c 111249 2003-02-22 10:02:05Z phk $ 5851974Smsmith */ 5951974Smsmith 6051974Smsmith/* 6151974Smsmith * Disk driver for AMI MegaRaid controllers 6251974Smsmith */ 6351974Smsmith 6451974Smsmith#include <sys/param.h> 6551974Smsmith#include <sys/systm.h> 6651974Smsmith#include <sys/kernel.h> 6751974Smsmith 6865245Smsmith#include <dev/amr/amr_compat.h> 6951974Smsmith#include <sys/bus.h> 7051974Smsmith#include <sys/conf.h> 7151974Smsmith#include <sys/devicestat.h> 7251974Smsmith#include <sys/disk.h> 7351974Smsmith 7451974Smsmith#include <machine/bus.h> 7551974Smsmith#include <sys/rman.h> 7651974Smsmith 7751974Smsmith#include <dev/amr/amrio.h> 7851974Smsmith#include <dev/amr/amrreg.h> 7951974Smsmith#include <dev/amr/amrvar.h> 8065245Smsmith#include <dev/amr/amr_tables.h> 8151974Smsmith 8251974Smsmith/* prototypes */ 8351974Smsmithstatic int amrd_probe(device_t dev); 8451974Smsmithstatic int amrd_attach(device_t dev); 8551974Smsmithstatic int amrd_detach(device_t dev); 8651974Smsmith 8751974Smsmithstatic d_open_t amrd_open; 8851974Smsmithstatic d_close_t amrd_close; 8951974Smsmithstatic d_strategy_t amrd_strategy; 9051974Smsmith 9151974Smsmith#define AMRD_CDEV_MAJOR 133 9251974Smsmith 9351974Smsmithstatic struct cdevsw amrd_cdevsw = { 9451974Smsmith /* open */ amrd_open, 9551974Smsmith /* close */ amrd_close, 9651974Smsmith /* read */ physread, 9751974Smsmith /* write */ physwrite, 98111249Sphk /* ioctl */ noioctl, 9951974Smsmith /* poll */ nopoll, 10051974Smsmith /* mmap */ nommap, 10151974Smsmith /* strategy */ amrd_strategy, 10251974Smsmith /* name */ "amrd", 10351974Smsmith /* maj */ AMRD_CDEV_MAJOR, 10451974Smsmith /* dump */ nodump, 10551974Smsmith /* psize */ nopsize, 10651974Smsmith /* flags */ D_DISK, 107107756Semoore#if __FreeBSD_version < 500000 108107756Semoore /* bmaj */ -1 109107756Semoore#endif 11051974Smsmith}; 11151974Smsmith 11251974Smsmithstatic devclass_t amrd_devclass; 11351974Smsmithstatic struct cdevsw amrddisk_cdevsw; 11465245Smsmith#ifdef FREEBSD_4 11551974Smsmithstatic int disks_registered = 0; 11665245Smsmith#endif 11751974Smsmith 11851974Smsmithstatic device_method_t amrd_methods[] = { 11951974Smsmith DEVMETHOD(device_probe, amrd_probe), 12051974Smsmith DEVMETHOD(device_attach, amrd_attach), 12151974Smsmith DEVMETHOD(device_detach, amrd_detach), 12251974Smsmith { 0, 0 } 12351974Smsmith}; 12451974Smsmith 12551974Smsmithstatic driver_t amrd_driver = { 12651974Smsmith "amrd", 12751974Smsmith amrd_methods, 12851974Smsmith sizeof(struct amrd_softc) 12951974Smsmith}; 13051974Smsmith 13151974SmsmithDRIVER_MODULE(amrd, amr, amrd_driver, amrd_devclass, 0, 0); 13251974Smsmith 13351974Smsmithstatic int 134105419Semooreamrd_open(dev_t dev, int flags, int fmt, d_thread_t *td) 13551974Smsmith{ 13658883Smsmith struct amrd_softc *sc = (struct amrd_softc *)dev->si_drv1; 137105419Semoore#if __FreeBSD_version < 500000 /* old buf style */ 138105419Semoore struct disklabel *label; 139105419Semoore#endif 14051974Smsmith 14165245Smsmith debug_called(1); 142105419Semoore 14351974Smsmith if (sc == NULL) 14451974Smsmith return (ENXIO); 14551974Smsmith 14651974Smsmith /* controller not active? */ 14751974Smsmith if (sc->amrd_controller->amr_state & AMR_STATE_SHUTDOWN) 14851974Smsmith return(ENXIO); 14951974Smsmith 150105419Semoore#if __FreeBSD_version < 500000 /* old buf style */ 151105419Semoore label = &sc->amrd_disk.d_label; 152105419Semoore bzero(label, sizeof(*label)); 153105419Semoore label->d_type = DTYPE_SCSI; 154105419Semoore label->d_secsize = AMR_BLKSIZE; 155105419Semoore label->d_nsectors = sc->amrd_drive->al_sectors; 156105419Semoore label->d_ntracks = sc->amrd_drive->al_heads; 157105419Semoore label->d_ncylinders = sc->amrd_drive->al_cylinders; 158105419Semoore label->d_secpercyl = sc->amrd_drive->al_sectors * sc->amrd_drive->al_heads; 159105419Semoore label->d_secperunit = sc->amrd_drive->al_size; 160105419Semoore#else 161103714Sphk sc->amrd_disk.d_sectorsize = AMR_BLKSIZE; 162103714Sphk sc->amrd_disk.d_mediasize = (off_t)sc->amrd_drive->al_size * AMR_BLKSIZE; 163103714Sphk sc->amrd_disk.d_fwsectors = sc->amrd_drive->al_sectors; 164103714Sphk sc->amrd_disk.d_fwheads = sc->amrd_drive->al_heads; 165105419Semoore#endif 16651974Smsmith 16751974Smsmith sc->amrd_flags |= AMRD_OPEN; 16851974Smsmith return (0); 16951974Smsmith} 17051974Smsmith 17151974Smsmithstatic int 172105419Semooreamrd_close(dev_t dev, int flags, int fmt, d_thread_t *td) 17351974Smsmith{ 17458883Smsmith struct amrd_softc *sc = (struct amrd_softc *)dev->si_drv1; 17551974Smsmith 17665245Smsmith debug_called(1); 177105419Semoore 17851974Smsmith if (sc == NULL) 17951974Smsmith return (ENXIO); 18051974Smsmith sc->amrd_flags &= ~AMRD_OPEN; 18151974Smsmith return (0); 18251974Smsmith} 18351974Smsmith 18451974Smsmith/* 18551974Smsmith * Read/write routine for a buffer. Finds the proper unit, range checks 18651974Smsmith * arguments, and schedules the transfer. Does not wait for the transfer 18751974Smsmith * to complete. Multi-page transfers are supported. All I/O requests must 18851974Smsmith * be a multiple of a sector in length. 18951974Smsmith */ 19051974Smsmithstatic void 19165245Smsmithamrd_strategy(struct bio *bio) 19251974Smsmith{ 19365245Smsmith struct amrd_softc *sc = (struct amrd_softc *)bio->bio_dev->si_drv1; 19451974Smsmith 19551974Smsmith /* bogus disk? */ 19651974Smsmith if (sc == NULL) { 19765245Smsmith bio->bio_error = EINVAL; 19851974Smsmith goto bad; 19951974Smsmith } 20051974Smsmith 20151974Smsmith devstat_start_transaction(&sc->amrd_stats); 20265245Smsmith amr_submit_bio(sc->amrd_controller, bio); 20351974Smsmith return; 20451974Smsmith 20551974Smsmith bad: 20665245Smsmith bio->bio_flags |= BIO_ERROR; 20751974Smsmith 20851974Smsmith /* 20951974Smsmith * Correctly set the buf to indicate a completed transfer 21051974Smsmith */ 21165245Smsmith bio->bio_resid = bio->bio_bcount; 21265245Smsmith biodone(bio); 21351974Smsmith return; 21451974Smsmith} 21551974Smsmith 21651974Smsmithvoid 21751974Smsmithamrd_intr(void *data) 21851974Smsmith{ 21965245Smsmith struct bio *bio = (struct bio *)data; 22065245Smsmith struct amrd_softc *sc = (struct amrd_softc *)bio->bio_dev->si_drv1; 22151974Smsmith 22265245Smsmith debug_called(2); 22358883Smsmith 22465245Smsmith if (bio->bio_flags & BIO_ERROR) { 22565245Smsmith bio->bio_error = EIO; 22665245Smsmith debug(1, "i/o error\n"); 22758883Smsmith } else { 22865245Smsmith bio->bio_resid = 0; 22958883Smsmith } 23051974Smsmith 231105419Semoore AMR_BIO_FINISH(bio); 23251974Smsmith} 23351974Smsmith 23451974Smsmithstatic int 23551974Smsmithamrd_probe(device_t dev) 23651974Smsmith{ 23751974Smsmith 23865245Smsmith debug_called(1); 239105419Semoore 240105419Semoore device_set_desc(dev, "LSILogic MegaRAID logical drive"); 24151974Smsmith return (0); 24251974Smsmith} 24351974Smsmith 24451974Smsmithstatic int 24551974Smsmithamrd_attach(device_t dev) 24651974Smsmith{ 24751974Smsmith struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev); 24851974Smsmith device_t parent; 24951974Smsmith 25065245Smsmith debug_called(1); 25151974Smsmith 25251974Smsmith parent = device_get_parent(dev); 25351974Smsmith sc->amrd_controller = (struct amr_softc *)device_get_softc(parent); 25451974Smsmith sc->amrd_unit = device_get_unit(dev); 25551974Smsmith sc->amrd_drive = device_get_ivars(dev); 25652274Smsmith sc->amrd_dev = dev; 25751974Smsmith 25852784Smsmith device_printf(dev, "%uMB (%u sectors) RAID %d (%s)\n", 25951974Smsmith sc->amrd_drive->al_size / ((1024 * 1024) / AMR_BLKSIZE), 26065245Smsmith sc->amrd_drive->al_size, sc->amrd_drive->al_properties & AMR_DRV_RAID_MASK, 26165245Smsmith amr_describe_code(amr_table_drvstate, AMR_DRV_CURSTATE(sc->amrd_drive->al_state))); 26251974Smsmith 26351974Smsmith devstat_add_entry(&sc->amrd_stats, "amrd", sc->amrd_unit, AMR_BLKSIZE, 26451974Smsmith DEVSTAT_NO_ORDERED_TAGS, 26554279Sken DEVSTAT_TYPE_STORARRAY | DEVSTAT_TYPE_IF_OTHER, 26654279Sken DEVSTAT_PRIORITY_ARRAY); 26751974Smsmith 26858883Smsmith sc->amrd_dev_t = disk_create(sc->amrd_unit, &sc->amrd_disk, 0, &amrd_cdevsw, &amrddisk_cdevsw); 26958883Smsmith sc->amrd_dev_t->si_drv1 = sc; 27065245Smsmith#ifdef FREEBSD_4 27151974Smsmith disks_registered++; 27265245Smsmith#endif 27351974Smsmith 27465245Smsmith /* set maximum I/O size to match the maximum s/g size */ 27565245Smsmith sc->amrd_dev_t->si_iosize_max = (AMR_NSEG - 1) * PAGE_SIZE; 27658883Smsmith 27751974Smsmith return (0); 27851974Smsmith} 27951974Smsmith 28051974Smsmithstatic int 28151974Smsmithamrd_detach(device_t dev) 28251974Smsmith{ 28351974Smsmith struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev); 28451974Smsmith 28565245Smsmith debug_called(1); 28651974Smsmith 28765245Smsmith if (sc->amrd_flags & AMRD_OPEN) 28865245Smsmith return(EBUSY); 28965245Smsmith 29051974Smsmith devstat_remove_entry(&sc->amrd_stats); 29165245Smsmith#ifdef FREEBSD_4 29265245Smsmith if (--disks_registered == 0) 29365245Smsmith cdevsw_remove(&amrddisk_cdevsw); 29465245Smsmith#else 295111216Sphk disk_destroy(&sc->amrd_disk); 29665245Smsmith#endif 29751974Smsmith return(0); 29851974Smsmith} 29951974Smsmith 300