Discussion:
RFI: Ethernet driver ported from Linux
(too old to reply)
Alan Garfield
2007-04-09 05:33:35 UTC
Permalink
Hello all!

I've got a couple of Sun Fire V20z (re-badged NewISys E2100) which have
little dedicated Service Processor on-board running Linux. The "SP" can
communicate via IPMI and also by Ethernet. It talks Ethernet to the SP
by using two small fifo buffers in the PRS via the LPC.

I have the GPL Linux source for the so-called 'jnet' Ethernet device. By
my reading of the code and the comments it's basically a small
Ethernet-looking driver that wraps around these 256 byte PRS buffers and
a single interrupt for events from each side of the PRS buffers.

-- FROM THE GPL DRIVER COMMENTS

Jnet is a ethernet adapter driver. As such, it provides what appears
to be a typical ethernet adapter interface which the platform can use
to send/receive IP traffic to the SP. The actual physical medium is
the PRS, which resides on the LPC bus, and provides two 256 byte fifo's
along with an interrupt and a status register.

When an interrupt is received, the status register can be read, which
will indicate either a Data Available (DAV), or a Data Acknowledge
(DAK). We can then choose to read or write data to the fifo, and thus
facilitate communication between the SP and Platform.

Because the fifo's provided by the PRS are only 256 bytes, our packet
size is limited. As a result, the only feature we can't support is
DHCP, since a DHCP packet is 313 bytes.

--

I'd like to port/re-write this driver for FreeBSD but I cannot find
enough documentation and examples of a basic Ethernet driver for
FreeBSD. (if_wlan and if_ef look like good candidates but if_clone and
the miibus confuse me a bit and there isn't any clear docs on them)

Can someone point me in the direction of an example or the relevant man
pages I should be reading to help with this.

The device driver for Linux seems quite simple.

Any help would be gratefully appreciated.

Many thanks,

Alan Garfield.
Andrew Thompson
2007-04-09 06:09:47 UTC
Permalink
Post by Alan Garfield
Hello all!
I've got a couple of Sun Fire V20z (re-badged NewISys E2100) which have
little dedicated Service Processor on-board running Linux. The "SP" can
communicate via IPMI and also by Ethernet. It talks Ethernet to the SP
by using two small fifo buffers in the PRS via the LPC.
--
I'd like to port/re-write this driver for FreeBSD but I cannot find
enough documentation and examples of a basic Ethernet driver for
FreeBSD. (if_wlan and if_ef look like good candidates but if_clone and
the miibus confuse me a bit and there isn't any clear docs on them)
Can someone point me in the direction of an example or the relevant man
pages I should be reading to help with this.
The device driver for Linux seems quite simple.
Any help would be gratefully appreciated.
You should look at the edsc driver, its a dummy ethernet driver and a
template for writing one.
http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/net/if_edsc.c


Andrew
Alan Garfield
2007-04-10 02:20:56 UTC
Permalink
Hello all!

I'm wondering if someone can point me in the direction of a solution to
my little problem.

I've been porting a Linux driver across to FreeBSD and I've come against
this lovely little hack in it's code.

I've tried to bus_alloc_resource() the IOAPIC_DEFAULT_ADDR and
IOAPIC_WINDOW but I never seem get allocated. Plus to my
knowing-little-about-kernels eye this seems like a really horrid hack to
figure out the IRQ.

Any suggestions?

Thanks,

Alan.

----------------------

/****************************************************************
Function: determineIrq
Arguments: none
Returns: IRQ vector
Purpose:
The issue is as follows. The Jnet interrupt is really at PCI_INT_D.
Depending on how the OS configures the IOAPIC, that could translate
to IRQ_19, or IRQ_?, (where ? = a pci interrupt lower than 15, usually
7, 10, or 11). Different kernel version do this differently. So, what
we
do to figure this out, is we read the IOAPIC configuration for IRQ_19
and see
if it has a valid interrupt vector, (non-zero). If it does, then the
IOAPIC is in fact configured, and we will be on IRQ_19. If it's not,
then we must be using one of the PCI interrupts, which we can determine
by reading from the PCI config space.
****************************************************************/
int determineIrq(void)
{

volatile uint32_t * addr =
(uint32_t *)ioremap(IOAPIC_DEFAULT_ADDR, sizeof(uint32_t));
volatile uint32_t * data =
(uint32_t *)ioremap(IOAPIC_WINDOW,
IOAPIC_WINDOW_SIZE*sizeof(uint32_t));
int irq;
uint32_t val;
struct pci_dev *pciPtr;
u16 vector;


if(addr == NULL || data == NULL) {
if(addr != NULL) {
iounmap((void *)addr);
}
if(data != NULL) {
iounmap((void *)data);
}
return -1;
}

*addr = IOAPIC_PCI_INTD_OFFSET; //we use pci_intd
val = *data;

if( (val & 0xff) > 0) { //if any bits are set, consider it
configured
#if LINUX_2_6_KERNEL
irq = val & 0xff;
#else
irq = IRQL;
#endif
} else {

[SNIP - looks at pci config and slot data to find IRQ]

}

iounmap((void *)data);
iounmap((void *)addr);

return irq;
}

----------------------
M. Warner Losh
2007-04-10 04:23:00 UTC
Permalink
In message: <***@hiro.auspc.com.au>
Alan Garfield <***@fromorbit.com> writes:
: I'd like to port/re-write this driver for FreeBSD but I cannot find
: enough documentation and examples of a basic Ethernet driver for
: FreeBSD. (if_wlan and if_ef look like good candidates but if_clone and
: the miibus confuse me a bit and there isn't any clear docs on them)
:
: Can someone point me in the direction of an example or the relevant man
: pages I should be reading to help with this.
:
: The device driver for Linux seems quite simple.
:
: Any help would be gratefully appreciated.

In addition to the other advise, you might also look at if_ed.c. It
is a little complicated since it talks to real hardware, and that
hardware is, ummm, a little icky.

Warner
Alan Garfield
2007-04-10 05:30:21 UTC
Permalink
Post by Alan Garfield
Hello all!
I'm wondering if someone can point me in the direction of a solution to
my little problem.
I've been porting a Linux driver across to FreeBSD and I've come against
this lovely little hack in it's code.
I've tried to bus_alloc_resource() the IOAPIC_DEFAULT_ADDR and
IOAPIC_WINDOW but I never seem get allocated. Plus to my
knowing-little-about-kernels eye this seems like a really horrid hack to
figure out the IRQ.
Any suggestions?
Further to this I've done the following :-

---------------------------
static void
jnet_identify(driver_t *driver, device_t parent)
{
uint32_t pci_intline;
device_t dev;

dev = pci_find_bsf(PCI_BUS, PCI_DEV, PCI_FUN);

if(dev == NULL) {
return;
}

device_printf(parent, "Looking for IRQ....\n");

pci_intline = pci_read_config(dev, PCIR_INTLINE, 1);
printf("%x\n", pci_intline);

return;
}
---------------------------

which just output the IRQ for the given bus,device,function. I can
locate the IRQ's for all devices I care to throw at it, but the 0:7:3
device is found, but the PCIR_INTLINE is always 0xFF.

Looking at the linux code I should get back 0x19.

Am I totally missing something?

Thanks in advance,
Alan.
Alan Garfield
2007-04-10 11:40:40 UTC
Permalink
Post by Alan Garfield
Hello all!
I'm wondering if someone can point me in the direction of a solution to
my little problem.
I've been porting a Linux driver across to FreeBSD and I've come against
this lovely little hack in it's code.
I've tried to bus_alloc_resource() the IOAPIC_DEFAULT_ADDR and
IOAPIC_WINDOW but I never seem get allocated. Plus to my
knowing-little-about-kernels eye this seems like a really horrid hack to
figure out the IRQ.
Any suggestions?
Well I think I've found a much nicer way that the low-level irq bashing
the Linux driver suffered from.

-------
DRIVER_MODULE(jnet, acpi, jnet_driver, jnet_devclass, 0, 0);

/**
* jnet_probe()
*
* Probes for the JNet device
*/
static int
jnet_probe(device_t dev)
{
ACPI_HANDLE h;
char *handle_str;

// Only accept device types
if(acpi_get_type(dev) != ACPI_TYPE_DEVICE)
return(ENXIO);

// Get the acpi handle and the device name
h = acpi_get_handle(dev);
handle_str = acpi_name(h);

// Compare the name looking for JNET
if(strcmp(handle_str, JNET_ACPI_NAME) != 0)
return(ENXIO);

// Woo we found it, set the description so we know what we are.
device_set_desc(dev, JNET_NAME);
return (BUS_PROBE_DEFAULT);
}
-------

I found the device was in the acpi data. I now have the interrupt and
the io ports available without any hacks (I hope).

Does this look sane to anyone??

Thanks again,

Alan.
Alan Garfield
2007-04-11 09:05:33 UTC
Permalink
Hi all,

When you have say :-

----
static int
jnet_probe(device_t
dev)
{
static char *jnet_ids[] = { "NWS8001",
NULL };

if (acpi_disabled("jnet")
||
ACPI_ID_PROBE(device_get_parent(dev), dev,
jnet_ids) == NULL)
return (ENXIO);

// Woo we found it, set the description s we know what we
are.
device_set_desc(dev, "JNet Ethernet System
Interface");
return (BUS_PROBE_DEFAULT);
}
----

and when the device is kldload'ed you get :-

----
jnet0: <JNet Ethernet System Interface> port 0xa8,0xae-0xaf irq 19 on
acpi0
----

are these resources automagically allocated for me? Or do I have to
allocate them myself?

I've got my driver mostly working but at the moment I've hard-coded in
the resources and I'm thinking this isn't correct given the acpi bus
knows what resources I'm expecting and lists them helpfully in the dmesg
output.

If the resources are allocated how do I access/see them?

I've been all through device_t and bus.h this and acpi.h that, and I
cannot find a good example of getting resources from the acpi bus.

Any help would be appreciated!

Thanks,
Alan.
t***@jp.freebsd.org
2007-04-11 09:51:04 UTC
Permalink
Post by Alan Garfield
Hi all,
When you have say :-
----
static int
jnet_probe(device_t
dev)
{
static char *jnet_ids[] = { "NWS8001",
NULL };
if (acpi_disabled("jnet")
||
ACPI_ID_PROBE(device_get_parent(dev), dev,
jnet_ids) == NULL)
return (ENXIO);
// Woo we found it, set the description s we know what we
are.
device_set_desc(dev, "JNet Ethernet System
Interface");
return (BUS_PROBE_DEFAULT);
}
----
and when the device is kldload'ed you get :-
----
jnet0: <JNet Ethernet System Interface> port 0xa8,0xae-0xaf irq 19 on
acpi0
----
are these resources automagically allocated for me? Or do I have to
allocate them myself?
You have to allocate the resource.
Post by Alan Garfield
I've got my driver mostly working but at the moment I've hard-coded in
the resources and I'm thinking this isn't correct given the acpi bus
knows what resources I'm expecting and lists them helpfully in the dmesg
output.
If the resources are allocated how do I access/see them?
sc->sc_rid1 = 0;
sc->sc_res1 = bus_alloc_resource_any(self, SYS_RES_IOPORT, &sc->sc_rid, RF_ACTIVE);
sc->sc_rid2 = 0;
sc->sc_res2 = bus_alloc_resource_any(self, SYS_RES_IOPORT, &sc->sc_rid, RF_ACTIVE);
value_af = bus_space_read_8(rman_get_bustag(sc->sc_res2), rman_get_bushandle(sc->sc_res2), 1);
Post by Alan Garfield
I've been all through device_t and bus.h this and acpi.h that, and I
cannot find a good example of getting resources from the acpi bus.
It is almost same as ISA-PnP aware device driver for devices that
requires I/O port resources.
Alan Garfield
2007-04-11 11:24:54 UTC
Permalink
Post by t***@jp.freebsd.org
Post by Alan Garfield
If the resources are allocated how do I access/see them?
sc->sc_rid1 = 0;
sc->sc_res1 = bus_alloc_resource_any(self, SYS_RES_IOPORT, &sc->sc_rid, RF_ACTIVE);
sc->sc_rid2 = 0;
sc->sc_res2 = bus_alloc_resource_any(self, SYS_RES_IOPORT, &sc->sc_rid, RF_ACTIVE);
value_af = bus_space_read_8(rman_get_bustag(sc->sc_res2), rman_get_bushandle(sc->sc_res2), 1);
Thanks for this, but how does on tell which resources have been
allocated to which other than manually specifying them with
bus_alloc_resource()?

This is the bit that's confusing me, it seem like magic happens but I
need to know which resource is which.

Many thanks in advance!

Alan.
Alan Garfield
2007-04-11 11:49:17 UTC
Permalink
Post by t***@jp.freebsd.org
Post by Alan Garfield
and when the device is kldload'ed you get :-
----
jnet0: <JNet Ethernet System Interface> port 0xa8,0xae-0xaf irq 19 on
acpi0
----
are these resources automagically allocated for me? Or do I have to
allocate them myself?
You have to allocate the resource.
Ok cool, but how do I get the resource list from acpi to allocated them
then? Other than having an array of ioports and irqs, is there a way to
get this information from acpi?

I've done an acpidump and indeed the are _CRS and _PRS ResourceTemplates
that describe the io and irq requirements perfectly. How do I access
this data? ACPI seems to have very little documentation and nothing else
seems to get resource lists (except fdc_acpi.c and uart_bus_acpi.c which
don't seem to be complete. ACPI_EVALUATE_OBJECT?!?)

Thanks,
Alan.
Craig Boston
2007-04-11 14:09:26 UTC
Permalink
If it seems like magic, that's because it is. :) For PnP busses like
PCI, ISAPnP, and ISA-ACPI/LPC-ACPI, the OS takes care of figuring out
what resources to use and allocates them.
I almost forgot, the busdma functions work for non-PnP busses like
really old ISA cards as well. The only difference is that the user has
to specify the resources manually in /boot/device.hints, but there's a
standard API for this as well.

Craig
Craig Boston
2007-04-11 14:02:14 UTC
Permalink
Post by Alan Garfield
I've done an acpidump and indeed the are _CRS and _PRS ResourceTemplates
that describe the io and irq requirements perfectly. How do I access
this data? ACPI seems to have very little documentation and nothing else
seems to get resource lists (except fdc_acpi.c and uart_bus_acpi.c which
don't seem to be complete. ACPI_EVALUATE_OBJECT?!?)
In general, you're not supposed to. Use bus_alloc_resource and the
bus_space_* functions. busdma was introduced in order to make it
possible to write device drivers without having to worry about the
specifics of resource allocation / access on any given platform.

If it seems like magic, that's because it is. :) For PnP busses like
PCI, ISAPnP, and ISA-ACPI/LPC-ACPI, the OS takes care of figuring out
what resources to use and allocates them. You only need to specify the
type (Memory, IO Port, IRQ) that you want and it takes care of whatever
needs to be done for the particular architecture and bus your device is
attached to.

This means that your driver will work regardless if the resources are
specified by ACPI, or if in the future if some mad scientist attaches
the hardware to the PCI bus on a SPARC64 instead (with only minimal
driver changes).

Craig
Alan Garfield
2007-04-11 14:37:07 UTC
Permalink
Post by Craig Boston
This means that your driver will work regardless if the resources are
specified by ACPI, or if in the future if some mad scientist attaches
the hardware to the PCI bus on a SPARC64 instead (with only minimal
driver changes).
Ok now I'm thoroughly confused! :)

I've got a very machine specific device (eg. it's built into the PRS
controller on the motherboard) so I don't think I have to worry about
machine independence.

At the moment I've got the io ports and irq's being hardcoded into the
driver, which seems icky to me. The acpi bus when the device is attached
outputs all the appropriate resources so _something_ knows what they
are. All I want is a way to access them and to know what they are.

Do I use bus_space_* to do this? Or is it simply the rid I pass to
bus_alloc_resource_any that gets my io ports and irq's?

At the moment I'm doing :-


----
// Allocate io resources
for(i = 0; i < IO_MAX; i++) {
if(sc->io[i] == NULL) {

sc->io_rid[i] = i;
sc->io[i] = bus_alloc_resource(dev,
SYS_RES_IOPORT, &sc->io_rid[i],
jnet_io_ports[i].addr,
jnet_io_ports[i].addr, 1, RF_ACTIVE);

if(sc->io[i] == NULL) {
device_printf(dev, "can't allocate io
port %x - %s\n",
jnet_io_ports[i].addr,
jnet_io_ports[i].desc);
return (ENOSPC);
}
sc->io_allocated[i] = 0;
}
}

// Allocate irq resource
if(sc->irq == NULL) {
sc->irq_rid = 0;
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
&sc->irq_rid,
JNET_IRQ, JNET_IRQ, 1, RF_ACTIVE);

if(sc->irq == NULL) {
device_printf(dev, "can't allocate irq %02i\n",
JNET_IRQ);
return (ENOSPC);
}
sc->irq_allocated = 0;
}
----

How do I know which io port/irq I get when I use bus_alloc_resource_any?

I should be able to get to the resources the acpi bus lists in dmesg
without hard-coding them in the driver surely. I know I'm probably
missing something completely obvious!

Many thanks in advance.

Alan.
Craig Boston
2007-04-11 15:37:03 UTC
Permalink
Ok, well just for the record it's been a while since I've worked with
busdma so my knowledge is more of a high level overview. Hopefully if
I get anything wrong someone will step in and correct me. :)
Post by Alan Garfield
I've got a very machine specific device (eg. it's built into the PRS
controller on the motherboard) so I don't think I have to worry about
machine independence.
Machine independence is just a side benefit of using busdma, really it's
the standard "FreeBSD driver API" way of doing things.
Post by Alan Garfield
At the moment I've got the io ports and irq's being hardcoded into the
driver, which seems icky to me. The acpi bus when the device is attached
outputs all the appropriate resources so _something_ knows what they
are. All I want is a way to access them and to know what they are.
The question is, do you really need to know what they are? The way it's
supposed to work is you do something like this.

int rid;

rid = i;
/* Allocate the i-th IO port resource */
sc->io[i] = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
/* Get a tag for use with bus_space */
sc->iot[i] = rman_get_bustag(sc->io[i]);
/* Get a handle describing the resource */
sc->ioh[i] = rman_get_bushandle(sc->io[i]);

bus_alloc_resource_any tells the OS to use the "default" resource
allocation, which for a device that's enumerated through ACPI will be
the values that you're seeing through acpi. The rman_get_* functions
retrieve the tag and handle associated with the resource for use with
the bus_space_* functions. AFAIK these are valid until you call
bus_release_resource on sc->io[i], at which point they should be
discarded.

Then to read or write to registers within your IO range, you would do
something like this:

bus_space_write_1(sc->iot[0], sc->ioh[0], offset, value);
/* Write a single byte to (your first IO port) + offset */
value = bus_space_read_2(sc->iot[1], sc->ioh[1], offset);
/* Read a word from (your second IO port) + offset */

When you use bus_space_*, you don't need to know the exact starting
address of your ports like you would with outb(). You only need to know
the offset within the range that your device uses, the API automatically
takes care of the rest.

Many drivers wrap bus_space_read_* and write_* in a set of macros that
automatically fill in the tag and handler, for convenience.

If you really want to know the address, for example to print out for
debugging messages:

start = rman_get_start(sc->io[i]);
size = rman_get_size(sc->io[i]);

The "io 0x??? - 0x??? irq X" messages that are printed when the device
attaches are normally handled by your parent bus, so you normally don't
even need to worry about what the actual port base is.

For an IRQ you typically call bus_setup_intr() with your resource
pointer and handler function. If you need to know the IRQ number for
some reason, rman_get_start() should work on that as well.

There are lots of examples of using the busdma API in the kernel tree
(virtually every driver).

Hope this helps,
Craig
Alan Garfield
2007-04-11 16:22:31 UTC
Permalink
Post by Craig Boston
Ok, well just for the record it's been a while since I've worked with
busdma so my knowledge is more of a high level overview. Hopefully if
I get anything wrong someone will step in and correct me. :)
You da man!

----
jnet0: <JNet Ethernet Interface> port 0xa8,0xae-0xaf irq 19 on acpi0
jnet0: alloc io port: 00a8 size: 1
jnet0: alloc io port: 00ae size: 2
jnet0: Ethernet address: 00:09:3d:00:00:03
----

Now for the irq!

Looking at this all now it's kind of obvious how it works but until you
gave me the break I was neck deep in confusion. The whole rid thing and
not knowing about rman_get_start() and rman_get_size() so I could see
what ports I was getting allocated was giving me grief. I was poking
around in the dark with a blunt stick!

Many thanks!

Alan.
Marcel Moolenaar
2007-04-11 15:45:10 UTC
Permalink
Post by Alan Garfield
Post by t***@jp.freebsd.org
Post by Alan Garfield
are these resources automagically allocated for me? Or do I have to
allocate them myself?
You have to allocate the resource.
Ok cool, but how do I get the resource list from acpi to allocated
them then? Other than having an array of ioports and irqs, is there
a way to get this information from acpi?
The device driver knows about the hardware and as such knows what
resources it needs and/or what resources the hardware makes
available. You allocate what you need. Use the resource ID in
combination with resource type to get what you want. If you
try to allocate something that's not there, then you have a new
situation that the driver needs to know about and you code
accordingly.

HTH,
--
Marcel Moolenaar
***@mac.com
Craig Boston
2007-04-11 16:40:50 UTC
Permalink
Post by Alan Garfield
----
jnet0: <JNet Ethernet Interface> port 0xa8,0xae-0xaf irq 19 on acpi0
jnet0: alloc io port: 00a8 size: 1
jnet0: alloc io port: 00ae size: 2
jnet0: Ethernet address: 00:09:3d:00:00:03
----
Looks like it's on the right track, glad I could help!
Post by Alan Garfield
Looking at this all now it's kind of obvious how it works but until you
gave me the break I was neck deep in confusion.
Looking back at the thread I see that you're porting a Linux driver,
that explains a lot of the confusion. It's been a while since I've
worked with the Linux kernel in depth, but I seem to remember that a lot
of drivers (especially machine-specific ones) would get the resource
directly, e.g. IO port base address, and then do stuff like

outb(base_addr + offset, value);
value = inb(base_addr + offset);

or write to mapped memory directly by constructing a pointer to the
address.

While doing this is possible in FreeBSD, it's discouraged as the
bus_space API tends to make for cleaner code and is also more portable.
On architectures with peculiar alignment requirements, or other
restrictions (DMA buffers having to be below a particular address comes
to mind, or bounce buffers for PAE), the OS will take care of most of
the nitty gritty details for you and allow the driver to contain
higher-level code.

Craig
Alan Garfield
2007-04-12 03:03:07 UTC
Permalink
Post by Craig Boston
Looking back at the thread I see that you're porting a Linux driver,
that explains a lot of the confusion. It's been a while since I've
worked with the Linux kernel in depth, but I seem to remember that a lot
of drivers (especially machine-specific ones) would get the resource
directly, e.g. IO port base address, and then do stuff like
outb(base_addr + offset, value);
value = inb(base_addr + offset);
or write to mapped memory directly by constructing a pointer to the
address.
Indeed mapped memory is how this is driver is written.
Post by Craig Boston
While doing this is possible in FreeBSD, it's discouraged as the
bus_space API tends to make for cleaner code and is also more portable.
On architectures with peculiar alignment requirements, or other
restrictions (DMA buffers having to be below a particular address comes
to mind, or bounce buffers for PAE), the OS will take care of most of
the nitty gritty details for you and allow the driver to contain
higher-level code.
Yes bus_space seems much nicer, and very useful I'm sure for platform
independence.

Cheers,
Alan.
t***@jp.freebsd.org
2007-04-11 11:48:04 UTC
Permalink
Post by t***@jp.freebsd.org
Post by t***@jp.freebsd.org
Post by Alan Garfield
If the resources are allocated how do I access/see them?
sc->sc_rid1 = 0;
sc->sc_res1 = bus_alloc_resource_any(self, SYS_RES_IOPORT, &sc->sc_rid,
RF_ACTIVE);
Post by t***@jp.freebsd.org
sc->sc_rid2 = 0;
Oops!
sc->sc_rid2 = 1;
Post by t***@jp.freebsd.org
Post by t***@jp.freebsd.org
sc->sc_res2 = bus_alloc_resource_any(self, SYS_RES_IOPORT, &sc->sc_rid,
RF_ACTIVE);
Post by t***@jp.freebsd.org
value_af = bus_space_read_8(rman_get_bustag(sc->sc_res2), rman_get_bus
handle(sc->sc_res2), 1);
Thanks for this, but how does on tell which resources have been
allocated to which other than manually specifying them with
bus_alloc_resource()?
Resource manager will do it. Device driver for a PnP aware bus will set
resource location for each device under the bus. At that time, the resource
is not allocated and activated. Then a device driver for a child device
will allocate bus resource. rid parameter tells the order of resource you
want to get.
Yar Tikhiy
2007-04-17 17:16:23 UTC
Permalink
Post by M. Warner Losh
: I'd like to port/re-write this driver for FreeBSD but I cannot find
: enough documentation and examples of a basic Ethernet driver for
: FreeBSD. (if_wlan and if_ef look like good candidates but if_clone and
: the miibus confuse me a bit and there isn't any clear docs on them)
: Can someone point me in the direction of an example or the relevant man
: pages I should be reading to help with this.
: The device driver for Linux seems quite simple.
: Any help would be gratefully appreciated.
In addition to the other advise, you might also look at if_ed.c. It
is a little complicated since it talks to real hardware, and that
hardware is, ummm, a little icky.
That little thing Alan is writing a driver for should be simpler
and clearer than the ed(4) hw, so Alan's driver will be a source
of knowledge itself when it's complete. :-) It can be a good
companion for if_edsc, as the latter doesn't work with hardware at
all and fails to illustrate some important points due to that.
--
Yar
Alan Garfield
2007-04-18 01:00:32 UTC
Permalink
Post by Yar Tikhiy
Post by M. Warner Losh
In addition to the other advise, you might also look at if_ed.c. It
is a little complicated since it talks to real hardware, and that
hardware is, ummm, a little icky.
That little thing Alan is writing a driver for should be simpler
and clearer than the ed(4) hw, so Alan's driver will be a source
of knowledge itself when it's complete. :-) It can be a good
companion for if_edsc, as the latter doesn't work with hardware at
all and fails to illustrate some important points due to that.
Thanks for your comments. :)

I just wish I could figure out what all this rtrequest/arp stuff was
about so I could finish it. :)

If anyone wants to look at the code just pop me an email. It's based on
a GPL driver (although there isn't anything really left of it other than
#defines and a few comments, the code is all new) so I don't know how/if
I can get it added to FreeBSD HEAD.

Anyway, back to figuring out arp. UGH!

-A.
Yar Tikhiy
2007-04-18 07:44:55 UTC
Permalink
Post by Alan Garfield
Post by Yar Tikhiy
Post by M. Warner Losh
In addition to the other advise, you might also look at if_ed.c. It
is a little complicated since it talks to real hardware, and that
hardware is, ummm, a little icky.
That little thing Alan is writing a driver for should be simpler
and clearer than the ed(4) hw, so Alan's driver will be a source
of knowledge itself when it's complete. :-) It can be a good
companion for if_edsc, as the latter doesn't work with hardware at
all and fails to illustrate some important points due to that.
Thanks for your comments. :)
I just wish I could figure out what all this rtrequest/arp stuff was
about so I could finish it. :)
If anyone wants to look at the code just pop me an email. It's based on
a GPL driver (although there isn't anything really left of it other than
#defines and a few comments, the code is all new) so I don't know how/if
I can get it added to FreeBSD HEAD.
Anyway, back to figuring out arp. UGH!
As a rule, an Ethernet driver needn't worry about ARP by itself
because ARP has own separate module in the network stack. Does
your driver have a partucular reason to?
--
Yar
Alan Garfield
2007-04-19 02:14:50 UTC
Permalink
Post by Yar Tikhiy
Post by Alan Garfield
Anyway, back to figuring out arp. UGH!
As a rule, an Ethernet driver needn't worry about ARP by itself
because ARP has own separate module in the network stack. Does
your driver have a partucular reason to?
Apart from using fake MAC addresses, I don't think so.

-A.
Yar Tikhiy
2007-04-19 07:56:05 UTC
Permalink
Post by Alan Garfield
Post by Yar Tikhiy
Post by Alan Garfield
Anyway, back to figuring out arp. UGH!
As a rule, an Ethernet driver needn't worry about ARP by itself
because ARP has own separate module in the network stack. Does
your driver have a partucular reason to?
Apart from using fake MAC addresses, I don't think so.
I don't understand the concept of a fake MAC address, sorry.
The classic Ethernet is a broadcast medium by design, so a very
primitive NIC can just receive all traffic and let the driver or
network stack decide if the host wants a particular frame. On
output, the network stack can usually put any source MAC address
into the frame -- it's true for the most of Ethernet network
interfaces. So MAC addresses are always "fake" in a sense, as
neither the hardware nor the medium design enforces them.

If I understand your case right, the two processors, CPU and SP,
share a hardware buffer, in which they can put some data for the
other side, e.g., an Ethernet frame, and then prod the other side
with an interrupt. That fits the Ethernet model ideally, so there
should be no need for hacks unless the other side, the SP running
a special Linux, takes the whole thing wrong.
--
Yar
Julian Elischer
2007-04-19 19:34:16 UTC
Permalink
Post by Alan Garfield
Post by Yar Tikhiy
Post by Alan Garfield
Apart from using fake MAC addresses, I don't think so.
I don't understand the concept of a fake MAC address, sorry.
The classic Ethernet is a broadcast medium by design, so a very
primitive NIC can just receive all traffic and let the driver or
network stack decide if the host wants a particular frame. On
output, the network stack can usually put any source MAC address
into the frame -- it's true for the most of Ethernet network
interfaces. So MAC addresses are always "fake" in a sense, as
neither the hardware nor the medium design enforces them.
You're right. I don't fully understand quite what's happening behind the
scene it would seem.
It sounds like this should be a "point-to-point" interface,
and not an Ethernet interface.. If I understand what you are saying there
is only ever communications between 2 entities.

What is on the other side of this connection?
Post by Alan Garfield
Post by Yar Tikhiy
If I understand your case right, the two processors, CPU and SP,
share a hardware buffer, in which they can put some data for the
other side, e.g., an Ethernet frame, and then prod the other side
with an interrupt. That fits the Ethernet model ideally, so there
should be no need for hacks unless the other side, the SP running
a special Linux, takes the whole thing wrong.
Again, you're correct. The Linux driver does have a certain 'quality' to
it, but otherwise it should work as you've said.
Alan.
_______________________________________________
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
Alan Garfield
2007-04-21 16:21:12 UTC
Permalink
Post by Yar Tikhiy
Post by Julian Elischer
What is on the other side of this connection?
Alan may be busy debugging the driver, so let me answer for him,
as he said my notion of the thing was correct. Sun Fire 20z is a
Nope sorry not debugging, I was out on my motorcycle riding around our
beautiful north coast here in Sydney, Australia.

I am however back at it now. :)

