static void ni5010_transmit(struct nic *nic, const char *d, /* Destination */ unsigned int t, /* Type */ unsigned int s, /* size */ const char *p) /* Packet */ { unsigned int len; int buf_offs, xmt_stat; unsigned long time; len = s + ETH_HLEN; if (len < ETH_ZLEN) len = ETH_ZLEN; buf_offs = NI5010_BUFSIZE - len; outb(0, EDLC_RMASK); /* Mask all receive interrupts */ outb(0, IE_MMODE); /* Put Xmit buffer on system bus */ outb(0xFF, EDLC_RCLR); /* Clear out pending rcv interrupts */ outw(buf_offs, IE_GP); /* Point GP at start of packet */ outsb(IE_XBUF, d, ETH_ALEN); /* Put dst in buffer */ outsb(IE_XBUF, nic->node_addr, ETH_ALEN);/* Put src in buffer */ outb(t >> 8, IE_XBUF); outb(t, IE_XBUF); outsb(IE_XBUF, p, s); /* Put data in buffer */ while (s++ < ETH_ZLEN - ETH_HLEN) /* Pad to min size */ outb(0, IE_XBUF); outw(buf_offs, IE_GP); /* Rewrite where packet starts */ /* should work without that outb() (Crynwr used it) */ /*outb(MM_MUX, IE_MMODE);*/ /* Xmt buffer to EDLC bus */ outb(MM_EN_XMT | MM_MUX, IE_MMODE); /* Begin transmission */ /* wait for transmit complete */ while (((xmt_stat = inb(IE_ISTAT)) & IS_EN_XMT) != 0) ; reset_receiver(); /* Immediately switch to receive */ }
uint8_t radio_resize_receiver_buffer(Radio * radio, size_t size) { uint8_t receiver_powered = radio->receiver_powered(); if(receiver_powered && radio->received_bytes_count) return 1; radio->receiver_power(0); radio->received_bytes_count = 0; radio->buffer_size = 0; if(radio->received_message) { free(radio->received_message); radio->received_message = 0; } radio->received_message = malloc(size); if(!radio->received_message) return 1; radio->buffer_size = size; reset_receiver(radio); if(receiver_powered) radio->receiver_power(1); return 0; }
uint8_t radio_send(void * radio_pointer, const uint8_t * content, size_t content_size) { Radio * radio = (Radio *)radio_pointer; uint8_t receiver_powered = radio->receiver_powered(); if(receiver_powered) { if(radio->received_bytes_count) return 1; radio->receiver_power(0); radio->received_bytes_count = 0; reset_receiver(radio); } radio->transmitting = 1; radio->transmitter_power(1); radio_transmit_bytes(radio, content, content_size); radio->transmitter_power(0); radio->transmitting = 0; if(receiver_powered) radio->receiver_power(1); return 0; }
static void ni5010_reset(struct nic *nic) { int i; /* Reset the hardware here. Don't forget to set the station address. */ outb(RS_RESET, EDLC_RESET); /* Hold up EDLC_RESET while configing board */ outb(0, IE_RESET); /* Hardware reset of ni5010 board */ outb(0, EDLC_XMASK); /* Disable all Xmt interrupts */ outb(0, EDLC_RMASK); /* Disable all Rcv interrupt */ outb(0xFF, EDLC_XCLR); /* Clear all pending Xmt interrupts */ outb(0xFF, EDLC_RCLR); /* Clear all pending Rcv interrupts */ outb(XMD_LBC, EDLC_XMODE); /* Only loopback xmits */ /* Set the station address */ for(i = 0; i < ETH_ALEN; i++) outb(nic->node_addr[i], EDLC_ADDR + i); outb(XMD_IG_PAR | XMD_T_MODE | XMD_LBC, EDLC_XMODE); /* Normal packet xmit mode */ outb(RMD_BROADCAST, EDLC_RMODE); /* Receive broadcast and normal packets */ reset_receiver(); outb(0x00, EDLC_RESET); /* Un-reset the ni5010 */ }
void radio_on_receive(Radio * radio) { if(radio->transmitting || !radio->callback_receive) return; radio_time time = radio->microseconds(); radio_time duration = time - radio->last_time; radio->last_time = time; if(time < radio->last_time) { reset_receiver(radio); return; } if(duration < 300) { reset_receiver(radio); return; } if(!radio->receiving) { radio->receiving = 1; radio->delay = duration /* sync */ / 31; radio->delay_tolerance = radio->delay * radio->tolerance * 0.01; radio->bit_count = 0; radio->received_bytes_count = 0; } if(between(duration, radio->delay, 3 * radio->delay, radio->delay_tolerance)) { if(byte_odd(radio->change_count)) { if(radio->received_bytes_count >= radio->buffer_size) { // Overflow // Realloc on simple uc would result in memory fragmentation // and freeze radio->received_bytes_count = 0; reset_receiver(radio); return; } if(received_one(radio, duration)) bit_on(&radio->received_message[radio->received_bytes_count], 7 - radio->bit_count++); else if(received_zero(radio, duration)) bit_off(&radio->received_message[radio->received_bytes_count], 7 - radio->bit_count++); else { reset_receiver(radio); return; } if(radio->bit_count == 8) { radio->bit_count = 0; radio->received_bytes_count++; } } } else if(radio->change_count > 1) { reset_receiver(radio); return; } radio->change_count++; }