Date: Sat, 12 May 2007 15:52:53 GMT From: Alexey Tarasov <taleks@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 119729 for review Message-ID: <200705121552.l4CFqrNQ070356@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=119729 Change 119729 by taleks@taleks_th on 2007/05/12 15:52:16 Added modules for working with ARP packets, updated pxe_core (function code and added MAC_ADDR member to pxe_packet structure). Now ISR and receiving cycle are separated. First is done in pxe_isr in vm86 mode (there is also stub pxe_core_isr(), that is for experiments only). Receiving cycle is started by pxe_core_recv_packets() call. Current ideas of packet receiving mechanism may be seen in pxe_arp_ip4mac() function. Affected files ... .. //depot/projects/soc2007/taleks-pxe_http/pxe_arp.c#1 add .. //depot/projects/soc2007/taleks-pxe_http/pxe_arp.h#1 add .. //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#6 edit .. //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#6 edit Differences ... ==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#6 (text+ko) ==== @@ -4,15 +4,15 @@ #include "btxv86.h" #include "pxe.h" +#include "pxe_arp.h" #include "pxe_core.h" #include "pxe_ip.h" +#include "pxe_isr.h" #include "pxe_mem.h" #include "pxe_mutex.h" /* PXE API calls here will be made in same way as in pxeboot. * the only difference - installation of isr, that was not needed in pxe.c. - * main problem is that, v86 monitors reflects interrupts, - * we need to change IDT, for correct irq and call pxe_core_isr() from it. */ /* NOTE: to think about using of this buffers */ @@ -39,6 +39,7 @@ /* NIC info */ pxe_ipaddr nic_ip = {0}; +MAC_ADDR nic_mac; /* may be init it also by zero? */ /* core packet statistics */ uint32_t packets_dropped = 0; @@ -168,6 +169,11 @@ /* 3. additional start UNDI */ + /* saving information about NIC */ + nic_ip.ip=bootplayer.yip; /* my ip */ + /* my MAC */ + pxe_memcpy(&nic_mac, bootplayer.CAddr, MAC_ADDR_LEN); + return (1); } @@ -185,31 +191,52 @@ pxe_core_call(PXENV_UNDI_GET_INFORMATION); if (undi_info->Status != 0) { - printf("pxe_isr_install: failed %x\n", undi_info->Status); + printf("pxe_core_install_isr(): failed %x\n", undi_info->Status); return; } - irq=(uint8_t)(undi_info->IntNumber); + __pxe_nic_irq=(uint16_t)(undi_info->IntNumber); #ifdef PXE_DEBUG - printf("pxe_isr_install() info:\n"); + printf("pxe_core_install_isr() info:\n"); printf("IRQ: %d\n", undi_info->IntNumber); printf("Base io: %d\n", undi_info->BaseIo); printf("MTU: %d\n", undi_info->MaxTranUnit); printf("RX buffer queue: %d\n", undi_info->RxBufCt); printf("TX buffer queue: %d\n", undi_info->TxBufCt); - printf("installing ISR\n"); #endif + +#ifndef PXE_PMBRANCH + /* main branch - ISR is handled in vm86, so installed also there + * __isr_install uses __pxe_nic_irq to determine interrupt number. + * Well, it may be simplified, cause interrupt number may be got + * in this code (as bellow int_num for PM). + * TODO: simplify pxe_isr.S code. + */ + bzero(&v86, sizeof(v86)); + + v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; + v86.addr = (VTOPSEG(__isr_install) << 16) | VTOPOFF(__isr_install); + v86.ebx = func; + v86int(); + v86.ctl = V86_FLAGS; +#else uint16_t int_num=(irq < 8) ? irq + 0x08 : irq + 0x68; caddr_t isr_addr=pxe_isr-__base; printf("setting interrupt: %d for 0x%x (0x%x, base = 0x%x)\n", int_num, pxe_isr, isr_addr, __base); + /* PMBRANCH - is subproject, which goal to use ISR in PM + * it's not main branch, so just for my own interests + * this __isr_install is syscall + */ __isr_install(isr_addr, int_num); +#endif + #ifdef PXE_DEBUG - printf("pxe_isr_install(): success\n"); + printf("pxe_core_install_isr(): success\n"); #endif } @@ -217,6 +244,19 @@ pxe_core_remove_isr() { +#ifdef PXE_PMBRANCH + /* here must be something */ +#else + + bzero(&v86, sizeof(v86)); + + v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; + v86.addr = (VTOPSEG(__isr_uninstall) << 16) | VTOPOFF(__isr_uninstall); + v86.ebx = func; + v86int(); + v86.ctl = V86_FLAGS; + +#endif } int @@ -275,32 +315,37 @@ int pxe_core_transmit(pxe_packet *pack) { + /* NOTE:all provided data must be in base segment of PXE, + * if it's not here, it must be copied here (TO IMPLEMENT) + */ t_PXENV_UNDI_TRANSMIT *undi_send = (t_PXENV_UNDI_TRANSMIT *)scratch_buffer; bzero(undi_send, sizeof(*undi_info)); - /* media address */ - uint_8_t media_addr[6] = {0,0,0,0,0,0}; - t_PXENV_UNDI_TBD tbd; tbd.ImmedLength = pack->data_size; /* packet length */ tbd.Xmit.segment = VTOPSEG(pack->data); /* immediate transmit buffer */ tbd.Xmit.offset = VTOPOFF(pack->data); - tbd.DataBlkCount = 1 ; /* one block */ - tbd.DataBlk[0].TDPtrType = 1; /* segment:offset type */ - tbd.DataBlk[0].TDRsvdByte = 0; /* reserved */ + tbd.DataBlkCount = 0 ; /* only immediate data */ + + undi_send->Protocol = pack->protocol; + undi_send->DestAddr.segment = VTOPSEG(pack->dest_mac); + undi_send->DestAddr.offset = VTOPOFF(pack->dest_mac); + undi_send->TBD.segment = VTOPSEG(&tbd); /* SEGOFF16 to xmit block data*/ + undi_send->TBD.offset = VTOPOFF(&tbd); + +/* NOTE: is it needed? we use only immediate block */ - /* NOTE: if it will work? Check params*/ +/* we've inited undi_info with zero, so two lines below are not needed */ +/* tbd.DataBlk[0].TDRsvdByte = 0; /* reserved */ +/* tbd.DataBlk[1].TDRsvdByte = 0; /* reserved */ tbd.DataBlk[0].TDDataLen=tbd.ImmedLength; /* size of packet*/ + tbd.DataBlk[0].TDPtrType = 1; /* segment:offset type */ tbd.DataBlk[0].TDDataPtr.segment = VTOPSEG(pack->data);; tbd.DataBlk[0].TDDataPtr.offset = VTOPOFF(pack->data);; - undi_send->Protocol = P_IP; - undi_send->DestAddr.segment = VTOPSEG(media_addr); - undi_send->DestAddr.offset = VTOPOFF(media_addr); - - pxe_core_call(PXENV_UNDI_GET_INFORMATION); + pxe_core_call(PXENV_UNDI_TRANSMIT_PACKET); if (undi_send->Status != 0) { printf("pxe_core_transmit(): failed %x\n", undi_info->Status); @@ -414,32 +459,48 @@ return (1); } +/* NOTE: now it's handled in real mode ISR, look pxe_isr.S */ void pxe_core_isr() { + + if (!pxe_core_is_ours()) { + return; /* not ours interrupt, handling is over */ + } +} + +/* + * recieves one packet, if there is any waiting in receiving queue. + * in: + * none + * out: + * 0 - there is no packets in receiving queue, or it's not interesting for us. + * positive - there were packets in queue and some protocol handler was interested in it. + */ +int +pxe_core_recv_packets() +{ + /* - * NOTE: code here it must be redone to separate receiving thread - * and interrupt handler. - * in fact real mode ISR implements pxe_core_is_ours() - * and modifies __pxe_isr_occured, which must be checked - * in receiving queue. + * TODO: make it simplier to understand, too many ifs, many lines. */ int buffer_size = 0; /* total size of packet*/ int protocol = 0; /* protocol */ - int recieved = 0; /* bytes received to buffer */ + int received = 0; /* bytes received to buffer */ void *frame_data = NULL;/* pointer to frame data */ int frame_size = 0; /* size of frame */ + int drop_flag = 0; + int processed_packets = 0; pxe_packet *pack=NULL; /* allocated packet */ pxe_packet dummy_pack; /* temporary struct, used to mimic * real packet struct */ + if (__pxe_isr_occured == 0) /* there are no packets for us to handle */ + return (0); - if (!pxe_core_is_ours()) { - return; /* not ours interrupt, handling is over */ - } - + __pxe_isr_occured = 0; t_PXENV_UNDI_ISR *undi_isr = (t_PXENV_UNDI_ISR *)scratch_buffer; @@ -447,8 +508,17 @@ bzero(undi_isr, sizeof(*undi_isr)); /* starting packet receive cycle */ - if (0 -- pxe_core_get_packet(PXENV_UNDI_ISR_IN_PROCESS, undi_isr)) { - return; + /* NOTE: pxe_core_recv_packet() name is similar tp pxe_core_get_packet(), + * may be renaming is needed. + */ + int func = PXENV_UNDI_ISR_IN_PROCESS; + +packet_start: + + drop_flag = 0; + + if (0 == pxe_core_get_packet(func, undi_isr)) { + return (processed_packets); } buffer_size = undi_isr->BufferLength; @@ -458,60 +528,75 @@ /* how to get in this address from userspace, which starts at 0xa800?*/ /* frame_data = undi_isr->Frame.segment << 4 + undi_isr->Frame.offset; */ + /* we are interested in ARP & IP packets */ - /* we are yet not interested in non-ip packets */ + if ( (protocol == PXE_PROTOCOL_UNKNOWN) || (protocol == PXE_PROTOCOL_RARP) ) { - if (protocol != PXE_PROTOCOL_IP) { ++packets_dropped; - return; + drop_flag = 1; /* clear queue, receiving all frames of packet */ } /* checking first fragment, this may help to avoid memory allocation * and memblock copy */ -/* if (buffer_size == frame_size) {*/ + if (!drop_flag) { + + pxe_ip *iphdr = (pxe_ip *)frame_data; + + dummy_pack.protocol = protocol; + dummy_pack.state = PXE_PACKET_STATE_USING; + dummy_pack.data = frame_data; + dummy_pack.data_size = frame_size; + dummy_pack.user_data = NULL; + + if (protocol == PXE_PROTOCOL_ARP) { + + pxe_arp_protocol(&dummy_pack, PXE_CORE_FRAG, NULL); + ++processed_packets; - pxe_ip *iphdr = (pxe_ip *)frame_data; + /* aasume ARP packet always in opne fragment */ + + func = PXE_UNDI_ISR_IN_GET_NEXT; - dummy_pack.protocol = protocol; - dummy_pack.state = PXE_PACKET_STATE_USING; - dummy_pack.data = frame_data; - dummy_pack.data_size = frame_size; - dummy_pack.user_data = NULL; + goto packet_start; + } /* TODO: calc ip checksum */ - if (core_protocol[iphdr->protocol]) { - if (core_protocol[iphdr->protocol](&dummy_pack, - PXE_CORE_FRAG, NULL)) { - return; - } - } -/* }*/ + if ( (!core_protocol[iphdr->protocol]) || + (!core_protocol[iphdr->protocol](&dummy_pack, + PXE_CORE_FRAG, NULL)) ) { + + drop_flag = 1; + } else { + + pack = pxe_core_alloc_packet(buffer_size); - pack = pxe_core_alloc_packet(buffer_size); + if (pack == NULL) { + pxe_core_flush_packets(); - if (pack == NULL) { - pxe_core_flush_packets(); + /* trying to get free packets by sending and dropping */ + pack = pxe_core_alloc_packet(buffer_size); - /* trying to get free packets by sending and dropping */ - pack = pxe_core_alloc_packet(buffer_size); + /* failed to alloc packet, dropping packet */ + if (pack == NULL) { + ++packets_dropped; + drop_flag = 1; + } + } - /* failed to alloc packet, dropping packet */ - if (pack == NULL) { - ++packets_dropped; - return; - } - } /* pointing user_data to beginning of data. * It's used by pxe_core_receive() during receiving packet. */ - pack->user_data = pack->data; + if (pack != NULL) + pack->user_data = pack->data; + } + } - while (recieved < buffer_size) { + while (received < buffer_size) { if (!pxe_core_get_packet(PXENV_UNDI_ISR_GET_NEXT, undi_isr)) break; @@ -521,33 +606,46 @@ /* frame_data = undi_isr->Frame.segment << 4 + undi_isr->Frame.offset; */ - pxe_core_recieve(pack, frame_data, frame_size); + if (!drop_flag) + pxe_core_recieve(pack, frame_data, frame_size); - recieved += frame_size; + received += frame_size; } - if (recieved < buffer_size) { /* pxe_core_get_packet() in cycle failed */ - pxe_core_drop(pack); - return; + if (received < buffer_size) { /* pxe_core_get_packet() in cycle failed */ + + if (!drop_flag) + pxe_core_drop(pack); + + return (processed_packets); /* it's failed, finish receive cycle */ } - pack->user_data = NULL; - ++packets_received; + if (!drop_flag) { + + pack->user_data = NULL; + ++packets_received; - pxe_ip *iphdr=(pxe_ip *)pack->data; + pxe_ip *iphdr=(pxe_ip *)pack->data; - /* TODO: calc ip checksum */ - pack->protocol = protocol; + /* TODO: calc ip checksum */ + pack->protocol = protocol; - if (core_protocol[iphdr->protocol]) { /* protocol registered */ - if (core_protocol[iphdr->protocol](pack, PXE_CORE_HANDLE, - NULL)) { - return; + if ( (!core_protocol[iphdr->protocol]) || + (!core_protocol[iphdr->protocol](pack, PXE_CORE_HANDLE, NULL)) ) { + /* protocol not interested in it */ + pxe_core_drop(pack); } } - /* no such protocol registered or protocol not interested in it */ - pxe_core_drop(pack); + ++processed_packets; + /* received one or more packets, but need check if there are any others */ + + func = PXE_UNDI_ISR_IN_GET_NEXT; + + goto packet_start; + + /* never getting here */ + return (0); } /* @@ -638,5 +736,12 @@ pxe_get_myip32() { - return nic_ip.ip; + return nic_ip.ip; +} + +const MAC_ADDR* +pxe_get_mymac() +{ + return &nic_mac; } + ==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#6 (text+ko) ==== @@ -35,6 +35,8 @@ void* data; /* pointer to buffer with packet data */ size_t data_size; /* size of packet data */ + + const MAC_ADDR *dest_mac; /* destination media address */ void* user_data; /* pointer to user data. * used by higher level protocols @@ -64,6 +66,8 @@ /* interrupt handler function, that used to get new packets */ void pxe_core_isr(); +/* recieves one packet if it's waiting */ +int pxe_core_recv_packets(); /* calls PXE/UNDI API, registers of processor must be filled in with * appropriate values. @@ -91,9 +95,11 @@ typedef int (*pxe_protocol_call)(pxe_packet *pack, uint8_t function, void *data); /* registers protocol */ -void pxe_core_register(uint8_t proto, pxe_protocol_call proc); +void pxe_core_register(uint8_t ip_proto, pxe_protocol_call proc); /* returns NIC ip */ uint32_t pxe_get_myip32(); +/* returns NIC MAC */ +const MAC_ADDR *pxe_get_mymac(); #endif // PXE_CORE_H_INCLUDED
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200705121552.l4CFqrNQ070356>