2021-09-21 07:55:53 +01:00
<!DOCTYPE HTML>
< html >
< head >
< meta http-equiv = "Content-Type" content = "text/html;charset=US-ASCII" >
2021-12-11 11:10:58 +00:00
< meta name = "generator" content = "ZealOS V1.07" >
2021-09-21 07:55:53 +01:00
< style type = "text/css" >
2021-10-08 07:06:11 +01:00
body {background-color:#1f1f1f;}
.cF0{color:#e3e3e3;background-color:#1f1f1f;}
.cF1{color:#4f84a6;background-color:#1f1f1f;}
.cF2{color:#73a255;background-color:#1f1f1f;}
.cF3{color:#297582;background-color:#1f1f1f;}
.cF4{color:#b34f4b;background-color:#1f1f1f;}
.cF5{color:#8a52c3;background-color:#1f1f1f;}
.cF6{color:#b7822f;background-color:#1f1f1f;}
.cF7{color:#444444;background-color:#1f1f1f;}
.cF8{color:#6d6d6d;background-color:#1f1f1f;}
.cF9{color:#94bfde;background-color:#1f1f1f;}
.cFA{color:#a1ce97;background-color:#1f1f1f;}
.cFB{color:#6db4be;background-color:#1f1f1f;}
.cFC{color:#e88e88;background-color:#1f1f1f;}
.cFD{color:#ca94e8;background-color:#1f1f1f;}
.cFE{color:#d4b475;background-color:#1f1f1f;}
.cFF{color:#1f1f1f;background-color:#1f1f1f;}
2021-09-21 07:55:53 +01:00
< / style >
< / head >
< body >
< pre style = "font-family:monospace;font-size:12pt" >
< a name = "l1" > < / a > < span class = cF2 > /*< / span > < span class = cF0 >
< a name = "l2" > < / a > < / span > < span class = cF2 > VirtIO Net driver ported from alec's Erythros.< / span > < span class = cF0 >
< a name = "l3" > < / a > < / span > < span class = cF2 > */< / span > < span class = cF0 >
< a name = "l4" > < / a >
< a name = "l5" > < / a > < / span > < span class = cF2 > //< / span > < span class = cF0 >
< a name = "l6" > < / a > < / span > < span class = cF2 > // PCI virtio I/O registers.< / span > < span class = cF0 >
< a name = "l7" > < / a > < / span > < span class = cF2 > //< / span > < span class = cF0 >
< a name = "l8" > < / a >
< a name = "l9" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_PCI_HOST_FEATURES < / span > < span class = cFE > 0< / span > < span class = cF0 > < / span > < span class = cF2 > // Features supported by the host< / span > < span class = cF0 >
< a name = "l10" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_PCI_GUEST_FEATURES < / span > < span class = cFE > 4< / span > < span class = cF0 > < / span > < span class = cF2 > // Features activated by the guest< / span > < span class = cF0 >
< a name = "l11" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_PCI_QUEUE_PFN < / span > < span class = cFE > 8< / span > < span class = cF0 > < / span > < span class = cF2 > // PFN for the currently selected queue< / span > < span class = cF0 >
< a name = "l12" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_PCI_QUEUE_SIZE < / span > < span class = cFE > 12< / span > < span class = cF0 > < / span > < span class = cF2 > // Queue size for the currently selected queue< / span > < span class = cF0 >
< a name = "l13" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_PCI_QUEUE_SEL < / span > < span class = cFE > 14< / span > < span class = cF0 > < / span > < span class = cF2 > // Queue selector< / span > < span class = cF0 >
< a name = "l14" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_PCI_QUEUE_NOTIFY < / span > < span class = cFE > 16< / span > < span class = cF0 > < / span > < span class = cF2 > // Queue notifier< / span > < span class = cF0 >
< a name = "l15" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_PCI_STATUS < / span > < span class = cFE > 18< / span > < span class = cF0 > < / span > < span class = cF2 > // Device status register< / span > < span class = cF0 >
< a name = "l16" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_PCI_ISR < / span > < span class = cFE > 19< / span > < span class = cF0 > < / span > < span class = cF2 > // Interrupt status register< / span > < span class = cF0 >
< a name = "l17" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_PCI_CONFIG < / span > < span class = cFE > 20< / span > < span class = cF0 > < / span > < span class = cF2 > // Configuration data block< / span > < span class = cF0 >
< a name = "l18" > < / a >
< a name = "l19" > < / a > < / span > < span class = cF2 > //< / span > < span class = cF0 >
< a name = "l20" > < / a > < / span > < span class = cF2 > // PCI virtio status register bits< / span > < span class = cF0 >
< a name = "l21" > < / a > < / span > < span class = cF2 > //< / span > < span class = cF0 >
< a name = "l22" > < / a >
< a name = "l23" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_CONFIG_S_ACKNOWLEDGE < / span > < span class = cFE > 1< / span > < span class = cF0 >
< a name = "l24" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_CONFIG_S_DRIVER < / span > < span class = cFE > 2< / span > < span class = cF0 >
< a name = "l25" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_CONFIG_S_DRIVER_OK < / span > < span class = cFE > 4< / span > < span class = cF0 >
< a name = "l26" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VIRTIO_CONFIG_S_FAILED < / span > < span class = cFE > 0x80< / span > < span class = cF0 >
< a name = "l27" > < / a >
< a name = "l28" > < / a > < / span > < span class = cF2 > //< / span > < span class = cF0 >
< a name = "l29" > < / a > < / span > < span class = cF2 > // Ring descriptor flags< / span > < span class = cF0 >
< a name = "l30" > < / a > < / span > < span class = cF2 > //< / span > < span class = cF0 >
< a name = "l31" > < / a >
< a name = "l32" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VRING_DESC_F_NEXT < / span > < span class = cFE > 1< / span > < span class = cF0 > < / span > < span class = cF2 > // Buffer continues via the next field< / span > < span class = cF0 >
< a name = "l33" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VRING_DESC_F_WRITE < / span > < span class = cFE > 2< / span > < span class = cF0 > < / span > < span class = cF2 > // Buffer is write-only (otherwise read-only)< / span > < span class = cF0 >
< a name = "l34" > < / a > #< / span > < span class = cF1 > define< / span > < span class = cF0 > VRING_DESC_F_INDIRECT < / span > < span class = cFE > 4< / span > < span class = cF0 > < / span > < span class = cF2 > // Buffer contains a list of buffer descriptors< / span > < span class = cF0 >
< a name = "l35" > < / a >
< a name = "l36" > < / a > < / span > < span class = cF1 > class< / span > < span class = cF0 > @virtio_queue_buf {
< a name = "l37" > < / a > < / span > < span class = cF9 > U64< / span > < span class = cF0 > address;
< a name = "l38" > < / a > < / span > < span class = cF9 > U32< / span > < span class = cF0 > length;
< a name = "l39" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > flags;
< a name = "l40" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > next;
< a name = "l41" > < / a > };
< a name = "l42" > < / a > < / span > < span class = cF1 > class< / span > < span class = cF0 > @virtio_avail {
< a name = "l43" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > flags;
< a name = "l44" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > index;
< a name = "l45" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > ring[< / span > < span class = cFE > 256< / span > < span class = cF0 > ];
< a name = "l46" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > int_index;
< a name = "l47" > < / a > };
< a name = "l48" > < / a > < / span > < span class = cF1 > class< / span > < span class = cF0 > @virtio_used_item {
< a name = "l49" > < / a > < / span > < span class = cF9 > U32< / span > < span class = cF0 > index;
< a name = "l50" > < / a > < / span > < span class = cF9 > U32< / span > < span class = cF0 > length;
< a name = "l51" > < / a > };
< a name = "l52" > < / a > < / span > < span class = cF1 > class< / span > < span class = cF0 > @virtio_used {
< a name = "l53" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > flags;
< a name = "l54" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > index;
< a name = "l55" > < / a > @virtio_used_item ring[< / span > < span class = cFE > 256< / span > < span class = cF0 > ];
< a name = "l56" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > int_index;
< a name = "l57" > < / a > };
< a name = "l58" > < / a > < / span > < span class = cF1 > class< / span > < span class = cF0 > @virtio_queue {
< a name = "l59" > < / a > @virtio_queue_buf buffers[< / span > < span class = cFE > 256< / span > < span class = cF0 > ];
< a name = "l60" > < / a > @virtio_avail available;
< a name = "l61" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > padding[< / span > < span class = cFE > 3578< / span > < span class = cF0 > ];
< a name = "l62" > < / a > @virtio_used used;
< a name = "l63" > < / a > };
< a name = "l64" > < / a >
< a name = "l65" > < / a > < / span > < span class = cF1 > class< / span > < span class = cF0 > @virtio_avail_buf {
< a name = "l66" > < / a > < / span > < span class = cF9 > U32< / span > < span class = cF0 > index;
< a name = "l67" > < / a > < / span > < span class = cF9 > U64< / span > < span class = cF0 > address;
< a name = "l68" > < / a > < / span > < span class = cF9 > U32< / span > < span class = cF0 > length;
< a name = "l69" > < / a > };
< a name = "l70" > < / a >
< a name = "l71" > < / a > < / span > < span class = cF1 > class< / span > < span class = cF0 > @virtio_buf_info {
< a name = "l72" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > *buffer;
< a name = "l73" > < / a > < / span > < span class = cF9 > U64< / span > < span class = cF0 > size;
< a name = "l74" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > flags;
< a name = "l75" > < / a >
< a name = "l76" > < / a > < / span > < span class = cF2 > // If the user wants to keep same buffer as passed in this struct, use " true" .< / span > < span class = cF0 >
< a name = "l77" > < / a > < / span > < span class = cF2 > // otherwise, the supplied buffer will be copied in the queues' buffer< / span > < span class = cF0 >
< a name = "l78" > < / a > < / span > < span class = cF1 > Bool< / span > < span class = cF0 > copy;
< a name = "l79" > < / a > };
< a name = "l80" > < / a >
< a name = "l81" > < / a > < / span > < span class = cF6 > " virtio " < / span > < span class = cF0 > ;
< a name = "l82" > < / a >
< a name = "l83" > < / a > < / span > < span class = cF2 > //< / span > < span class = cF0 >
< a name = "l84" > < / a > < / span > < span class = cF2 > // PCI VirtIO Net< / span > < span class = cF0 >
< a name = "l85" > < / a > < / span > < span class = cF2 > //< / span > < span class = cF0 >
< a name = "l86" > < / a >
< a name = "l87" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > rx_buffer_ptr = < / span > < span class = cFE > 0< / span > < span class = cF0 > ;
< a name = "l88" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > tx_buffer_ptr = < / span > < span class = cFE > 0< / span > < span class = cF0 > ;
< a name = "l89" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > rx_buffer_count = < / span > < span class = cFE > 255< / span > < span class = cF0 > ;
< a name = "l90" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > tx_buffer_count = < / span > < span class = cFE > 256< / span > < span class = cF0 > ;
< a name = "l91" > < / a > < / span > < span class = cF9 > U64< / span > < span class = cF0 > rx_buffers = < / span > < span class = cF5 > MAlloc< / span > < span class = cF0 > (ETHERNET_FRAME_SIZE * rx_buffer_count);
< a name = "l92" > < / a > < / span > < span class = cF9 > U64< / span > < span class = cF0 > tx_buffers = < / span > < span class = cF5 > MAlloc< / span > < span class = cF0 > (ETHERNET_FRAME_SIZE * tx_buffer_count);
< a name = "l93" > < / a >
< a name = "l94" > < / a > < / span > < span class = cF1 > class< / span > < span class = cF0 > @virtio_net {
< a name = "l95" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > port;
< a name = "l96" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > mac[< / span > < span class = cFE > 6< / span > < span class = cF0 > ];
< a name = "l97" > < / a > @virtio_queue *rq;
< a name = "l98" > < / a > @virtio_queue *sq;
< a name = "l99" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > rq_size;
< a name = "l100" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > rq_index;
< a name = "l101" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > sq_size;
< a name = "l102" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > sq_index;
< a name = "l103" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > rx_packets;
< a name = "l104" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > rx_bytes;
< a name = "l105" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > tx_packets;
< a name = "l106" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > tx_bytes;
< a name = "l107" > < / a > };
< a name = "l108" > < / a >
< a name = "l109" > < / a > < / span > < span class = cF1 > class< / span > < span class = cF0 > @virtio_net_header {
< a name = "l110" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > flags;
< a name = "l111" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > gso_type;
< a name = "l112" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > header_length;
< a name = "l113" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > gso_size;
< a name = "l114" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > checksum_start;
< a name = "l115" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > checksum_offset;
< a name = "l116" > < / a > };
< a name = "l117" > < / a >
< a name = "l118" > < / a > @virtio_net VirtioNet;
< a name = "l119" > < / a > < / span > < span class = cF5 > MemSet< / span > < span class = cF0 > (& VirtioNet, < / span > < span class = cFE > 0< / span > < span class = cF0 > , < / span > < span class = cF1 > sizeof< / span > < span class = cF7 > (< / span > < span class = cF0 > @virtio_net< / span > < span class = cF7 > )< / span > < span class = cF0 > );
< a name = "l120" > < / a >
< a name = "l121" > < / a > @virtio_net_header *def_pkt_hdr = < / span > < span class = cF5 > CAlloc< / span > < span class = cF0 > (< / span > < span class = cF1 > sizeof< / span > < span class = cF7 > (< / span > < span class = cF0 > @virtio_net_header< / span > < span class = cF7 > )< / span > < span class = cF0 > );
< a name = "l122" > < / a >
< a name = "l123" > < / a > < / span > < span class = cF1 > static< / span > < span class = cF0 > < / span > < span class = cF9 > I64< / span > < span class = cF0 > @virtio_net_alloc_tx_packet(< / span > < span class = cF1 > U8< / span > < span class = cF0 > **buffer_out, < / span > < span class = cF9 > I64< / span > < span class = cF0 > length< / span > < span class = cF2 > /*, I64 flags*/< / span > < span class = cF0 > ) {
< a name = "l124" > < / a > < / span > < span class = cF2 > // FIXME: validate length< / span > < span class = cF0 >
< a name = "l125" > < / a > < / span > < span class = cF2 > // flags = flags;< / span > < span class = cF0 >
< a name = "l126" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > sq_idx = VirtioNet.sq-> available.index % < / span > < span class = cFE > 256< / span > < span class = cF0 > ;
< a name = "l127" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > sq_idx2 = sq_idx % < / span > < span class = cFE > 128< / span > < span class = cF0 > ;
< a name = "l128" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > index = tx_buffer_ptr;
< a name = "l129" > < / a > tx_buffer_ptr = (tx_buffer_ptr + < / span > < span class = cFE > 1< / span > < span class = cF0 > ) & (tx_buffer_count - < / span > < span class = cFE > 1< / span > < span class = cF0 > );
< a name = "l130" > < / a > *buffer_out = tx_buffers + index * ETHERNET_FRAME_SIZE;
< a name = "l131" > < / a >
< a name = "l132" > < / a > VirtioNet.sq-> buffers[sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ].address = def_pkt_hdr;
< a name = "l133" > < / a > VirtioNet.sq-> buffers[sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ].length = < / span > < span class = cF1 > sizeof< / span > < span class = cF0 > (@virtio_net_header);
< a name = "l134" > < / a > VirtioNet.sq-> buffers[sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ].flags = VRING_DESC_F_NEXT;
< a name = "l135" > < / a > VirtioNet.sq-> buffers[sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ].next = (sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ;
< a name = "l136" > < / a > VirtioNet.sq-> buffers[(sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ].address = *buffer_out;
< a name = "l137" > < / a > VirtioNet.sq-> buffers[(sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ].length = length;
< a name = "l138" > < / a > VirtioNet.sq-> buffers[(sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ].flags = < / span > < span class = cF3 > NULL< / span > < span class = cF0 > ;
< a name = "l139" > < / a > VirtioNet.sq-> buffers[(sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ].next = < / span > < span class = cFE > 0< / span > < span class = cF0 > ;
< a name = "l140" > < / a > VirtioNet.sq-> available.ring[sq_idx] = sq_idx2 * < / span > < span class = cFE > 2< / span > < span class = cF0 > ;
< a name = "l141" > < / a >
< a name = "l142" > < / a > VirtioNet.sq-> available.index++;
< a name = "l143" > < / a >
< a name = "l144" > < / a > VirtioNet.tx_packets++;
< a name = "l145" > < / a > VirtioNet.tx_bytes += length;
< a name = "l146" > < / a >
< a name = "l147" > < / a > < / span > < span class = cF1 > return< / span > < span class = cF0 > index;
< a name = "l148" > < / a > }
< a name = "l149" > < / a >
< a name = "l150" > < / a > < / span > < span class = cF1 > static< / span > < span class = cF0 > < / span > < span class = cF9 > I64< / span > < span class = cF0 > @virtio_net_finish_tx_packet(< / span > < span class = cF9 > I64< / span > < span class = cF0 > ) {
< a name = "l151" > < / a > < / span > < span class = cF5 > OutU16< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_QUEUE_NOTIFY, < / span > < span class = cFE > 1< / span > < span class = cF0 > );
< a name = "l152" > < / a > < / span > < span class = cF1 > return< / span > < span class = cF0 > < / span > < span class = cFE > 0< / span > < span class = cF0 > ;
< a name = "l153" > < / a > }
< a name = "l154" > < / a >
< a name = "l155" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > *loopback_frame = < / span > < span class = cF5 > MAlloc< / span > < span class = cF0 > (ETHERNET_FRAME_SIZE);
< a name = "l156" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > loopback_length = < / span > < span class = cFE > 0< / span > < span class = cF0 > ;
< a name = "l157" > < / a >
< a name = "l158" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > EthernetFrameAllocate(< / span > < span class = cF1 > U8< / span > < span class = cF0 > **buffer_out, < / span > < span class = cF1 > U8< / span > < span class = cF0 > *src_addr, < / span > < span class = cF1 > U8< / span > < span class = cF0 > *dst_addr,
< a name = "l159" > < / a > < / span > < span class = cF9 > U16< / span > < span class = cF0 > ethertype, < / span > < span class = cF9 > I64< / span > < span class = cF0 > length< / span > < span class = cF2 > /*, I64 flags*/< / span > < span class = cF0 > ) {
< a name = "l160" > < / a >
< a name = "l161" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > *frame;
< a name = "l162" > < / a >
< a name = "l163" > < / a > < / span > < span class = cF2 > // APAD_XMT doesn't seem to work in VirtualBox, so we have to pad the frame< / span > < span class = cF0 >
< a name = "l164" > < / a > < / span > < span class = cF2 > // ourselves< / span > < span class = cF0 >
< a name = "l165" > < / a > < / span > < span class = cF1 > if< / span > < span class = cF0 > (length < < / span > < span class = cFE > 46< / span > < span class = cF0 > )
< a name = "l166" > < / a > length = < / span > < span class = cFE > 46< / span > < span class = cF0 > ;
< a name = "l167" > < / a >
< a name = "l168" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > index;
< a name = "l169" > < / a >
< a name = "l170" > < / a > < / span > < span class = cF1 > if< / span > < span class = cF0 > (!< / span > < span class = cF5 > MemCompare< / span > < span class = cF7 > (< / span > < span class = cF0 > dst_addr, & VirtioNet.mac, < / span > < span class = cFE > 6< / span > < span class = cF7 > )< / span > < span class = cF0 > ) < / span > < span class = cF7 > {< / span > < span class = cF0 >
< a name = "l171" > < / a > frame = loopback_frame;
< a name = "l172" > < / a > loopback_length = length;
< a name = "l173" > < / a > index = < / span > < span class = cF3 > I64_MAX< / span > < span class = cF0 > ;
< a name = "l174" > < / a > < / span > < span class = cF7 > }< / span > < span class = cF0 > < / span > < span class = cF1 > else< / span > < span class = cF0 > < / span > < span class = cF7 > {< / span > < span class = cF0 >
< a name = "l175" > < / a > index = @virtio_net_alloc_tx_packet(& frame, < / span > < span class = cFE > 14< / span > < span class = cF0 > + length< / span > < span class = cF2 > /*, flags*/< / span > < span class = cF0 > );
< a name = "l176" > < / a > < / span > < span class = cF1 > if< / span > < span class = cF0 > (index < < / span > < span class = cFE > 0< / span > < span class = cF0 > )
< a name = "l177" > < / a > < / span > < span class = cF1 > return< / span > < span class = cF0 > index;
< a name = "l178" > < / a > < / span > < span class = cF7 > }< / span > < span class = cF0 >
< a name = "l179" > < / a >
< a name = "l180" > < / a > < / span > < span class = cF5 > MemCopy< / span > < span class = cF0 > (frame + < / span > < span class = cFE > 0< / span > < span class = cF0 > , dst_addr, < / span > < span class = cFE > 6< / span > < span class = cF0 > );
< a name = "l181" > < / a > < / span > < span class = cF5 > MemCopy< / span > < span class = cF0 > (frame + < / span > < span class = cFE > 6< / span > < span class = cF0 > , src_addr, < / span > < span class = cFE > 6< / span > < span class = cF0 > );
< a name = "l182" > < / a > frame[< / span > < span class = cFE > 12< / span > < span class = cF0 > ] = (ethertype > > < / span > < span class = cFE > 8< / span > < span class = cF0 > );
< a name = "l183" > < / a > frame[< / span > < span class = cFE > 13< / span > < span class = cF0 > ] = (ethertype & < / span > < span class = cFE > 0xff< / span > < span class = cF0 > );
< a name = "l184" > < / a >
< a name = "l185" > < / a > *buffer_out = frame + < / span > < span class = cFE > 14< / span > < span class = cF0 > ;
< a name = "l186" > < / a > < / span > < span class = cF1 > return< / span > < span class = cF0 > index;
< a name = "l187" > < / a > }
< a name = "l188" > < / a >
< a name = "l189" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > EthernetFrameFinish(< / span > < span class = cF9 > I64< / span > < span class = cF0 > index) {
< a name = "l190" > < / a > < / span > < span class = cF1 > if< / span > < span class = cF0 > (index == < / span > < span class = cF3 > I64_MAX< / span > < span class = cF0 > & & loopback_frame & & loopback_length) < / span > < span class = cF7 > {< / span > < span class = cF0 >
< a name = "l191" > < / a > NetQueuePush(loopback_frame, loopback_length);
< a name = "l192" > < / a > loopback_length = < / span > < span class = cFE > 0< / span > < span class = cF0 > ;
< a name = "l193" > < / a > < / span > < span class = cF1 > return< / span > < span class = cF0 > < / span > < span class = cFE > 0< / span > < span class = cF0 > ;
< a name = "l194" > < / a > < / span > < span class = cF7 > }< / span > < span class = cF0 >
< a name = "l195" > < / a > < / span > < span class = cF1 > return< / span > < span class = cF0 > @virtio_net_finish_tx_packet(index);
< a name = "l196" > < / a > }
< a name = "l197" > < / a >
< a name = "l198" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > *EthernetMACGet() { < / span > < span class = cF1 > return< / span > < span class = cF0 > & VirtioNet.mac; }
< a name = "l199" > < / a >
< a name = "l200" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > @virtio_net_init() {
< a name = "l201" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > i, j;
< a name = "l202" > < / a >
< a name = "l203" > < / a > < / span > < span class = cF2 > // Scan for device< / span > < span class = cF0 >
< a name = "l204" > < / a > j = < / span > < span class = cF5 > PCIClassFind< / span > < span class = cF0 > (< / span > < span class = cFE > 0x020000< / span > < span class = cF0 > , < / span > < span class = cFE > 0< / span > < span class = cF0 > );
< a name = "l205" > < / a > < / span > < span class = cF1 > if< / span > < span class = cF0 > (j < < / span > < span class = cFE > 0< / span > < span class = cF0 > ) < / span > < span class = cF7 > {< / span > < span class = cF0 >
< a name = "l206" > < / a > < / span > < span class = cF6 > " \nVirtio-net device not found.\n" < / span > < span class = cF0 > ;
< a name = "l207" > < / a > < / span > < span class = cF1 > return< / span > < span class = cF0 > -< / span > < span class = cFE > 1< / span > < span class = cF0 > ;
< a name = "l208" > < / a > < / span > < span class = cF7 > }< / span > < span class = cF0 >
< a name = "l209" > < / a > VirtioNet.port = < / span > < span class = cF5 > PCIReadU32< / span > < span class = cF0 > (j.u8[< / span > < span class = cFE > 2< / span > < span class = cF0 > ], j.u8[< / span > < span class = cFE > 1< / span > < span class = cF0 > ], j.u8[< / span > < span class = cFE > 0< / span > < span class = cF0 > ], < / span > < span class = cFE > 0x10< / span > < span class = cF0 > ) & < / span > < span class = cFE > 0xFFFFFFFC< / span > < span class = cF0 > ;
< a name = "l210" > < / a > < / span > < span class = cF1 > for< / span > < span class = cF0 > (i = < / span > < span class = cFE > 0< / span > < span class = cF0 > ; i < < / span > < span class = cFE > 6< / span > < span class = cF0 > ; i++) < / span > < span class = cF7 > {< / span > < span class = cF0 >
< a name = "l211" > < / a > VirtioNet.mac[i] = < / span > < span class = cF5 > InU8< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_CONFIG + i);
< a name = "l212" > < / a > < / span > < span class = cF7 > }< / span > < span class = cF0 >
< a name = "l213" > < / a >
< a name = "l214" > < / a > < / span > < span class = cF2 > // Reset Device< / span > < span class = cF0 >
< a name = "l215" > < / a > < / span > < span class = cF5 > OutU8< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_STATUS, < / span > < span class = cFE > 0< / span > < span class = cF0 > );
< a name = "l216" > < / a >
< a name = "l217" > < / a > < / span > < span class = cF2 > // Found Driver< / span > < span class = cF0 >
< a name = "l218" > < / a > < / span > < span class = cF5 > OutU8< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_STATUS,
< a name = "l219" > < / a > < / span > < span class = cF5 > InU8< / span > < span class = cF7 > (< / span > < span class = cF0 > VirtioNet.port + VIRTIO_PCI_STATUS< / span > < span class = cF7 > )< / span > < span class = cF0 > | VIRTIO_CONFIG_S_ACKNOWLEDGE |
< a name = "l220" > < / a > VIRTIO_CONFIG_S_DRIVER);
< a name = "l221" > < / a >
< a name = "l222" > < / a > < / span > < span class = cF2 > // Set up receive queue< / span > < span class = cF0 >
< a name = "l223" > < / a > < / span > < span class = cF5 > OutU16< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_QUEUE_SEL, < / span > < span class = cFE > 0< / span > < span class = cF0 > );
< a name = "l224" > < / a > VirtioNet.rq_size = < / span > < span class = cF5 > InU16< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_QUEUE_SIZE); < / span > < span class = cF2 > // 256< / span > < span class = cF0 >
< a name = "l225" > < / a > VirtioNet.rq = < / span > < span class = cF5 > CAllocAligned< / span > < span class = cF0 > (< / span > < span class = cF1 > sizeof< / span > < span class = cF7 > (< / span > < span class = cF0 > @virtio_queue< / span > < span class = cF7 > )< / span > < span class = cF0 > , < / span > < span class = cFE > 4096< / span > < span class = cF0 > , < / span > < span class = cF5 > Fs< / span > < span class = cF0 > -> code_heap);
< a name = "l226" > < / a > < / span > < span class = cF5 > OutU32< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_QUEUE_PFN, VirtioNet.rq / < / span > < span class = cFE > 4096< / span > < span class = cF0 > );
< a name = "l227" > < / a >
< a name = "l228" > < / a > < / span > < span class = cF2 > // Set up send queue< / span > < span class = cF0 >
< a name = "l229" > < / a > < / span > < span class = cF5 > OutU16< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_QUEUE_SEL, < / span > < span class = cFE > 1< / span > < span class = cF0 > );
< a name = "l230" > < / a > VirtioNet.sq_size = < / span > < span class = cF5 > InU16< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_QUEUE_SIZE); < / span > < span class = cF2 > // 256< / span > < span class = cF0 >
< a name = "l231" > < / a > VirtioNet.sq = < / span > < span class = cF5 > CAllocAligned< / span > < span class = cF0 > (< / span > < span class = cF1 > sizeof< / span > < span class = cF7 > (< / span > < span class = cF0 > @virtio_queue< / span > < span class = cF7 > )< / span > < span class = cF0 > , < / span > < span class = cFE > 4096< / span > < span class = cF0 > , < / span > < span class = cF5 > Fs< / span > < span class = cF0 > -> code_heap);
< a name = "l232" > < / a > < / span > < span class = cF5 > OutU32< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_QUEUE_PFN, VirtioNet.sq / < / span > < span class = cFE > 4096< / span > < span class = cF0 > );
< a name = "l233" > < / a >
< a name = "l234" > < / a > < / span > < span class = cF1 > for< / span > < span class = cF0 > (i = < / span > < span class = cFE > 0< / span > < span class = cF0 > ; i < < / span > < span class = cFE > 128< / span > < span class = cF0 > ; i++) < / span > < span class = cF7 > {< / span > < span class = cF0 >
< a name = "l235" > < / a > VirtioNet.rq-> buffers[i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ].address = < / span > < span class = cF5 > CAlloc< / span > < span class = cF0 > (< / span > < span class = cF1 > sizeof< / span > < span class = cF7 > (< / span > < span class = cF0 > @virtio_net_header< / span > < span class = cF7 > )< / span > < span class = cF0 > );
< a name = "l236" > < / a > VirtioNet.rq-> buffers[i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ].length = < / span > < span class = cF1 > sizeof< / span > < span class = cF0 > (@virtio_net_header);
< a name = "l237" > < / a > VirtioNet.rq-> buffers[i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ].flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
< a name = "l238" > < / a > VirtioNet.rq-> buffers[i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ].next = (i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ;
< a name = "l239" > < / a > VirtioNet.rq-> buffers[(i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ].address = < / span > < span class = cF5 > CAlloc< / span > < span class = cF0 > (ETHERNET_FRAME_SIZE);
< a name = "l240" > < / a > VirtioNet.rq-> buffers[(i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ].length = ETHERNET_FRAME_SIZE;
< a name = "l241" > < / a > VirtioNet.rq-> buffers[(i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ].flags = VRING_DESC_F_WRITE;
< a name = "l242" > < / a > VirtioNet.rq-> buffers[(i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ) + < / span > < span class = cFE > 1< / span > < span class = cF0 > ].next = < / span > < span class = cFE > 0< / span > < span class = cF0 > ;
< a name = "l243" > < / a > VirtioNet.rq-> available.ring[i] = i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ;
< a name = "l244" > < / a > VirtioNet.rq-> available.ring[i + < / span > < span class = cFE > 128< / span > < span class = cF0 > ] = i * < / span > < span class = cFE > 2< / span > < span class = cF0 > ;
< a name = "l245" > < / a > < / span > < span class = cF7 > }< / span > < span class = cF0 >
< a name = "l246" > < / a > VirtioNet.rq-> available.index = < / span > < span class = cFE > 1< / span > < span class = cF0 > ;
< a name = "l247" > < / a >
< a name = "l248" > < / a > < / span > < span class = cF2 > // Init OK< / span > < span class = cF0 >
< a name = "l249" > < / a > < / span > < span class = cF5 > OutU8< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_STATUS,
< a name = "l250" > < / a > < / span > < span class = cF5 > InU8< / span > < span class = cF7 > (< / span > < span class = cF0 > VirtioNet.port + VIRTIO_PCI_STATUS< / span > < span class = cF7 > )< / span > < span class = cF0 > | VIRTIO_CONFIG_S_DRIVER_OK);
< a name = "l251" > < / a > < / span > < span class = cF5 > OutU16< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_QUEUE_NOTIFY, < / span > < span class = cFE > 0< / span > < span class = cF0 > );
< a name = "l252" > < / a > < / span > < span class = cF6 > " \x1b[33mVirtio-net device detected, MAC address " < / span > < span class = cF0 >
< a name = "l253" > < / a > < / span > < span class = cF6 > " %02x:%02x:%02x:%02x:%02x:%02x\x1b[0m\n" < / span > < span class = cF0 > ,
< a name = "l254" > < / a > VirtioNet.mac[< / span > < span class = cFE > 0< / span > < span class = cF0 > ], VirtioNet.mac[< / span > < span class = cFE > 1< / span > < span class = cF0 > ], VirtioNet.mac[< / span > < span class = cFE > 2< / span > < span class = cF0 > ], VirtioNet.mac[< / span > < span class = cFE > 3< / span > < span class = cF0 > ],
< a name = "l255" > < / a > VirtioNet.mac[< / span > < span class = cFE > 4< / span > < span class = cF0 > ], VirtioNet.mac[< / span > < span class = cFE > 5< / span > < span class = cF0 > ];
< a name = "l256" > < / a > }
< a name = "l257" > < / a >
< a name = "l258" > < / a > < / span > < span class = cF6 > " virtio-net " < / span > < span class = cF0 > ;
< a name = "l259" > < / a > @virtio_net_init;
< a name = "l260" > < / a >
< a name = "l261" > < / a > < / span > < span class = cF2 > /*< / span > < span class = cF0 >
< a name = "l262" > < / a > < / span > < span class = cF2 > U0 @virtio_net_handle_net_fifo_entry(CNetFifoEntry *e) {< / span > < span class = cF0 >
< a name = "l263" > < / a > < / span > < span class = cF2 > CEthFrame l2_frame;< / span > < span class = cF0 >
< a name = "l264" > < / a >
< a name = "l265" > < / a > < / span > < span class = cF2 > if (EthernetFrameParse(& l2_frame, e-> frame, e-> length) < 0)< / span > < span class = cF0 >
< a name = "l266" > < / a > < / span > < span class = cF2 > return;< / span > < span class = cF0 >
< a name = "l267" > < / a >
< a name = "l268" > < / a > < / span > < span class = cF2 > CL3Protocol *l3 = l3_protocols;< / span > < span class = cF0 >
< a name = "l269" > < / a >
< a name = "l270" > < / a > < / span > < span class = cF2 > while (l3) {< / span > < span class = cF0 >
< a name = "l271" > < / a > < / span > < span class = cF2 > if (l3-> ethertype == l2_frame.ethertype) {< / span > < span class = cF0 >
< a name = "l272" > < / a > < / span > < span class = cF2 > l3-> handler(& l2_frame);< / span > < span class = cF0 >
< a name = "l273" > < / a > < / span > < span class = cF2 > break;< / span > < span class = cF0 >
< a name = "l274" > < / a > < / span > < span class = cF2 > }< / span > < span class = cF0 >
< a name = "l275" > < / a > < / span > < span class = cF2 > l3 = l3-> next;< / span > < span class = cF0 >
< a name = "l276" > < / a > < / span > < span class = cF2 > }< / span > < span class = cF0 >
< a name = "l277" > < / a > < / span > < span class = cF2 > }< / span > < span class = cF0 >
< a name = "l278" > < / a > < / span > < span class = cF2 > */< / span > < span class = cF0 >
< a name = "l279" > < / a > < / span > < span class = cF1 > U0< / span > < span class = cF0 > @virtio_net_handler_task() {
< a name = "l280" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > idx_used, idx_rec;
< a name = "l281" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > i, j;
< a name = "l282" > < / a > @virtio_used_item *item;
< a name = "l283" > < / a > < / span > < span class = cF1 > U8< / span > < span class = cF0 > *buffer;
< a name = "l284" > < / a > < / span > < span class = cF9 > I64< / span > < span class = cF0 > length;
< a name = "l285" > < / a > < / span > < span class = cF1 > while< / span > < span class = cF0 > (< / span > < span class = cFE > 1< / span > < span class = cF0 > ) < / span > < span class = cF7 > {< / span > < span class = cF0 >
< a name = "l286" > < / a > idx_rec = VirtioNet.rq_index;
< a name = "l287" > < / a > idx_used = VirtioNet.rq-> used.index;
< a name = "l288" > < / a >
< a name = "l289" > < / a > < / span > < span class = cF1 > if< / span > < span class = cF0 > (idx_used < idx_rec) {
< a name = "l290" > < / a > idx_used += < / span > < span class = cFE > 0x10000< / span > < span class = cF0 > ;
< a name = "l291" > < / a > }
< a name = "l292" > < / a >
< a name = "l293" > < / a > < / span > < span class = cF1 > if< / span > < span class = cF0 > (idx_rec != idx_used & & idx_used) {
< a name = "l294" > < / a >
< a name = "l295" > < / a > j = < / span > < span class = cFE > 0< / span > < span class = cF0 > ;
< a name = "l296" > < / a > < / span > < span class = cF1 > for< / span > < span class = cF0 > (i = idx_rec; i < idx_used; i++) < / span > < span class = cF7 > {< / span > < span class = cF0 >
< a name = "l297" > < / a > item = VirtioNet.rq-> used.ring;
< a name = "l298" > < / a > buffer = VirtioNet.rq-> buffers[item[i % < / span > < span class = cFE > 256< / span > < span class = cF0 > ].index + < / span > < span class = cFE > 1< / span > < span class = cF0 > ];
< a name = "l299" > < / a > length = item[i % < / span > < span class = cFE > 256< / span > < span class = cF0 > ].length;
< a name = "l300" > < / a > NetQueuePush(buffer, length - < / span > < span class = cFE > 10< / span > < span class = cF0 > );
< a name = "l301" > < / a > j++;
< a name = "l302" > < / a > VirtioNet.rx_packets++;
< a name = "l303" > < / a > VirtioNet.rx_bytes += length - < / span > < span class = cFE > 10< / span > < span class = cF0 > ;
< a name = "l304" > < / a > < / span > < span class = cF7 > }< / span > < span class = cF0 >
< a name = "l305" > < / a > VirtioNet.rq_index = idx_used % < / span > < span class = cFE > 0x10000< / span > < span class = cF0 > ;
< a name = "l306" > < / a > VirtioNet.rq-> available.index += j;
< a name = "l307" > < / a > < / span > < span class = cF5 > OutU16< / span > < span class = cF0 > (VirtioNet.port + VIRTIO_PCI_QUEUE_NOTIFY, < / span > < span class = cFE > 0< / span > < span class = cF0 > );
< a name = "l308" > < / a > }
< a name = "l309" > < / a > CNetQueueEntry *e = NetQueuePull;
< a name = "l310" > < / a > < / span > < span class = cF1 > if< / span > < span class = cF0 > (e) {
< a name = "l311" > < / a > < / span > < span class = cF2 > // @virtio_net_handle_net_fifo_entry(e);< / span > < span class = cF0 >
< a name = "l312" > < / a > }
< a name = "l313" > < / a > < / span > < span class = cF5 > Sleep< / span > < span class = cF0 > (< / span > < span class = cFE > 30< / span > < span class = cF0 > );
< a name = "l314" > < / a > < / span > < span class = cF7 > }< / span > < span class = cF0 >
< a name = "l315" > < / a > }
< a name = "l316" > < / a >
< a name = "l317" > < / a > < / span > < span class = cF5 > Spawn< / span > < span class = cF0 > (& @virtio_net_handler_task,, < / span > < span class = cF6 > " Virtio-net" < / span > < span class = cF0 > );< / span > < / pre > < / body >
< / html >