summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/ahci.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/sys/dev/pci/ahci.c b/sys/dev/pci/ahci.c
index c279da9380f..ec872c296de 100644
--- a/sys/dev/pci/ahci.c
+++ b/sys/dev/pci/ahci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ahci.c,v 1.32 2007/01/04 08:39:21 dlg Exp $ */
+/* $OpenBSD: ahci.c,v 1.33 2007/01/04 11:37:12 dlg Exp $ */
/*
* Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
@@ -145,6 +145,7 @@ struct ahci_prdt {
u_int32_t flags;
} __packed;
+/* this makes ahci_cmd 512 bytes, which is good for alignment */
#define AHCI_MAX_PRDT 24
struct ahci_cmd {
@@ -174,6 +175,10 @@ struct ahci_dmamem {
struct ahci_softc;
struct ahci_ccb {
+ int ccb_id;
+
+ struct ahci_cmd *ccb_cmd;
+
bus_dmamap_t ccb_dmamap;
TAILQ_ENTRY(ahci_ccb) ccb_entry;
@@ -183,10 +188,12 @@ struct ahci_port {
struct ahci_softc *ap_sc;
bus_space_handle_t ap_ioh;
+ struct ahci_dmamem *ap_dmamem;
+ struct ahci_rfis *ap_rfis;
+ struct ahci_cmd_list *ap_cmd_list;
+
struct ahci_ccb *ap_ccbs;
TAILQ_HEAD(, ahci_ccb) ap_ccb_free;
-
- struct ahci_dmamem *ap_dmamem;
};
struct ahci_softc {
@@ -425,6 +432,7 @@ ahci_port_alloc(struct ahci_softc *sc, u_int port)
{
struct ahci_port *ap;
struct ahci_ccb *ccb;
+ u_int8_t *kva;
int i;
ap = malloc(sizeof(struct ahci_port), M_DEVBUF, M_NOWAIT);
@@ -454,7 +462,17 @@ ahci_port_alloc(struct ahci_softc *sc, u_int port)
goto freeccbs;
}
- /* XXX alloc dma mem */
+ /* calculate the size of the dmaable memory this port will need. */
+ i = sizeof(struct ahci_cmd) * sc->sc_ncmds +
+ sizeof(struct ahci_rfis) +
+ sizeof(struct ahci_cmd_list) * sc->sc_ncmds;
+ ap->ap_dmamem = ahci_dmamem_alloc(sc, i);
+ if (ap->ap_dmamem == NULL) {
+ printf("unable to allocate dmamem for port %d\n", DEVNAME(sc),
+ port);
+ goto freeccbs;
+ }
+ kva = AHCI_DMA_KVA(ap->ap_dmamem);
for (i = 0; i < sc->sc_ncmds; i++) {
ccb = &ap->ap_ccbs[i];
@@ -466,11 +484,18 @@ ahci_port_alloc(struct ahci_softc *sc, u_int port)
goto freemaps;
}
- /* XXX point ccb at its cmd structures in dma mem */
+ ccb->ccb_id = i;
+ ccb->ccb_cmd = (struct ahci_cmd *)kva;
+ kva += sizeof(struct ahci_cmd);
ahci_put_ccb(ap, ccb);
}
+ ap->ap_rfis = (struct ahci_rfis *)kva;
+ kva += sizeof(struct ahci_rfis);
+
+ ap->ap_cmd_list = (struct ahci_cmd_list *)kva;
+
sc->sc_ports[port] = ap;
return (0);
@@ -478,7 +503,7 @@ ahci_port_alloc(struct ahci_softc *sc, u_int port)
freemaps:
while ((ccb = ahci_get_ccb(ap)) != NULL)
bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
- /* XXX free dma mem */
+ ahci_dmamem_free(sc, ap->ap_dmamem);
freeccbs:
free(ap->ap_ccbs, M_DEVBUF);
freeport:
@@ -501,7 +526,7 @@ ahci_port_free(struct ahci_softc *sc, u_int port)
bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
}
- /* XXX free dma mem */
+ ahci_dmamem_free(sc, ap->ap_dmamem);
/* bus_space(9) says we dont free the subregions handle */
free(ap->ap_ccbs, M_DEVBUF);
free(ap, M_DEVBUF);