summaryrefslogtreecommitdiff
path: root/sys/dev/pci/qli_pci.c
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2007-09-04 23:04:00 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2007-09-04 23:04:00 +0000
commitf35ebf20cef8f059d3a14d09ca460ddd5d89e871 (patch)
tree59809ca338b0b96f7f3c911ae76f5fefab9033c7 /sys/dev/pci/qli_pci.c
parent6d1005b0932de9ecfaf5efa12fbe197d37e9a44a (diff)
Add mailbox command handler and "about firmware" command
Diffstat (limited to 'sys/dev/pci/qli_pci.c')
-rw-r--r--sys/dev/pci/qli_pci.c101
1 files changed, 96 insertions, 5 deletions
diff --git a/sys/dev/pci/qli_pci.c b/sys/dev/pci/qli_pci.c
index a6427b8edc7..4a89be39655 100644
--- a/sys/dev/pci/qli_pci.c
+++ b/sys/dev/pci/qli_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: qli_pci.c,v 1.1 2007/08/31 16:18:57 marco Exp $ */
+/* $OpenBSD: qli_pci.c,v 1.2 2007/09/04 23:03:59 marco Exp $ */
/*
* Copyright (c) 2007 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2007 David Collins <dave@davec.name>
@@ -46,7 +46,7 @@
#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
-#define QLI_DEBUG
+/* #define QLI_DEBUG */
#ifdef QLI_DEBUG
#define DPRINTF(x...) do { if (qli_debug) printf(x); } while(0)
#define DNPRINTF(n,x...) do { if (qli_debug & n) printf(x); } while(0)
@@ -96,6 +96,7 @@ struct qli_softc {
u_int32_t sc_resource; /* nr for semaphores */
struct rwlock sc_lock;
+ struct rwlock sc_mbox_lock;
};
int qli_scsi_cmd(struct scsi_xfer *);
@@ -115,6 +116,7 @@ void qli_hw_reset(struct qli_softc *);
int qli_soft_reset(struct qli_softc *);
int qli_get_fw_state(struct qli_softc *, u_int32_t *);
int qli_start_firmware(struct qli_softc *);
+int qli_mgmt(struct qli_softc *, int, u_int32_t *);
int qli_intr(void *);
int qli_attach(struct qli_softc *);
#ifndef SMALL_KERNEL
@@ -240,7 +242,7 @@ qli_pci_attach(struct device *parent, struct device *self, void *aux)
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_QLOGIC_ISP4010_HBA;
if (qli_attach(sc)) {
- printf(": %s can't attach\n", DEVNAME(sc));
+ printf("%s: can't attach\n", DEVNAME(sc));
goto intrdis;
}
@@ -599,15 +601,89 @@ done:
}
int
+qli_mgmt(struct qli_softc *sc, int len, u_int32_t *mbox)
+{
+ int rv = 1, s, i;
+ u_int32_t x;
+
+ DNPRINTF(QLI_D_MISC, "%s: qli_mgmt\n", DEVNAME(sc));
+
+ if (!mbox)
+ goto done;
+
+ s = splbio();
+ rw_enter_write(&sc->sc_mbox_lock);
+
+ if (qli_read(sc, &sc->sc_reg->qlr_ctrl_status) &
+ QLI_REG_CTRLSTAT_SCSI_PROC_INTR) {
+ /* this should not happen */
+ printf("%s: qli_mgmt called while interrupt is pending\n",
+ DEVNAME(sc));
+ qli_intr(sc);
+ }
+
+ /* mbox[0] needs to be written last so write backwards */
+ DNPRINTF(QLI_D_MISC, "%s: qli_mgmt: ", DEVNAME(sc));
+ for (i = QLI_MBOX_SIZE - 1; i >= 0; i--) {
+ DNPRINTF(QLI_D_MISC, "mbox[%d] = 0x%08x ", i, mbox[i]);
+ qli_write(sc, &sc->sc_reg->qlr_mbox[i], i < len ? mbox[i] : 0);
+ }
+ DNPRINTF(QLI_D_MISC, "\n");
+
+ /* notify chip it has to deal with mailbox */
+ qli_write(sc, &sc->sc_reg->qlr_ctrl_status,
+ QLI_SET_MASK(QLI_REG_CTRLSTAT_EP_INTR));
+
+ /* wait for completion */
+ if (cold)
+ for (i = 0; i < 6000000 /* up to a minute */; i++) {
+ delay(10);
+ if ((qli_read(sc, &sc->sc_reg->qlr_ctrl_status) &
+ (QLI_REG_CTRLSTAT_SCSI_RESET_INTR |
+ QLI_REG_CTRLSTAT_SCSI_COMPL_INTR |
+ QLI_REG_CTRLSTAT_SCSI_PROC_INTR)))
+ break;
+ }
+ else {
+ /* XXX tsleep */
+ }
+
+ DNPRINTF(QLI_D_MISC, "%s: qli_mgmt: ", DEVNAME(sc));
+ for (i = 0; i < QLI_MBOX_SIZE; i++) {
+ DNPRINTF(QLI_D_MISC, "mbox[%d] = 0x%08x ", i, qli_read(sc,
+ &sc->sc_reg->qlr_mbox[i]));
+ }
+ DNPRINTF(QLI_D_MISC, "\n");
+
+ x = qli_read(sc, &sc->sc_reg->qlr_mbox[0]);
+ switch (x) {
+ case QLI_MBOX_STATUS_COMMAND_COMPLETE:
+ for (i = 0; i < QLI_MBOX_SIZE; i++)
+ mbox[i] = qli_read(sc, &sc->sc_reg->qlr_mbox[i]);
+ rv = 0;
+ break;
+ default:
+ printf("%s: qli_mgmt: mailbox failed opcode 0x%08x failed "
+ "with error code 0x%08x\n", DEVNAME(sc), mbox[0], x);
+ }
+
+ rw_exit_write(&sc->sc_mbox_lock);
+ splx(s);
+done:
+ return (rv);
+}
+
+int
qli_attach(struct qli_softc *sc)
{
/* struct scsibus_attach_args saa; */
int rv = 1;
- u_int32_t f;
+ u_int32_t f, mbox[QLI_MBOX_SIZE];
DNPRINTF(QLI_D_MISC, "%s: qli_attach\n", DEVNAME(sc));
rw_init(&sc->sc_lock, "qli_lock");
+ rw_init(&sc->sc_mbox_lock, "qli_mbox_lock");
if (sc->sc_ql4010)
sc->sc_resource = QLI_SEM_4010_SCSI;
@@ -619,7 +695,19 @@ qli_attach(struct qli_softc *sc)
DNPRINTF(QLI_D_MISC, "%s: qli_attach resource: %d\n", DEVNAME(sc),
sc->sc_resource);
- qli_start_firmware(sc);
+ if (qli_start_firmware(sc)) {
+ printf("%s: could not start firmware\n", DEVNAME(sc));
+ goto done;
+ }
+
+ bzero(mbox, sizeof(mbox));
+ mbox[0] = QLI_MBOX_OPC_ABOUT_FIRMWARE;
+ if (qli_mgmt(sc, 4, mbox)) {
+ printf("%s: about firmware command failed\n", DEVNAME(sc));
+ goto done;
+ }
+ printf("%s: version %d.%d.%d.%d\n", DEVNAME(sc), mbox[1], mbox[2],
+ mbox[3], mbox[4]);
#if NBIO > 0
if (bio_register(&sc->sc_dev, qli_ioctl) != 0)
@@ -633,17 +721,20 @@ qli_attach(struct qli_softc *sc)
#endif /* SMALL_KERNEL */
#endif /* NBIO > 0 */
+done:
return (rv);
}
int
qli_scsi_cmd(struct scsi_xfer *xs)
{
+#ifdef QLI_DEBUG
struct scsi_link *link = xs->sc_link;
struct qli_softc *sc = link->adapter_softc;
DNPRINTF(QLI_D_CMD, "%s: qli_scsi_cmd opcode: %#x\n",
DEVNAME(sc), xs->cmd->opcode);
+#endif
goto stuffup;