Example #1
0
static int nic_send_frame(snic *nic, frame_buffer *buffer) 
{
	unsigned int iobase = nic->iobase;

	if (buffer->len>MAX_FRSIZE) return ETOOBIG;

	outportg(0x00, iobase + INTERRUPTMASK); // Disable interrupts
		
	nic->tx_frame = tx_wait_pkt = buffer;
	nic->tx_frame->page = nic->pstart ;
	nic_block_output(nic,(struct frame_buffer *)nic->tx_frame);

	if(nic_send(nic)<0) 
	{
		outportg(IMR_DEFAULT, iobase + INTERRUPTMASK);
		nic->tx_frame = NULL;

		return ERR;
	}

	outportg(IMR_DEFAULT, iobase + INTERRUPTMASK);
	return NOERR;
}
Example #2
0
/* TODO- Have it check how lonk a transmission is taking and attempt to 
    restart the card if it's too long. */
int nic_send_packet(snic *nic, packet_buffer *buffer) {
	uint timeout;	uint f;	int iobase;
/*	kprintf("nic_send_packet()\n"); */
	if(!buffer) return ERRARG;
	if(!buffer->count || !buffer->buf) return ERRARG;
	if(!nic || !nic->iobase) return ERR;
	iobase=nic->iobase;

	t(A);
        
	buffer->len=0;
	for(f=0;f<buffer->count;f++) buffer->len+=buffer->buf[f].len;
	if(buffer->len>MAX_LENGTH) return ERRTOOBIG;

        t(B);
        
	/* the following wait for anyother tasks that are calling 
	// nic_send_packet() right now.  Note that this doesn't use
	// an atomic semaphore, so something MAY leak through. */
/*	timeout=ticks+10;	wait 10 ticks */
	timeout=ticks+100;
	while(nic->busy && ticks<=timeout) idle();
	/* Replace this with a proper timeout thing that doesn't use the
	// ticks method which will be diffrent on each OS. */
	t(C);
        if(nic->busy) {
		kprintf("NE2000: ERROR: Card stalled, timeout.\n");
		return ERRTIMEOUT;
	}
	nic->busy=1;	/* mark as busy, replace with semaphore */

        t(D);
        
	outb_p(0x00, iobase + INTERRUPTMASK);	/* mask ints for now */
        t(E);
        
	timeout=ticks+TIMEOUT_TX;
	while(idle(), ticks<=timeout) for(f=0;f<MAX_TX;f++) {
		if(!nic->tx_packet[f]) {
                    t(F);
                    
/*			nic->tx_packet[f]=*buffer;*/
			nic->tx_packet[f]=buffer;
			nic->tx_packet[f]->page=nic->pstart + (f * MAX_PAGESPERPACKET);
								/*output page */

/*			kprintf("NE2000: sending packet with count:%x on page:%X with buffer:%x\n",
				buffer->count,buffer->page,buffer->buf); */
                        t(>);
                        
                        nic_block_output(nic,nic->tx_packet[f]);

                        t(<);
                        
			if(!nic->sending) {
				nic->send=f;	nic->sending=1;
				/* now let's actually trigger the transmitter */
                                t(I);
                                
                                if(nic_send(nic,f)<0) {
					nic->sending=0;
					break; }
                                
				/* note, the nic_tx() interrupt will mark this
				// tx_packet buffer as free again once it
				// confirms that the packet was sent. */
			}
                        t(J);
                                
			nic->stat.tx_buffered++;
			outb_p(IMR_DEFAULT, iobase + INTERRUPTMASK); /* unmask */
			nic->busy=0;	/* V() */
                        t(K);
                        
			return NOERR;
		}
	}