summaryrefslogtreecommitdiffstats
path: root/sys/scsi/uk.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1994-12-16 06:03:28 +0000
committerphk <phk@FreeBSD.org>1994-12-16 06:03:28 +0000
commit79b9c1263f080d302520cf64529707fd363e63d8 (patch)
tree607fd120fb8764aec7677552ecced37d39235225 /sys/scsi/uk.c
parentb95c9bb3382bde3c95738404bd046f22cee126e6 (diff)
downloadFreeBSD-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.c90
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));
}
OpenPOWER on IntegriCloud