Skip site navigation (1)Skip section navigation (2)
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>