summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1994-08-19 00:32:52 +0000
committerjkh <jkh@FreeBSD.org>1994-08-19 00:32:52 +0000
commit0dd81803dd3a677aabc42896dea95fdbb380cdfc (patch)
tree0f86a6e02401680746d10146a0ab1deec8983af0 /sys
parenta8a9b8d89bccc8d87a7b579545c9c08e763fe17e (diff)
downloadFreeBSD-src-0dd81803dd3a677aabc42896dea95fdbb380cdfc.zip
FreeBSD-src-0dd81803dd3a677aabc42896dea95fdbb380cdfc.tar.gz
Smash together Poul-Henning's, Garrett's and Steve Gerakines 24f changes
into one, hopefully functioning, Ultrastore driver. Any Ultrastore owners out there - please speak up! We need to test this puppy. Reviewed by: Submitted by:
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/isa/ultra14f.c330
1 files changed, 264 insertions, 66 deletions
diff --git a/sys/i386/isa/ultra14f.c b/sys/i386/isa/ultra14f.c
index 3a93461..d723ea0 100644
--- a/sys/i386/isa/ultra14f.c
+++ b/sys/i386/isa/ultra14f.c
@@ -19,13 +19,16 @@
* commenced: Sun Sep 27 18:14:01 PDT 1992
* slight mod to make work with 34F as well: Wed Jun 2 18:05:48 WST 1993
*
- * $Id: ultra14f.c,v 1.20 1994/08/13 03:50:17 wollman Exp $
+ * today: Fri Jun 2 17:21:03 EST 1994
+ * added 24F support ++sg
+ *
+ * $Id: ultra14f.c,v 1.21 1994/08/18 23:36:40 phk Exp $
*/
#include <sys/types.h>
#ifdef KERNEL /* don't laugh.. this compiles to a program too.. look */
-#include "uha.h"
+#include <uha.h>
#include <sys/param.h>
#include <sys/systm.h>
@@ -50,10 +53,6 @@
#define NUHA 1
#endif /*KERNEL */
-#ifndef NetBSD
-typedef timeout_func_t timeout_t;
-#endif
-
typedef struct {
unsigned char addr[4];
} physaddr;
@@ -77,40 +76,51 @@ extern int hz;
#define UHA_NSEG 33 /* number of dma segments supported */
/************************** board definitions *******************************/
-/*
- * I/O Port Interface
- */
-#define UHA_LMASK (0x000) /* local doorbell mask reg */
-#define UHA_LINT (0x001) /* local doorbell int/stat reg */
-#define UHA_SMASK (0x002) /* system doorbell mask reg */
-#define UHA_SINT (0x003) /* system doorbell int/stat reg */
-#define UHA_ID0 (0x004) /* product id reg 0 */
-#define UHA_ID1 (0x005) /* product id reg 1 */
-#define UHA_CONF1 (0x006) /* config reg 1 */
-#define UHA_CONF2 (0x007) /* config reg 2 */
-#define UHA_OGM0 (0x008) /* outgoing mail ptr 0 least sig */
-#define UHA_OGM1 (0x009) /* outgoing mail ptr 1 least mid */
-#define UHA_OGM2 (0x00a) /* outgoing mail ptr 2 most mid */
-#define UHA_OGM3 (0x00b) /* outgoing mail ptr 3 most sig */
-#define UHA_ICM0 (0x00c) /* incoming mail ptr 0 */
-#define UHA_ICM1 (0x00d) /* incoming mail ptr 1 */
-#define UHA_ICM2 (0x00e) /* incoming mail ptr 2 */
-#define UHA_ICM3 (0x00f) /* incoming mail ptr 3 */
+struct uha_reg
+{
+ int id; /* product id reg */
+ int type; /* product type reg */
+ int ectl; /* EISA expansion control bits */
+ int config; /* configuration bits */
+ int lmask; /* local doorbell mask reg */
+ int lint; /* local doorbell int/stat reg */
+ int smask; /* system doorbell mask reg */
+ int sint; /* system doorbell int/stat reg */
+ int ogmcmd; /* outgoing mail command */
+ int ogmptr; /* outgoing mail ptr */
+ int icmcmd; /* incoming mail command */
+ int icmptr; /* incoming mail ptr */
+} *uhareg[NUHA];
+
+struct uha_bits
+{
+ /* uha_lint (read) */
+ unsigned char ldip;
-/*
- * UHA_LMASK bits (read only)
- */
+ /* uha_lint (write) */
+ unsigned char adrst;
+ unsigned char sbrst;
+ unsigned char asrst;
+ unsigned char abort;
+ unsigned char ogmint;
+
+ /* uha_sint (read) */
+ unsigned char sintp;
+ unsigned char abort_succ;
+ unsigned char abort_fail;
+
+ /* uha_sint (write) */
+ unsigned char abort_ack;
+ unsigned char icm_ack;
+} *uhabits[NUHA];
-#define UHA_LDIE 0x80 /* local doorbell int enabled */
-#define UHA_SRSTE 0x40 /* soft reset enabled */
-#define UHA_ABORTEN 0x10 /* abort MSCP enabled */
-#define UHA_OGMINTEN 0x01 /* outgoing mail interrupt enabled */
/*
* UHA_LINT bits (read)
*/
#define UHA_LDIP 0x80 /* local doorbell int pending */
+#define U24_LDIP 0x02
/*
* UHA_LINT bits (write)
@@ -121,6 +131,11 @@ extern int hz;
#define UHA_ASRST 0x60 /* adapter and scsi reset */
#define UHA_ABORT 0x10 /* abort MSCP */
#define UHA_OGMINT 0x01 /* tell adapter to get mail */
+#define U24_SBRST 0x40 /* scsi bus reset */
+#define U24_ADRST 0x80 /* adapter soft reset */
+#define U24_ASRST 0xc0 /* adapter and scsi reset */
+#define U24_ABORT 0x10 /* same? */
+#define U24_OGMINT 0x02 /* enable OGM interrupt */
/*
* UHA_SMASK bits (read)
@@ -145,6 +160,9 @@ extern int hz;
#define UHA_SINTP 0x80 /* system doorbell int pending */
#define UHA_ABORT_SUCC 0x10 /* abort MSCP successful */
#define UHA_ABORT_FAIL 0x18 /* abort MSCP failed */
+#define U24_SINTP 0x02 /* system doorbell int pending */
+#define U24_ABORT_SUCC 0x10 /* same? */
+#define U24_ABORT_FAIL 0x18 /* same? */
/*
* UHA_SINT bits (write)
@@ -152,6 +170,8 @@ extern int hz;
#define UHA_ABORT_ACK 0x18 /* acknowledge status and clear */
#define UHA_ICM_ACK 0x01 /* acknowledge ICM and clear */
+#define U24_ABORT_ACK 0x18 /* same */
+#define U24_ICM_ACK 0x02 /* 24F acknowledge ICM and clear */
/*
* UHA_CONF1 bits (read only)
@@ -165,6 +185,9 @@ extern int hz;
#define UHA_IRQ11 0x20 /* 11 */
#define UHA_IRQ10 0x30 /* 10 */
+#define EISA_CONFIG 0x0c80 /* Configuration base port */
+#define EISA_DISABLE 0x01 /* EISA disable bit */
+
/*
* ha_status error codes
*/
@@ -227,7 +250,8 @@ struct mscp {
struct uha_data {
int flags;
-#define UHA_INIT 0x01;
+#define UHA_INIT 0x01
+#define UHA_24F 0x02
int baseport;
struct mscp *mscphash[MSCP_HASH_SIZE];
struct mscp *free_mscp;
@@ -242,7 +266,7 @@ int uhaprobe();
int uha_attach();
int uhaintr();
int32 uha_scsi_cmd();
-void uha_timeout(caddr_t);
+void uha_timeout(caddr_t, int);
void uha_free_mscp();
int uha_abort();
void uhaminphys();
@@ -311,10 +335,12 @@ uha_send_mbox(int unit, struct mscp *mscp)
struct uha_data *uha = uhadata[unit];
int port = uha->baseport;
int spincount = 100000; /* 1s should be enough */
+ struct uha_reg *ur = uhareg[unit];
+ struct uha_bits *ub = uhabits[unit];
int s = splbio();
while (--spincount) {
- if ((inb(port + UHA_LINT) & UHA_LDIP) == 0)
+ if ((inb(ur->lint) & ub->ldip) == 0)
break;
DELAY(100);
}
@@ -322,8 +348,9 @@ uha_send_mbox(int unit, struct mscp *mscp)
printf("uha%d: uha_send_mbox, board not responding\n", unit);
Debugger("ultra14f");
}
- outl(port + UHA_OGM0, KVTOPHYS(mscp));
- outb(port + UHA_LINT, (UHA_OGMINT));
+ outl(ur->ogmptr, KVTOPHYS(mscp));
+ if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1);
+ outb(ur->lint, ub->ogmint);
splx(s);
}
@@ -337,10 +364,12 @@ uha_abort(int unit, struct mscp *mscp)
int port = uha->baseport;
int spincount = 100; /* 1 mSec */
int abortcount = 200000; /*2 secs */
+ struct uha_reg *ur = uhareg[unit];
+ struct uha_bits *ub = uhabits[unit];
int s = splbio();
while (--spincount) {
- if ((inb(port + UHA_LINT) & UHA_LDIP) == 0)
+ if ((inb(ur->lint) & ub->ldip) == 0)
break;
DELAY(10);
}
@@ -348,11 +377,12 @@ uha_abort(int unit, struct mscp *mscp)
printf("uha%d: uha_abort, board not responding\n", unit);
Debugger("ultra14f");
}
- outl(port + UHA_OGM0, KVTOPHYS(mscp));
- outb(port + UHA_LINT, UHA_ABORT);
+ outl(ur->ogmptr,KVTOPHYS(mscp));
+ if (uha->flags & UHA_24F) outb(ur->ogmcmd, 1);
+ outb(ur->lint, ub->abort);
while (--abortcount) {
- if (inb(port + UHA_SINT) & UHA_ABORT_FAIL)
+ if (inb(ur->sint) & ub->abort_fail)
break;
DELAY(10);
}
@@ -360,12 +390,12 @@ uha_abort(int unit, struct mscp *mscp)
printf("uha%d: uha_abort, board not responding\n", unit);
Debugger("ultra14f");
}
- if ((inb(port + UHA_SINT) & 0x10) != 0) {
- outb(port + UHA_SINT, UHA_ABORT_ACK);
+ if ((inb(ur->sint) & 0x10) != 0) {
+ outb(ur->sint, ub->abort_ack);
splx(s);
return (1);
} else {
- outb(port + UHA_SINT, UHA_ABORT_ACK);
+ outb(ur->sint, ub->abort_ack);
splx(s);
return (0);
}
@@ -381,11 +411,13 @@ uha_poll(int unit, int wait)
{
struct uha_data *uha = uhadata[unit];
int port = uha->baseport;
- int stport = port + UHA_SINT;
+ struct uha_reg *ur = uhareg[unit];
+ struct uha_bits *ub = uhabits[unit];
+ int stport = ur->sint;
retry:
while (--wait) {
- if (inb(stport) & UHA_SINTP)
+ if (inb(stport) & ub->sintp)
break;
DELAY(1000); /* 1 mSec per loop */
}
@@ -408,6 +440,8 @@ uhaprobe(dev)
{
int unit = uha_unit;
struct uha_data *uha;
+ struct uha_reg *ur;
+ struct uha_bits *ub;
dev->id_unit = unit;
@@ -433,20 +467,40 @@ uhaprobe(dev)
return 0;
}
bzero(uha, sizeof(struct uha_data));
+
+ ur = malloc(sizeof(struct uha_reg), M_TEMP, M_NOWAIT);
+ if (!ur) {
+ printf("uha%d: cannot malloc!\n", unit);
+ return 0;
+ }
+ bzero(ur, sizeof(struct uha_reg));
+
+ ub = malloc(sizeof(struct uha_bits), M_TEMP, M_NOWAIT);
+ if (!ub) {
+ printf("uha%d: cannot malloc!\n", unit);
+ return 0;
+ }
+ bzero(ub, sizeof(struct uha_bits));
+
+ uhareg[unit] = ur;
+ uhabits[unit] = ub;
uhadata[unit] = uha;
uha->baseport = dev->id_iobase;
/*
* Try initialise a unit at this location
* sets up dma and bus speed, loads uha->vect
*/
- if (uha_init(unit) != 0) {
+ if (uha_init(unit) != 0 && uha24_init(unit) != 0) {
uhadata[unit] = NULL;
free(uha, M_TEMP);
+ free(ur, M_TEMP);
+ free(ub, M_TEMP);
return (0);
}
/* if it's there put in its interrupt and DRQ vectors */
dev->id_irq = (1 << uha->vect);
dev->id_drq = uha->dma;
+ dev->id_iobase = uha->baseport;
uha_unit++;
return (16);
@@ -501,6 +555,8 @@ uhaintr(unit)
struct mscp *mscp;
u_char uhastat;
unsigned long int mboxval;
+ struct uha_reg *ur = uhareg[unit];
+ struct uha_bits *ub = uhabits[unit];
int port = uha->baseport;
@@ -508,14 +564,14 @@ uhaintr(unit)
printf("uhaintr ");
#endif /*UHADEBUG */
- while (inb(port + UHA_SINT) & UHA_SINTP) {
+ while ((uhastat = inb(ur->sint)) & ub->sintp) {
/*
* First get all the information and then
* acknowledge the interrupt
*/
- uhastat = inb(port + UHA_SINT);
- mboxval = inl(port + UHA_ICM0);
- outb(port + UHA_SINT, UHA_ICM_ACK);
+ mboxval = inl(ur->icmptr);
+ outb(ur->sint, ub->icm_ack);
+ if (uha->flags & UHA_24F) outb(ur->icmcmd, 0);
#ifdef UHADEBUG
printf("status = 0x%x ", uhastat);
@@ -529,7 +585,7 @@ uhaintr(unit)
printf("uha: BAD MSCP RETURNED\n");
return (0); /* whatever it was, it'll timeout */
}
- untimeout((timeout_t)uha_timeout, (caddr_t)mscp);
+ untimeout(uha_timeout, (caddr_t)mscp);
uha_done(unit, mscp);
}
@@ -735,17 +791,44 @@ uha_init(unit)
int port = uha->baseport;
int i;
int resetcount = 4000; /* 4 secs? */
+ struct uha_reg *ur = uhareg[unit];
+ struct uha_bits *ub = uhabits[unit];
- model = inb(port + UHA_ID0);
- submodel = inb(port + UHA_ID1);
- if ((model != 0x56) & (submodel != 0x40)) {
- printf("uha%d: uha_init, board not responding\n", unit);
- return (ENXIO);
- }
+ /*
+ * Prepare to use a 14/34F.
+ */
+ ur->id = port + 0x04;
+ ur->type = port + 0x00; /* 24F only */
+ ur->ectl = port + 0x00; /* 24F only */
+ ur->config = port + 0x06; /* 0-1 for 14F */
+ ur->lmask = port + 0x00;
+ ur->lint = port + 0x01;
+ ur->smask = port + 0x02;
+ ur->sint = port + 0x03;
+ ur->ogmcmd = port + 0x00; /* 24F only */
+ ur->ogmptr = port + 0x08;
+ ur->icmcmd = port + 0x00; /* 24F only */
+ ur->icmptr = port + 0x0c;
+
+ ub->ldip = UHA_LDIP;
+ ub->adrst = UHA_ADRST;
+ ub->sbrst = UHA_SBRST;
+ ub->asrst = UHA_ASRST;
+ ub->abort = UHA_ABORT;
+ ub->ogmint = UHA_OGMINT;
+ ub->sintp = UHA_SINTP;
+ ub->abort_succ = UHA_ABORT_SUCC;
+ ub->abort_fail = UHA_ABORT_FAIL;
+ ub->abort_ack = UHA_ABORT_ACK;
+ ub->icm_ack = UHA_ICM_ACK;
+
+ model = inb(ur->id);
+ submodel = inb(ur->id + 1);
+ if ((model != 0x56) & (submodel != 0x40)) return(ENXIO);
printf("uha%d: reading board settings, ", unit);
- config_reg1 = inb(port + UHA_CONF1);
- config_reg2 = inb(port + UHA_CONF2);
+ config_reg1 = inb(ur->config);
+ config_reg2 = inb(ur->config + 1);
dma_ch = (config_reg1 & 0xc0);
irq_ch = (config_reg1 & 0x30);
uha_id = (config_reg2 & 0x07);
@@ -796,9 +879,9 @@ uha_init(unit)
/*
* Note that we are going and return (to probe)
*/
- outb(port + UHA_LINT, UHA_ASRST);
+ outb(ur->lint, ub->asrst);
while (--resetcount) {
- if (inb(port + UHA_LINT))
+ if (inb(ur->lint))
break;
DELAY(1000); /* 1 mSec per loop */
}
@@ -806,10 +889,125 @@ uha_init(unit)
printf("uha%d: board timed out during reset\n", unit);
return (ENXIO);
}
- outb(port + UHA_SMASK, 0x81); /* make sure interrupts are enabled */
+ outb(ur->smask, 0x81); /* make sure interrupts are enabled */
uha->flags |= UHA_INIT;
return (0);
}
+
+
+/*
+ * Initialize an Ultrastor 24F
+ */
+int
+uha24_init(unit)
+int unit;
+{
+ unsigned char p0, p1, p2, p3, p5, p6, p7;
+ unsigned char id[7], rev, emu, haid;
+ int slot, port, irq, i;
+ int resetcount = 4000;
+ struct uha_data *uha = uhadata[unit];
+ struct uha_reg *ur = uhareg[unit];
+ struct uha_bits *ub = uhabits[unit];
+
+ /* Search for the 24F's product ID */
+ for (slot = 1; slot < 15; slot++) {
+ /*
+ * Prepare to use a 24F.
+ */
+ port = EISA_CONFIG | (slot << 12);
+ ur->id = port + 0x00;
+ ur->type = port + 0x02;
+ ur->ectl = port + 0x04;
+ ur->config = port + 0x05; /* 0-2 for 24F */
+ ur->lmask = port + 0x0c;
+ ur->lint = port + 0x0d;
+ ur->smask = port + 0x0e;
+ ur->sint = port + 0x0f;
+ ur->ogmcmd = port + 0x16;
+ ur->ogmptr = port + 0x17;
+ ur->icmcmd = port + 0x1b;
+ ur->icmptr = port + 0x1c;
+
+ ub->ldip = U24_LDIP;
+ ub->adrst = U24_ADRST;
+ ub->sbrst = U24_SBRST;
+ ub->asrst = U24_ASRST;
+ ub->abort = U24_ABORT;
+ ub->ogmint = U24_OGMINT;
+ ub->sintp = U24_SINTP;
+ ub->abort_succ = U24_ABORT_SUCC;
+ ub->abort_fail = U24_ABORT_FAIL;
+ ub->abort_ack = U24_ABORT_ACK;
+ ub->icm_ack = U24_ICM_ACK;
+
+ /* Make sure an EISA card is installed in this slot. */
+ outb(ur->id, 0xff);
+ p0 = inb(ur->id);
+ if (p0 == 0xff || (p0 & 0x80) != 0) continue;
+
+ /* It's EISA, so make sure the card is enabled. */
+ if ((inb(ur->ectl) & EISA_DISABLE) == 0) continue;
+
+ /* Found an enabled card. Grab the product ID. */
+ p1 = inb(ur->id+1);
+ p2 = inb(ur->type);
+ p3 = inb(ur->type+1);
+ id[0] = 0x40 + ((p0 >> 2) & 0x1f);
+ id[1] = 0x40 + (((p0 & 0x03) << 3) | ((p1 >> 5) & 0x07));
+ id[2] = 0x40 + (p1 & 0x1f);
+ id[3] = "0123456789abcdef"[(p2 >> 4) & 0x0f];
+ id[4] = "0123456789abcdef"[p2 & 0x0f];
+ id[5] = "0123456789abcdef"[(p3 >> 4) & 0x0f];
+ id[6] = '\0';
+ rev = p3 & 0xf;
+
+ /* We only want the 24F product ID. */
+ if (!strcmp(id, "USC024")) break;
+ }
+ if (slot == 15) return(ENODEV);
+
+ /* We have the card! Grab remaining config. */
+ p5 = inb(ur->config);
+ p6 = inb(ur->config+1);
+ p7 = inb(ur->config+2);
+
+ /* If the 24F is currently emulating an ISA device, leave. */
+ emu = ((p6 & 0x04) >> 1) | ((p5 & 0x08) >> 3);
+ if (emu != 3) return(ENODEV);
+
+ switch (p5 & 0xf0) {
+ case 0x10: irq = 15; break;
+ case 0x20: irq = 14; break;
+ case 0x40: irq = 11; break;
+ case 0x80: irq = 10; break;
+ default:
+ printf("uha%d: bad 24F irq\n", unit);
+ return(ENXIO);
+ }
+
+ haid = (p7 & 0x07);
+ printf("uha%d: UltraStor 24F int=%d id=%d\n", unit, irq, haid);
+
+ /* Issue SCSI and adapter reset */
+ outb(ur->lint, ub->asrst);
+ while (--resetcount) {
+ if (inb(ur->lint))
+ break;
+ DELAY(1000); /* 1 mSec per loop */
+ }
+ if (resetcount == 0) {
+ printf("uha%d: board timed out during reset\n", unit);
+ return (ENXIO);
+ }
+ outb(ur->smask, 0xc2); /* make sure interrupts are enabled */
+ uha->flags |= (UHA_INIT | UHA_24F);
+ uha->baseport = port;
+ uha->our_id = haid;
+ uha->vect = irq;
+ uha->dma = -1;
+ return(0);
+}
#ifndef min
#define min(x,y) (x < y ? x : y)
@@ -1050,7 +1248,7 @@ uha_scsi_cmd(xs)
if (!(flags & SCSI_NOMASK)) {
s = splbio();
uha_send_mbox(unit, mscp);
- timeout((timeout_t)uha_timeout, (caddr_t)mscp, (xs->timeout * hz) / 1000);
+ timeout(uha_timeout, (caddr_t)mscp, (xs->timeout * hz) / 1000);
splx(s);
SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
return (SUCCESSFULLY_QUEUED);
@@ -1081,7 +1279,7 @@ uha_scsi_cmd(xs)
}
void
-uha_timeout(caddr_t arg1)
+uha_timeout(caddr_t arg1, int arg2)
{
struct mscp *mscp = (struct mscp *)arg1;
int unit;
@@ -1107,7 +1305,7 @@ uha_timeout(caddr_t arg1)
uha_done(unit, mscp, FAIL);
} else { /* abort the operation that has timed out */
printf("\n");
- timeout((timeout_t)uha_timeout, (caddr_t)mscp, 2 * hz);
+ timeout(uha_timeout, (caddr_t)mscp, 2 * hz);
mscp->flags = MSCP_ABORTED;
}
splx(s);
OpenPOWER on IntegriCloud