Page MenuHomeFreeBSD

D58372.id182348.diff
No OneTemporary

D58372.id182348.diff

Index: sys/dev/sound/pci/hdspe-pcm.c
===================================================================
--- sys/dev/sound/pci/hdspe-pcm.c
+++ sys/dev/sound/pci/hdspe-pcm.c
@@ -562,14 +562,13 @@
length -= offset;
}
} else {
- /* Position per channel is n times smaller than PCM. */
+ /* Snapshot the write position before synchronizing the buffer. */
pos = sndbuf_getfreeptr(ch->buffer) / n;
- /* Get DMA buffer write position. */
dma_pos = hdspe_read_2(sc, HDSPE_STATUS_REG);
dma_pos &= HDSPE_BUF_POSITION_MASK;
- /* Copy what is newly available. */
length = (dma_pos + HDSPE_CHANBUF_SIZE) - pos;
length %= HDSPE_CHANBUF_SIZE;
+ bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_POSTREAD);
}
/* Position and length in samples (4 bytes). */
@@ -598,6 +597,12 @@
row = hdspe_port_first(ports);
}
+ if (ch->dir == PCMDIR_PLAY && length > 0) {
+ bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_PREWRITE);
+ } else if (ch->dir == PCMDIR_REC) {
+ bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_PREREAD);
+ }
+
ch->position = ((pos + length) * 4) % HDSPE_CHANBUF_SIZE;
}
@@ -617,6 +622,11 @@
if (ch->dir == PCMDIR_PLAY)
buf = sc->pbuf;
+ if (ch->dir == PCMDIR_PLAY)
+ bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_POSTWRITE);
+ else
+ bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_POSTREAD);
+
/* Iterate through rows of ports with contiguous slots. */
ports = ch->ports;
row = hdspe_port_first_row(ports);
@@ -632,6 +642,12 @@
row = hdspe_port_first_row(ports);
}
+ if (ch->dir == PCMDIR_PLAY)
+ bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_PREWRITE);
+ else
+ bus_dmamap_sync(sc->dmat, sc->rmap,
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+
ch->position = 0;
return (0);
@@ -749,8 +765,8 @@
#if 0
device_printf(scp->dev, "hdspechan_trigger(): stop or abort\n");
#endif
- clean(ch);
hdspechan_enable(ch, 0);
+ clean(ch);
hdspe_stop_audio(sc);
break;
Index: sys/dev/sound/pci/hdspe.h
===================================================================
--- sys/dev/sound/pci/hdspe.h
+++ sys/dev/sound/pci/hdspe.h
@@ -240,6 +240,9 @@
uint32_t bufsize;
bus_dmamap_t pmap;
bus_dmamap_t rmap;
+ /* DMA buffer bus addresses. */
+ bus_addr_t paddr;
+ bus_addr_t raddr;
uint32_t period;
uint32_t speed;
uint32_t force_period;
Index: sys/dev/sound/pci/hdspe.c
===================================================================
--- sys/dev/sound/pci/hdspe.c
+++ sys/dev/sound/pci/hdspe.c
@@ -138,11 +138,14 @@
}
static void
-hdspe_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+hdspe_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
-#if 0
- device_printf(sc->dev, "hdspe_dmapsetmap()\n");
-#endif
+ bus_addr_t *addr = arg;
+
+ *addr = BUS_SPACE_MAXADDR;
+ if (error != 0 || nseg != 1)
+ return;
+ *addr = segs[0].ds_addr;
}
static int
@@ -174,16 +177,16 @@
return (ENXIO);
}
- /* Allocate DMA resources. */
+ /* Allocate one page-aligned DMA segment per direction. */
if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev),
- /*alignment*/4,
+ /*alignment*/4096,
/*boundary*/0,
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
/*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL,
/*filterarg*/NULL,
- /*maxsize*/2 * HDSPE_DMASEGSIZE,
- /*nsegments*/2,
+ /*maxsize*/HDSPE_DMASEGSIZE,
+ /*nsegments*/1,
/*maxsegsz*/HDSPE_DMASEGSIZE,
/*flags*/0,
/*lockfunc*/NULL,
@@ -194,35 +197,40 @@
}
sc->bufsize = HDSPE_DMASEGSIZE;
+ sc->paddr = BUS_SPACE_MAXADDR;
+ sc->raddr = BUS_SPACE_MAXADDR;
/* pbuf (play buffer). */
- if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_WAITOK,
- &sc->pmap)) {
+ if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf,
+ BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->pmap)) {
device_printf(sc->dev, "Can't alloc pbuf.\n");
return (ENXIO);
}
if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->bufsize,
- hdspe_dmapsetmap, sc, BUS_DMA_NOWAIT)) {
+ hdspe_dma_map_addr, &sc->paddr, BUS_DMA_NOWAIT) != 0 ||
+ sc->paddr == BUS_SPACE_MAXADDR) {
device_printf(sc->dev, "Can't load pbuf.\n");
return (ENXIO);
}
/* rbuf (rec buffer). */
- if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_WAITOK,
- &sc->rmap)) {
+ if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf,
+ BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->rmap)) {
device_printf(sc->dev, "Can't alloc rbuf.\n");
return (ENXIO);
}
if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->bufsize,
- hdspe_dmapsetmap, sc, BUS_DMA_NOWAIT)) {
+ hdspe_dma_map_addr, &sc->raddr, BUS_DMA_NOWAIT) != 0 ||
+ sc->raddr == BUS_SPACE_MAXADDR) {
device_printf(sc->dev, "Can't load rbuf.\n");
return (ENXIO);
}
- bzero(sc->pbuf, sc->bufsize);
- bzero(sc->rbuf, sc->bufsize);
+ /* Synchronize the buffers before the first DMA cycle. */
+ bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_PREREAD);
return (0);
}
@@ -230,17 +238,14 @@
static void
hdspe_map_dmabuf(struct sc_info *sc)
{
- uint32_t paddr, raddr;
int i;
- paddr = vtophys(sc->pbuf);
- raddr = vtophys(sc->rbuf);
-
+ /* Program the hardware page tables with 4KB bus addresses. */
for (i = 0; i < HDSPE_MAX_SLOTS * 16; i++) {
hdspe_write_4(sc, HDSPE_PAGE_ADDR_BUF_OUT + 4 * i,
- paddr + i * 4096);
+ sc->paddr + (bus_addr_t)i * 4096);
hdspe_write_4(sc, HDSPE_PAGE_ADDR_BUF_IN + 4 * i,
- raddr + i * 4096);
+ sc->raddr + (bus_addr_t)i * 4096);
}
}
@@ -857,6 +862,8 @@
hdspe_dmafree(struct sc_info *sc)
{
+ bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->dmat, sc->rmap);
bus_dmamap_unload(sc->dmat, sc->pmap);
bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap);

File Metadata

Mime Type
text/plain
Expires
Tue, Aug 4, 9:31 AM (8 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35961519
Default Alt Text
D58372.id182348.diff (5 KB)

Event Timeline