UART driver as kld - how?
Oleksandr Tymoshenko
gonzo at bluezbox.com
Sun Nov 3 04:23:32 UTC 2019
Milan Obuch (freebsd-hackers at dino.sk) wrote:
> On Mon, 28 Oct 2019 20:19:52 +0100
> Milan Obuch <freebsd-hackers at dino.sk> wrote:
>
> [ snip ]
>
> > Hi,
> >
> > I found uart_dev_snps.c being somewhat near what I need. I am trying
> > to extract necessary bits from this and other files (what you wrote is
> > just one bit), it seems our docs are lacking in this area.
> >
> > Regards,
> > Milan
> >
>
> After studying other uart_dev_xxx.c files I am able to create working
> skeleton uart driver. I can compile it, kldload, and get some console
> output. Right now, I hit another problem - uart framework is not
> documented well, at least no man page is found in share/man directory.
>
> My probe function is similar to that in uart_dev_snps.c file,
> simplified, and I need to know what arguments should uart_bus_probe
> function be invoked with. In many device drivers there are mostly
> zeros, but this does not work for me.
>
> Currently I am getting error 6, ENXIO, so I am not correctly attaching
> my driver to device. Putting some printf here and there, I found test
> at line 508, file uart_core.c, fails - sc->sc_class is null. Question
> is, now, where and how should this field in this structure be
> initialized...
>
> I am sure I need docs/description for other functions as well, so if
> anybody knows where good uart framework description could be found,
> please advice. Or if somebody already has good understanding of it and
> could help me with my issues, it wil be greatly appreciated.
if you follow uart_dev_snsps.c template, the sc_class is set in
probe function:
uart_class = (struct uart_class *)ofw_bus_search_compatible(dev,
compat_data)->ocd_data;
if (uart_class == NULL)
return (ENXIO);
freq = 0;
sc = device_get_softc(dev);
sc->ns8250.base.sc_class = uart_class;
ocd_data is the second element in your compat_data var:
static struct ofw_compat_data compat_data[] = {
{ "snps,dw-apb-uart", (uintptr_t)&uart_snps_class },
{ "marvell,armada-38x-uart", (uintptr_t)&uart_snps_class },
{ NULL, (uintptr_t)NULL }
};
Every uart_dev_ driver has its own softc structure (device-specific data
associated with the device instance): struct uart_pl011_softc, struct
snps_softc. uart_core operates with uart_softc. Device-specific
softc is supposed to have uart_softc variable as the very first member:
struct uart_pl011_softc {
struct uart_softc base;
uint16_t imsc; /* Interrupt mask */
};
This way it can be converted to uart_softc by a pointer cast. Poor man's
OOP so to say.
In your case, my guess would be: you either do not set the sc_class
member var in probe function or your base var is not the first in the
struct.
--
gonzo
More information about the freebsd-hackers
mailing list