diff options
author | phk <phk@FreeBSD.org> | 1994-12-16 06:03:28 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 1994-12-16 06:03:28 +0000 |
commit | 79b9c1263f080d302520cf64529707fd363e63d8 (patch) | |
tree | 607fd120fb8764aec7677552ecced37d39235225 /sys/scsi/uk.c | |
parent | b95c9bb3382bde3c95738404bd046f22cee126e6 (diff) | |
download | FreeBSD-src-79b9c1263f080d302520cf64529707fd363e63d8.zip FreeBSD-src-79b9c1263f080d302520cf64529707fd363e63d8.tar.gz |
Allocate all scsi-devices on the fly, not just CDs.
Reviewed by: phk
Submitted by: rgrimes
Diffstat (limited to 'sys/scsi/uk.c')
-rw-r--r-- | sys/scsi/uk.c | 90 |
1 files changed, 70 insertions, 20 deletions
diff --git a/sys/scsi/uk.c b/sys/scsi/uk.c index 06fa1d7..f09fbbf 100644 --- a/sys/scsi/uk.c +++ b/sys/scsi/uk.c @@ -2,16 +2,16 @@ * Dummy driver for a device we can't identify. * by Julian Elischer (julian@tfs.com) * - * $Id: uk.c,v 1.3 1993/12/19 00:55:01 wollman Exp $ + * $Id: uk.c,v 1.4 1994/08/13 03:50:31 wollman Exp $ */ #include <sys/param.h> #include <sys/systm.h> #include <sys/errno.h> #include <sys/ioctl.h> +#include <sys/malloc.h> #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> -#define NUK 16 /* * This driver is so simple it uses all the default services @@ -29,10 +29,14 @@ struct scsi_device uk_switch = struct uk_data { u_int32 flags; +#define UK_KNOWN 0x02 struct scsi_link *sc_link; /* all the inter level info */ -} uk_data[NUK]; +}; -#define UK_KNOWN 0x02 +struct uk_driver { + u_int32 size; + struct uk_data **uk_data; +} uk_driver; static u_int32 next_uk_unit = 0; @@ -45,30 +49,69 @@ ukattach(sc_link) struct scsi_link *sc_link; { u_int32 unit, i, stat; + struct uk_data *uk, **ukrealloc; unsigned char *tbl; SC_DEBUG(sc_link, SDEV_DB2, ("ukattach: ")); + /* - * Check we have the resources for another drive + * allocate the resources for another drive + * if we have already allocate a uk_data pointer we must + * copy the old pointers into a new region that is + * larger and release the old region, aka realloc + */ + /* XXX + * This if will always be true for now, but future code may + * preallocate more units to reduce overhead. This would be + * done by changing the malloc to be (next_uk_unit * x) and + * the uk_driver.size++ to be +x */ unit = next_uk_unit++; - if (unit >= NUK) { - printf("Too many unknown devices..(%d > %d) reconfigure kernel\n", - (unit + 1), NUK); + if (unit >= uk_driver.size) { + ukrealloc = + malloc(sizeof(uk_driver.uk_data) * next_uk_unit, + M_DEVBUF, M_NOWAIT); + if (!ukrealloc) { + printf("uk%ld: malloc failed for ukrealloc\n", unit); + return (0); + } + /* Make sure we have something to copy before we copy it */ + bzero(ukrealloc, sizeof(uk_driver.uk_data) * next_uk_unit); + if (uk_driver.size) { + bcopy(uk_driver.uk_data, ukrealloc, + sizeof(uk_driver.uk_data) * uk_driver.size); + free(uk_driver.uk_data, M_DEVBUF); + } + uk_driver.uk_data = ukrealloc; + uk_driver.uk_data[unit] = NULL; + uk_driver.size++; + } + if (uk_driver.uk_data[unit]) { + printf("uk%ld: Already has storage!\n", unit); return (0); } /* + * alloate the per drive data area + */ + uk = uk_driver.uk_data[unit] = + malloc(sizeof(struct uk_data), M_DEVBUF, M_NOWAIT); + if (!uk) { + printf("uk%ld: malloc failed for uk_data\n", unit); + return (0); + } + bzero(uk, sizeof(struct uk_data)); + + /* * Store information needed to contact our base driver */ - uk_data[unit].sc_link = sc_link; + uk->sc_link = sc_link; sc_link->device = &uk_switch; sc_link->dev_unit = unit; printf("uk%d: unknown device\n", unit); - uk_data[unit].flags = UK_KNOWN; + uk->flags = UK_KNOWN; return 1; /* XXX ??? */ - } /* @@ -80,21 +123,23 @@ ukopen(dev) { errval errcode = 0; u_int32 unit, mode; + struct uk_data *uk; struct scsi_link *sc_link; unit = minor(dev); /* * Check the unit is legal */ - if (unit >= NUK) { - printf("uk%d: uk %d > %d\n", unit, unit, NUK); + if (unit >= uk_driver.size) { + printf("uk%d: uk %d > %d\n", unit, unit, uk_driver.size); return ENXIO; } + uk = uk_driver.uk_data[unit]; /* * Make sure the device has been initialised */ - if((uk_data[unit].flags & UK_KNOWN) == 0) { + if((!uk) || (!(uk->flags & UK_KNOWN))) { printf("uk%d: not set up\n", unit); return ENXIO; } @@ -102,14 +147,14 @@ ukopen(dev) /* * Only allow one at a time */ - sc_link = uk_data[unit].sc_link; + sc_link = uk->sc_link; if (sc_link->flags & SDEV_OPEN) { printf("uk%d: already open\n", unit); return ENXIO; } sc_link->flags |= SDEV_OPEN; - SC_DEBUG(sc_link, SDEV_DB1, ("ukopen: dev=0x%x (unit %d (of %d))\n" - ,dev, unit, NUK)); + SC_DEBUG(sc_link, SDEV_DB1, ("ukopen: dev=0x%x (unit %d (of %d))\n", + dev, unit, uk_driver.size)); /* * Catch any unit attention errors. */ @@ -124,10 +169,13 @@ errval ukclose(dev) dev_t dev; { - unsigned char unit = 0, mode; /* XXX !!! XXX FIXME!!! 0??? */ + u_int32 unit = minor(dev); + unsigned mode; /* XXX !!! XXX FIXME!!! 0??? */ + struct uk_data *uk; struct scsi_link *sc_link; - sc_link = uk_data[unit].sc_link; + uk = uk_driver.uk_data[unit]; + sc_link = uk->sc_link; SC_DEBUG(sc_link, SDEV_DB1, ("Closing device")); sc_link->flags &= ~SDEV_OPEN; @@ -146,13 +194,15 @@ ukioctl(dev, cmd, arg, mode) int mode; { unsigned char unit; + struct uk_data *uk; struct scsi_link *sc_link; /* * Find the device that the user is talking about */ unit = minor(dev); - sc_link = uk_data[unit].sc_link; + uk = uk_driver.uk_data[unit]; + sc_link = uk->sc_link; return(scsi_do_ioctl(sc_link,cmd,arg,mode)); } |