2525#include < malloc.h>
2626// loosely based on OSdev article http://wiki.osdev.org/Intel_Ethernet_i217
2727
28+ static int deferred_event = 0 ;
29+ static std::vector<e1000 *> deferred_devices;
30+
2831e1000 ::e1000 (hw::PCI_Device& d) :
2932 Link (Link_protocol{{this , &e1000 ::transmit}, mac ()}, bufstore_),
3033 m_pcidev(d), bufstore_{1024 , 2048 }
@@ -40,6 +43,11 @@ e1000::e1000(hw::PCI_Device& d) :
4043 __arch_enable_legacy_irq (this ->m_irq );
4144 INFO2 (" Subscribed on IRQ %u" , this ->m_irq );
4245
46+ if (deferred_event == 0 )
47+ {
48+ deferred_event = Events::get ().subscribe (&e1000 ::do_deferred_xmit);
49+ }
50+
4351 // shared-memory & I/O address
4452 this ->shm_base = d.get_bar (0 );
4553 this ->io_base = d.iobase ();
@@ -208,6 +216,8 @@ void e1000::event_handler()
208216
209217void e1000::recv_handler ()
210218{
219+ uint16_t old_idx = 0xffff ;
220+
211221 while (rx.desc [rx.current ].status & 1 )
212222 {
213223 auto & tk = rx.desc [rx.current ];
@@ -221,11 +231,11 @@ void e1000::recv_handler()
221231 tk.addr = (uint64_t ) this ->new_rx_packet ();
222232 tk.status = 0 ;
223233 // go to next index
224- uint16_t old_idx = rx.current ;
234+ old_idx = rx.current ;
225235 rx.current = (rx.current + 1 ) % NUM_RX_DESC;
226- write_cmd (REG_RXDESCTAIL, old_idx);
227236 }
228-
237+ if (old_idx != 0xffff )
238+ write_cmd (REG_RXDESCTAIL, old_idx);
229239}
230240
231241void e1000::transmit (net::Packet_ptr pckt)
@@ -265,12 +275,28 @@ void e1000::transmit_data(uint8_t* data, uint16_t length)
265275 tk.status = 0 ;
266276
267277 tx.current = (tx.current + 1 ) % NUM_TX_DESC;
278+ if (tx.deferred == false )
279+ {
280+ tx.deferred = true ;
281+ deferred_devices.push_back (this );
282+ Events::get ().trigger_event (deferred_event);
283+ }
284+ }
285+ void e1000::xmit_kick ()
286+ {
268287 write_cmd (REG_TXDESCTAIL, tx.current );
288+ tx.deferred = false ;
289+ }
290+ void e1000::do_deferred_xmit ()
291+ {
292+ for (auto & dev : deferred_devices)
293+ dev->xmit_kick ();
294+ deferred_devices.clear ();
269295}
270296
271297void e1000::flush ()
272298{
273-
299+ this -> transmit ( std::move (sendq));
274300}
275301void e1000::poll ()
276302{
@@ -283,7 +309,7 @@ void e1000::deactivate()
283309}
284310void e1000::move_to_this_cpu ()
285311{
286-
312+ // TODO: implement me
287313}
288314
289315#include < kernel/pci_manager.hpp>
@@ -294,5 +320,6 @@ static void register_func()
294320 PCI_manager::register_nic (PCI::VENDOR_INTEL, 0x100E , &e1000 ::new_instance);
295321 PCI_manager::register_nic (PCI::VENDOR_INTEL, 0x100F , &e1000 ::new_instance);
296322 PCI_manager::register_nic (PCI::VENDOR_INTEL, 0x153A , &e1000 ::new_instance);
323+ PCI_manager::register_nic (PCI::VENDOR_INTEL, 0x1539 , &e1000 ::new_instance);
297324 PCI_manager::register_nic (PCI::VENDOR_INTEL, 0x10EA , &e1000 ::new_instance);
298325}
0 commit comments