summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorad <ad@NetBSD.org>2003-12-09 19:43:53 +0000
committerad <ad@NetBSD.org>2003-12-09 19:43:53 +0000
commitee5a33f5aa91ef7de53515877e9e1d4fd73b35c2 (patch)
treee524571abcef09420d4dcb3668c58011f52ef9a1 /sys/dev
parente58307e45854de088be188dc46fc9bc275539ae4 (diff)
Match Promise controllers.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/i2o/iop.c59
-rw-r--r--sys/dev/i2o/iopvar.h3
-rw-r--r--sys/dev/pci/iop_pci.c28
3 files changed, 66 insertions, 24 deletions
diff --git a/sys/dev/i2o/iop.c b/sys/dev/i2o/iop.c
index b8429a6e117..b052b8bf89b 100644
--- a/sys/dev/i2o/iop.c
+++ b/sys/dev/i2o/iop.c
@@ -1,4 +1,4 @@
-/* $NetBSD: iop.c,v 1.41 2003/10/30 01:58:17 simonb Exp $ */
+/* $NetBSD: iop.c,v 1.42 2003/12/09 19:43:54 ad Exp $ */
/*-
* Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: iop.c,v 1.41 2003/10/30 01:58:17 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: iop.c,v 1.42 2003/12/09 19:43:54 ad Exp $");
#include "opt_i2o.h"
#include "iop.h"
@@ -244,6 +244,7 @@ static int iop_passthrough(struct iop_softc *, struct ioppt *,
static void iop_reconf_thread(void *);
static void iop_release_mfa(struct iop_softc *, u_int32_t);
static int iop_reset(struct iop_softc *);
+static int iop_sys_enable(struct iop_softc *);
static int iop_systab_set(struct iop_softc *);
static void iop_tfn_print(struct iop_softc *, struct i2o_fault_notify *);
@@ -548,8 +549,7 @@ iop_config_interrupts(struct device *self)
printf("%s: unable to set system table\n", sc->sc_dv.dv_xname);
return;
}
- if (iop_simple_cmd(sc, I2O_TID_IOP, I2O_EXEC_SYS_ENABLE, IOP_ICTX, 1,
- 30000) != 0) {
+ if (iop_sys_enable(sc) != 0) {
printf("%s: unable to enable system\n", sc->sc_dv.dv_xname);
return;
}
@@ -1229,6 +1229,39 @@ iop_lct_get(struct iop_softc *sc)
}
/*
+ * Post a SYS_ENABLE message to the adapter.
+ */
+int
+iop_sys_enable(struct iop_softc *sc)
+{
+ struct iop_msg *im;
+ struct i2o_msg mf;
+ int rv;
+
+ im = iop_msg_alloc(sc, IM_WAIT | IM_NOSTATUS);
+
+ mf.msgflags = I2O_MSGFLAGS(i2o_msg);
+ mf.msgfunc = I2O_MSGFUNC(I2O_TID_IOP, I2O_EXEC_SYS_ENABLE);
+ mf.msgictx = IOP_ICTX;
+ mf.msgtctx = im->im_tctx;
+
+ rv = iop_msg_post(sc, im, &mf, 30000);
+ if (rv == 0) {
+ if ((im->im_flags & IM_FAIL) != 0)
+ rv = ENXIO;
+ else if (im->im_reqstatus == I2O_STATUS_SUCCESS ||
+ (im->im_reqstatus == I2O_STATUS_ERROR_NO_DATA_XFER &&
+ im->im_detstatus == I2O_DSC_INVALID_REQUEST))
+ rv = 0;
+ else
+ rv = EIO;
+ }
+
+ iop_msg_free(sc, im);
+ return (rv);
+}
+
+/*
* Request the specified parameter group from the target. If an initiator
* is specified (a) don't wait for the operation to complete, but instead
* let the initiator's interrupt handler deal with the reply and (b) place a
@@ -1240,7 +1273,6 @@ iop_field_get_all(struct iop_softc *sc, int tid, int group, void *buf,
{
struct iop_msg *im;
struct i2o_util_params_op *mf;
- struct i2o_reply *rf;
int rv;
struct iop_pgop *pgop;
u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
@@ -1250,13 +1282,7 @@ iop_field_get_all(struct iop_softc *sc, int tid, int group, void *buf,
iop_msg_free(sc, im);
return (ENOMEM);
}
- if ((rf = malloc(sizeof(*rf), M_DEVBUF, M_WAITOK)) == NULL) {
- iop_msg_free(sc, im);
- free(pgop, M_DEVBUF);
- return (ENOMEM);
- }
im->im_dvcontext = pgop;
- im->im_rb = rf;
mf = (struct i2o_util_params_op *)mb;
mf->msgflags = I2O_MSGFLAGS(i2o_util_params_op);
@@ -1284,11 +1310,11 @@ iop_field_get_all(struct iop_softc *sc, int tid, int group, void *buf,
/* Detect errors; let partial transfers to count as success. */
if (ii == NULL && rv == 0) {
- if (rf->reqstatus == I2O_STATUS_ERROR_PARTIAL_XFER &&
- le16toh(rf->detail) == I2O_DSC_UNKNOWN_ERROR)
+ if (im->im_reqstatus == I2O_STATUS_ERROR_PARTIAL_XFER &&
+ im->im_detstatus == I2O_DSC_UNKNOWN_ERROR)
rv = 0;
else
- rv = (rf->reqstatus != 0 ? EIO : 0);
+ rv = (im->im_reqstatus != 0 ? EIO : 0);
if (rv != 0)
printf("%s: FIELD_GET failed for tid %d group %d\n",
@@ -1299,7 +1325,6 @@ iop_field_get_all(struct iop_softc *sc, int tid, int group, void *buf,
iop_msg_unmap(sc, im);
iop_msg_free(sc, im);
free(pgop, M_DEVBUF);
- free(rf, M_DEVBUF);
}
return (rv);
@@ -1735,6 +1760,7 @@ iop_handle_reply(struct iop_softc *sc, u_int32_t rmfa)
iop_reply_print(sc, rb);
#endif
im->im_reqstatus = status;
+ im->im_detstatus = le16toh(rb->detail);
/* Copy the reply frame, if requested. */
if (im->im_rb != NULL) {
@@ -2540,7 +2566,8 @@ iopioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
break;
case IOPIOCRECONFIG:
- rv = iop_reconfigure(sc, 0);
+ if ((rv = lockmgr(&sc->sc_conflock, LK_UPGRADE, NULL)) == 0)
+ rv = iop_reconfigure(sc, 0);
break;
case IOPIOCGTIDMAP:
diff --git a/sys/dev/i2o/iopvar.h b/sys/dev/i2o/iopvar.h
index 7cf8c9bc092..055be8da75f 100644
--- a/sys/dev/i2o/iopvar.h
+++ b/sys/dev/i2o/iopvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: iopvar.h,v 1.12 2002/11/15 13:51:30 ad Exp $ */
+/* $NetBSD: iopvar.h,v 1.13 2003/12/09 19:43:54 ad Exp $ */
/*-
* Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
@@ -62,6 +62,7 @@ struct iop_msg {
void *im_dvcontext; /* Un*x device context */
struct i2o_reply *im_rb; /* Reply buffer */
u_int im_reqstatus; /* Status from reply */
+ u_int im_detstatus; /* Detailed status code */
struct iop_xfer im_xfer[IOP_MAX_MSG_XFERS];
};
#define IM_SYSMASK 0x00ff
diff --git a/sys/dev/pci/iop_pci.c b/sys/dev/pci/iop_pci.c
index 7a7d0b1b365..ecb74c92c6a 100644
--- a/sys/dev/pci/iop_pci.c
+++ b/sys/dev/pci/iop_pci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: iop_pci.c,v 1.13 2002/11/15 17:51:33 itojun Exp $ */
+/* $NetBSD: iop_pci.c,v 1.14 2003/12/09 19:43:53 ad Exp $ */
/*-
* Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: iop_pci.c,v 1.13 2002/11/15 17:51:33 itojun Exp $");
+__KERNEL_RCSID(0, "$NetBSD: iop_pci.c,v 1.14 2003/12/09 19:43:53 ad Exp $");
#include "opt_i2o.h"
@@ -76,6 +76,8 @@ static int
iop_pci_match(struct device *parent, struct cfdata *match, void *aux)
{
struct pci_attach_args *pa;
+ u_int product, vendor;
+ pcireg_t reg;
pa = aux;
@@ -90,13 +92,24 @@ iop_pci_match(struct device *parent, struct cfdata *match, void *aux)
return (1);
/*
- * Match DPT/Adaptec boards that don't conform exactly to the spec.
+ * Match boards that don't conform exactly to the spec.
*/
- if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_DPT &&
- (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DPT_RAID_I2O ||
- PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DPT_RAID_2005S))
+ vendor = PCI_VENDOR(pa->pa_id);
+ product = PCI_PRODUCT(pa->pa_id);
+
+ if (vendor == PCI_VENDOR_DPT &&
+ (product == PCI_PRODUCT_DPT_RAID_I2O ||
+ product == PCI_PRODUCT_DPT_RAID_2005S))
return (1);
+ if (vendor == PCI_VENDOR_INTEL &&
+ (product == PCI_PRODUCT_INTEL_80960RM_2 ||
+ product == PCI_PRODUCT_INTEL_80960_RP)) {
+ reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
+ if (PCI_VENDOR(reg) == PCI_VENDOR_PROMISE)
+ return (1);
+ }
+
return (0);
}
@@ -140,7 +153,8 @@ iop_pci_attach(struct device *parent, struct device *self, void *aux)
}
/* Map the 2nd register window. */
- if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DPT_RAID_2005S) {
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_DPT &&
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DPT_RAID_2005S) {
i += 4; /* next BAR */
if (i == PCI_MAPREG_END) {
printf("can't find mapping\n");