* Rewrote transmit buffer allocation

* Made the read_hook logically more correct


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18466 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Niels Sascha Reedijk 2006-08-09 08:28:37 +00:00
parent 48b8e27155
commit 8680d4fcfb

View File

@ -107,7 +107,7 @@ typedef struct rtl8139_properties {
uint16 receivebufferoffset;/* Offset for the next package */ uint16 receivebufferoffset;/* Offset for the next package */
uint8 writes; /* Number of writes (0, maximum 4) */ uint8 writes; /* Number of writes (0, maximum 4) */
area_id transmitbuffer[4]; /* Transmitbuffers */ area_id transmitbuffer; /* Transmitbuffers */
void *transmitbufferlog[4]; /* Logical addresses of the transmit buffer */ void *transmitbufferlog[4]; /* Logical addresses of the transmit buffer */
void *transmitbufferphy[4]; /* Physical addresses of the transmit buffer */ void *transmitbufferphy[4]; /* Physical addresses of the transmit buffer */
uint8 transmitstatus[4]; /* Transmitstatus: 0 means empty and 1 means in use */ uint8 transmitstatus[4]; /* Transmitstatus: 0 means empty and 1 means in use */
@ -175,7 +175,6 @@ static status_t close_hook(void *);
} }
#endif #endif
/* ---------- /* ----------
init_hardware - called once the first time the driver is loaded init_hardware - called once the first time the driver is loaded
----- */ ----- */
@ -424,7 +423,7 @@ open_hook(const char *name, uint32 flags, void** cookie) {
//settings: The Rx Buffer length is 64k + 16 bytes (= 11) //settings: The Rx Buffer length is 64k + 16 bytes (= 11)
//settings: continue last packet in memory if it exceeds buffer length. //settings: continue last packet in memory if it exceeds buffer length.
WRITE_32(RxConfig, /*RXFTH2 | RXFTH1 | */ WRITE_32(RxConfig, /*RXFTH2 | RXFTH1 | */
RBLEN_1 | RBLEN_0 | WRAP | MXDMA_2 | MXDMA_1 | APM | AB); RBLEN_1 | RBLEN_0 | MXDMA_2 | MXDMA_1 | APM | AB);
//Disable blocking //Disable blocking
data->nonblocking = 0; data->nonblocking = 0;
@ -442,21 +441,19 @@ open_hook(const char *name, uint32 flags, void** cookie) {
WRITE_16(MULINT, 0); WRITE_16(MULINT, 0);
//Allocate buffers for transmit (There can be two buffers in one page) //Allocate buffers for transmit (There can be two buffers in one page)
data->transmitbuffer[0] = alloc_mem(&(data->transmitbufferlog[0]), &(data->transmitbufferphy[0]), 4096, "txbuffer01"); data->transmitbuffer = alloc_mem(&(data->transmitbufferlog[0]) , &(data->transmitbufferphy[0]) , 8192 , "tx buffer");
WRITE_32(TSAD0, (int32)data->transmitbufferphy[0]); WRITE_32(TSAD0 , (int32)data->transmitbufferphy[0]);
data->transmitbuffer[1] = data->transmitbuffer[0];
data->transmitbufferlog[1] = (void *)((uint32)data->transmitbufferlog[0] + 2048); data->transmitbufferlog[1] = (void *)((uint32)data->transmitbufferlog[0] + 2048);
data->transmitbufferphy[1] = (void *)((uint32)data->transmitbufferphy[0] + 2048); data->transmitbufferphy[1] = (void *)((uint32)data->transmitbufferphy[0] + 2048);
WRITE_32(TSAD1, (int32)data->transmitbufferphy[1]); WRITE_32(TSAD1, (int32)data->transmitbufferphy[1]);
data->transmitbufferlog[2] = (void *)((uint32)data->transmitbufferlog[1] + 2048);
data->transmitbuffer[2] = alloc_mem(&(data->transmitbufferlog[2]), &(data->transmitbufferphy[2]), 4096, "txbuffer23"); data->transmitbufferphy[2] = (void *)((uint32)data->transmitbufferphy[1] + 2048);
WRITE_32(TSAD2, (int32)data->transmitbufferphy[2]); WRITE_32( TSAD2 , (int32)data->transmitbufferphy[2] );
data->transmitbuffer[3] = data->transmitbuffer[2];
data->transmitbufferlog[3] = (void *)((uint32)data->transmitbufferlog[2] + 2048); data->transmitbufferlog[3] = (void *)((uint32)data->transmitbufferlog[2] + 2048);
data->transmitbufferphy[3] = (void *)((uint32)data->transmitbufferphy[2] + 2048); data->transmitbufferphy[3] = (void *)((uint32)data->transmitbufferphy[2] + 2048);
WRITE_32(TSAD3, (int32)data->transmitbufferphy[3]); WRITE_32(TSAD3, (int32)data->transmitbufferphy[3]);
if(data->transmitbuffer[0] == B_ERROR || data->transmitbuffer[2] == B_ERROR) { if(data->transmitbuffer == B_ERROR) {
TRACE(("rtl8139_nielx open_hook(): memory allocation for transmitbuffer failed\n")); TRACE(("rtl8139_nielx open_hook(): memory allocation for transmitbuffer failed\n"));
return B_ERROR; return B_ERROR;
} }
@ -544,13 +541,19 @@ read_hook (void* cookie, off_t position, void *buf, size_t* num_bytes)
rtl8139_properties_t *data =/* (rtl8139_properties_t *)*/cookie; rtl8139_properties_t *data =/* (rtl8139_properties_t *)*/cookie;
packetheader_t *packet_header; packetheader_t *packet_header;
cpu_status former; cpu_status former;
status_t status = B_ERROR;
uint16 length = 0;
TRACE(("rtl8139_nielx: read_hook()\n")); TRACE(("rtl8139_nielx: read_hook()\n"));
//if(!data->nonblocking)
acquire_sem_etc(data->input_wait, 1, B_CAN_INTERRUPT, 0);
restart: restart:
// Acquire the sem if we are allowed to block
if((status = acquire_sem_etc(data->input_wait , 1 , B_CAN_INTERRUPT | data->nonblocking , 0)) != B_NO_ERROR) {
TRACE(("rtl8139_nielx read_hook: Cannot acquire sem: %lx , %s\n" , status , strerror(status)));
return status;
}
// Let's lock and get the thing going
former = lock(); former = lock();
//Next: check in command register if there's actually anything to be read //Next: check in command register if there's actually anything to be read
@ -559,9 +562,9 @@ restart:
unlock(former); unlock(former);
return B_IO_ERROR; return B_IO_ERROR;
} }
// Retrieve the packet header // Retrieve the packet header
packet_header = (packetheader_t *) ((uint8 *)data->receivebufferlog + data->receivebufferoffset); packet_header = (packetheader_t *) ((uint32)data->receivebufferlog + data->receivebufferoffset);
// Check if the transfer is already done: EarlyRX // Check if the transfer is already done: EarlyRX
if (packet_header->length == 0xfff0) { if (packet_header->length == 0xfff0) {
@ -581,16 +584,19 @@ restart:
TRACE(("rtl8139_nielx read_hook(): Packet size: %u Receiveheader: %u Buffer size: %lu\n", packet_header->length, packet_header->bits, *num_bytes)); TRACE(("rtl8139_nielx read_hook(): Packet size: %u Receiveheader: %u Buffer size: %lu\n", packet_header->length, packet_header->bits, *num_bytes));
//Copy the packet //Copy the packet
*num_bytes = packet_header->length - 4; length = packet_header->length - 4;
if (data->receivebufferoffset + *num_bytes > 65536) { if (data->receivebufferoffset + length > 65536)
//Packet wraps around, copy last bits except header (= +4) {
//Packet wraps around , copy last bits except header ( = +4 )
memcpy(buf, (void *)((uint32)data->receivebufferlog + data->receivebufferoffset + 4), 0x10000 - (data->receivebufferoffset + 4)); memcpy(buf, (void *)((uint32)data->receivebufferlog + data->receivebufferoffset + 4), 0x10000 - (data->receivebufferoffset + 4));
//copy remaining bytes from the beginning //copy remaining bytes from the beginning
memcpy((void *) ((uint32)buf + 0x10000 - (data->receivebufferoffset + 4)), data->receivebufferlog, *num_bytes - (0x10000 - (data->receivebufferoffset + 4))); memcpy((void *)((uint32)buf + 0x10000 - (data->receivebufferoffset + 4)), data->receivebufferlog, length - (0x10000 - (data->receivebufferoffset + 4 )));
TRACE(("rtl8139_nielx read_hook: Wrapping around end of buffer\n")); TRACE(("rtl8139_nielx read_hook: Wrapping around end of buffer\n"));
} }
else else
memcpy(buf, (void *) ((uint32)data->receivebufferlog + data->receivebufferoffset + 4), packet_header->length - 4); //length-4 because we don't want to copy the 4 bytes CRC memcpy(buf, (void *) ((uint32)data->receivebufferlog + data->receivebufferoffset + 4), length); //length-4 because we don't want to copy the 4 bytes CRC
*num_bytes = length;
//Update the buffer -- 4 for the header length, plus 3 for the dword allignment //Update the buffer -- 4 for the header length, plus 3 for the dword allignment
data->receivebufferoffset = (data->receivebufferoffset + packet_header->length + 4 + 3) & ~3; data->receivebufferoffset = (data->receivebufferoffset + packet_header->length + 4 + 3) & ~3;
@ -600,7 +606,7 @@ restart:
unlock(former); unlock(former);
return packet_header->length - 4; return B_OK;
} }
@ -649,7 +655,7 @@ write_hook (void* cookie, off_t position, const void* buffer, size_t* num_bytes)
return B_IO_ERROR; return B_IO_ERROR;
} }
dprintf("rtl8139_nielx write_hook(): TransmitID: %u Packagelen: %u Register: %lx\n", transmitid, buflen, TSD0 + (sizeof(uint32) * transmitid)); TRACE(("rtl8139_nielx write_hook(): TransmitID: %u Packagelen: %u Register: %lx\n", transmitid, buflen, TSD0 + (sizeof(uint32) * transmitid)));
data->writes++; data->writes++;
// Set the buffer as used // Set the buffer as used
@ -781,26 +787,26 @@ rtl8139_interrupt(void *cookie)
// If a register isn't used, continue next run // If a register isn't used, continue next run
temp8 = data->finished_packets % 4 ; temp8 = data->finished_packets % 4 ;
txstatus = READ_32(TSD0 + temp8 * sizeof(int32)); txstatus = READ_32(TSD0 + temp8 * sizeof(int32));
dprintf("run: %u txstatus: %lu Register: %lx\n", temp8, txstatus, TSD0 + temp8 * sizeof(int32)); TRACE(("run: %u txstatus: %lu Register: %lx\n", temp8, txstatus, TSD0 + temp8 * sizeof(int32)));
if (!(txstatus & (TOK | TUN | TABT))) { if (!(txstatus & (TOK | TUN | TABT))) {
dprintf("NOT FINISHED\n"); TRACE(("NOT FINISHED\n"));
break; break;
} }
if (txstatus & (TABT | OWC)) { if (txstatus & (TABT | OWC)) {
dprintf("MAJOR ERROR\n"); TRACE(("MAJOR ERROR\n"));
continue; continue;
} }
if (txstatus &(TUN)) { if (txstatus &(TUN)) {
dprintf("TRANSMIT UNDERRUN\n"); TRACE(("TRANSMIT UNDERRUN\n"));
continue; continue;
} }
if ((txstatus & TOK)) { if ((txstatus & TOK)) {
//this one is the one! //this one is the one!
dprintf("NIELX INTERRUPT: TXOK, clearing register %u\n", temp8); TRACE(("NIELX INTERRUPT: TXOK, clearing register %u\n", temp8));
data->transmitstatus[temp8] = 0; //That's all there is to it data->transmitstatus[temp8] = 0; //That's all there is to it
data->writes--; data->writes--;
data->finished_packets++; data->finished_packets++;
@ -887,8 +893,7 @@ free_hook (void* cookie)
//Free Rx and Tx buffers //Free Rx and Tx buffers
delete_area(data->receivebuffer); delete_area(data->receivebuffer);
delete_area(data->transmitbuffer[0]); delete_area(data->transmitbuffer);
delete_area(data->transmitbuffer[2]);
delete_area(data->ioarea); //Only does something on ppc delete_area(data->ioarea); //Only does something on ppc
// mark this device as closed // mark this device as closed