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. 27119418Sobrien */ 28139749Simp/*- 29106225Semoore * Copyright (c) 2002 Eric Moore 30106225Semoore * Copyright (c) 2002 LSI Logic Corporation 31106225Semoore * All rights reserved. 32106225Semoore * 33106225Semoore * Redistribution and use in source and binary forms, with or without 34106225Semoore * modification, are permitted provided that the following conditions 35106225Semoore * are met: 36106225Semoore * 1. Redistributions of source code must retain the above copyright 37106225Semoore * notice, this list of conditions and the following disclaimer. 38106225Semoore * 2. Redistributions in binary form must reproduce the above copyright 39106225Semoore * notice, this list of conditions and the following disclaimer in the 40106225Semoore * documentation and/or other materials provided with the distribution. 41105419Semoore * 3. The party using or redistributing the source code and binary forms 42106225Semoore * agrees to the disclaimer below and the terms and conditions set forth 43105419Semoore * herein. 44105419Semoore * 45106225Semoore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46106225Semoore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47106225Semoore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48106225Semoore * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49106225Semoore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50106225Semoore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51106225Semoore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52106225Semoore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53106225Semoore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54106225Semoore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55106225Semoore * SUCH DAMAGE. 5651974Smsmith */ 5751974Smsmith 58119418Sobrien#include <sys/cdefs.h> 59119418Sobrien__FBSDID("$FreeBSD$"); 60119418Sobrien 6151974Smsmith/* 6251974Smsmith * Disk driver for AMI MegaRaid controllers 6351974Smsmith */ 6451974Smsmith 6551974Smsmith#include <sys/param.h> 6651974Smsmith#include <sys/systm.h> 6751974Smsmith#include <sys/kernel.h> 68129879Sphk#include <sys/module.h> 6951974Smsmith 70148850Sscottl#include <sys/bio.h> 7151974Smsmith#include <sys/bus.h> 7251974Smsmith#include <sys/conf.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 87111441Sphkstatic disk_open_t amrd_open; 88111441Sphkstatic disk_strategy_t amrd_strategy; 8951974Smsmith 9051974Smsmithstatic devclass_t amrd_devclass; 9165245Smsmith#ifdef FREEBSD_4 92153409Sscottlint amr_disks_registered = 0; 9365245Smsmith#endif 9451974Smsmith 9551974Smsmithstatic device_method_t amrd_methods[] = { 9651974Smsmith DEVMETHOD(device_probe, amrd_probe), 9751974Smsmith DEVMETHOD(device_attach, amrd_attach), 9851974Smsmith DEVMETHOD(device_detach, amrd_detach), 9951974Smsmith { 0, 0 } 10051974Smsmith}; 10151974Smsmith 10251974Smsmithstatic driver_t amrd_driver = { 10351974Smsmith "amrd", 10451974Smsmith amrd_methods, 10551974Smsmith sizeof(struct amrd_softc) 10651974Smsmith}; 10751974Smsmith 10851974SmsmithDRIVER_MODULE(amrd, amr, amrd_driver, amrd_devclass, 0, 0); 10951974Smsmith 11051974Smsmithstatic int 111111441Sphkamrd_open(struct disk *dp) 11251974Smsmith{ 113111441Sphk struct amrd_softc *sc = (struct amrd_softc *)dp->d_drv1; 11451974Smsmith 11565245Smsmith debug_called(1); 116105419Semoore 11751974Smsmith if (sc == NULL) 11851974Smsmith return (ENXIO); 11951974Smsmith 12051974Smsmith /* controller not active? */ 12151974Smsmith if (sc->amrd_controller->amr_state & AMR_STATE_SHUTDOWN) 12251974Smsmith return(ENXIO); 12351974Smsmith 12451974Smsmith return (0); 12551974Smsmith} 126120988Sps/******************************************************************************** 127120988Sps * System crashdump support 128120988Sps */ 12951974Smsmith 130120988Spsstatic int 131120988Spsamrd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length) 132120988Sps{ 133120988Sps 134120988Sps struct amrd_softc *amrd_sc; 135120988Sps struct amr_softc *amr_sc; 136120988Sps int error; 137120988Sps struct disk *dp; 138120988Sps 139120988Sps dp = arg; 140120988Sps amrd_sc = (struct amrd_softc *)dp->d_drv1; 141126116Scperciva if (amrd_sc == NULL) 142126116Scperciva return(ENXIO); 143120988Sps amr_sc = (struct amr_softc *)amrd_sc->amrd_controller; 144120988Sps 145120988Sps if (length > 0) { 146120988Sps int driveno = amrd_sc->amrd_drive - amr_sc->amr_drive; 147120988Sps if ((error = amr_dump_blocks(amr_sc,driveno,offset / AMR_BLKSIZE ,(void *)virtual,(int) length / AMR_BLKSIZE )) != 0) 148120988Sps return(error); 149120988Sps 150120988Sps } 151120988Sps return(0); 152120988Sps} 153120988Sps 15451974Smsmith/* 15551974Smsmith * Read/write routine for a buffer. Finds the proper unit, range checks 15651974Smsmith * arguments, and schedules the transfer. Does not wait for the transfer 15751974Smsmith * to complete. Multi-page transfers are supported. All I/O requests must 15851974Smsmith * be a multiple of a sector in length. 15951974Smsmith */ 16051974Smsmithstatic void 16165245Smsmithamrd_strategy(struct bio *bio) 16251974Smsmith{ 163111441Sphk struct amrd_softc *sc = (struct amrd_softc *)bio->bio_disk->d_drv1; 16451974Smsmith 16551974Smsmith /* bogus disk? */ 16651974Smsmith if (sc == NULL) { 16765245Smsmith bio->bio_error = EINVAL; 16851974Smsmith goto bad; 16951974Smsmith } 17051974Smsmith 17165245Smsmith amr_submit_bio(sc->amrd_controller, bio); 17251974Smsmith return; 17351974Smsmith 17451974Smsmith bad: 17565245Smsmith bio->bio_flags |= BIO_ERROR; 17651974Smsmith 17751974Smsmith /* 17851974Smsmith * Correctly set the buf to indicate a completed transfer 17951974Smsmith */ 18065245Smsmith bio->bio_resid = bio->bio_bcount; 18165245Smsmith biodone(bio); 18251974Smsmith return; 18351974Smsmith} 18451974Smsmith 18551974Smsmithvoid 18651974Smsmithamrd_intr(void *data) 18751974Smsmith{ 18865245Smsmith struct bio *bio = (struct bio *)data; 18951974Smsmith 19065245Smsmith debug_called(2); 19158883Smsmith 19265245Smsmith if (bio->bio_flags & BIO_ERROR) { 19365245Smsmith bio->bio_error = EIO; 19465245Smsmith debug(1, "i/o error\n"); 19558883Smsmith } else { 19665245Smsmith bio->bio_resid = 0; 19758883Smsmith } 19851974Smsmith 199148850Sscottl biodone(bio); 20051974Smsmith} 20151974Smsmith 20251974Smsmithstatic int 20351974Smsmithamrd_probe(device_t dev) 20451974Smsmith{ 20551974Smsmith 20665245Smsmith debug_called(1); 207105419Semoore 208105419Semoore device_set_desc(dev, "LSILogic MegaRAID logical drive"); 20951974Smsmith return (0); 21051974Smsmith} 21151974Smsmith 21251974Smsmithstatic int 21351974Smsmithamrd_attach(device_t dev) 21451974Smsmith{ 21551974Smsmith struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev); 21651974Smsmith device_t parent; 21751974Smsmith 21865245Smsmith debug_called(1); 21951974Smsmith 22051974Smsmith parent = device_get_parent(dev); 22151974Smsmith sc->amrd_controller = (struct amr_softc *)device_get_softc(parent); 22251974Smsmith sc->amrd_unit = device_get_unit(dev); 22351974Smsmith sc->amrd_drive = device_get_ivars(dev); 22452274Smsmith sc->amrd_dev = dev; 22551974Smsmith 22652784Smsmith device_printf(dev, "%uMB (%u sectors) RAID %d (%s)\n", 22751974Smsmith sc->amrd_drive->al_size / ((1024 * 1024) / AMR_BLKSIZE), 22865245Smsmith sc->amrd_drive->al_size, sc->amrd_drive->al_properties & AMR_DRV_RAID_MASK, 22965245Smsmith amr_describe_code(amr_table_drvstate, AMR_DRV_CURSTATE(sc->amrd_drive->al_state))); 23051974Smsmith 231125975Sphk sc->amrd_disk = disk_alloc(); 232125975Sphk sc->amrd_disk->d_drv1 = sc; 233125975Sphk sc->amrd_disk->d_maxsize = (AMR_NSEG - 1) * PAGE_SIZE; 234125975Sphk sc->amrd_disk->d_open = amrd_open; 235125975Sphk sc->amrd_disk->d_strategy = amrd_strategy; 236125975Sphk sc->amrd_disk->d_name = "amrd"; 237125975Sphk sc->amrd_disk->d_dump = (dumper_t *)amrd_dump; 238125975Sphk sc->amrd_disk->d_unit = sc->amrd_unit; 239163834Spjd sc->amrd_disk->d_flags = DISKFLAG_CANFLUSHCACHE; 240148840Sscottl sc->amrd_disk->d_sectorsize = AMR_BLKSIZE; 241148840Sscottl sc->amrd_disk->d_mediasize = (off_t)sc->amrd_drive->al_size * AMR_BLKSIZE; 242148840Sscottl sc->amrd_disk->d_fwsectors = sc->amrd_drive->al_sectors; 243148840Sscottl sc->amrd_disk->d_fwheads = sc->amrd_drive->al_heads; 244125975Sphk disk_create(sc->amrd_disk, DISK_VERSION); 24551974Smsmith 24651974Smsmith return (0); 24751974Smsmith} 24851974Smsmith 24951974Smsmithstatic int 25051974Smsmithamrd_detach(device_t dev) 25151974Smsmith{ 25251974Smsmith struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev); 25351974Smsmith 25465245Smsmith debug_called(1); 25551974Smsmith 256125975Sphk if (sc->amrd_disk->d_flags & DISKFLAG_OPEN) 25765245Smsmith return(EBUSY); 25865245Smsmith 25965245Smsmith#ifdef FREEBSD_4 260153409Sscottl if (--amr_disks_registered == 0) 26165245Smsmith cdevsw_remove(&amrddisk_cdevsw); 26265245Smsmith#else 263125975Sphk disk_destroy(sc->amrd_disk); 26465245Smsmith#endif 26551974Smsmith return(0); 26651974Smsmith} 26751974Smsmith 268