summaryrefslogtreecommitdiffstats
path: root/sys/dev/proto
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/proto')
-rw-r--r--sys/dev/proto/proto_bus_pci.c19
-rw-r--r--sys/dev/proto/proto_busdma.c22
-rw-r--r--sys/dev/proto/proto_dev.h6
3 files changed, 35 insertions, 12 deletions
diff --git a/sys/dev/proto/proto_bus_pci.c b/sys/dev/proto/proto_bus_pci.c
index 46ec41e..53ebb5e 100644
--- a/sys/dev/proto/proto_bus_pci.c
+++ b/sys/dev/proto/proto_bus_pci.c
@@ -82,6 +82,7 @@ proto_pci_attach(device_t dev)
{
struct proto_softc *sc;
struct resource *res;
+ uint32_t val;
int bar, rid, type;
sc = device_get_softc(dev);
@@ -91,15 +92,17 @@ proto_pci_attach(device_t dev)
for (bar = 0; bar < PCIR_MAX_BAR_0; bar++) {
rid = PCIR_BAR(bar);
- type = SYS_RES_MEMORY;
+ val = pci_read_config(dev, rid, 4);
+ type = (PCI_BAR_IO(val)) ? SYS_RES_IOPORT : SYS_RES_MEMORY;
res = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE);
- if (res == NULL) {
- type = SYS_RES_IOPORT;
- res = bus_alloc_resource_any(dev, type, &rid,
- RF_ACTIVE);
- }
- if (res != NULL)
- proto_add_resource(sc, type, rid, res);
+ if (res == NULL)
+ continue;
+ proto_add_resource(sc, type, rid, res);
+ if (type == SYS_RES_IOPORT)
+ continue;
+ /* Skip over adjacent BAR for 64-bit memory BARs. */
+ if ((val & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64)
+ bar++;
}
rid = 0;
diff --git a/sys/dev/proto/proto_busdma.c b/sys/dev/proto/proto_busdma.c
index ced4eed..e01e76f 100644
--- a/sys/dev/proto/proto_busdma.c
+++ b/sys/dev/proto/proto_busdma.c
@@ -129,6 +129,16 @@ proto_busdma_tag_lookup(struct proto_busdma *busdma, u_long key)
return (NULL);
}
+static void
+proto_busdma_mem_alloc_callback(void *arg, bus_dma_segment_t *segs, int nseg,
+ int error)
+{
+ struct proto_ioc_busdma *ioc = arg;
+
+ ioc->u.mem.bus_nsegs = nseg;
+ ioc->u.mem.bus_addr = segs[0].ds_addr;
+}
+
static int
proto_busdma_mem_alloc(struct proto_busdma *busdma, struct proto_tag *tag,
struct proto_ioc_busdma *ioc)
@@ -153,10 +163,18 @@ proto_busdma_mem_alloc(struct proto_busdma *busdma, struct proto_tag *tag,
return (error);
}
md->physaddr = pmap_kextract((uintptr_t)(md->virtaddr));
+ error = bus_dmamap_load(md->bd_tag, md->bd_map, md->virtaddr,
+ tag->maxsz, proto_busdma_mem_alloc_callback, ioc, BUS_DMA_NOWAIT);
+ if (error) {
+ bus_dmamem_free(md->bd_tag, md->virtaddr, md->bd_map);
+ bus_dma_tag_destroy(md->bd_tag);
+ free(md, M_PROTO_BUSDMA);
+ return (error);
+ }
LIST_INSERT_HEAD(&tag->mds, md, peers);
LIST_INSERT_HEAD(&busdma->mds, md, mds);
- ioc->u.mem.nsegs = 1;
- ioc->u.mem.physaddr = md->physaddr;
+ ioc->u.mem.phys_nsegs = 1;
+ ioc->u.mem.phys_addr = md->physaddr;
ioc->result = (uintptr_t)(void *)md;
return (0);
}
diff --git a/sys/dev/proto/proto_dev.h b/sys/dev/proto/proto_dev.h
index 0050f0b..88a61a7 100644
--- a/sys/dev/proto/proto_dev.h
+++ b/sys/dev/proto/proto_dev.h
@@ -62,8 +62,10 @@ struct proto_ioc_busdma {
struct {
unsigned long tag;
unsigned int flags;
- unsigned int nsegs;
- unsigned long physaddr;
+ unsigned int phys_nsegs;
+ unsigned long phys_addr;
+ unsigned long bus_addr;
+ unsigned int bus_nsegs;
} mem;
} u;
unsigned long result;
OpenPOWER on IntegriCloud