Transcript 8085 Architecture & Its Assembly language programming
Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati
• • •
PCI Devices NIC Cards
–
Specific to 82573 (Intel NIC)
–
How transmit works
–
How receive work
Network Device Driver
16 doublewords 31 Status Command Register BIST Header Type Register Latency Timer Cache Line Size 0 31 0 Device Vendor ID Class Code Class/SubClass/ProgIF ID Revision ID Dwords 1 - 0 3 - 2 Base Address 1 Base Address 0 5 - 4 Base Address 3 Base Address 2 7 - 6 Base Address 5 Subsystem Device ID reserved Subsystem Vendor ID capabilities pointer Maximum Minimum Interrupt Latency Grant Pin Interrupt Line Base Address 4 CardBus CIS Pointer Expansion ROM Base Address reserved 9 - 8 11 - 10 13 - 12 15 - 14
accessed using a large variety of processor instructions (mov, add, or, shr, push, etc.) and virtual-to-physical address-translation
memory space (4GB)
accessed only by using the processor’s special ‘in’ and ‘out’ instructions (without any translation of port-addresses)
i/o space (64KB) PCI configuration space (16MB)
i/o-ports 0x0CF8-0x0CFF dedicated to accessing PCI Configuration Space
CONFADD ( 0x0CF8)
PCI Configuration Space Address Port (32-bits)
31
E N reserved
23
bus (8-bits)
16 15 11 10 8 7
device (5-bits) function (3-bits) doubleword (6-bits)
2 0 00
Enable Configuration Space Mapping (1=yes, 0=no)
CONFDAT ( 0x0CFC)
31 PCI Configuration Space Data Port (32-bits) 0
• • •
Step one: Output the desired longword’s
address (bus, device, function, and dword) with bit 31 set to 1 (to enable access) to the Configuration-Space Address-Port
Step two: Read the designated data from the
Configuration-Space Data-Port Already discussed PCI-probes pciprobes.c
– Lect 29..Showing vram, pciprobe.cpp
How ‘transmit’ works
List of Buffer-Descriptors descriptor0 descriptor1 descriptor2 descriptor3 0 0 0 0 We setup each data-packets that we want to be transmitted in a ‘Buffer’ area in ram We also create a list of buffer-descriptors and inform the NIC of its location and size Then, when ready, we tell the NIC to ‘Go!’ (i.e., start transmitting), but let us know when these transmissions are ‘Done’ Buffer0 Buffer1 Buffer2 Buffer3 Random Access Memory
• • •
Memory-information registers
– TDBA(L/H) = Transmit-Descriptor Base-Address Low/High (64-bits) – TDLEN = Transmit-Descriptor array Length – TDH = Transmit-Descriptor Head – TDT = Transmit-Descriptor Tail
Transmit-engine control registers
– TXDCTL = Transmit-Descriptor Control Register – TCTL = Transmit Control Register
Notification timing registers
– TIDV = Transmit Interrupt Delay Value – TADV = Transmit-interrupt Absolute Delay Value
TDLEN (in bytes)
0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80
Circular buffer (128-bytes minimum) TDBA base-address TDH (head) TDT (tail)
= owned by hardware (nic) = owned by software (cpu)
0
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17
0 0 0 0 0 0
G R A N
0 0
WTHRESH (Writeback Threshold) 16
0
15 14 13 12 11 10 9 8 7 6 5 4 3 2
0 0
FRC DPLX SPD
0 0
I S 0 0
0
A S D E
0
L R S T 1 0
0 0 0 0
“This register controls the fetching and write back of transmit descriptors.
The three threshhold values are used to determine when descriptors are read from, and written to, host memory. Their values can be in units of cache lines or of descriptors (each descriptor is 16 bytes), based on the value of the GRAN bit (0=cache lines, 1=descriptors). When GRAN = 1, all descriptors are written back (even if not requested).” --Intel manual
Recommended for 82573: 0x01010000 (GRAN=1, WTHRESH=1)
R =0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 R =0 R =0 MULR TXCSCMT UNO RTX RTLC R =0 SW XOFF COLD (upper 6-bits) (COLLISION DISTANCE) 15 14 13 12 11 10 9 8 7 6 5 4 3 2 COLD (lower 4-bits) (COLLISION DISTANCE) 0 ASDV CT I S S SPEED U TBI mode P S P 1 0 R 0 0 =0 E N R =0 EN = Transmit Enable PSP = Pad Short Packets CT = Collision Threshold (=0xF) COLD = Collision Distance (=0x3F) SWXOFF = Software XOFF Transmission RLTC = Retransmit on Late Collision UNORTX = Underrun No Re-Transmit TXCSCMT = TxDescriptor Minimum Threshold MULR = Multiple Request Support
82573L
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 ANE Tx Config ITCE
R
=0 IAME
R
=0 DF PAR EN PB PAR EN Tx LS Tx LS Flow =0
R
=0 Phy Pwr Down En DMA Dyn GE
R
=0 RO DIS 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 SPD BYPS
R
=0 EE RST ASD CHK
R
=0
R
=0
R
TxConfigWord =0 =0
R
=0
R
=0
R
=0
R
=0 1 0
0 0
ANE = Auto-Negotiation Enable TxConfig = Transmit Configuration Control bit TxConfigWord = Transmit Configuration Word
This register has two meanings, depending on the state of the ANE bit (i.e., setting ANE=1 enables the hardware auto-negotiation machine).
Applicable only in SerDes mode; program as 0 for internal-PHY mode.
82573L
7 6 5 4 3 2 1 0
IDE VLE DEXT reserved =0 RS IC IFCS EOP EOP = End Of Packet (1=yes, 0=no) IFCS = Insert Frame CheckSum (1=yes, 0=no) – provided EOP is set IC = Insert CheckSum (1=yes, 0=no) as indicated by CSO/CSS fields RS = Report Status (1=yes, 0=no) DEXT = Descriptor Extension (1=yes, 0=no) use ‘0’ for Legacy-Mode VLE = VLAN-Packet Enable (1=yes, 0=no) – provided EOP is set IDE = Interrupt-Delay Enable (1=yes, 0=no)
3 2 1 0
reserved =0
LC EC DD
DD = Descriptor Done this bit is written back after the NIC processes the descriptor provided the descriptor’s RS-bit was set (i.e., Report Status) EC = Excess Collisions indicates that the packet has experienced more than the maximum number of excessive collisions (as defined by the TCTL.CT field) and therefore was not transmitted. (This bit is meaningful only in HALF-DUPLEX mode.) LC = Late Collision indicates that Late Collision has occurred while operating in HALF-DUPLEX mode. Note that the collision window size is dependent on the SPEED: 64-bytes for 10/100-MBps, or 512-bytes for 1000-Mbps.
?
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 0 0 0 0 0 0 0 0 0 0 0 GIO Master EN 0 0 0
some undocumented functionality?
0 15 14 13 12 11 10 9 8 7 6 5 4 3 2 I S 0 0 0 0 PHY reset ASDV O S L U 0 TX OFF ID 1 0 F D FD = Full-Duplex LU = Link Up TXOFF = Transmission Paused SPEED (00=10Mbps,01=100Mbps, 10=1000Mbps, 11=reserved) ASDV = Auto-negotiation Speed Detection Value
82573L
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 PHY RST VME
R
=0 TFCE RFCE RST
R
=0
R
=0
R
=0
R
=0
R
=0 ADV D3 WUC
R
=0 D/UD status
R
=0
R
=0
R
=0 15 14 13 12 11 10 9 8 7 6 5 4 3 2
R
=0
R
=0 FRC DPLX FRC SPD
R
=0 SPEED
R
=0 S L U
R
=0
R
=0
R
=1 GIO
0 0
D 1 0 =0 F D FD = Full-Duplex GIOMD = GIO Master Disable SLU = Set Link Up FRCSPD = Force Speed FRCDPLX = Force Duplex SPEED (00=10Mbps, 01=100Mbps, 10=1000Mbps, 11=reserved) ADVD3WUP = Advertise Cold Wake Up Capability D/UD = Dock/Undock status RST = Device Reset PHYRST = Phy Reset RFCE = Rx Flow-Control Enable TFCE = Tx Flow-Control Enable VME = VLAN Mode Enable
82573L
• • Total size normally can vary from 64 bytes up to 1536 bytes (unless ‘jumbo’ packets and/or ‘undersized’ packets are enabled) The NIC expects a 14-byte packet ‘header’ and it appends a 4-byte CRC check-sum 0 6 12 14
destination MAC address (6-bytes) source MAC address (6-bytes) Type/length (2-bytes) the packet’s data ‘payload’ goes here (usually varies from 56 to 1500 bytes) Cyclic Redundancy Checksum (4-bytes)
List of Buffer-Descriptors descriptor0 descriptor1 descriptor2 descriptor3 0 0 0 0
We setup memory-buffers where we want received packets to be placed by the NIC We also create a list of buffer-descriptors and inform the NIC of its location and size Then, when ready, we tell the NIC to ‘Go!’ (i.e., start receiving), but to let us know when these receptions have occurred
Buffer0 Buffer1 Buffer2 Buffer3
Random Access Memory
R
=0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17
0
SE CRC BSEX
R
=0 PMCF DPF
R
=0 CFI CFI EN VFE 16 BSIZE 15 14 13 12 11 10 9 8 7 6 5 4 3 2 B A M
R
=0 MO DTYP RDMTS I L O S LBM S L U LPE MPE UPE 1 0
0 0
E N
R
=0 EN = Receive Enable SBP = Store Bad Packets DTYP = Descriptor Type MO = Multicast Offset DPF = Discard Pause Frames PMCF = Pass MAC Control Frames UPE = Unicast Promiscuous En BAM = Broadcast Accept Mode BSEX = Buffer Size Extension MPE = Multicast Promiscuous En BSIZE = Receive Buffer Size SECRC = Strip Ethernet CRC LPE = Long Packet reception Ena VFE = VLAN Filter Enable LBM = Loopback Mode FLXBUF = Flexible Buffer size CFIEN = Canonical Form Indicator Enable RDMTS = Rx-Descriptor Minimum Threshold Size CFI = Cannonical Form Indic
• • •
Memory-information registers
– RDBA(L/H) = Receive-Descriptor Base-Address Low/High (64 bits) – RDLEN = Receive-Descriptor array Length – RDH = Receive-Descriptor Head – RDT = Receive-Descriptor Tail
Receive-engine control registers
– RXDCTL = Receive-Descriptor Control Register – RCTL = Receive Control Register
Notification timing registers
– RDTR = Receive-interrupt packet Delay Timer – RADV = Receive-interrupt Absolute Delay Value
RDBA base-address RDLEN (in bytes) 0x00 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 Circular buffer (128-bytes minimum) RDH (head) RDT (tail) = owned by hardware (nic) = owned by software (cpu)
R
=0 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17
R
=0
R
=0
R
=0
R
=0
R
=0
R
=0 G R A N
R
=0
R
=0 1 -------- 0 GRAN (Granularity): 1=descriptor-size, 0=cacheline-size ADV D3 SDP1 WTHRESH -------- 0 SDP0 -------- status
0
16
R
15 14 13 12 11 10 9 8 7 6 5 4 3 2 =0
R
=0
0
FRC DPLX SPD
0 R
=0
R
=0 A S D E L
0
PTHRESH T 1 0
Prefetch Threshold – A prefetch operation is considered when the number of valid, but unprocessed, receive descriptors that the ethernet controller has in its on-chip buffer drops below this threshold. Host Threshold - A prefetch occurs if at least this many valid descriptors are available in host memory Writeback Threshold - This field controls the writing back to host memory of already processed receive descriptors in the ethernet controller’s on-chip buffer which are ready to be written back to host memory
7 6 5 4 3 2 1 0 PIF IPCS TCPCS UDPCS VP IXSM EOP DD
DD = Descriptor Done (1=yes, 0=no) shows if nic is finished with descriptor EOP = End Of Packet (1=yes, 0=no) shows if this packet is logically last IXSM = Ignore Checksum Indications (1=yes, 0=no) VP = VLAN Packet match (1=yes, 0=no) USPCS = UDP Checksum calculated in packet (1=yes, 0=no) TCPCS = TCP Checksum calculated in packet (1=yes, 0=no) IPCS = IPv4 Checksum calculated on packet (1=yes, 0=no) PIF = Passed In-exact Filter (1=yes, 0=no) shows if software must check
7 6 5 4 3 2 1 0 RXE IPE TCPE
reserved =0 reserved =0
SEQ SE CE RXE = Received-data Error (1=yes, 0=no) IPE = IPv4-checksum error TCPE = TCP/UDP checksum error (1=yes, 0=no) SEQ = Sequence error (1=yes, 0=no) SE = Symbol Error (1=yes, 0=no) CE = CRC Error or alignment error (1=yes, 0=no)
• • • The 82573L has several dozen statistical counters which automatically operate to keep track of significant events affecting the ethernet controller’s performance Most are 32-bit ‘read-only’ registers, and they are automatically cleared when read Your module’s initialization routine could read them all (to start counting from zero)
• • The statistical counters all have address offsets in the range 0x04000 – 0x04FFF You can use a very simple program-loop to ‘clear’ each of these read-only registers } { // Here ‘io’ is the virtual base-address // of the nic’s i/o-memory region int r; // clear all of the Pro/1000 controller’s statistical counters for (r = 0x4000; r < 0x4FFF; r += 4) ioread32( io + r );
0x4000 CRCERRS 0x400C RXERRC 0x4014SCC 0x4018ECOL 0x4074GPRC 0x4078BPRC 0x407CMPRC
0x40D0 0x40D4
0x40F0MPTC 0x40F4BPTC CRC Errors Count Receive Error Count Single Collision Count Excessive Collision Count Good Packets Received Broadcast Packets Received Multicast Packets Received
TPR TPT Total Packets Received Total Packets Transmitted
Multicast Packets Transmitted Broadcast Packets Transmitted
my_fops ioctl open read write release module_init() my_isr() my_ioctl() my_open() my_read() my_write() my_release() module_exit()
• • • • • Network interface driver similar to mounted block devices A Special block devices registers its disk and methods with kernel and Transmit and Receive block on request Socket Read/Write system call Network driver receive Asyn packet from Outside world Ask to push incoming packet towards kernel
• • Many administrative works – Setting up address, modify transmission param, maintaining traffic, error statistics Network subsystem completely protocol independent – Software (IP) and Hardware (Eth, Ring)
• • • Linux loop back driver At drivers/net/loopback.c
It simulates conversations with real remote hosts in order to demonstrate the task of writing network drivers
• • • • • Suppose two interfaces in system sn0, sn1 interfaces Loopback: it really don’t send/simulate But to send actually: toggle LSBit of third octet of both src & dest address – It changes both the network number and host number of class C IP number – The net effect is packet sent to network interface sn0 appears on sn1 Snullnet0: network connected to sn0 interface, Snullnet1:network connected to sn1 interface – Must have 24 bit masks local0, local1: IP address assigned: must differs in the Lsbit of their in 3 rd and 4 th octet
• • • • • • Snull interface correspond to Ethernet class It emulates Ethernet Kernel offers some generalized support of Ethernet devices Ethernet is strong: plip (interface used for printer): declares itself as Ethernet device Watch packets: tcpump Snull works only wit IP Packets – Modify src,dst,chksu in the IP headers: without checking wheather it actually conve IP infos
• • Loopback.c, plip.c, e100.c are examples of network drivers : /drivers/net/ Device registration: – Alloc net devices (Request for resources and offer facilities) • Struct net_devices *snull_dev[2] ; //linux/netdevice.h
• snull_dev[0]=alloc_netdev(sizeof(struct snull_priv), “sn%d”,snull_init); • Alloac_etherdev(int sizeof_priv); /wrapper to alloc_netdev – After initialization complete register the devices • register_netdev(snull_dev[i]); // return 1 if fails
• • • Snull uses alloc_netdev, it have a separate initialization function Ether_setup(dev);//it assign some field – dev->open=snull_open; – dev->close=snull_release; – set_config, hard_start_txmit, do_ioctl, get_stats, rebuild_header, tx_timeout, watchdog_timeo, – flag|=IFFNOARP; – Features|=NETIF_F_NO_CSUM – hard_header_cache=NULL//disable caching Private data pointers: priv with al netdevices
• • Strcut snull_priv *priv=nedev_priv(dev); Strcu snull_priv { struct net_devices_stats stats; int status; strcut snull_packet *ppool; struct snul_packet *rx_queue; int rx_enabled, tc_packele; u8 *tx_packetdata; struct sk_bff *skb; spinlock_t lock; }; Initialization priv=netdriv_priv(dev); memset(priv,0,sizeof(strcutn null_priv)); spin_lock_init(&priv->lock); snull_rx_inits(dev,1); //enable revice interrupts
• • Cleanup (snull_dev[i]){ unregister_netdev(snull_dev[i]); snull_teardown_pool(snull_dev[i]); } free_netdev(snull_dev[i]); Tearown_pool: flush packet pool and bufffer of private data
• • • • Global Information – name: name of device – State: state of device – net_device *next; // ptr to next dev in global list – init_funtion: An init fun called by reg_netdev(); Hardware Information Interface Information Device methods
• • • • • • Low level hardware information Base_address: io_base address of network interface Char irq: dev->irq, the assigned interrupt number..ifconfig
Char if_port: the port is in use on multiport device..10base
Char dma; // dma allcoated by the device for ISA bus Device memory information: address of shared memory used by the devices – Rmem (rx mem) , mem (tx_mem) – rmem_start, rmem_end, mem-start, mem_end;
• • • • • Init setup most of the information But device specific setup information need to setup later on Non ethernet interface can use helper functions – fc_setup, ltalk_setup, fddi_setup – Fiber channel, local talk, fiber dis data ineterface, token ring, hihh perf parllel interface (hppi_setup) Non default interface filed – Hard_headerlen,MTU (max tx unit=1500 oct ), tx_queue_len (ether=1000, pipl=10), short type, char adresslen; char dev_addeess[Max_add_len], breadcast[max_ad_len] Flags bt sets: Mask bits, loopback, debug, noarp, multicast Special hardware capability the device has: DMA
• • • Fundamental method – Open, Stop, Hard_start_xmit – Hard_header, Rebuild_header – Tx_timeout, Net_device_stats, Set_config Optional methods – Poll, poll_controller, do_ioctl, set_multicastlist – Set_mac_address,change_mtu, header_cache, header_cache_update, hard_header_parse Utilities fileds (not methods) – Trans_start, last_rx, watchdog_timeo, *priv, mc_list, mc_count, xmit_lock, xmit_lock_owner
int snull_open(struct net_device *dev) { /* request_region( ), request_irq( ), Assign the hardware address of the board: use "\0SNULx", where * x is 0 or 1. The first byte is '\0' to avoid being a multicast } * address (the first byte of multicast addrs is odd). */
memcpy(dev->dev_addr, "\0SNUL0", ETH_ALEN); if (dev = = snull_devs[1]) dev->dev_addr[ETH_ALEN-1]++; /* \0SNUL1 */ netif_start_queue(dev); return 0;
} int snull_release(struct net_device *dev) { /* release ports, irq and such -- like fops->close */
netif_stop_queue(dev); /* can't transmit any more */
return 0;
int snull_tx(struct sk_buff *skb, struct net_device *dev){ int len; char *data, shortpkt[ETH_ZLEN]; struct snull_priv *priv = netdev_priv(dev); data = skb->data; len = skb->len; if (len < ETH_ZLEN) { memset(shortpkt, 0, ETH_ZLEN); memcpy(shortpkt, skb->data, skb->len); len = ETH_ZLEN; data = shortpkt; } dev->trans_start = jiffies; /* save the timestamp */ /* Remember the skb, so we can free it at interrupt time */ priv->skb = skb; } /* actual deliver of data is device-specific, and not shown here */ snull_hw_tx(data, len, dev); return 0;
void snull_rx(struct net_device *dev, struct snull_packet *pkt) { struct sk_buff *skb; struct snull_priv *priv = netdev_priv(dev); /* * The packet has been retrieved from the transmission * medium. Build an skb around it, so upper layers can handle it */ skb = dev_alloc_skb(pkt->datalen + 2); if (!skb) { if (printk_ratelimit( )) printk(KERN_NOTICE "snull rx: low on mem - packet dropped\n"); priv->stats.rx_dropped++; goto out; } memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen); /* Write metadata, and then pass to the receive level */ skb->dev = dev; skb >protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ priv->stats.rx_packets++; priv->stats.rx_bytes += pkt->datalen; netif_rx(skb); out: return; }