static void inject_packet( enet_iface_t *iface, const char *packet, int len ) { enet2_ring_t *r = me->rx_ring + me->rx_tail; struct iovec vec[2]; int nvec; if( !me->running || r->psize || (nvec=prepare_iovec(r,&vec,0)) <= 0 ) return; r->psize = memcpy_tovec( vec, nvec, packet, len ); dbg_dump_packet(C_YELLOW "INJECTED_PACKET", vec, nvec ); me->rx_tail = (me->rx_tail+1) & me->rx_mask; irq_line_hi( me->irq ); }
static int osip_enet2_kick( int sel, int *params ) { struct iovec vec[2]; if( !me->running ) return 1; for( ;; ) { enet2_ring_t *r = me->tx_ring + me->tx_head; int nvec = 1; if( !r->psize ) break; vec[0].iov_len = r->psize; if( !(vec[0].iov_base=transl_mphys(r->buf)) ) goto fault; if( (r->flags & kEnet2SplitBufferFlag) ) { enet2_ring_t *r2 = me->tx_of_ring + me->tx_head; vec[1].iov_len = r2->psize; if( !(vec[1].iov_base=transl_mphys(r2->buf)) ) goto fault; nvec = 2; } dbg_dump_packet(C_RED "OUTGOING PACKET", vec, nvec ); send_packet( &me->iface, vec, nvec ); me->tx_head = (me->tx_head + 1) & me->tx_mask; r->psize = 0; } return 0; fault: printm("enet2_kick: Bad Access\n"); me->running = 0; return 1; }
static void rx_packet_handler( int fd, int events ) { char dummy; int n = 0; if( !me->running ) { while( read(fd, &dummy, sizeof(dummy)) >= 0 ) ; return; } for( ;; ) { enet2_ring_t *r = me->rx_ring + me->rx_tail; struct iovec vec[2]; int s, nvec; if( r->psize ) { /* ring full, dropping packets */ printm("rx ring full\n"); while( read(fd, &dummy, sizeof(dummy)) >=0 ) n++; break; } if( (nvec=prepare_iovec(r, &vec, IFACE.packet_pad)) <= 0 ) break; if( (s=receive_packet(&IFACE, vec, nvec)) <= 0 ) break; dbg_dump_packet(C_GREEN "INCOMING_PACKET", vec, nvec ); r->psize = s - IFACE.packet_pad; me->rx_tail = (me->rx_tail+1) & me->rx_mask; n++; } if( n && me->irq_enable ) irq_line_hi( me->irq ); }
/* * Returns true/false indicating data successfully read from hypervisor. * Used both to get packets for tty connections and to advance the state * machine during console handshaking (in which case tty = NULL and we ignore * incoming data). */ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip, struct tty_struct **hangup, struct hvsi_struct **handshake) { uint8_t *packet = hp->inbuf; int chunklen; *flip = NULL; *hangup = NULL; *handshake = NULL; chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ); if (chunklen == 0) { pr_debug("%s: 0-length read\n", __FUNCTION__); return 0; } pr_debug("%s: got %i bytes\n", __FUNCTION__, chunklen); dbg_dump_hex(hp->inbuf_end, chunklen); hp->inbuf_end += chunklen; /* handle all completed packets */ while ((packet < hp->inbuf_end) && got_packet(hp, packet)) { struct hvsi_header *header = (struct hvsi_header *)packet; if (!is_header(packet)) { printk(KERN_ERR "hvsi%i: got malformed packet\n", hp->index); /* skip bytes until we find a header or run out of data */ while ((packet < hp->inbuf_end) && (!is_header(packet))) packet++; continue; } pr_debug("%s: handling %i-byte packet\n", __FUNCTION__, len_packet(packet)); dbg_dump_packet(packet); switch (header->type) { case VS_DATA_PACKET_HEADER: if (!is_open(hp)) break; if (hp->tty == NULL) break; /* no tty buffer to put data in */ *flip = hvsi_recv_data(hp, packet); break; case VS_CONTROL_PACKET_HEADER: hvsi_recv_control(hp, packet, hangup, handshake); break; case VS_QUERY_RESPONSE_PACKET_HEADER: hvsi_recv_response(hp, packet); break; case VS_QUERY_PACKET_HEADER: hvsi_recv_query(hp, packet); break; default: printk(KERN_ERR "hvsi%i: unknown HVSI packet type 0x%x\n", hp->index, header->type); dump_packet(packet); break; } packet += len_packet(packet); if (*hangup || *handshake) { pr_debug("%s: hangup or handshake\n", __FUNCTION__); /* * we need to send the hangup now before receiving any more data. * If we get "data, hangup, data", we can't deliver the second * data before the hangup. */ break; } } compact_inbuf(hp, packet); return 1; }