summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2007-03-04 13:47:09 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2007-03-04 13:47:09 +0000
commit9362473e0a0f318093d885416f4b490b01be8e64 (patch)
treeec54eea17c7273d66b1e22454a9db736ef71f9d7
parent1ffd41c412ad73618d680477d452905e4756a5cf (diff)
Add function to set up Physical Region Descriptor Tables, mostly from dlg@
-rw-r--r--sys/dev/pci/ahci.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/sys/dev/pci/ahci.c b/sys/dev/pci/ahci.c
index 6919873f7c0..1d3b691d2ac 100644
--- a/sys/dev/pci/ahci.c
+++ b/sys/dev/pci/ahci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ahci.c,v 1.56 2007/03/04 13:32:41 pascoe Exp $ */
+/* $OpenBSD: ahci.c,v 1.57 2007/03/04 13:47:08 pascoe Exp $ */
/*
* Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
@@ -379,6 +379,8 @@ void ahci_unmap_intr(struct ahci_softc *,
int ahci_port_alloc(struct ahci_softc *, u_int);
void ahci_port_free(struct ahci_softc *, u_int);
+int ahci_load_prdt(struct ahci_ccb *, struct ata_xfer *);
+
int ahci_intr(void *);
struct ahci_ccb *ahci_get_ccb(struct ahci_port *);
@@ -750,6 +752,50 @@ ahci_port_free(struct ahci_softc *sc, u_int port)
}
int
+ahci_load_prdt(struct ahci_ccb *ccb, struct ata_xfer *xa)
+{
+ struct ahci_port *ap = ccb->ccb_port;
+ struct ahci_softc *sc = ap->ap_sc;
+ struct ahci_prdt *prdt = ccb->ccb_cmd_table->prdt, *prd;
+ bus_dmamap_t dmap = ccb->ccb_dmamap;
+ struct ahci_cmd_hdr *cmd_slot;
+ u_int64_t addr;
+ int i, error;
+
+ if (xa->datalen == 0)
+ return (0);
+
+ error = bus_dmamap_load(sc->sc_dmat, dmap,
+ xa->data, xa->datalen, NULL,
+ (xa->flags & ATA_F_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
+ if (error != 0) {
+ printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
+ return (1);
+ }
+
+ for (i = 0; i < dmap->dm_nsegs; i++) {
+ prd = &prdt[i];
+
+ addr = dmap->dm_segs[i].ds_addr;
+ prd->dba_hi = htole32((u_int32_t)(addr >> 32));
+ prd->dba_lo = htole32((u_int32_t)addr);
+
+ prd->flags = htole32(dmap->dm_segs[i].ds_len - 1);
+ }
+ prd->flags |= htole32(AHCI_PRDT_FLAG_INTR);
+
+ cmd_slot = &ap->ap_cmd_list[ccb->ccb_slot];
+ cmd_slot->prdtl = htole16(ccb->ccb_dmamap->dm_nsegs);
+ cmd_slot->prdbc = 0;
+
+ bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
+ (xa->flags & ATA_F_READ) ? BUS_DMASYNC_PREREAD :
+ BUS_DMASYNC_PREWRITE);
+
+ return (0);
+}
+
+int
ahci_intr(void *arg)
{
return (0);