Mercurial > archived > louis > epitech > mq > rathaxes
view e1000_initialize_transmission.patch @ 83:27f0e70df342
Wip on the transmission, tx init done, and tx hooked from Ethernet send
author | Louis Opter <louis@lse.epitech.net> |
---|---|
date | Sun, 08 Jul 2012 10:00:25 +0200 |
parents | 71f76c0f235f |
children |
line wrap: on
line source
# HG changeset patch # Parent e2e48ad161482555c5e87550e76cf15ef7fdbd3e rathaxes: initialize transmission on the e1000 sample: - This is documented in details in the sections 14.5 and 3.3 of the Intel Gigabit Controller Software Developer manual. diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt --- a/rathaxes/samples/e1000/e1000.blt +++ b/rathaxes/samples/e1000/e1000.blt @@ -34,6 +34,59 @@ } /* + * This is a generic tx descriptor for the e1000. When you use TCP + * Segmentation Offload (TSO) the hardware actually uses two types of + * tx descriptors in its tx ring: + * - context descriptors: this descriptor doesn't actually point to data to + * send but initialize the offloading engine for the data descriptor that + * follow; + * - data descriptors: this descriptor points to data from the skbuffs. + */ + template type e1000::TxDescriptor() + { + chunk LKM::includes() + { + static const ${e1000::TxDescriptor} force_rtx_e1000_tx_descriptor_decl; + } + + chunk ::decl() + { + typedef struct rtx_e1000_tx_descriptor + { + unsigned long int /* __le64 */ buff_addr; + union + { + unsigned int /* __le32 */ data; + struct + { + unsigned short /* __le16 */ length; + unsigned char csum_offset; /* CSO */ + unsigned char cmd; + } fields; + } lower; + union + { + unsigned int /* __le32 */ data; + struct + { + unsigned char status; + unsigned char csum_start; /* CSS */ + unsigned short /* __le16 */ special; + } fields; + } upper; + } *rtx_e1000_tx_descriptor_p; + } + + chunk ::init() + { + } + + map + { + } + } + + /* * Ring of e1000::RxDescriptors and their corresponding skbuffs. * * - size: total size of the ring in bytes. @@ -73,6 +126,43 @@ } } + /* + * Ring of e1000::TxDescriptors, this is a bit similar to the Rx ring except + * that we don't really have to manage the skbuffs themselves (they are + * given to use by the kernel). + * + * - size: total size of the ring in bytes. + * - base: address of the ring (we can't use the typedef here until we get + * CNorm unstrict); + * - dma_base: (physical) address of the ring where the device can access + * the different descriptors. + */ + template type e1000::TxRing() + { + chunk LKM::includes() + { + static const ${e1000::TxRing} force_rtx_e1000_tx_ring_decl; + } + + chunk ::decl() + { + struct rtx_e1000_tx_ring + { + unsigned int size; + struct rtx_e1000_tx_descriptor *base; + void* /* dma_addr_t */ dma_base; + }; + } + + chunk ::init() + { + } + + map + { + } + } + template type e1000::Context() { chunk LKM::includes() @@ -99,6 +189,7 @@ /* we can't use the Rathaxes type here (#8) */ struct rtx_e1000_rx_ring rx_ring; + struct rtx_e1000_tx_ring tx_ring; } *rtx_e1000_ctx_p; } @@ -139,6 +230,7 @@ E1000_FCT = 0x00030, /* Flow Control Type */ E1000_RCTL = 0x00100, /* Receive Control */ E1000_FCTTV = 0x00170, /* Flow Control Transmit Timer Value */ + E1000_TCTL = 0x00400, /* Transmit Control */ E1000_CRCERRS = 0x04000, /* CRC Error Count (base address of the statistic register spaces) */ E1000_RAL = 0x05400, /* Receive Address Low */ E1000_RAH = 0x05404, /* Receive Address High */ @@ -148,6 +240,11 @@ E1000_RDLEN = 0x02808, /* Receive Descriptor Length */ E1000_RDH = 0x02810, /* Receive Descriptor Head */ E1000_RDT = 0x02818, /* Receive Descriptor Tail */ + E1000_TDBAL = 0x03800, /* Transmit Descriptor Base Address (Low 32 bits) */ + E1000_TDBAH = 0x03804, /* Transmit Descriptor Base Address (High 33 bits) */ + E1000_TDLEN = 0x03808, /* Transmit Descriptor Length */ + E1000_TDH = 0x03810, /* Transmit Descriptor Head */ + E1000_TDT = 0x03818, /* Transmit Descriptor Tail */ }; } @@ -226,6 +323,8 @@ E1000_RCTL_BSIZE_4096 = (E1000_RCTL_BSEX | (1 << 16) | (1 << 17)), E1000_RCTL_BSIZE_8192 = (E1000_RCTL_BSEX | (1 << 17)), E1000_RCTL_BSIZE_16384 = (E1000_RCTL_BSEX | (1 << 16)), + E1000_TCTL_EN = (1 << 1), /* Transmitter Enable */ + E1000_TCTL_PSP = (1 << 3), /* Pad Short Packet */ }; } @@ -728,11 +827,64 @@ } /* + * Transmission initialization (section 14.5): + * + * 1. Allocate the transmit descriptors ring and map it to make it + * accessible by the device; + * 2. Write the start address of the ring in TDBAL/TDBAH and set + * TDLEN to the size of the ring; + * 3. Set the TDH/TDT indexes to the beginning and end of the ring; + * 4. Set TCTL.PSP to pad short packets and TCTL.EN to enable the + * transmitter. + */ + + /* + * XXX: at this point we must be careful to not fuck up with i, or + * we are going go have surprises in `err_skbuffs_alloc`. Maybe it's + * time to separate the rx and tx initialization in two functions. + */ + + /* 1. Allocate the tx ring */ + hw_ctx->tx_ring.size = ${config.tx_ring_size} * sizeof(*hw_ctx->tx_ring.base); + hw_ctx->tx_ring.size = ALIGN(hw_ctx->tx_ring.size, 4096); + hw_ctx->tx_ring.base = dma_alloc_coherent( + &${ctx}->pci_dev->dev, + hw_ctx->tx_ring.size, + (dma_addr_t *)&hw_ctx->tx_ring.dma_base, + GFP_KERNEL); + if (!hw_ctx->rx_ring.base) + { + ${Log::info("cannot allocate the descriptors for the tx ring")}; + goto err_tx_ring_alloc; + } + + { + ${Log::info("setup_device: tx descriptors allocated")}; + } + + /* 2. Save the emplacement and the size of the ring in TDBA/TDLEN */ + rtx_e1000_register_write32(hw_ctx, E1000_TDBAL, (dma_addr_t)hw_ctx->tx_ring.dma_base & 0xffffffff); + rtx_e1000_register_write32(hw_ctx, E1000_TDBAH, (dma_addr_t)hw_ctx->tx_ring.dma_base >> 32); + rtx_e1000_register_write32(hw_ctx, E1000_TDLEN, hw_ctx->tx_ring.size); + + /* 3. Setup TDH/TDT to zero: the queue is empty */ + rtx_e1000_register_write32(hw_ctx, E1000_TDH, 0); + rtx_e1000_register_write32(hw_ctx, E1000_TDT, 0); + + /* 4. Set TCTL.PSP and enable the transmitter */ + rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_PSP); + + { + ${Log::info("transmit registers configured and transmitter enabled")}; + } + + /* * XXX: We can't return here since we are not in a function but in * a chunk of code (injected in a function). */ goto ok; + err_tx_ring_alloc: /* * Likewise, always the same problem with error handling, we don't * know where we are at in the "parent context": @@ -788,6 +940,15 @@ ${Log::info("free_rx_tx: rx ring free'ed")}; } + /* + * Free the tx ring: + * - Free the descriptors array. + */ + dma_free_coherent(&${ctx}->pci_dev->dev, hw_ctx->tx_ring.size, + hw_ctx->tx_ring.base, (dma_addr_t)hw_ctx->tx_ring.dma_base); + { + ${Log::info("free_rx_tx: tx ring free'ed")}; + } } } diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti --- a/rathaxes/samples/e1000/e1000.rti +++ b/rathaxes/samples/e1000/e1000.rti @@ -2,7 +2,9 @@ { provided type e1000::Context; provided type e1000::RxDescriptor; + provided type e1000::TxDescriptor; provided type e1000::RxRing; + provided type e1000::TxRing; /* * These two types should actually be registers definitions in the frontend: diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx --- a/rathaxes/samples/e1000/lkm.rtx +++ b/rathaxes/samples/e1000/lkm.rtx @@ -73,6 +73,7 @@ Ethernet::ifname = "rtx%d"; e1000::rx_ring_size = 256; /* Number of incoming packets we can buffer */ + e1000::tx_ring_size = 256; /* Mumber of buffers we can have in the tx queue */ /* * The e1000 supports seven receive buffer sizes: 256, 512, 1024, 2048, * 4096, 8192 and 16384 bytes: