summaryrefslogtreecommitdiff
path: root/sys/dev/ic/mpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/mpi.c')
-rw-r--r--sys/dev/ic/mpi.c206
1 files changed, 205 insertions, 1 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c
index ef3930e36f9..0adb880f3b5 100644
--- a/sys/dev/ic/mpi.c
+++ b/sys/dev/ic/mpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpi.c,v 1.5 2006/05/28 02:32:55 dlg Exp $ */
+/* $OpenBSD: mpi.c,v 1.6 2006/05/28 21:59:23 dlg Exp $ */
/*
* Copyright (c) 2005, 2006 David Gwynne <dlg@openbsd.org>
@@ -100,6 +100,13 @@ int mpi_eventnotify(struct mpi_softc *);
void mpi_eventnotify_done(struct mpi_ccb *);
int mpi_portenable(struct mpi_softc *);
+int mpi_cfg_hdr(struct mpi_softc *, u_int8_t, u_int8_t,
+ u_int32_t, struct mpi_cfg_hdr *);
+int mpi_cfg_page(struct mpi_softc *, u_int32_t,
+ struct mpi_cfg_hdr *, int, void *, size_t);
+
+int mpi_cfg_manufacturer0(struct mpi_softc *);
+
#define DEVNAME(s) ((s)->sc_dev.dv_xname)
#define dwordsof(s) (sizeof(s) / sizeof(u_int32_t))
@@ -179,6 +186,11 @@ mpi_attach(struct mpi_softc *sc)
goto free_replies;
}
+ if (mpi_cfg_manufacturer0(sc) != 0) {
+ printf("%s: unable to read config pages\n", DEVNAME(sc));
+ goto free_replies;
+ }
+
/* we should be good to go now, attach scsibus */
sc->sc_link.device = &mpi_dev;
sc->sc_link.adapter = &mpi_switch;
@@ -1447,3 +1459,195 @@ mpi_portenable(struct mpi_softc *sc)
return (0);
}
+
+int
+mpi_cfg_manufacturer0(struct mpi_softc *sc)
+{
+ struct mpi_cfg_hdr hdr;
+ struct mpi_cfg_manufacturing_pg0 pg0;
+
+ DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
+
+ if (mpi_cfg_hdr(sc, MPI_CONFIG_REQ_PAGE_TYPE_MANUFACTURING, 0, 0x0,
+ &hdr) != 0)
+ return (1);
+
+ if (mpi_cfg_page(sc, 0x0, &hdr, 1, &pg0, sizeof(pg0)) != 0)
+ return (1);
+
+ printf("%s: chip_name: %s\n", DEVNAME(sc), pg0.chip_name);
+ printf("%s: chip_revision: %s\n", DEVNAME(sc), pg0.chip_revision);
+ printf("%s: board_name: %s\n", DEVNAME(sc), pg0.board_name);
+ printf("%s: board_assembly: %s\n", DEVNAME(sc), pg0.board_assembly);
+ printf("%s: board_tracer_numer: %s\n", DEVNAME(sc),
+ pg0.board_tracer_number);
+
+ return (0);
+}
+
+int
+mpi_cfg_hdr(struct mpi_softc *sc, u_int8_t type, u_int8_t number,
+ u_int32_t address, struct mpi_cfg_hdr *hdr)
+{
+ struct mpi_ccb *ccb;
+ struct mpi_msg_config_request *cq;
+ struct mpi_msg_config_reply *cp;
+ int s;
+
+ DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
+
+ s = splbio();
+ ccb = mpi_get_ccb(sc);
+ splx(s);
+ if (ccb == NULL) {
+ DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__);
+ return (1);
+ }
+
+ ccb->ccb_done = mpi_empty_done;
+ cq = ccb->ccb_cmd;
+
+ cq->function = MPI_FUNCTION_CONFIG;
+ cq->msg_context = htole32(ccb->ccb_id);
+
+ cq->action = MPI_CONFIG_REQ_ACTION_PAGE_HEADER;
+
+ cq->config_header.page_number = number;
+ cq->config_header.page_type = type;
+ cq->page_address = htole32(address);
+ cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
+ MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL);
+
+ mpi_poll(sc, ccb);
+
+ cp = ccb->ccb_reply;
+ if (cp == NULL)
+ panic("%s: unable to fetch config header\n", DEVNAME(sc));
+
+#ifdef MPI_DEBUG
+ if (mpidebug) {
+ printf("%s: action: 0x%02x msg_length: %d function: 0x%02x\n",
+ DEVNAME(sc), cp->action, cp->msg_length, cp->function);
+
+ printf("%s: ext_page_length: %d ext_page_type: 0x%02x "
+ "msg_flags: 0x%02x\n", DEVNAME(sc),
+ letoh16(cp->ext_page_length), cp->ext_page_type,
+ cp->msg_flags);
+
+ printf("%s: msg_context: 0x%08x\n", DEVNAME(sc),
+ letoh32(cp->msg_context));
+
+ printf("%s: ioc_status: 0x%04x\n", DEVNAME(sc),
+ letoh16(cp->ioc_status));
+
+ printf("%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc),
+ letoh32(cp->ioc_loginfo));
+
+ printf("%s: page_version: 0x%02x page_length: %d "
+ "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
+ cp->config_header.page_version,
+ cp->config_header.page_length,
+ cp->config_header.page_number,
+ cp->config_header.page_type);
+ }
+#endif /* MPI_DEBUG */
+
+ *hdr = cp->config_header;
+
+ mpi_push_reply(sc, ccb->ccb_reply_dva);
+ mpi_put_ccb(sc, ccb);
+
+ return (0);
+}
+
+int
+mpi_cfg_page(struct mpi_softc *sc, u_int32_t address, struct mpi_cfg_hdr *hdr,
+ int read, void *page, size_t len)
+{
+ struct mpi_ccb *ccb;
+ struct mpi_msg_config_request *cq;
+ struct mpi_msg_config_reply *cp;
+ char *kva;
+ int s;
+
+ DPRINTF("%s: %s\n", DEVNAME(sc), __func__);
+
+ if (len > MPI_REQUEST_SIZE - sizeof(struct mpi_msg_config_request) ||
+ len < hdr->page_length * 4)
+ return (1);
+
+ s = splbio();
+ ccb = mpi_get_ccb(sc);
+ splx(s);
+ if (ccb == NULL) {
+ DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__);
+ return (1);
+ }
+
+ ccb->ccb_done = mpi_empty_done;
+ cq = ccb->ccb_cmd;
+
+ cq->function = MPI_FUNCTION_CONFIG;
+ cq->msg_context = htole32(ccb->ccb_id);
+
+ cq->action = (read ? MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT :
+ MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT);
+
+ cq->config_header = *hdr;
+ cq->config_header.page_type &= MPI_CONFIG_REQ_PAGE_TYPE_MASK;
+ cq->page_address = htole32(address);
+ cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE |
+ MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL | len);
+
+ /* bounce the page via the request space to avoid more bus_dma games */
+ cq->page_buffer.sg_addr = htole32(MPI_DMA_DVA(sc->sc_requests) +
+ ccb->ccb_offset + sizeof(struct mpi_msg_config_request));
+ kva = MPI_DMA_KVA(sc->sc_requests);
+ kva += ccb->ccb_offset + sizeof(struct mpi_msg_config_request);
+ if (!read)
+ bcopy(page, kva, len);
+
+ mpi_poll(sc, ccb);
+
+ cp = ccb->ccb_reply;
+ if (cp == NULL) {
+ mpi_put_ccb(sc, ccb);
+ return (1);
+ }
+
+#ifdef MPI_DEBUG
+ if (mpidebug) {
+ printf("%s: action: 0x%02x msg_length: %d function: 0x%02x\n",
+ DEVNAME(sc), cp->action, cp->msg_length, cp->function);
+
+ printf("%s: ext_page_length: %d ext_page_type: 0x%02x "
+ "msg_flags: 0x%02x\n", DEVNAME(sc),
+ letoh16(cp->ext_page_length), cp->ext_page_type,
+ cp->msg_flags);
+
+ printf("%s: msg_context: 0x%08x\n", DEVNAME(sc),
+ letoh32(cp->msg_context));
+
+ printf("%s: ioc_status: 0x%04x\n", DEVNAME(sc),
+ letoh16(cp->ioc_status));
+
+ printf("%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc),
+ letoh32(cp->ioc_loginfo));
+
+ printf("%s: page_version: 0x%02x page_length: %d "
+ "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
+ cp->config_header.page_version,
+ cp->config_header.page_length,
+ cp->config_header.page_number,
+ cp->config_header.page_type);
+ }
+#endif /* MPI_DEBUG */
+
+ if (read)
+ bcopy(kva, page, len);
+
+ mpi_push_reply(sc, ccb->ccb_reply_dva);
+ mpi_put_ccb(sc, ccb);
+
+ return (0);
+}