File:  [DragonFly] / src / sys / dev / raid / amr / amr_disk.c
Revision 1.8: download - view: text, annotated - select for diffs
Thu May 13 23:49:18 2004 UTC (10 years, 5 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*-
    2:  * Copyright (c) 1999 Jonathan Lemon
    3:  * Copyright (c) 1999, 2000 Michael Smith
    4:  * Copyright (c) 2000 BSDi
    5:  * All rights reserved.
    6:  *
    7:  * Redistribution and use in source and binary forms, with or without
    8:  * modification, are permitted provided that the following conditions
    9:  * are met:
   10:  * 1. Redistributions of source code must retain the above copyright
   11:  *    notice, this list of conditions and the following disclaimer.
   12:  * 2. Redistributions in binary form must reproduce the above copyright
   13:  *    notice, this list of conditions and the following disclaimer in the
   14:  *    documentation and/or other materials provided with the distribution.
   15:  *
   16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26:  * SUCH DAMAGE.
   27:  *
   28:  * Copyright (c) 2002 Eric Moore
   29:  * Copyright (c) 2002 LSI Logic Corporation
   30:  * All rights reserved.
   31:  *
   32:  * Redistribution and use in source and binary forms, with or without
   33:  * modification, are permitted provided that the following conditions
   34:  * are met:
   35:  * 1. Redistributions of source code must retain the above copyright
   36:  *    notice, this list of conditions and the following disclaimer.
   37:  * 2. Redistributions in binary form must reproduce the above copyright
   38:  *    notice, this list of conditions and the following disclaimer in the
   39:  *    documentation and/or other materials provided with the distribution.
   40:  * 3. The party using or redistributing the source code and binary forms
   41:  *    agrees to the disclaimer below and the terms and conditions set forth
   42:  *    herein.
   43:  *
   44:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   45:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   46:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   47:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   48:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   49:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   50:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   51:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   52:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   53:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   54:  * SUCH DAMAGE.
   55:  *
   56:  * $FreeBSD: src/sys/dev/amr/amr_disk.c,v 1.5.2.5 2002/12/20 15:12:04 emoore Exp $
   57:  * $DragonFly: src/sys/dev/raid/amr/amr_disk.c,v 1.8 2004/05/13 23:49:18 dillon Exp $
   58:  */
   59: 
   60: /*
   61:  * Disk driver for AMI MegaRaid controllers
   62:  */
   63: 
   64: #include <sys/param.h>
   65: #include <sys/systm.h>
   66: #include <sys/kernel.h>
   67: 
   68: #include "amr_compat.h"
   69: #include <sys/bus.h>
   70: #include <sys/conf.h>
   71: #include <sys/devicestat.h>
   72: #include <sys/disk.h>
   73: 
   74: #include <vm/vm.h>
   75: #include <vm/pmap.h>
   76: 
   77: #include <machine/bus.h>
   78: #include <machine/md_var.h>
   79: #include <sys/rman.h>
   80: 
   81: #include "amrio.h"
   82: #include "amrreg.h"
   83: #include "amrvar.h"
   84: #include "amr_tables.h"
   85: 
   86: /* prototypes */
   87: static int amrd_probe(device_t dev);
   88: static int amrd_attach(device_t dev);
   89: static int amrd_detach(device_t dev);
   90: 
   91: static	d_open_t	amrd_open;
   92: static	d_close_t	amrd_close;
   93: static	d_strategy_t	amrd_strategy;
   94: static	d_ioctl_t	amrd_ioctl;
   95: static	d_dump_t	amrd_dump;
   96: 
   97: #define AMRD_CDEV_MAJOR	133
   98: 
   99: static struct cdevsw amrd_cdevsw = {
  100: 		/* name */ 	"amrd",
  101: 		/* maj */	AMRD_CDEV_MAJOR,
  102: 		/* flags */	D_DISK,
  103: 		/* port */      NULL,
  104: 		/* clone */	NULL,
  105: 
  106: 		/* open */	amrd_open,
  107: 		/* close */	amrd_close,
  108: 		/* read */	physread,
  109: 		/* write */	physwrite,
  110: 		/* ioctl */	amrd_ioctl,
  111: 		/* poll */	nopoll,
  112: 		/* mmap */	nommap,
  113: 		/* strategy */	amrd_strategy,
  114: 		/* dump */	amrd_dump,
  115: 		/* psize */ 	nopsize
  116: };
  117: 
  118: static devclass_t	amrd_devclass;
  119: 
  120: static device_method_t amrd_methods[] = {
  121:     DEVMETHOD(device_probe,	amrd_probe),
  122:     DEVMETHOD(device_attach,	amrd_attach),
  123:     DEVMETHOD(device_detach,	amrd_detach),
  124:     { 0, 0 }
  125: };
  126: 
  127: static driver_t amrd_driver = {
  128:     "amrd",
  129:     amrd_methods,
  130:     sizeof(struct amrd_softc)
  131: };
  132: 
  133: DRIVER_MODULE(amrd, amr, amrd_driver, amrd_devclass, 0, 0);
  134: 
  135: static int
  136: amrd_open(dev_t dev, int flags, int fmt, d_thread_t *td)
  137: {
  138:     struct amrd_softc	*sc = (struct amrd_softc *)dev->si_drv1;
  139: #if defined(__DragonFly__) || __FreeBSD_version < 500000		/* old buf style */
  140:     struct disklabel    *label;
  141: #endif
  142: 
  143:     debug_called(1);
  144: 
  145:     if (sc == NULL)
  146: 	return (ENXIO);
  147: 
  148:     /* controller not active? */
  149:     if (sc->amrd_controller->amr_state & AMR_STATE_SHUTDOWN)
  150: 	return(ENXIO);
  151: 
  152: #if defined(__DragonFly__) || __FreeBSD_version < 500000		/* old buf style */
  153:     label = &sc->amrd_disk.d_label;
  154:     bzero(label, sizeof(*label));
  155:     label->d_type       = DTYPE_SCSI;
  156:     label->d_secsize    = AMR_BLKSIZE;
  157:     label->d_nsectors   = sc->amrd_drive->al_sectors;
  158:     label->d_ntracks    = sc->amrd_drive->al_heads;
  159:     label->d_ncylinders = sc->amrd_drive->al_cylinders;
  160:     label->d_secpercyl  = sc->amrd_drive->al_sectors * sc->amrd_drive->al_heads;
  161:     label->d_secperunit = sc->amrd_drive->al_size;
  162: #else
  163:     sc->amrd_disk.d_sectorsize = AMR_BLKSIZE;
  164:     sc->amrd_disk.d_mediasize = (off_t)sc->amrd_drive->al_size * AMR_BLKSIZE;
  165:     sc->amrd_disk.d_fwsectors = sc->amrd_drive->al_sectors;
  166:     sc->amrd_disk.d_fwheads = sc->amrd_drive->al_heads;
  167: #endif
  168: 
  169:     sc->amrd_flags |= AMRD_OPEN;
  170:     return (0);
  171: }
  172: 
  173: static int
  174: amrd_close(dev_t dev, int flags, int fmt, d_thread_t *td)
  175: {
  176:     struct amrd_softc	*sc = (struct amrd_softc *)dev->si_drv1;
  177: 
  178:     debug_called(1);
  179: 
  180:     if (sc == NULL)
  181: 	return (ENXIO);
  182:     sc->amrd_flags &= ~AMRD_OPEN;
  183:     return (0);
  184: }
  185: 
  186: static int
  187: amrd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *td)
  188: {
  189: 
  190:     return (ENOTTY);
  191: }
  192: 
  193: 
  194: /********************************************************************************
  195:  * System crashdump support
  196:  */
  197: int
  198: amrd_dump(dev_t dev)
  199: {
  200:     
  201:     struct amrd_softc	*amrd_sc = (struct amrd_softc *)dev->si_drv1;
  202:     struct amr_softc	*amr_sc;
  203:     u_int		count, blkno, secsize;
  204:     vm_paddr_t		addr = 0;
  205:     long		blkcnt;
  206:     int			dumppages = MAXDUMPPGS;
  207:     int			error = 0;
  208:     int			driveno;
  209:     int			i;
  210: 
  211:     debug_called(1);
  212: 
  213:     if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize)))
  214:         return(error);
  215: 
  216:     amr_sc  = (struct amr_softc *)amrd_sc->amrd_controller;
  217: 
  218:     if (!amrd_sc || !amr_sc)
  219: 	return(ENXIO);
  220: 
  221:     blkcnt = howmany(PAGE_SIZE, secsize);
  222: 
  223:     driveno = amrd_sc->amrd_drive - amr_sc->amr_drive;
  224: 
  225:     while (count > 0) {
  226:     	caddr_t	va = NULL;
  227: 
  228: 	if ((count / blkcnt) < dumppages)
  229: 	    dumppages = count / blkcnt;
  230: 
  231: 	for (i = 0; i < dumppages; ++i) {
  232: 	    vm_paddr_t a = addr + (i * PAGE_SIZE);
  233: 	    if (is_physical_memory(a))
  234: 		va = pmap_kenter_temporary(trunc_page(a), i);
  235: 	    else
  236: 		va = pmap_kenter_temporary(trunc_page(0), i);
  237: 	}
  238: 
  239: 	if ((error = amr_dump_blocks(amr_sc, driveno, blkno, (void *)va,
  240: 				      (PAGE_SIZE * dumppages) / AMR_BLKSIZE)) != 0)
  241: 	    	return(error);
  242: 
  243: 	if (dumpstatus(addr, (off_t)count * DEV_BSIZE) < 0)
  244: 	    return(EINTR);
  245: 
  246: 	blkno += blkcnt * dumppages;
  247: 	count -= blkcnt * dumppages;
  248: 	addr += PAGE_SIZE * dumppages;
  249:     }
  250:     return (0);
  251: }
  252: /*
  253:  * Read/write routine for a buffer.  Finds the proper unit, range checks
  254:  * arguments, and schedules the transfer.  Does not wait for the transfer
  255:  * to complete.  Multi-page transfers are supported.  All I/O requests must
  256:  * be a multiple of a sector in length.
  257:  */
  258: static void
  259: amrd_strategy(struct bio *bio)
  260: {
  261:     struct amrd_softc	*sc = (struct amrd_softc *)bio->bio_dev->si_drv1;
  262: 
  263:     /* bogus disk? */
  264:     if (sc == NULL) {
  265: 	bio->bio_error = EINVAL;
  266: 	goto bad;
  267:     }
  268: 
  269:     devstat_start_transaction(&sc->amrd_stats);
  270:     amr_submit_bio(sc->amrd_controller, bio);
  271:     return;
  272: 
  273:  bad:
  274:     bio->bio_flags |= BIO_ERROR;
  275: 
  276:     /*
  277:      * Correctly set the buf to indicate a completed transfer
  278:      */
  279:     bio->bio_resid = bio->bio_bcount;
  280:     biodone(bio);
  281:     return;
  282: }
  283: 
  284: void
  285: amrd_intr(void *data)
  286: {
  287:     struct bio *bio = (struct bio *)data;
  288:     struct amrd_softc *sc = (struct amrd_softc *)bio->bio_dev->si_drv1;
  289: 
  290:     debug_called(2);
  291: 
  292:     if (bio->bio_flags & BIO_ERROR) {
  293: 	bio->bio_error = EIO;
  294: 	debug(1, "i/o error\n");
  295:     } else {
  296: 	bio->bio_resid = 0;
  297:     }
  298: 
  299:     AMR_BIO_FINISH(bio);
  300: }
  301: 
  302: static int
  303: amrd_probe(device_t dev)
  304: {
  305: 
  306:     debug_called(1);
  307: 
  308:     device_set_desc(dev, "LSILogic MegaRAID logical drive");
  309:     return (0);
  310: }
  311: 
  312: static int
  313: amrd_attach(device_t dev)
  314: {
  315:     struct amrd_softc	*sc = (struct amrd_softc *)device_get_softc(dev);
  316:     device_t		parent;
  317:     
  318:     debug_called(1);
  319: 
  320:     parent = device_get_parent(dev);
  321:     sc->amrd_controller = (struct amr_softc *)device_get_softc(parent);
  322:     sc->amrd_unit = device_get_unit(dev);
  323:     sc->amrd_drive = device_get_ivars(dev);
  324:     sc->amrd_dev = dev;
  325: 
  326:     device_printf(dev, "%uMB (%u sectors) RAID %d (%s)\n",
  327: 		  sc->amrd_drive->al_size / ((1024 * 1024) / AMR_BLKSIZE),
  328: 		  sc->amrd_drive->al_size, sc->amrd_drive->al_properties & AMR_DRV_RAID_MASK, 
  329: 		  amr_describe_code(amr_table_drvstate, AMR_DRV_CURSTATE(sc->amrd_drive->al_state)));
  330: 
  331:     devstat_add_entry(&sc->amrd_stats, "amrd", sc->amrd_unit, AMR_BLKSIZE,
  332: 		      DEVSTAT_NO_ORDERED_TAGS,
  333: 		      DEVSTAT_TYPE_STORARRAY | DEVSTAT_TYPE_IF_OTHER, 
  334: 		      DEVSTAT_PRIORITY_ARRAY);
  335: 
  336:     sc->amrd_dev_t = disk_create(sc->amrd_unit, &sc->amrd_disk, 0, &amrd_cdevsw);
  337:     sc->amrd_dev_t->si_drv1 = sc;
  338: 
  339:     /* set maximum I/O size to match the maximum s/g size */
  340:     sc->amrd_dev_t->si_iosize_max = (AMR_NSEG - 1) * PAGE_SIZE;
  341: 
  342:     return (0);
  343: }
  344: 
  345: static int
  346: amrd_detach(device_t dev)
  347: {
  348:     struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev);
  349: 
  350:     debug_called(1);
  351: 
  352:     if (sc->amrd_flags & AMRD_OPEN)
  353: 	return(EBUSY);
  354: 
  355:     devstat_remove_entry(&sc->amrd_stats);
  356:     disk_destroy(&sc->amrd_disk);
  357:     return(0);
  358: }
  359: