penma's corner on the web

AVR-PCI bridge

This page will be updated in irregular intervals.

Jump to section: What?! - Why? - Current status - To do - Code

What?!

RTL8169 being detected on the bus
Two cards on the same bus using a riser card

Connecting PCI cards to an AVR ATmega. 33 MHz PCI is specified to not only fixed 33 MHz, much slower clock rates are also allowed, as well as non-uniform clock speed. The good thing is that the clock is provided by the system board - which is emulated by the AVR. So the clock is slowed down to whatever the AVR can actually handle.

I am currently using a development board with an ATmega2560 on it. PCI has quite a lot of pins that are used in both directions, so I can directly access all signals without extra hardware. The 2560 was just the cheapest one I could get right now.

Together with a riser card and jumper wires, the board is able to talk to two cards on the same bus.

Future versions might use bidirectional shift registers and/or I2C port expanders instead. There is an untested layout with a much cheaper ATmega32 and four 74HC299. It will probably be revised.

Why?

Everyone on the internet says that it is impossible to talk PCI using an AVR but apparently nobody has actually tried it. This has to change.

Also, I wanted to connect an AVR to the network and I fiddled around with the infamous ENC28J60 modules, which are quite easy to get working. But they only support 10baseT. While the AVR can probably not process packets at 10 Mbit/s anyway, interesting things happen when you connect 10baseT devices to modern networking hardware.

In 10 Mbit Ethernet, the TX and RX pairs had designated plus and minus wires and the polarity was relevant. Starting with 100 Mbit, the wires had no specific polarity anymore. At some point in the past, circuit board designers of switches started swapping the plus and minus wires internally on some ports, because it made routing the traces easier - and since the whole world is using unpolarized 100 Mbit or Gigabit anyway, nobody cares.

Unfortunately, true 10 Mbit hardware does care and will not work on half of the switch ports because they have the polarity wrong. The ENC28J60 is able to detect but not correct the situation. (This bug is known for a long time but it has not been fixed in any of the three silicon revisions released thereafter...)

The obvious fix: use real network cards instead of toys.

Current status

RTL8139 100 Mbit card

A RTL8139D card from Level One was tested and detected correctly (although in the beginning it appeared to not work and was sometimes detected as 8131, but this was never reproduced). Currently working on a driver for this card. Missing features in the PCI protocol support are added as needed.

Two RTL8139B cards tested, need a few cycles after powerup, but otherwise work fine. Currently trying to obtain other RTL8139 variants (B/C) for further testing and driver development.

RTL8169 Gigabit network card

Card 1 (8169S-32) seems to work fine. Currently developing a driver.

Card 2 (8169SC) needs a bit more time for power to stabilize, or it won't work. It does however not need extra PCI clock cycles, any kind of delay will do.

Advantech PCI-1756 Digital I/O card

Setting output pins works. Other things have not been tested yet.

This card uses a PLX-9052 chip as an interface to the PCI bus. Some of the accesses take quite some time, so this card is useful in testing border cases in the PCI implementation (retry requests, slow devices, ...)

Other cards

Should be able to at least detect any PCI card. Some cards that were tested:

Most of these should work fine if anyone could be bothered to write a driver for them. Before that happens, there should be some kind of PCI driver framework for AVR. Maybe it is made partially compatible to Linux or FreeBSD, so porting drivers gets very easy, but still suitable for the limited target platform.

Interesting things happen when you run cards on an unusual bus.

Because of a bug, GNT# was inverted, and therefore permanently asserted. This means that the PCI card should be in control of the bus. It actually wasn't, and the AVR put data on the bus. While some cards do not care until they actually try to become bus master, others refuse to do anything. The Silan, the Adaptec and the firewire card are not detected because of this. The sound card might have other problems (in the test setup it shuts down the whole board because of overcurrent)

The PCI specification demands a large number of PCI clock cycles after a bus reset before any data transfer can start. At the slow clock speed of the AVR, this takes several seconds. While some cards do not care about the clock cycles (notably, Realtek network cards, but also the Token Ring card and the VIA USB), others (Silan, Adaptec, NEC, firewire, and sometimes the Accton) are very strict about it. Currently the extra cycles are disabled because they waste time. In the future, the necessity for extra cycles will be detected automatically.

It appears some cards run some circuits on the PCI clock. Slowing it down will then lead to interesting behavior in these parts. A network card sometimes does not receive any packets if the PCI clock is stopped.

Powering PCI cards from an USB port is as funny as it sounds - you can sometimes see the network activity in the brightness of the debug display :-)

To do / plans

Code

It's currently a mess. But it will eventually appear on Github.