summaryrefslogtreecommitdiffstats
path: root/sys/dev/pst
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2003-04-28 08:10:27 +0000
committersos <sos@FreeBSD.org>2003-04-28 08:10:27 +0000
commite4d0be5799de5eb1f1f39497ae6f59ba0be217f7 (patch)
tree5898bc19a4e88c6f75e85b4d29759a242d7ce1ff /sys/dev/pst
parent1b6624b99947fc439495bb677aefb00a9b89872f (diff)
downloadFreeBSD-src-e4d0be5799de5eb1f1f39497ae6f59ba0be217f7.zip
FreeBSD-src-e4d0be5799de5eb1f1f39497ae6f59ba0be217f7.tar.gz
Pull the pst driver out from under GAINT.
Diffstat (limited to 'sys/dev/pst')
-rw-r--r--sys/dev/pst/pst-iop.c91
-rw-r--r--sys/dev/pst/pst-iop.h23
-rw-r--r--sys/dev/pst/pst-pci.c19
-rw-r--r--sys/dev/pst/pst-raid.c93
4 files changed, 151 insertions, 75 deletions
diff --git a/sys/dev/pst/pst-iop.c b/sys/dev/pst/pst-iop.c
index 98c2f1d..dd372ef 100644
--- a/sys/dev/pst/pst-iop.c
+++ b/sys/dev/pst/pst-iop.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2001,2002,2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,8 @@
#include <sys/bus.h>
#include <sys/bio.h>
#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/stdarg.h>
@@ -46,6 +48,11 @@
#include "dev/pst/pst-iop.h"
+struct iop_request {
+ struct i2o_single_reply *reply;
+ u_int32_t mfa;
+};
+
/* local vars */
MALLOC_DEFINE(M_PSTIOP, "PSTIOP", "Promise SuperTrak IOP driver");
@@ -136,13 +143,19 @@ iop_attach(struct iop_softc *sc)
continue;
switch (sc->lct[i].class) {
+ case I2O_CLASS_DDM:
+ if (sc->lct[i].sub_class == I2O_SUBCLASS_ISM)
+ sc->ism = sc->lct[i].local_tid;
+ break;
+
case I2O_CLASS_RANDOM_BLOCK_STORAGE:
pst_add_raid(sc, &sc->lct[i]);
break;
}
}
+
/* setup and enable interrupts */
- bus_setup_intr(sc->dev, sc->r_irq, INTR_TYPE_BIO | INTR_ENTROPY,
+ bus_setup_intr(sc->dev, sc->r_irq, INTR_TYPE_BIO|INTR_ENTROPY|INTR_MPSAFE,
iop_intr, sc, &sc->handle);
sc->reg->oqueue_intr_mask = 0x0;
}
@@ -155,21 +168,22 @@ iop_intr(void *data)
u_int32_t mfa;
/* we might get more than one finished request pr interrupt */
+ mtx_lock(&sc->mtx);
while (1) {
if ((mfa = sc->reg->oqueue) == 0xffffffff)
if ((mfa = sc->reg->oqueue) == 0xffffffff)
- return;
+ break;
reply = (struct i2o_single_reply *)(sc->obase + (mfa - sc->phys_obase));
- /* If this is an event register reply, shout! */
+ /* if this is an event register reply, shout! */
if (reply->function == I2O_UTIL_EVENT_REGISTER) {
struct i2o_util_event_reply_message *event =
(struct i2o_util_event_reply_message *)reply;
printf("pstiop: EVENT!! idx=%08x data=%08x\n",
event->event_mask, event->event_data[0]);
- return;
+ break;
}
/* if reply is a failurenotice we need to free the original mfa */
@@ -180,6 +194,7 @@ iop_intr(void *data)
((void (*)(struct iop_softc *, u_int32_t, struct i2o_single_reply *))
(reply->initiator_context))(sc, mfa, reply);
}
+ mtx_unlock(&sc->mtx);
}
int
@@ -226,7 +241,7 @@ iop_init_outqueue(struct iop_softc *sc)
I2O_IOP_OUTBOUND_FRAME_SIZE,
M_PSTIOP, M_NOWAIT,
0x00010000, 0xFFFFFFFF,
- sizeof(u_int32_t), 0))) {
+ PAGE_SIZE, 0))) {
printf("pstiop: contigmalloc of outqueue buffers failed!\n");
return 0;
}
@@ -268,7 +283,6 @@ iop_init_outqueue(struct iop_softc *sc)
DELAY(1000);
}
- iop_free_mfa(sc, mfa);
return 1;
}
@@ -281,7 +295,7 @@ iop_get_lct(struct iop_softc *sc)
#define ALLOCSIZE (PAGE_SIZE + (256 * sizeof(struct i2o_lct_entry)))
if (!(reply = contigmalloc(ALLOCSIZE, M_PSTIOP, M_NOWAIT | M_ZERO,
- 0x00010000, 0xFFFFFFFF, sizeof(u_int32_t), 0)))
+ 0x00010000, 0xFFFFFFFF, PAGE_SIZE, 0)))
return 0;
mfa = iop_get_mfa(sc);
@@ -325,11 +339,11 @@ iop_get_util_params(struct iop_softc *sc, int target, int operation, int group)
int mfa;
if (!(param = contigmalloc(PAGE_SIZE, M_PSTIOP, M_NOWAIT | M_ZERO,
- 0x00010000, 0xFFFFFFFF, sizeof(u_int32_t), 0)))
+ 0x00010000, 0xFFFFFFFF, PAGE_SIZE, 0)))
return NULL;
if (!(reply = contigmalloc(PAGE_SIZE, M_PSTIOP, M_NOWAIT | M_ZERO,
- 0x00010000, 0xFFFFFFFF, sizeof(u_int32_t), 0)))
+ 0x00010000, 0xFFFFFFFF, PAGE_SIZE, 0)))
return NULL;
mfa = iop_get_mfa(sc);
@@ -395,25 +409,54 @@ iop_free_mfa(struct iop_softc *sc, int mfa)
sc->reg->iqueue = mfa;
}
+static void
+iop_done(struct iop_softc *sc, u_int32_t mfa, struct i2o_single_reply *reply)
+{
+ struct iop_request *request =
+ (struct iop_request *)reply->transaction_context;
+
+ request->reply = reply;
+ request->mfa = mfa;
+ wakeup(request);
+}
+
int
iop_queue_wait_msg(struct iop_softc *sc, int mfa, struct i2o_basic_message *msg)
{
struct i2o_single_reply *reply;
- int out_mfa, status, timeout = 10000;
-
- sc->reg->iqueue = mfa;
-
- while (--timeout && ((out_mfa = sc->reg->oqueue) == 0xffffffff))
- DELAY(1000);
- if (!timeout) {
- printf("pstiop: timeout waiting for message response\n");
- iop_free_mfa(sc, mfa);
- return -1;
+ struct iop_request request;
+ u_int32_t out_mfa;
+ int status, timeout = 10000;
+
+ mtx_lock(&sc->mtx);
+ if (!(sc->reg->oqueue_intr_mask & 0x08)) {
+ msg->transaction_context = (u_int32_t)&request;
+ msg->initiator_context = (u_int32_t)iop_done;
+ sc->reg->iqueue = mfa;
+ if (msleep(&request, &sc->mtx, PRIBIO, "pstwt", 10 * hz)) {
+ printf("pstiop: timeout waiting for message response\n");
+ iop_free_mfa(sc, mfa);
+ mtx_unlock(&sc->mtx);
+ return -1;
+ }
+ status = request.reply->status;
+ sc->reg->oqueue = request.mfa;
}
-
- reply = (struct i2o_single_reply *)(sc->obase + (out_mfa - sc->phys_obase));
- status = reply->status;
- sc->reg->oqueue = out_mfa;
+ else {
+ sc->reg->iqueue = mfa;
+ while (--timeout && ((out_mfa = sc->reg->oqueue) == 0xffffffff))
+ DELAY(1000);
+ if (!timeout) {
+ printf("pstiop: timeout waiting for message response\n");
+ iop_free_mfa(sc, mfa);
+ mtx_unlock(&sc->mtx);
+ return -1;
+ }
+ reply = (struct i2o_single_reply *)(sc->obase+(out_mfa-sc->phys_obase));
+ status = reply->status;
+ sc->reg->oqueue = out_mfa;
+ }
+ mtx_unlock(&sc->mtx);
return status;
}
diff --git a/sys/dev/pst/pst-iop.h b/sys/dev/pst/pst-iop.h
index 3b45d89..9badbf8 100644
--- a/sys/dev/pst/pst-iop.h
+++ b/sys/dev/pst/pst-iop.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2001,2002,2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,10 @@ struct iop_softc {
struct i2o_status_get_reply *status;
int lct_count;
struct i2o_lct_entry *lct;
+ int ism;
device_t dev;
+ struct mtx mtx;
+ int outstanding;
void *handle;
struct intr_config_hook *iop_delayed_attach;
};
@@ -121,6 +124,7 @@ struct i2o_sgl {
#define I2O_EXEC_SYSTAB_SET 0xa3
#define I2O_EXEC_IOP_RESET 0xbd
#define I2O_EXEC_SYS_ENABLE 0xd1
+#define I2O_PRIVATE_MESSAGE 0xff
/* basic message layout */
struct i2o_basic_message {
@@ -498,7 +502,7 @@ struct i2o_get_param_operation {
} __packed;
struct i2o_get_param_reply {
- u_int16_t result_count;;
+ u_int16_t result_count;
u_int16_t reserved;
u_int16_t block_size;
u_int8_t block_status;
@@ -580,6 +584,21 @@ struct i2o_util_config_dialog_message {
struct i2o_sgl sgl[2];
} __packed;
+struct i2o_private_message {
+ u_int8_t version_offset;
+ u_int8_t message_flags;
+ u_int16_t message_size;
+ u_int32_t target_address:12;
+ u_int32_t initiator_address:12;
+ u_int32_t function:8;
+ u_int32_t initiator_context;
+ u_int32_t transaction_context;
+ u_int16_t function_code;
+ u_int16_t organization_id;
+ struct i2o_sgl in_sgl;
+ struct i2o_sgl out_sgl;
+} __packed;
+
struct i2o_bsa_rw_block_message {
u_int8_t version_offset;
u_int8_t message_flags;
diff --git a/sys/dev/pst/pst-pci.c b/sys/dev/pst/pst-pci.c
index 0955450..47272dc 100644
--- a/sys/dev/pst/pst-pci.c
+++ b/sys/dev/pst/pst-pci.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2001,2002,2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,8 @@
#include <sys/bus.h>
#include <sys/bio.h>
#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/stdarg.h>
@@ -93,16 +95,29 @@ iop_pci_attach(device_t dev)
sc->phys_ibase = vtophys(sc->ibase);
sc->reg = (struct i2o_registers *)sc->ibase;
sc->dev = dev;
+ mtx_init(&sc->mtx, "pst lock", MTX_DEF, 0);
if (!iop_init(sc))
return 0;
-
return bus_generic_attach(dev);
}
+static int
+iop_pci_detach(device_t dev)
+{
+ struct iop_softc *sc = device_get_softc(dev);
+
+ bus_teardown_intr(dev, sc->r_irq, sc->handle);
+ bus_release_resource(dev, SYS_RES_IRQ, 0x00, sc->r_irq);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0x10, sc->r_mem);
+ return bus_generic_detach(dev);
+}
+
+
static device_method_t pst_pci_methods[] = {
DEVMETHOD(device_probe, iop_pci_probe),
DEVMETHOD(device_attach, iop_pci_attach),
+ DEVMETHOD(device_detach, iop_pci_detach),
{ 0, 0 }
};
diff --git a/sys/dev/pst/pst-raid.c b/sys/dev/pst/pst-raid.c
index b7c96de..957d3b7 100644
--- a/sys/dev/pst/pst-raid.c
+++ b/sys/dev/pst/pst-raid.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001,2002 Søren Schmidt <sos@FreeBSD.org>
+ * Copyright (c) 2001,2002,2003 Søren Schmidt <sos@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,8 +57,6 @@ struct pst_softc {
struct i2o_bsa_device *info;
struct disk disk;
struct bio_queue_head queue;
- struct mtx mtx;
- int outstanding;
};
struct pst_request {
@@ -149,13 +147,12 @@ pst_attach(device_t dev)
contigfree(reply, PAGE_SIZE, M_PSTRAID);
bioq_init(&psc->queue);
- mtx_init(&psc->mtx, "pst lock", MTX_DEF, 0);
psc->disk.d_name = "pst";
psc->disk.d_strategy = pststrategy;
psc->disk.d_maxsize = 64 * 1024; /*I2O_SGL_MAX_SEGS * PAGE_SIZE;*/
psc->disk.d_drv1 = psc;
- disk_create(lun, &psc->disk, 0, NULL, NULL);
+ disk_create(lun, &psc->disk, DISKFLAG_NOGIANT, NULL, NULL);
psc->disk.d_sectorsize = psc->info->block_size;
psc->disk.d_mediasize = psc->info->capacity;
@@ -199,10 +196,10 @@ pststrategy(struct bio *bp)
{
struct pst_softc *psc = bp->bio_disk->d_drv1;
- mtx_lock(&psc->mtx);
+ mtx_lock(&psc->iop->mtx);
bioq_disksort(&psc->queue, bp);
pst_start(psc);
- mtx_unlock(&psc->mtx);
+ mtx_unlock(&psc->iop->mtx);
}
static void
@@ -212,7 +209,7 @@ pst_start(struct pst_softc *psc)
struct bio *bp;
u_int32_t mfa;
- if (psc->outstanding < (I2O_IOP_OUTBOUND_FRAME_COUNT - 1) &&
+ if (psc->iop->outstanding < (I2O_IOP_OUTBOUND_FRAME_COUNT - 1) &&
(bp = bioq_first(&psc->queue))) {
if ((mfa = iop_get_mfa(psc->iop)) != 0xffffffff) {
bioq_remove(&psc->queue, bp);
@@ -223,19 +220,14 @@ pst_start(struct pst_softc *psc)
iop_free_mfa(psc->iop, mfa);
return;
}
- psc->outstanding++;
+ psc->iop->outstanding++;
request->psc = psc;
request->mfa = mfa;
request->bp = bp;
- if (dumping)
- request->timeout_handle.callout = NULL;
- else
- request->timeout_handle =
- timeout((timeout_t*)pst_timeout, request, 10 * hz);
if (pst_rw(request)) {
biofinish(request->bp, NULL, EIO);
iop_free_mfa(request->psc->iop, request->mfa);
- psc->outstanding--;
+ psc->iop->outstanding--;
free(request, M_PSTRAID);
}
}
@@ -253,38 +245,9 @@ pst_done(struct iop_softc *sc, u_int32_t mfa, struct i2o_single_reply *reply)
request->bp->bio_resid = request->bp->bio_bcount - reply->donecount;
biofinish(request->bp, NULL, reply->status ? EIO : 0);
free(request, M_PSTRAID);
- mtx_lock(&psc->mtx);
psc->iop->reg->oqueue = mfa;
- psc->outstanding--;
+ psc->iop->outstanding--;
pst_start(psc);
- mtx_unlock(&psc->mtx);
-}
-
-static void
-pst_timeout(struct pst_request *request)
-{
- printf("pst: timeout mfa=0x%08x cmd=0x%02x\n",
- request->mfa, request->bp->bio_cmd);
- mtx_lock(&request->psc->mtx);
- iop_free_mfa(request->psc->iop, request->mfa);
- if ((request->mfa = iop_get_mfa(request->psc->iop)) == 0xffffffff) {
- printf("pst: timeout no mfa possible\n");
- biofinish(request->bp, NULL, EIO);
- request->psc->outstanding--;
- mtx_unlock(&request->psc->mtx);
- return;
- }
- if (dumping)
- request->timeout_handle.callout = NULL;
- else
- request->timeout_handle =
- timeout((timeout_t*)pst_timeout, request, 10 * hz);
- if (pst_rw(request)) {
- iop_free_mfa(request->psc->iop, request->mfa);
- biofinish(request->bp, NULL, EIO);
- request->psc->outstanding--;
- }
- mtx_unlock(&request->psc->mtx);
}
int
@@ -315,7 +278,7 @@ pst_rw(struct pst_request *request)
sgl_flag = I2O_SGL_DIR;
break;
default:
- printf("pst: unknown command type\n");
+ printf("pst: unknown command type 0x%02x\n", request->bp->bio_cmd);
return -1;
}
msg->initiator_context = (u_int32_t)pst_done;
@@ -323,21 +286,57 @@ pst_rw(struct pst_request *request)
msg->time_multiplier = 1;
msg->bytecount = request->bp->bio_bcount;
msg->lba = ((u_int64_t)request->bp->bio_pblkno) * (DEV_BSIZE * 1LL);
+
if (!iop_create_sgl((struct i2o_basic_message *)msg, request->bp->bio_data,
request->bp->bio_bcount, sgl_flag))
return -1;
+
request->psc->iop->reg->iqueue = request->mfa;
+
+ if (dumping)
+ request->timeout_handle.callout = NULL;
+ else
+ request->timeout_handle =
+ timeout((timeout_t*)pst_timeout, request, 10 * hz);
return 0;
}
static void
+pst_timeout(struct pst_request *request)
+{
+ printf("pst: timeout mfa=0x%08x cmd=0x%02x\n",
+ request->mfa, request->bp->bio_cmd);
+ mtx_lock(&request->psc->iop->mtx);
+ iop_free_mfa(request->psc->iop, request->mfa);
+ if ((request->mfa = iop_get_mfa(request->psc->iop)) == 0xffffffff) {
+ printf("pst: timeout no mfa possible\n");
+ biofinish(request->bp, NULL, EIO);
+ request->psc->iop->outstanding--;
+ mtx_unlock(&request->psc->iop->mtx);
+ return;
+ }
+ if (dumping)
+ request->timeout_handle.callout = NULL;
+ else
+ request->timeout_handle =
+ timeout((timeout_t*)pst_timeout, request, 10 * hz);
+ if (pst_rw(request)) {
+ iop_free_mfa(request->psc->iop, request->mfa);
+ biofinish(request->bp, NULL, EIO);
+ request->psc->iop->outstanding--;
+ }
+ mtx_unlock(&request->psc->iop->mtx);
+}
+
+static void
bpack(int8_t *src, int8_t *dst, int len)
{
int i, j, blank;
int8_t *ptr, *buf = dst;
for (i = j = blank = 0 ; i < len; i++) {
- if (blank && src[i] == ' ') continue;
+ if (blank && src[i] == ' ')
+ continue;
if (blank && src[i] != ' ') {
dst[j++] = src[i];
blank = 0;
OpenPOWER on IntegriCloud