Date: Mon, 24 Sep 2018 15:30:14 -0300 From: "Dr. Rolf Jansen" <rj@obsigna.com> To: Farhan Khan <khanzf@gmail.com> Cc: freebsd-drivers@freebsd.org Subject: Re: Writing a PCIe-Driver Message-ID: <0E9C0EFE-F2EE-47A3-B7E6-60E9404E3904@obsigna.com> In-Reply-To: <CAFd4kYAuD1nDwQv-AtZnEqKJZ4wvo3ik1ERyOSjYp_kaOAS7fQ@mail.gmail.com> References: <F756788B-591D-4B9D-B58B-B0C07FE4E233@obsigna.com> <CAFd4kYAuD1nDwQv-AtZnEqKJZ4wvo3ik1ERyOSjYp_kaOAS7fQ@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Farhan, Thank you very much for sharing your findings. I will also look into the = code, and I started with checking out the FreeBSD source tree to my = development machine, so examine the code of the various drivers is more = easy. Anyway, the outline which you revealed is already a good starting = point, and it will help me a lot to find my way in the jungle. Best regards Rolf > Am 24.09.2018 um 01:53 schrieb Farhan Khan <khanzf@gmail.com>: >=20 > Hi Rolf, >=20 > I have been reading up on this code myself. I do not claim expertise, > so hopefully others can chim in here if I make a mistake. On the WiFi > side of things, I've pretty consistently I've seen the following > routine: >=20 > A call to pci_find_cap(9), typically as follows from the WiFi code > I've looked into: > pci_find_cap(dev, PCIY_EXPRESS, &sc->sc_cap_off); >=20 > A write to clear the PCI Retry timeout, by writing 0x41 to the device > with pci_write_config(9): > pci_write_config(dev, 0x41, 0, 1); >=20 > Obtain the base address registers using PCIR_BAR(), an abstraction of > bus_alloc_resource(), and store that value. > rid =3D PCIR_BAR(0) >=20 > Allocate IO DMA memory to the device: > sc->sc_mem =3D bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, = RF_ACTIVE); > Most drivers check this return value and return ENXIO if the value is = NULL. >=20 > I do not fully understand what rman_get_bustag(9) does, but I see this > called on all drivers I've looked at as follows: > sc->sc_st =3D rman_get_bustag(sc->sc_mem); > sc->sc_sh =3D rman_get_bushandle(sc->sc_mem); >=20 > Typically I see Interrupt handler code setup here. In the case of > rtwn(4) and iwm(4). This might not be relevant to your driver, > depending on what it does. I see a call to pci_alloc_msi as follows: > rid =3D 1; > if (pci_alloc_msi(dev, &rid) =3D=3D 0) > rid =3D 1; > else > rid =3D 0; > pci->irq =3D bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE = | > (rid !=3D 0 ? 0 : RF_SHAREABLE)); >=20 > Then assign an interrupt handler function as follows so you know to > read from the DMA. > error =3D bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE, > NULL, your_function_here, sc, &sc->sc_ih); >=20 > Capture the DMA tag as follows: > sc->sc_dmat =3D bus_get_dma_tag(sc->sc_dev); >=20 > =46rom here, I see the following sequence: > 1. bus_dma_tag_create(), where the first argument is the DMA tag > (sc->sc_dmat), and the last argument is the memory it is mapped to. > 2. bus_dmamem_alloc() > 3. bus_dmamap_load() > 4. bus_dmamap_sync() >=20 > At this point, you may need to initialize the interrupts, depending on > your hardware. If/when the interrupt arrives, you need to determine > what type it is and read from the DMA memory, as allocated in the DMA > sequence. On every assign and allocation you should also do > error-checking on all return values. >=20 > That is my understanding. Again, someone else can jump in if I made a > mistake. I read rtwn(4), iwm(4) and iwi(4) while writing this and they > are excellent references. >=20 > Hope this helps! > -- > Farhan Khan > PGP Fingerprint: B28D 2726 E2BC A97E 3854 5ABE 9A9F 00BC D525 16EE >=20 >=20 > On Sun, Sep 23, 2018 at 10:46 PM Dr. Rolf Jansen <rj@obsigna.com> = wrote: >>=20 >> Hello, >>=20 >> A couple of years ago, with the valuable help of people on this list, = I managed to write a PCI driver for the National Instruments DAQ card, = NI PCI-6251. The driver was kept very simple, only map the BAR=E2=80=99s = and some DMA memory into the user space. The DAC/ADC and DIO is then all = controlled from user space by writing command codes to certain offsets = from the mapped BAR=E2=80=99s, and reading data from the mapped DMA = memory and/or from other given offsets. >>=20 >> See: How to map device addresses into user space >> = https://lists.freebsd.org/pipermail/freebsd-drivers/2013-January/thread.ht= ml >>=20 >>=20 >> Now, I need to do exactly the same for a PCIe card, namely the NI = PCIe-6351. However, I even cannot see where to start. For PCI cards, the = respective chapter 11 in the FreeBSD Architecture Handbook was quite = helpful, for getting started, in no time, I got the PCI card probed and = attached. >>=20 >> = https://www.freebsd.org/doc/en_US.ISO8859-1/books/arch-handbook/pci.html >>=20 >> The dumb approach, probing the device ID and attaching the PCI(e) = driver to the PCIe device in a similar fashion didn=E2=80=99t work - I = didn=E2=80=99t expect this either, however, where would I start? How do = I attach my driver to a PCIe card on FreeBSD 11 or 12? >>=20 >> Please can somebody push me into the right direction. Once I got the = driver attached to the card, I guess, I would be able to adapt the = mem-mapping code of my old driver for the new card. >>=20 >> Best regards >>=20 >> Rolf >> _______________________________________________ >> freebsd-drivers@freebsd.org mailing list >> https://lists.freebsd.org/mailman/listinfo/freebsd-drivers >> To unsubscribe, send any mail to = "freebsd-drivers-unsubscribe@freebsd.org"
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?0E9C0EFE-F2EE-47A3-B7E6-60E9404E3904>