summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2006-04-07 20:05:32 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2006-04-07 20:05:32 +0000
commita9227b0df02e20908f2f6ced9a343c55485dd2f2 (patch)
tree98fd4a8a07e74bb99ca4bce148671df7a9bb9809 /sys/dev/ic
parent1bb8732b2d498319e868487d40275578266968df (diff)
Add memory allocator functions.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/mfi.c81
-rw-r--r--sys/dev/ic/mfivar.h20
2 files changed, 98 insertions, 3 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c
index e2aaf69b296..b65143f0db2 100644
--- a/sys/dev/ic/mfi.c
+++ b/sys/dev/ic/mfi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfi.c,v 1.5 2006/04/07 17:02:15 marco Exp $ */
+/* $OpenBSD: mfi.c,v 1.6 2006/04/07 20:05:31 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -66,7 +66,63 @@ struct scsi_device mfi_dev = {
NULL, NULL, NULL, NULL
};
-int mfi_transition_firmware(struct mfi_softc *);
+struct mfi_mem *mfi_allocmem(struct mfi_softc *, size_t);
+void mfi_freemem(struct mfi_softc *, struct mfi_mem *);
+int mfi_transition_firmware(struct mfi_softc *);
+
+struct mfi_mem *
+mfi_allocmem(struct mfi_softc *sc, size_t size)
+{
+ struct mfi_mem *mm;
+ int nsegs;
+
+ mm = malloc(sizeof(struct mfi_mem), M_DEVBUF, M_NOWAIT);
+ if (mm == NULL)
+ return (NULL);
+
+ memset(mm, 0, sizeof(struct mfi_mem));
+ mm->am_size = size;
+
+ if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
+ BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mm->am_map) != 0)
+ goto amfree;
+
+ if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mm->am_seg, 1,
+ &nsegs, BUS_DMA_NOWAIT) != 0)
+ goto destroy;
+
+ if (bus_dmamem_map(sc->sc_dmat, &mm->am_seg, nsegs, size, &mm->am_kva,
+ BUS_DMA_NOWAIT) != 0)
+ goto free;
+
+ if (bus_dmamap_load(sc->sc_dmat, mm->am_map, mm->am_kva, size, NULL,
+ BUS_DMA_NOWAIT) != 0)
+ goto unmap;
+
+ memset(mm->am_kva, 0, size);
+ return (mm);
+
+unmap:
+ bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, size);
+free:
+ bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
+destroy:
+ bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
+amfree:
+ free(mm, M_DEVBUF);
+
+ return (NULL);
+}
+
+void
+mfi_freemem(struct mfi_softc *sc, struct mfi_mem *mm)
+{
+ bus_dmamap_unload(sc->sc_dmat, mm->am_map);
+ bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, mm->am_size);
+ bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
+ bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
+ free(mm, M_DEVBUF);
+}
int
mfi_transition_firmware(struct mfi_softc *sc)
@@ -143,9 +199,30 @@ mfiminphys(struct buf *bp)
int
mfi_attach(struct mfi_softc *sc)
{
+ uint32_t status;
+
if (mfi_transition_firmware(sc))
return (1);
+ status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MFI_OMSG0);
+ /* XXX add barrier */
+ sc->sc_max_cmds = status & MFI_STATE_MAXCMD_MASK;
+ sc->sc_max_sgl = (status & MFI_STATE_MAXSGL_MASK) >> 16;
+ DNPRINTF(MFI_D_MISC, "%s: max commands: %u, max sgl: %u\n",
+ DEVNAME(sc), sc->sc_max_cmds, sc->sc_max_sgl);
+
+ /* reply queue memory */
+ sc->sc_reply_q = mfi_allocmem(sc,
+ sizeof(uint32_t) * (sc->sc_max_cmds + 1));
+ if (sc->sc_reply_q == NULL) {
+ printf("%s: unable to allocate reply queue memory\n",
+ DEVNAME(sc));
+ return (1);
+ }
+
+ /* enable interrupts */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MFI_OMSK, 0x01);
+
return (0);
}
diff --git a/sys/dev/ic/mfivar.h b/sys/dev/ic/mfivar.h
index 15072878660..ed01725ae7c 100644
--- a/sys/dev/ic/mfivar.h
+++ b/sys/dev/ic/mfivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfivar.h,v 1.3 2006/04/07 16:28:07 marco Exp $ */
+/* $OpenBSD: mfivar.h,v 1.4 2006/04/07 20:05:31 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -32,6 +32,17 @@ extern uint32_t mfi_debug;
#define DNPRINTF(n,x...)
#endif
+struct mfi_mem {
+ bus_dmamap_t am_map;
+ bus_dma_segment_t am_seg;
+ size_t am_size;
+ caddr_t am_kva;
+};
+
+#define MFIMEM_MAP(_am) ((_am)->am_map)
+#define MFIMEM_DVA(_am) ((_am)->am_map->dm_segs[0].ds_addr)
+#define MFIMEM_KVA(_am) ((void *)(_am)->am_kva)
+
struct mfi_softc {
struct device sc_dev;
void *sc_ih;
@@ -42,6 +53,13 @@ struct mfi_softc {
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
bus_dma_tag_t sc_dmat;
+
+ /* firmware determined max and totals */
+ uint32_t sc_max_cmds;
+ uint32_t sc_max_sgl;
+
+ /* reply queue */
+ struct mfi_mem *sc_reply_q;
};
int mfi_attach(struct mfi_softc *sc);