You've nailed it pretty bang on there Yar, thanks very much.

Cheers,
Alan.

Alan Garfield
2007-04-19 08:49:30 UTC
Permalink
Post by Yar Tikhiy
Post by Alan Garfield
Apart from using fake MAC addresses, I don't think so.
I don't understand the concept of a fake MAC address, sorry.
The classic Ethernet is a broadcast medium by design, so a very
primitive NIC can just receive all traffic and let the driver or
network stack decide if the host wants a particular frame. On
output, the network stack can usually put any source MAC address
into the frame -- it's true for the most of Ethernet network
interfaces. So MAC addresses are always "fake" in a sense, as
neither the hardware nor the medium design enforces them.
You're right. I don't fully understand quite what's happening behind the
scene it would seem.
Post by Yar Tikhiy
If I understand your case right, the two processors, CPU and SP,
share a hardware buffer, in which they can put some data for the
other side, e.g., an Ethernet frame, and then prod the other side
with an interrupt. That fits the Ethernet model ideally, so there
should be no need for hacks unless the other side, the SP running
a special Linux, takes the whole thing wrong.
Again, you're correct. The Linux driver does have a certain 'quality' to
it, but otherwise it should work as you've said.

Alan.
Yar Tikhiy
2007-04-20 23:20:08 UTC
Permalink
Post by Julian Elischer
Post by Alan Garfield
Post by Yar Tikhiy
Post by Alan Garfield
Apart from using fake MAC addresses, I don't think so.
I don't understand the concept of a fake MAC address, sorry.
The classic Ethernet is a broadcast medium by design, so a very
primitive NIC can just receive all traffic and let the driver or
network stack decide if the host wants a particular frame. On
output, the network stack can usually put any source MAC address
into the frame -- it's true for the most of Ethernet network
interfaces. So MAC addresses are always "fake" in a sense, as
neither the hardware nor the medium design enforces them.
You're right. I don't fully understand quite what's happening behind the
scene it would seem.
It sounds like this should be a "point-to-point" interface,
and not an Ethernet interface.. If I understand what you are saying there
is only ever communications between 2 entities.
What is on the other side of this connection?
Alan may be busy debugging the driver, so let me answer for him,
as he said my notion of the thing was correct. Sun Fire 20z is a
more or less conventional amd64 machine but, besides the usual
components forming the main system (CPU, RAM, bus, etc) it contains
an additional small embedded-style computer (seems to be m68k based)
with the role of monitoring and managing the main system hardware
independently from the host OS, which can be overloaded with heavy
tasks, unstable, or unresponsive. The small computer has its own
external Ethernet interface for remote management and also can
communicate with the main host OS via a small hardware buffer. It
runs a custom Linux, and there's not much control over its properties.
The Linux is hard-coded to send and receive but Ethernet frames via
the buffer, so the main host OS has little choice there, too.
Post by Julian Elischer
Post by Alan Garfield
Post by Yar Tikhiy
If I understand your case right, the two processors, CPU and SP,
share a hardware buffer, in which they can put some data for the
other side, e.g., an Ethernet frame, and then prod the other side
with an interrupt. That fits the Ethernet model ideally, so there
should be no need for hacks unless the other side, the SP running
a special Linux, takes the whole thing wrong.
Again, you're correct. The Linux driver does have a certain 'quality' to
it, but otherwise it should work as you've said.
Alan.
_______________________________________________
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
--
Yar
Alan Garfield
2007-04-21 16:18:42 UTC
Permalink
Post by Yar Tikhiy
components forming the main system (CPU, RAM, bus, etc) it contains
an additional small embedded-style computer (seems to be m68k based)
PPC actually.
And very limited in what they've included in it's base OS (no telnet, no
vi!).
power control as well as system/environment monitoring (eg the CPU
fans run at >16,000RPM).
And they're noisy suckers (pun intended) when the the SP is resetting or
not running, as they default to max power when uncontrolled. The suction
from the front is quite impressive. :)

Alan.
Peter Jeremy
2007-04-21 08:12:10 UTC
Permalink
Loading...