From owner-freebsd-hackers Tue Apr 11 20:57:55 2000 Delivered-To: freebsd-hackers@freebsd.org Received: from rover.village.org (rover.village.org [204.144.255.49]) by hub.freebsd.org (Postfix) with ESMTP id 9D62737B5E4 for ; Tue, 11 Apr 2000 20:57:49 -0700 (PDT) (envelope-from imp@harmony.village.org) Received: from harmony.village.org (harmony.village.org [10.0.0.6]) by rover.village.org (8.9.3/8.9.3) with ESMTP id VAA26324 for ; Tue, 11 Apr 2000 21:57:47 -0600 (MDT) (envelope-from imp@harmony.village.org) Received: from harmony.village.org (localhost.village.org [127.0.0.1]) by harmony.village.org (8.9.3/8.8.3) with ESMTP id VAA34787 for ; Tue, 11 Apr 2000 21:57:35 -0600 (MDT) Message-Id: <200004120357.VAA34787@harmony.village.org> To: freebsd-hackers@freebsd.org Subject: PCI DMA Questions Date: Tue, 11 Apr 2000 21:57:35 -0600 From: Warner Losh Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG I'm debugging a hunk of PCI hardware that I have under NDA. It doesn't seem to be initiating DMA transfers. This may be a hardware problem, but before I go back to the vendor, I want to make sure that I'm doing the DMA initialization right. It was my understanding that DMA just happened on the PCI bus and nothing special was needed. Here's what I'm doing in my attach routine. Most of this code was culled from ahc.c and friends. /* Create "master" or parent dma tag for all dma entities */ /* XXX Should be child of pci bus dma tag */ err = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MAXBSIZE, NSEG, DMA_TRANSFER_SIZE, BUS_DMA_ALLOCNOW, &sc->parent_dmat); if (err) { bail; } sc->dma_init_level = 1; /* Create the dma tags for our data */ err = bus_dma_tag_create(sc->parent_dmat, 4, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MAX_DATUM_SIZE, DATUM_COUNT, BUS_SPACE_MAXSIZE_32BIT, 0, &sc->datum_dmat); if (err) { bail; } sc->dma_init_level++; for (i = 0; i < BUFFER_COUNT; i++) { /* Allocate them */ if (bus_dmamem_alloc(sc->datum_dmat, (void *) &sc->BM_buf[i], BUS_DMA_NOWAIT, &sc->datum_dmamap[i]) != 0) { bail; } /* And permanently map them */ bus_dmamap_load(sc->datum_dmat, sc->datum_dmamap[i], sc->BM_buf[i], MAX_DATUM_SIZE, mydmamapcb, &sc->phy_add[i], 0); } sc->dma_init_level++; When I want to do DMA from the chip, I pass sc->phy_add[i] to the DMA target address register on the pci card. I then copyout the data that BM_buf[i] points to in a ioctl. Trouble is, the hardware interrupts, but its DMA target length register (which acts like uio->uio_resid) hasn't changed, indicating that no data was transferred. So, I thought I'd post here asking to see if I'm using this undocumented interface correctly. The NetBSD man pages describe a later version of this interface, and I can't seem to find a description of the old interface. Likely a good thing since this interface won't cope well on machine that don't have a coherent cache wrt DMA (think MIPS). Am I doing this right? Is there something unobviously named that is used to "start" the DMA or tell some DMA controller that DMA is going to happen? I didn't see anything in any of the pci drivers, and I don't recall ever having to deal with this in the past. If I get enough help, I'll do a followup article to the "how to write a bog-simple newbus/busspaced driver on FreeBSD 4 or newer" talking about the dma busspace in freebsd. :-) Warner To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message