Mercurial > archived > louis > epitech > mq > rathaxes
view rathaxes_samples_e1000_split_set_up_device.patch @ 124:ecba077e0f73
WIP
author | Louis Opter <louis@lse.epita.fr> |
---|---|
date | Sat, 03 Aug 2013 20:14:51 -0700 |
parents | 52402232483f |
children | 518d9c8ac70c |
line wrap: on
line source
# HG changeset patch # Parent d62a08753da7cec4d44246b747ff79847d9b4238 rathaxes: split and refactor e1000::set_up_device in {Rx,Tx}Ring methods 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 @@ -1,4 +1,4 @@ -with e1000, Ethernet, Socket, PCI, LKM, Log, Builtin +with e1000, Ethernet, Socket, DMA, PCI, LKM, Log, Builtin { template type e1000::RxDescriptor() { @@ -96,8 +96,163 @@ { } + chunk Ethernet::adapter_init_rx(Ethernet::Device rtx_ether_ctx) + { + { + ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; + + /* + * Receive initialization (section 14.4): + * + * 1. Program the receive address, in RAL/RAH; + * 2. Initialize the Multicast Table Array; + * 3. Program the interrupt mask register (done in + * e1000::activate_device_interruption); + * 4. Allocate the receive descriptor ring and map it to make it + * accessible by the device; + * 5. Write the start address of the ring in RDBAL/RDBAH and set + * RDLEN (Receive Descriptor Length) to the size of the ring; + * 6. Set the RDH/RDT (Receive Descriptor Head/Tail) indexes to the + * beginning and end of the ring; + * 7. Make sure that RCTL.BSIZE and .BSEX are at 0 to configure the + * receive buffer size to 2048 bytes (e1000::rx_buffer_len). + * 8. Set RCTL.EN to enable the receiver. + * + * The ugly casts here are caused by the lack of CNorm unstrict. + */ + + int i; + + /* 1. Program the receive address */ + + /* (We should use uint{32,16}_t but CNorm doesn't know them yet) */ + rtx_e1000_register_write32(hw_ctx, E1000_RAL, + *(unsigned int *)(${rtx_ether_ctx.dev_addr})); + /* + * The 16 upper bits of RAH also store the AS bits (which should be + * 0) and the AV bit (should be 1 to set the address as valid). + */ + rtx_e1000_register_write32(hw_ctx, E1000_RAH, + *(unsigned short *)(&${rtx_ether_ctx.dev_addr}[4])); + rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV); + + ${Log::info("adapter_init_rx: receive address programmed")}; + + /* 2. Initialize the MTA */ + + for (i = 0; i != 128; ++i) + rtx_e1000_register_write32(hw_ctx, E1000_MTA + i * 4, 0); + + ${Log::info("adapter_init_rx: MTA init done")}; + + /* 4. Setup the receive descriptor ring */ + + /* Allocate the descriptors */ + hw_ctx->rx_ring.size = ${config.rx_ring_size} * sizeof(*hw_ctx->rx_ring.base); + hw_ctx->rx_ring.size = ALIGN(hw_ctx->rx_ring.size, 4096); + hw_ctx->rx_ring.base = dma_alloc_coherent( + ${rtx_ether_ctx.device}, + hw_ctx->rx_ring.size, + &hw_ctx->rx_ring.dma_base, + GFP_KERNEL); + /* XXX + * The first arg is recognized as Ethernet::Device instead of + * Device::AbstractDevice. + */ + hw_ctx->rx_ring.base = ${DMA::alloc_coherent( + rtx_ether_ctx.device, local.hw_ctx.rx_ring.size, local.hw_ctx.rx_ring.dma_base.dma_handle + )}; + if (!hw_ctx->rx_ring.base) + { + ${Log::info("adapter_init_rx: cannot allocate the descriptors for the rx ring")}; + goto err_rx_ring_alloc; + } + + ${Log::info("adapter_init_rx: rx descriptors allocated")}; + + /* + * Allocate the skbuffs, map them for DMA, and write their address + * in the corresponding descriptor. + */ + for (i = 0; i != ${config.rx_ring_size}; ++i) + { + // XXX #46: ${Socket::SKBuff.ref} skbuff = ${rtx_ether_ctx.net_device.alloc_rx_skbuff(config.rx_buffer_len)}; + ${Socket::AbstractSKBuff.ref} k_sk_buff = (${Socket::AbstractSKBuff.ref})netdev_alloc_skb( + ${rtx_ether_ctx.net_device.k_net_dev}, ${config.rx_buffer_len} + ); + if (!k_sk_buff) + { + ${Log::info("adapter_init_rx: cannot allocate a skbuff for the rx ring")}; + goto err_skbuffs_alloc; + } + ${Socket::SKBuff.ref} skbuff = &hw_ctx->rx_ring.skbuffs[i]; + // XXX breaks rtxGen: ${local.skbuff.init(local.k_sk_buff)}; + skbuff->skbuff = k_sk_buff; + skbuff->dma_handle = 0; + // XXX #46: ${local.skbuff.map_from(rtx_ether_ctx.device)}; + if (rtx_socket_skbuff_map(${local.skbuff}, ${rtx_ether_ctx.device}, RTX_DMA_FROM_DEVICE)) + { + ${Log::info("adapter_init_rx: cannot dma-map a skbuff for the rx ring")}; + goto err_skbuffs_map; + } + hw_ctx->rx_ring.base[i].buff_addr = cpu_to_le64(${local.skbuff.sk_buff}); + } + + ${Log::info("adapter_init_rx: skbuffs allocated")}; + + /* 5. Save the emplacement and the size of the ring in RDBA/RDLEN */ + rtx_e1000_register_write32(hw_ctx, E1000_RDBAL, hw_ctx->rx_ring.dma_base & 0xffffffff); + rtx_e1000_register_write32(hw_ctx, E1000_RDBAH, hw_ctx->rx_ring.dma_base >> 32); + rtx_e1000_register_write32(hw_ctx, E1000_RDLEN, hw_ctx->rx_ring.size); + + /* 6. Setup RDH/RDT */ + rtx_e1000_register_write32(hw_ctx, E1000_RDH, 0); + rtx_e1000_register_write32(hw_ctx, E1000_RDT, ${config.rx_ring_size} - 1); + + /* 7. Configure the buffer size, */ + rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_BSIZE_${config.rx_buffer_len}); + + /* 8. Enable the receiver */ + rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_EN); + + ${Log::info("adapter_init_rx: receive registers configured and receiver 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 init_rx_ok; + + err_skbuffs_alloc: + while (i--) + { + dma_unmap_single( + ${rtx_ether_ctx.device}, + hw_ctx->rx_ring.skbuffs[i].dma_handle, + ${config.rx_buffer_len}, + DMA_FROM_DEVICE); + err_skbuffs_map: + /* XXX leaking cast: */ + dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff); + } + + dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx->rx_ring.size, + hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base); + err_rx_ring_alloc: + /* + * XXX: Likewise, if there is something else to rollback in the + * enclosing function, this won't be done. + */ + return -ENOMEM; + + init_rx_ok: (void)0; /* NOP, to make this a valid label. */ + } + } + map { + size: ((${self}).size); + dma_base: ((${self}).dma_base); } } @@ -208,7 +363,62 @@ } } - method clean() + chunk Ethernet::adapter_init_tx(Ethernet::Device rtx_ether_ctx) + { + { + ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; + + /* + * 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. + */ + + /* 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( + ${rtx_ether_ctx.device}, + hw_ctx->tx_ring.size, + &hw_ctx->tx_ring.dma_base, + GFP_KERNEL); + if (!hw_ctx->rx_ring.base) + { + ${Log::info("adapter_init_tx: cannot allocate the descriptors for the tx ring")}; + /* + * XXX: If there is something else to rollback in the enclosing + * function, this won't be done. + */ + return -ENOMEM; + } + + ${Log::info("adapter_init_tx: tx descriptors allocated")}; + + /* 2. Save the emplacement and the size of the ring in TDBA/TDLEN */ + rtx_e1000_register_write32(hw_ctx, E1000_TDBAL, hw_ctx->tx_ring.dma_base & 0xffffffff); + rtx_e1000_register_write32(hw_ctx, E1000_TDBAH, 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); + hw_ctx->tx_ring.head = 0; + hw_ctx->tx_ring.tail = 0; + + /* 4. Set TCTL.PSP and enable the transmitter */ + rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_EN); + + ${Log::info("adapter_init_tx: transmit registers configured and transmitter enabled")}; + } + } + + method clean() { rtx_e1000_tx_ring_clean(${self}); } @@ -247,9 +457,8 @@ { int bars; unsigned char /* __iomem */ *ioaddr; - - ${e1000::RxRing} rx_ring; - ${e1000::TxRing} tx_ring; + ${e1000::RxRing.scalar} rx_ring; + ${e1000::TxRing.scalar} tx_ring; } chunk Ethernet::HardwareContext() @@ -309,10 +518,53 @@ } } + chunk Ethernet::adapter_setup(Ethernet::Device rtx_ether_ctx) + { + { + ${e1000::Context.ref} hw_ctx = &${rtx_ether_ctx}->hw_ctx; + + /* + * "General Configuration" (section 14.3): + * + * - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection & + * negociation; + * - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation; + * - CTRL.PHY_RST: Unset it; + * - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal); + * - CTRL.VME: Make sure it's not set to disable VLAN support; + * - Set the control flow registers to 0; + * - Finally, initialize all the statistic registers from + * E1000_CRCERRS to E1000_TSCTFC. + */ + rtx_e1000_register_set32(hw_ctx, E1000_CTRL, + E1000_CMD_ASDE | + E1000_CMD_SLU); + rtx_e1000_register_unset32(hw_ctx, E1000_CTRL, + E1000_CMD_LRST | + E1000_CMD_FRCSPD | + E1000_CMD_PHY_RST | + E1000_CMD_ILOS | + E1000_CMD_VME); + rtx_e1000_register_write32(hw_ctx, E1000_FCAH, 0); + rtx_e1000_register_write32(hw_ctx, E1000_FCAL, 0); + rtx_e1000_register_write32(hw_ctx, E1000_FCT, 0); + rtx_e1000_register_write32(hw_ctx, E1000_FCTTV, 0); + /* + * XXX: Using int i clashes with another int i from the + * "parent" chunk: + */ + for (int j = 0; j != 64; ++j) + rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + j * 4, 0); + + ${Log::info("adapter_setup: general configuration done")}; + } + } + map { + rx_ring: ((${self})->rx_ring); + //tx_ring: ((${self})->tx_ring); } - } template type e1000::Register() @@ -615,269 +867,6 @@ } } - /* TODO: refactor - * - * Split into two method methods: - * - e1000::RxRing::init_rx() - * - e1000::TxRing::init_tx() - * - * Also it should use the new methods in Socket::SKbuff. - */ - template sequence set_up_device(Ethernet::Device rtx_ether_ctx) - { - chunk ::CALL() - { - /* - * This part is documented in the Intel Gigabit Ethernet Controller - * Software Developper manual. (You can find it in the doc/hardware - * directory). - * - * Since this part is actually completely device specific it should - * not be written here. (but in the front-end). - */ - - /* - * shortcut hw_ctx... maybe we should directly take an - * e1000::Context? (but we would need to make it point back to - * the struct net_device) - */ - ${e1000::Context.ref} hw_ctx; - hw_ctx = &${rtx_ether_ctx}->hw_ctx; - - /* - * "General Configuration" (section 14.3): - * - * - CTRL.ASDE/CTRL.SLU: Let the PHY handle the speed detection & - * negociation; - * - CTRL.LRST/FRCSPD: Unset them to initiate the auto-negociation; - * - CTRL.PHY_RST: Unset it; - * - CTRL.ILOS: Unset it (ILOS is Invert Loss Of Signal); - * - CTRL.VME: Make sure it's not set to disable VLAN support; - * - Set the control flow registers to 0; - * - Finally, initialize all the statistic registers from - * E1000_CRCERRS to E1000_TSCTFC. - */ - - int i; - - rtx_e1000_register_set32(hw_ctx, E1000_CTRL, - E1000_CMD_ASDE | - E1000_CMD_SLU); - rtx_e1000_register_unset32(hw_ctx, E1000_CTRL, - E1000_CMD_LRST | - E1000_CMD_FRCSPD | - E1000_CMD_PHY_RST | - E1000_CMD_ILOS | - E1000_CMD_VME); - rtx_e1000_register_write32(hw_ctx, E1000_FCAH, 0); - rtx_e1000_register_write32(hw_ctx, E1000_FCAL, 0); - rtx_e1000_register_write32(hw_ctx, E1000_FCT, 0); - rtx_e1000_register_write32(hw_ctx, E1000_FCTTV, 0); - for (i = 0; i != 64; ++i) - rtx_e1000_register_write32(hw_ctx, E1000_CRCERRS + i * 4, 0); - - { - ${Log::info("setup_device: general configuration done")}; - } - - /* - * Receive initialization (section 14.4): - * - * 1. Program the receive address, in RAL/RAH; - * 2. Initialize the Multicast Table Array; - * 3. Program the interrupt mask register (done in - * e1000::activate_device_interruption); - * 4. Allocate the receive descriptor ring and map it to make it - * accessible by the device; - * 5. Write the start address of the ring in RDBAL/RDBAH and set - * RDLEN (Receive Descriptor Length) to the size of the ring; - * 6. Set the RDH/RDT (Receive Descriptor Head/Tail) indexes to the - * beginning and end of the ring; - * 7. Make sure that RCTL.BSIZE and .BSEX are at 0 to configure the - * receive buffer size to 2048 bytes (e1000::rx_buffer_len). - * 8. Set RCTL.EN to enable the receiver. - * - * The ugly casts here are caused by the lack of CNorm unstrict. - */ - - /* 1. Program the receive address */ - - /* (We should use uint{32,16}_t but CNorm doesn't know them yet) */ - rtx_e1000_register_write32(hw_ctx, E1000_RAL, - *(unsigned int *)(${rtx_ether_ctx.dev_addr})); - /* - * The 16 upper bits of RAH also store the AS bits (which should be - * 0) and the AV bit (should be 1 to set the address as valid). - */ - rtx_e1000_register_write32(hw_ctx, E1000_RAH, - *(unsigned short *)(&${rtx_ether_ctx.dev_addr}[4])); - rtx_e1000_register_set32(hw_ctx, E1000_RAH, E1000_RAH_AV); - - { - ${Log::info("setup_device: receive address programmed")}; - } - - /* 2. Initialize the MTA */ - - for (i = 0; i != 128; ++i) - rtx_e1000_register_write32(hw_ctx, E1000_MTA + i * 4, 0); - - { - ${Log::info("setup_device: MTA init done")}; - } - - /* 4. Setup the receive descriptor ring */ - - /* Allocate the descriptors */ - hw_ctx->rx_ring.size = ${config.rx_ring_size} * sizeof(*hw_ctx->rx_ring.base); - hw_ctx->rx_ring.size = ALIGN(hw_ctx->rx_ring.size, 4096); - hw_ctx->rx_ring.base = dma_alloc_coherent( - ${rtx_ether_ctx.device}, - hw_ctx->rx_ring.size, - &hw_ctx->rx_ring.dma_base, - GFP_KERNEL); - if (!hw_ctx->rx_ring.base) - { - ${Log::info("cannot allocate the descriptors for the rx ring")}; - goto err_rx_ring_alloc; - } - - { - ${Log::info("setup_device: rx descriptors allocated")}; - } - - /* - * Allocate the skbuffs, map them for DMA, and write their address - * in the corresponding descriptor. - */ - for (i = 0; i != ${config.rx_ring_size}; ++i) - { - hw_ctx->rx_ring.skbuffs[i].skbuff = (${Socket::AbstractSKBuff}*)netdev_alloc_skb( - ${rtx_ether_ctx.net_device.k_net_dev}, /* XXX: .k_net_dev isn't expanded here */ - ${config.rx_buffer_len}); - if (!hw_ctx->rx_ring.skbuffs[i].skbuff) - { - ${Log::info("cannot allocate a skbuff for the rx ring")}; - goto err_skbuffs_alloc; - } - hw_ctx->rx_ring.skbuffs[i].dma_handle = dma_map_single( - ${rtx_ether_ctx.device}, - (struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff, /* XXX leaking cast */ - ${config.rx_buffer_len}, - DMA_FROM_DEVICE); - int dma_error = dma_mapping_error(${rtx_ether_ctx.device}, - hw_ctx->rx_ring.skbuffs[i].dma_handle); - if (dma_error) - { - ${Log::info("cannot dma-map a skbuff for the rx ring")}; - goto err_skbuffs_map; - } - hw_ctx->rx_ring.base[i].buff_addr = cpu_to_le64( - hw_ctx->rx_ring.skbuffs[i].skbuff); - } - - ${Log::info("setup_device: skbuffs allocated")}; - - /* 5. Save the emplacement and the size of the ring in RDBA/RDLEN */ - rtx_e1000_register_write32(hw_ctx, E1000_RDBAL, hw_ctx->rx_ring.dma_base & 0xffffffff); - rtx_e1000_register_write32(hw_ctx, E1000_RDBAH, hw_ctx->rx_ring.dma_base >> 32); - rtx_e1000_register_write32(hw_ctx, E1000_RDLEN, hw_ctx->rx_ring.size); - - /* 6. Setup RDH/RDT */ - rtx_e1000_register_write32(hw_ctx, E1000_RDH, 0); - rtx_e1000_register_write32(hw_ctx, E1000_RDT, ${config.rx_ring_size} - 1); - - /* 7. Configure the buffer size, */ - rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_BSIZE_${config.rx_buffer_len}); - - /* 8. Enable the receiver */ - rtx_e1000_register_set32(hw_ctx, E1000_RCTL, E1000_RCTL_EN); - - ${Log::info("setup_device: receive registers configured and receiver enabled")}; - - /* - * 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( - ${rtx_ether_ctx.device}, - hw_ctx->tx_ring.size, - &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, hw_ctx->tx_ring.dma_base & 0xffffffff); - rtx_e1000_register_write32(hw_ctx, E1000_TDBAH, 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); - hw_ctx->tx_ring.head = 0; - hw_ctx->tx_ring.tail = 0; - - /* 4. Set TCTL.PSP and enable the transmitter */ - rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_EN); - - ${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": - */ - err_skbuffs_alloc: - while (i--) - { - dma_unmap_single( - ${rtx_ether_ctx.device}, - hw_ctx->rx_ring.skbuffs[i].dma_handle, - ${config.rx_buffer_len}, - DMA_FROM_DEVICE); - err_skbuffs_map: - /* XXX leaking cast: */ - dev_kfree_skb((struct sk_buff *)hw_ctx->rx_ring.skbuffs[i].skbuff); - } - - dma_free_coherent(${rtx_ether_ctx.device}, hw_ctx->rx_ring.size, - hw_ctx->rx_ring.base, hw_ctx->rx_ring.dma_base); - err_rx_ring_alloc: - return -ENOMEM; - - ok: - } - } - /* TODO: * * Refactor into two methods (one in RxRing and one in TxRing) and make use 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 @@ -1,23 +1,10 @@ -interface e1000 : Socket, Ethernet, PCI, LKM, Builtin +interface e1000 : Socket, Ethernet, DMA, PCI, LKM, Builtin { required variable Builtin::number rx_ring_size; required variable Builtin::number tx_ring_size; required variable Builtin::number rx_buffer_len; required variable Builtin::number tx_max_data_per_desc; - provided type Context - { - chunk Ethernet::HardwareContext(); - decl data_types(); - - /* Callbacks/Hooks which should probably be in the front-end: */ - chunk Ethernet::adapter_init_context(Ethernet::Device, - Builtin::number, - Builtin::symbol); - chunk Ethernet::adapter_reset(Ethernet::Device); - chunk Ethernet::adapter_load_mac_address(Ethernet::Device); - } - provided type RxDescriptor { chunk LKM::includes(); @@ -35,6 +22,32 @@ { decl data_types(); method init(); + + /* XXX: Callback that should be in the front-end: */ + chunk Ethernet::adapter_init_rx(Ethernet::Device); + + attribute DMA::DMAHandle.scalar dma_base; + attribute Builtin::number.scalar size; + } + + provided type Context + { + chunk Ethernet::HardwareContext(); + decl data_types(); + + /* XXX: + * These callbacks/Hooks which should probably be in the front-end. + * Also, I'm not too happy about the names, it's difficult to make + * the difference between the probe and open parts. + */ + chunk Ethernet::adapter_init_context(Ethernet::Device, + Builtin::number, + Builtin::symbol); + chunk Ethernet::adapter_reset(Ethernet::Device); + chunk Ethernet::adapter_load_mac_address(Ethernet::Device); + chunk Ethernet::adapter_setup(Ethernet::Device); + + attribute RxRing.scalar rx_ring; } provided type TxRing @@ -44,6 +57,9 @@ decl data_types(); method init(); + /* XXX: Callback that should be in the front-end: */ + chunk Ethernet::adapter_init_tx(Ethernet::Device); + /* Clean the ring (i.e: move the head closer to the tail): */ method clean(); /* Return the number of clean descriptors left in the ring: */ diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt --- a/rathaxes/samples/e1000/ethernet.blt +++ b/rathaxes/samples/e1000/ethernet.blt @@ -170,6 +170,9 @@ ${Log::info("Cannot register the interrupt handler")}; return error; } + ${pointcut Ethernet::adapter_setup(local.rtx_ether_ctx)}; + ${pointcut Ethernet::adapter_init_rx(local.rtx_ether_ctx)}; + ${pointcut Ethernet::adapter_init_tx(local.rtx_ether_ctx)}; ${pointcut ::IMPLEMENTATION(local.rtx_ether_ctx)}; return 0; diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti --- a/rathaxes/samples/e1000/ethernet.rti +++ b/rathaxes/samples/e1000/ethernet.rti @@ -52,6 +52,15 @@ provided chunk LKM::includes(); provided chunk LKM::prototypes(); provided chunk LKM::code(); + + /* + * For e1000, this part is documented in the Intel Gigabit Ethernet + * Controller Software Developper manual. (You can find it in the + * doc/hardware directory). + */ + provided pointcut Ethernet::adapter_setup(Ethernet::Device); + provided pointcut Ethernet::adapter_init_rx(Ethernet::Device); + provided pointcut Ethernet::adapter_init_tx(Ethernet::Device); } required sequence send(Ethernet::Device, Socket::AbstractSKBuff) 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 @@ -4,10 +4,6 @@ { Log::info("opening the device"); - - e1000::set_up_device(dev); - Log::info("device activated"); - e1000::activate_device_interruption(dev); Log::info("interruption enabled"); diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti --- a/rathaxes/samples/e1000/socket.rti +++ b/rathaxes/samples/e1000/socket.rti @@ -15,6 +15,10 @@ decl data_types(); method init(Socket::AbstractSKBuff); method dump_infos(); + /* + * map_to and map_from return a non-zero value on failure (which + * doesn't correspond to an errno value): + */ method map_to(Device::AbstractDevice); method map_from(Device::AbstractDevice); method unmap_to_and_free(Device::AbstractDevice);