AM79C960 was a rather common ISA Ethernet card, used mostly in PCs. It may be a little out-dated by now, but still serves as a good example.
Normally the module and device class would both have been named AM79C960, but because Virtutech already had a AM79C960 device model written in C, the sample DML module and the device class are named AM79C960-dml.
It may be good to have the documentation for the AM79C960 chip when looking at the sample code, so that you can compare the code to the specification. The documentation can be found on the Internet, search for am79c960.pdf on www.google.com and you will get lots of links to it.
The source code for the sample device can be found in the directory [simics]/src/devices/AM79C960-dml. If you want to try modifying the AM79C960-dml module yourself, we recommend that you set up a user workspace and copy the source code there, as described in section 3.
If you compile the AM79C960-dml module yourself, you will see some compilation warnings like this:
/home/mve/simics/src/devices/AM79C960-dml/AM79C960.dml:567: In AM79C960_dml.mac_address.set /home/mve/simics/src/devices/AM79C960-dml/AM79C960.dml:567: warning: not a function: sscanf
They do not indicate any error. They are caused by a limitation in the current DML compiler. There is currently no support for proper declarations of C functions with variable numbers of arguments, which causes the warnings.
If your distribution contains the simulated machine enterprise, you can find the Simics script enterprise-AM79C960-dml.simics in the directory [simics]/targets/x86-440bx. This file creates an enterprise machine using the AM79C960-dml module instead of the default AM79C960 module. The AM79C960 object is called lance0.
To do something interesting with the AM79C960 model we need to connect it to something that it can talk to. We can use a service-node for this. These commands create an ethernet-link, a service-node and connect the AM79C960 device to the ethernet-link:
simics> new-ethernet-link Created ethernet-link ethlink0 simics> new-service-node link = ethlink0 ip = 10.10.0.1 netmask = 255.255.255.0 Created service-node ethlink0_sn0 Connecting ethlink0_sn0 to ethlink0 Setting IP address of ethlink0_sn0 on network ethlink0 to 10.10.0.1 ethlink0_sn0 simics> lance0.connect ethlink0
Start the simulation and let the machine boot and login as the user root. No password is required. Stop the simulation and set the log level of the lance0 object to 2:
simics> lance0.log-level 2 [lance0] Changing log level: 1 -> 2
You can now start the simulation again and send a ping packet to the service-node by entering ping -c 1 10.10.0.1 in the console on the simulated machine. The lance0 object will log what happens:
simics> c [lance0 info] Packet sent, dst ff:ff:ff:ff:ff:ff, src 10:10:10:10:10:30, length 64 bytes. [lance0 info] Packet received, dst 10:10:10:10:10:30, src 20:20:20:20:20:00, length 64 bytes. [lance0 info] MAC address matches, packet accepted. [lance0 info] Packet sent, dst 20:20:20:20:20:00, src 10:10:10:10:10:30, length 102 bytes. [lance0 info] Packet received, dst 10:10:10:10:10:30, src 20:20:20:20:20:00, length 102 bytes. [lance0 info] MAC address matches, packet accepted.
We can see that the enterprise machine first sends a 64-byte packet to the broadcast address ff:ff:ff:ff:ff:ff and then receives a 64-byte reply from 20:20:20:20:20:00, the MAC address of the service-node. These are an ARP request and an ARP reply to get the MAC address of the service-node.
After this the enterprise machines sends a 102-byte packet to the service-node and receives a 102-byte reply. These are the actual ping request and ping reply.
If you try to ping again you may not see the ARP packets, since the simulated machine may already have the MAC address of the service-node.
If you want more detailed logs you can change the log level to 3 or 4. At log level 3 a lot more information about what is going on in the device will be logged. The device polls for packets to transmit regularly, so this will cause a lot of output. At log level 4 all accesses that the processor does to the device will also be logged.
The source code of the AM79C960 module is quite richly commented, so if you have the documentation for the AM79C960 chip you should hopefully be able to understand most of the code without too much problem.
The AM79C960 model is far from complete, it implements just enough functionality that the device model can be used with Linux 2.4. A list of known limitations can be found at the top of the source file.
The implementation of the model is quite straight forward. There is one unusual design, though. The AM79C960 device has many 32-bit and 64-bit values that are split into multiple 16-bit register. The model stores many of these values in a separate attributes, and makes the registers reflect the attribute by using the data_accessor template.
For example, the 64-bit Logical Address Filter that resides in CSR8 - CSR11 is stored in the logical_address_filter attribute. Some of the registers, for example, CSR24 and CSR 25 that contain Base Address of Receive Ring, are not even implemented and the values are only stored in separate attributes.