Sync with local repository:
1.23: fix some compile errors on PPC 1.24: Finalising some PPC changes. In theory it should work 1.25: Second round of PPC fixes. I hope it works now. 1.26: Adding the reset function when there are rx problems 1.27: Added the chip id for the 8101L 1.28: Minor code cleanup 1.29: Implemented multipe card support 1.30: drop some debug output 1.31: FINALLY fixed the receive problem (where large packets slow down everything) What remains to be done is to fix the transmit bug, where the card suddenly stops to send packets (after it gets behind by one). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3993 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
e793a55e78
commit
5767925f0e
@ -31,23 +31,30 @@
|
|||||||
#include <Errors.h>
|
#include <Errors.h>
|
||||||
#include <PCI.h>
|
#include <PCI.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "ether_driver.h"
|
#include "ether_driver.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#define RTL_MAX_CARDS 4
|
||||||
|
|
||||||
//#define RTL_NODEBUG
|
#define RTL_NODEBUG
|
||||||
#ifdef RTL_NODEBUG
|
#ifdef RTL_NODEBUG
|
||||||
#define dprintf no_printf
|
#define TRACE no_printf
|
||||||
void no_printf( const char *useless , ... ) {};
|
void no_printf( const char *useless , ... ) {};
|
||||||
|
#else
|
||||||
|
#define TRACE TRACE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
global data
|
global data
|
||||||
----- */
|
----- */
|
||||||
static pci_info *m_device = 0;
|
static pci_info *m_devices[RTL_MAX_CARDS];
|
||||||
static pci_module_info *m_pcimodule = 0; //To call methods of pci
|
static pci_module_info *m_pcimodule = 0; //To call methods of pci
|
||||||
static int16 m_isopen = 0; //Is the thing already opened?
|
static char *rtl8139_names[RTL_MAX_CARDS +1];
|
||||||
|
static int32 m_openmask = 0; //Is the thing already opened?
|
||||||
|
|
||||||
|
|
||||||
int32 api_version = B_CUR_DRIVER_API_VERSION; //Procedure
|
int32 api_version = B_CUR_DRIVER_API_VERSION; //Procedure
|
||||||
|
|
||||||
@ -116,7 +123,11 @@ enum Receiver_actions {
|
|||||||
|
|
||||||
enum TransmitDescription {
|
enum TransmitDescription {
|
||||||
OWN = 0x2000 ,
|
OWN = 0x2000 ,
|
||||||
TOK = 0x8000
|
TUN = 0x4000 ,
|
||||||
|
TOK = 0x8000 ,
|
||||||
|
OWC = 0x20000000 ,
|
||||||
|
TABT = 0x40000000 ,
|
||||||
|
CRS = 0x80000000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -138,7 +149,7 @@ enum BMCR_Commands {
|
|||||||
Restart_Auto_Negotiation = 0x400
|
Restart_Auto_Negotiation = 0x400
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum chiptype { RTL_8139_C , RTL_8139_D } chiptype;
|
typedef enum chiptype { RTL_8139_C , RTL_8139_D , RTL_8101_L } chiptype;
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
structure that stores internal data
|
structure that stores internal data
|
||||||
@ -148,7 +159,9 @@ typedef struct rtl8139_properties
|
|||||||
{
|
{
|
||||||
pci_info *pcii; /* Pointer to PCI Info for the device */
|
pci_info *pcii; /* Pointer to PCI Info for the device */
|
||||||
uint32 reg_base; /* Base address for registers */
|
uint32 reg_base; /* Base address for registers */
|
||||||
|
area_id ioarea; /* PPC: Area where the mmaped registers are */
|
||||||
chiptype chip_type; /* Storage for the chip type */
|
chiptype chip_type; /* Storage for the chip type */
|
||||||
|
uint8 device_id; /* Which device id this is... */
|
||||||
|
|
||||||
area_id receivebuffer; /* Memoryaddress for the receive buffer */
|
area_id receivebuffer; /* Memoryaddress for the receive buffer */
|
||||||
void *receivebufferlog; /* Logical address */
|
void *receivebufferlog; /* Logical address */
|
||||||
@ -160,13 +173,14 @@ typedef struct rtl8139_properties
|
|||||||
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 */
|
||||||
uint8 nexttransmitstatus;
|
uint32 queued_packets; /* Number of queued tx that have been written */
|
||||||
|
uint32 finished_packets; /* Number of finished transfers */
|
||||||
|
|
||||||
uint8 multiset; /* determines if multicast address is set */
|
uint8 multiset; /* determines if multicast address is set */
|
||||||
ether_address_t address; /* holds the MAC address */
|
ether_address_t address; /* holds the MAC address */
|
||||||
sem_id lock; /* lock this structure: still interrupt */
|
sem_id lock; /* lock this structure: still interrupt */
|
||||||
sem_id input_wait; /* locked until there is a packet to be read */
|
sem_id input_wait; /* locked until there is a packet to be read */
|
||||||
uint8 nonblocking; /* determines if the card blocks on read requests */
|
uint8 nonblocking; /* determines if the card blocks on read requests */
|
||||||
} rtl8139_properties_t;
|
} rtl8139_properties_t;
|
||||||
|
|
||||||
typedef struct packetheader
|
typedef struct packetheader
|
||||||
@ -192,17 +206,40 @@ static status_t close_hook( void * );
|
|||||||
void rtl8139_init_registers( rtl8139_properties_t *data )
|
void rtl8139_init_registers( rtl8139_properties_t *data )
|
||||||
{
|
{
|
||||||
data->reg_base = data->pcii->u.h0.base_registers[0];
|
data->reg_base = data->pcii->u.h0.base_registers[0];
|
||||||
|
//TRACE( "NIELX@@: registers %lu\n" , data->reg_base );
|
||||||
|
}
|
||||||
|
#else /* PPC */
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
#define WRITE_8( offset , value) (*((volatile uint8 *)(data->reg_base + (offset))) = (value))
|
||||||
|
#define WRITE_16( offset , value) (*((volatile uint8 *)(data->reg_base + (offset))) = B_HOST_TO_LENDIAN_INT16(value))
|
||||||
|
#define WRITE_32( offset , value) (*((volatile uint8 *)(data->reg_base + (offset))) = B_HOST_TO_LENDIAN_INT32(value))
|
||||||
|
|
||||||
|
#define READ_8( offset ) (*((volatile uint8*)(data->reg_base + (offset))))
|
||||||
|
#define READ_16( offset ) B_LENDIAN_TO_HOST_INT16(*((volatile uint16*)(data->reg_base + (offset))))
|
||||||
|
#define READ_32( offset ) B_LENDIAN_TO_HOST_INT32(*((volatile uint32*)(data->reg_base + (offset))))
|
||||||
|
|
||||||
|
void rtl8139_init_registers( rtl8139_properties_t *data )
|
||||||
|
{
|
||||||
|
int32 base, size, offset;
|
||||||
|
base = data->pcii->u.h0.base_registers[0];
|
||||||
|
size = data->pcii->u.h0.base_register_sizes[0];
|
||||||
|
|
||||||
|
/* Round down to nearest page boundary */
|
||||||
|
base = base & ~(B_PAGE_SIZE-1);
|
||||||
|
|
||||||
|
/* Adjust the size */
|
||||||
|
offset = data->pcii->u.h0.base_registers[0] - base;
|
||||||
|
size += offset;
|
||||||
|
size = (size +(B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1);
|
||||||
|
|
||||||
|
TRACE("rtl8139_nielx _open_hook(): PCI base=%lx size=%lx offset=%lx\n", base, size, offset);
|
||||||
|
|
||||||
|
data->ioarea = map_physical_memory("rtl8139_regs", (void *)base, size, B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA, (void **)&data->reg_base);
|
||||||
|
|
||||||
|
data->reg_base = data->reg_base + offset;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -----
|
|
||||||
null-terminated array of device names supported by this driver
|
|
||||||
----- */
|
|
||||||
|
|
||||||
static const char *rtl8139_name[] = {
|
|
||||||
"net/rtl8139/0",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
init_hardware - called once the first time the driver is loaded
|
init_hardware - called once the first time the driver is loaded
|
||||||
@ -211,7 +248,7 @@ status_t
|
|||||||
init_hardware (void)
|
init_hardware (void)
|
||||||
{
|
{
|
||||||
// Nielx: no special requirements here...
|
// Nielx: no special requirements here...
|
||||||
dprintf( "rtl8139_nielx: init_hardware\n" );
|
TRACE( "rtl8139_nielx: init_hardware\n" );
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,55 +262,60 @@ init_driver (void)
|
|||||||
{
|
{
|
||||||
status_t status; //Storage for statuses
|
status_t status; //Storage for statuses
|
||||||
pci_info *item; //Storage used while looking through pci
|
pci_info *item; //Storage used while looking through pci
|
||||||
int32 i; //Counter
|
int32 i, found; //Counter
|
||||||
|
|
||||||
m_device = 0; //...
|
TRACE( "rtl8139_nielx: init_driver()\n" );
|
||||||
|
|
||||||
/*
|
|
||||||
Nielx: Some notes
|
|
||||||
- I will implement multiple cards later
|
|
||||||
- For now this thing just searches for the card and use it.
|
|
||||||
*/
|
|
||||||
dprintf( "rtl8139_nielx: init_driver()\n" );
|
|
||||||
|
|
||||||
// Try if the PCI module is loaded (it would be weird if it wouldn't, but alas)
|
// Try if the PCI module is loaded (it would be weird if it wouldn't, but alas)
|
||||||
if( ( status = get_module( B_PCI_MODULE_NAME, (module_info **)&m_pcimodule )) != B_OK)
|
if( ( status = get_module( B_PCI_MODULE_NAME, (module_info **)&m_pcimodule )) != B_OK)
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx init_driver(): Get PCI module failed! %lu \n", status);
|
TRACE( "rtl8139_nielx init_driver(): Get PCI module failed! %lu \n", status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
i = 0;
|
i = 0;
|
||||||
item = (pci_info *)malloc(sizeof(pci_info));
|
item = (pci_info *)malloc(sizeof(pci_info));
|
||||||
while( true )
|
for ( i = found = 0 ; m_pcimodule->get_nth_pci_info(i, item) == B_OK ; i++ )
|
||||||
{
|
{
|
||||||
if ((status = m_pcimodule->get_nth_pci_info(i, item)) != B_OK)
|
|
||||||
break;
|
|
||||||
// Vendorid = 0x10ec and device_id = 0x8139
|
// Vendorid = 0x10ec and device_id = 0x8139
|
||||||
if ( ( item->vendor_id == 0x10ec ) && ( item->device_id == 0x8139 ) )
|
if ( ( item->vendor_id == 0x10ec ) && ( item->device_id == 0x8139 ) )
|
||||||
{
|
{
|
||||||
//Also done in etherpci sample code
|
//Also done in etherpci sample code
|
||||||
if ((item->u.h0.interrupt_line == 0) || (item->u.h0.interrupt_line == 0xFF)) {
|
if ((item->u.h0.interrupt_line == 0) || (item->u.h0.interrupt_line == 0xFF))
|
||||||
dprintf( "rtl8139_nielx init_driver(): found with invalid IRQ - check IRQ assignement\n");
|
{
|
||||||
|
TRACE( "rtl8139_nielx init_driver(): found with invalid IRQ - check IRQ assignement\n");
|
||||||
i++; //next
|
i++; //next
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
dprintf("rtl8139_nielx init_driver(): found at IRQ %u \n", item->u.h0.interrupt_line);
|
TRACE("rtl8139_nielx init_driver(): found at IRQ %u \n", item->u.h0.interrupt_line);
|
||||||
m_device = item;
|
m_devices[found] = item;
|
||||||
break;
|
item = (pci_info *)malloc(sizeof(pci_info));
|
||||||
|
found++;
|
||||||
}
|
}
|
||||||
i++; //Look for the next one
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free( item );
|
||||||
|
|
||||||
//Check if we have found any devices:
|
//Check if we have found any devices:
|
||||||
if ( m_device == 0 )
|
if ( found == 0 )
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx init_driver(): no device found\n" );
|
TRACE( "rtl8139_nielx init_driver(): no device found\n" );
|
||||||
put_module(B_PCI_MODULE_NAME ); //dereference module
|
put_module(B_PCI_MODULE_NAME ); //dereference module
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Create the devices list
|
||||||
|
{
|
||||||
|
char name[32];
|
||||||
|
|
||||||
|
for (i = 0; i < found; i++)
|
||||||
|
{
|
||||||
|
sprintf(name, "net/rtl8139/%ld", i);
|
||||||
|
rtl8139_names[i] = strdup(name);
|
||||||
|
}
|
||||||
|
rtl8139_names[i] = NULL;
|
||||||
|
}
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +327,16 @@ init_driver (void)
|
|||||||
void
|
void
|
||||||
uninit_driver (void)
|
uninit_driver (void)
|
||||||
{
|
{
|
||||||
free ( m_device );
|
int index;
|
||||||
|
void *item;
|
||||||
|
TRACE( "rtl8139_nielx: uninit_driver()\n" );
|
||||||
|
|
||||||
|
for (index = 0; (item = rtl8139_names[index]) != NULL; index++)
|
||||||
|
{
|
||||||
|
free(item);
|
||||||
|
free(m_devices[index]);
|
||||||
|
}
|
||||||
|
|
||||||
put_module( B_PCI_MODULE_NAME );
|
put_module( B_PCI_MODULE_NAME );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,6 +345,9 @@ uninit_driver (void)
|
|||||||
open_hook - handle open() calls
|
open_hook - handle open() calls
|
||||||
----- */
|
----- */
|
||||||
|
|
||||||
|
//FWD declaration:
|
||||||
|
static status_t free_hook( void *cookie );
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
open_hook(const char *name, uint32 flags, void** cookie)
|
open_hook(const char *name, uint32 flags, void** cookie)
|
||||||
{
|
{
|
||||||
@ -304,32 +358,43 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
uint32 temp32;
|
uint32 temp32;
|
||||||
unsigned char cmd;
|
unsigned char cmd;
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx open_hook()\n" );
|
TRACE( "rtl8139_nielx open_hook()\n" );
|
||||||
// Check if the device name is ours
|
|
||||||
if ( strcmp( name , rtl8139_name[0] ) != 0 )
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
if ( m_isopen == 1 )
|
|
||||||
{
|
|
||||||
dprintf( "rtl8139_nielx open_hook(): Device already in use\n" );
|
|
||||||
return B_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
//We are now officially opening (don't know if it is possible that there
|
// verify device access
|
||||||
//are multiple calls, however, this could prevent some ugly bugs)
|
{
|
||||||
m_isopen = 1;
|
char *thisName;
|
||||||
|
int32 mask;
|
||||||
|
|
||||||
|
// search for device name
|
||||||
|
for (temp8 = 0; (thisName = rtl8139_names[temp8]) != NULL; temp8++) {
|
||||||
|
if (!strcmp(name, thisName))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!thisName)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
// check if device is already open
|
||||||
|
mask = 1L << temp8;
|
||||||
|
if (atomic_or(&m_openmask, mask) & mask)
|
||||||
|
return B_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
//Create a structure that contains the internals
|
//Create a structure that contains the internals
|
||||||
if (!(*cookie = data = (rtl8139_properties_t *)malloc(sizeof(rtl8139_properties_t))))
|
if (!(*cookie = data = (rtl8139_properties_t *)malloc(sizeof(rtl8139_properties_t))))
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx open_hook(): Out of memory\n" );
|
TRACE( "rtl8139_nielx open_hook(): Out of memory\n" );
|
||||||
m_isopen = 0;
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Set status to open:
|
||||||
|
m_openmask &= ~( 1L << temp8 );
|
||||||
|
|
||||||
//Clear memory
|
//Clear memory
|
||||||
memset( data , 0 , sizeof( rtl8139_properties_t ) );
|
memset( data , 0 , sizeof( rtl8139_properties_t ) );
|
||||||
|
|
||||||
|
//Set the ID
|
||||||
|
data->device_id = temp8;
|
||||||
|
|
||||||
// Create lock
|
// Create lock
|
||||||
data->lock = create_sem( 1 , "rtl8139_nielx data protect" );
|
data->lock = create_sem( 1 , "rtl8139_nielx data protect" );
|
||||||
set_sem_owner( data->lock , B_SYSTEM_TEAM );
|
set_sem_owner( data->lock , B_SYSTEM_TEAM );
|
||||||
@ -337,7 +402,7 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
set_sem_owner( data->input_wait , B_SYSTEM_TEAM );
|
set_sem_owner( data->input_wait , B_SYSTEM_TEAM );
|
||||||
|
|
||||||
//Set up the cookie
|
//Set up the cookie
|
||||||
data->pcii = m_device;
|
data->pcii = m_devices[data->device_id];
|
||||||
|
|
||||||
//Enable the registers
|
//Enable the registers
|
||||||
rtl8139_init_registers( data );
|
rtl8139_init_registers( data );
|
||||||
@ -352,8 +417,8 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
|
|
||||||
if ( temp32 == 0xFFFFFF )
|
if ( temp32 == 0xFFFFFF )
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx open_hook(): Faulty chip\n" );
|
TRACE( "rtl8139_nielx open_hook(): Faulty chip\n" );
|
||||||
m_isopen = 0;
|
free_hook( cookie );
|
||||||
put_module( B_PCI_MODULE_NAME );
|
put_module( B_PCI_MODULE_NAME );
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
@ -363,17 +428,22 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
switch( temp32 )
|
switch( temp32 )
|
||||||
{
|
{
|
||||||
case 0x74000000:
|
case 0x74000000:
|
||||||
dprintf( "rtl8139_nielx open_hook(): Chip is the 8139 C\n" );
|
TRACE( "rtl8139_nielx open_hook(): Chip is the 8139 C\n" );
|
||||||
data->chip_type = RTL_8139_C;
|
data->chip_type = RTL_8139_C;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x74400000:
|
case 0x74400000:
|
||||||
dprintf( "rtl8139_niels open_hook(): Chip is the 8139 D\n" );
|
TRACE( "rtl8139_niels open_hook(): Chip is the 8139 D\n" );
|
||||||
data->chip_type = RTL_8139_D;
|
data->chip_type = RTL_8139_D;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x74C00000:
|
||||||
|
TRACE( "rtl8139_nielx open_hook(): Chip is the 8101L\n" );
|
||||||
|
data->chip_type = RTL_8101_L;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintf( "rtl8139_nielx open_hook(): Unknown chip, assuming 8139 C\n" );
|
TRACE( "rtl8139_nielx open_hook(): Unknown chip, assuming 8139 C\n" );
|
||||||
data->chip_type = RTL_8139_C;
|
data->chip_type = RTL_8139_C;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,12 +457,11 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
|
|
||||||
if ( temp16 == 0 )
|
if ( temp16 == 0 )
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx open_hook(): Reset failed... Bailing out\n" );
|
TRACE( "rtl8139_nielx open_hook(): Reset failed... Bailing out\n" );
|
||||||
m_isopen = 0;
|
free_hook( cookie );
|
||||||
free( data );
|
|
||||||
return EIO;
|
return EIO;
|
||||||
}
|
}
|
||||||
dprintf( "rtl8139_nielx open_hook(): Chip reset: %u \n" , temp16 );
|
TRACE( "rtl8139_nielx open_hook(): Chip reset: %u \n" , temp16 );
|
||||||
|
|
||||||
/* Enable writing to the configuration registers */
|
/* Enable writing to the configuration registers */
|
||||||
WRITE_8( _9346CR , 0xc0 );
|
WRITE_8( _9346CR , 0xc0 );
|
||||||
@ -419,7 +488,7 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
//settings: Max DMA burst size per Tx DMA burst is 1024 ( = 110 )
|
//settings: Max DMA burst size per Tx DMA burst is 1024 ( = 110 )
|
||||||
//settings: Interframe GAP time according to IEEE standard ( = 11 )
|
//settings: Interframe GAP time according to IEEE standard ( = 11 )
|
||||||
WRITE_32( TxConfig ,
|
WRITE_32( TxConfig ,
|
||||||
READ_32( TxConfig ) | MXDMA_2 | MXDMA_1 );
|
IFG_1 | IFG_0 | MXDMA_1 );
|
||||||
|
|
||||||
/* Configure the Receive Register */
|
/* Configure the Receive Register */
|
||||||
//settings: Early Rx Treshold is 1024 kB ( = 110 ) DISABLED
|
//settings: Early Rx Treshold is 1024 kB ( = 110 ) DISABLED
|
||||||
@ -436,7 +505,7 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
data->receivebuffer = alloc_mem( &(data->receivebufferlog) , &(data->receivebufferphy) , 1024 * 64 + 16 , "rx buffer" );
|
data->receivebuffer = alloc_mem( &(data->receivebufferlog) , &(data->receivebufferphy) , 1024 * 64 + 16 , "rx buffer" );
|
||||||
if( data->receivebuffer == B_ERROR )
|
if( data->receivebuffer == B_ERROR )
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx open_hook(): memory allocation for ringbuffer failed\n" );
|
TRACE( "rtl8139_nielx open_hook(): memory allocation for ringbuffer failed\n" );
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
WRITE_32( RBSTART , (int32) data->receivebufferphy );
|
WRITE_32( RBSTART , (int32) data->receivebufferphy );
|
||||||
@ -449,35 +518,31 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
data->transmitbuffer[0] = alloc_mem( &(data->transmitbufferlog[0]) , &(data->transmitbufferphy[0]) , 4096 , "txbuffer01" );
|
data->transmitbuffer[0] = alloc_mem( &(data->transmitbufferlog[0]) , &(data->transmitbufferphy[0]) , 4096 , "txbuffer01" );
|
||||||
WRITE_32( TSAD0 , (int32)data->transmitbufferphy[0] );
|
WRITE_32( TSAD0 , (int32)data->transmitbufferphy[0] );
|
||||||
data->transmitbuffer[1] = data->transmitbuffer[0];
|
data->transmitbuffer[1] = data->transmitbuffer[0];
|
||||||
data->transmitbufferlog[1] = data->transmitbufferlog[0] + 2048;
|
data->transmitbufferlog[1] = (void *)( (uint32)data->transmitbufferlog[0] + 2048 );
|
||||||
data->transmitbufferphy[1] = 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->transmitbuffer[2] = alloc_mem( &(data->transmitbufferlog[2]) , &(data->transmitbufferphy[2]) , 4096 , "txbuffer23" );
|
data->transmitbuffer[2] = alloc_mem( &(data->transmitbufferlog[2]) , &(data->transmitbufferphy[2]) , 4096 , "txbuffer23" );
|
||||||
WRITE_32( TSAD2 , (int32)data->transmitbufferphy[2] );
|
WRITE_32( TSAD2 , (int32)data->transmitbufferphy[2] );
|
||||||
data->transmitbuffer[3] = data->transmitbuffer[2];
|
data->transmitbuffer[3] = data->transmitbuffer[2];
|
||||||
data->transmitbufferlog[3] = data->transmitbufferlog[2] + 2048;
|
data->transmitbufferlog[3] = (void *)( (uint32)data->transmitbufferlog[2] + 2048 );
|
||||||
data->transmitbufferphy[3] = 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[0] == B_ERROR || data->transmitbuffer[2] == B_ERROR )
|
||||||
{
|
{
|
||||||
dprintf( "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;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->nexttransmitstatus = 0;
|
data->queued_packets = 0;
|
||||||
|
data->finished_packets = 0;
|
||||||
|
|
||||||
// Receive hardware MAC address
|
// Receive hardware MAC address
|
||||||
// Suggestion by Marcus Overhagen: Make it a nice for loop...
|
for( temp8 = 0 ; temp8 < 6; temp8++ )
|
||||||
temp8 = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
data->address.ebyte[ temp8 ] = READ_8( IDR0 + temp8 );
|
data->address.ebyte[ temp8 ] = READ_8( IDR0 + temp8 );
|
||||||
temp8++;
|
|
||||||
} while ( temp8 < 6 );
|
TRACE( "rlt8139_nielx open_hook(): MAC address: %x:%x:%x:%x:%x:%x\n",
|
||||||
|
|
||||||
dprintf( "rlt8139_nielx open_hook(): MAC address: %x:%x:%x:%x:%x:%x\n",
|
|
||||||
data->address.ebyte[0] , data->address.ebyte[1] , data->address.ebyte[2] ,
|
data->address.ebyte[0] , data->address.ebyte[1] , data->address.ebyte[2] ,
|
||||||
data->address.ebyte[3] , data->address.ebyte[4] , data->address.ebyte[5] );
|
data->address.ebyte[3] , data->address.ebyte[4] , data->address.ebyte[5] );
|
||||||
|
|
||||||
@ -493,7 +558,7 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
/* We want interrupts! */
|
/* We want interrupts! */
|
||||||
if ( install_io_interrupt_handler( data->pcii->u.h0.interrupt_line , rtl8139_interrupt , data , 0 ) != B_OK )
|
if ( install_io_interrupt_handler( data->pcii->u.h0.interrupt_line , rtl8139_interrupt , data , 0 ) != B_OK )
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx open_hook(): Error installing interrupt handler\n" );
|
TRACE( "rtl8139_nielx open_hook(): Error installing interrupt handler\n" );
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,11 +573,11 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
|
|
||||||
//Check if Tx and Rx are enabled
|
//Check if Tx and Rx are enabled
|
||||||
if( !( READ_8( Command ) & EnableReceive ) || !( READ_8( Command ) & EnableTransmit ) )
|
if( !( READ_8( Command ) & EnableReceive ) || !( READ_8( Command ) & EnableTransmit ) )
|
||||||
dprintf( "TRANSMIT AND RECEIVE NOT ENABLED!!!\n" );
|
TRACE( "TRANSMIT AND RECEIVE NOT ENABLED!!!\n" );
|
||||||
else
|
else
|
||||||
dprintf( "TRANSMIT AND RECEIVE ENABLED!!!\n" );
|
TRACE( "TRANSMIT AND RECEIVE ENABLED!!!\n" );
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx open_hook(): Basic Mode Status Register: 0x%x ESRS: 0x%x\n" ,
|
TRACE( "rtl8139_nielx open_hook(): Basic Mode Status Register: 0x%x ESRS: 0x%x\n" ,
|
||||||
READ_16( BMSR ) ,
|
READ_16( BMSR ) ,
|
||||||
READ_8( ESRS ) );
|
READ_8( ESRS ) );
|
||||||
|
|
||||||
@ -520,6 +585,31 @@ open_hook(const char *name, uint32 flags, void** cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* --------------
|
||||||
|
rtl8139_reset - resets the card
|
||||||
|
----- */
|
||||||
|
|
||||||
|
static void rtl8139_reset( rtl8139_properties_t *data )
|
||||||
|
{
|
||||||
|
// Stop everything and disable interrupts
|
||||||
|
WRITE_8( Command , Reset );
|
||||||
|
WRITE_16( IMR , 0 );
|
||||||
|
|
||||||
|
//Reset the buffer pointers
|
||||||
|
WRITE_16( CBR , 0 );
|
||||||
|
WRITE_16( CAPR , 0 - 16 );
|
||||||
|
data->receivebufferoffset = 0;
|
||||||
|
|
||||||
|
//Re-enable interrupts
|
||||||
|
WRITE_16( IMR ,
|
||||||
|
ReceiveOk | ReceiveError | TransmitOk | TransmitError |
|
||||||
|
ReceiveOverflow | ReceiveUnderflow | ReceiveFIFOOverrun |
|
||||||
|
TimeOut | SystemError );
|
||||||
|
|
||||||
|
//Start rx/tx
|
||||||
|
WRITE_8( Command , EnableReceive | EnableTransmit );
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
read_hook - handle read() calls
|
read_hook - handle read() calls
|
||||||
----- */
|
----- */
|
||||||
@ -529,16 +619,21 @@ 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;
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx: read_hook()\n" );
|
TRACE( "rtl8139_nielx: read_hook()\n" );
|
||||||
|
|
||||||
//if( !data->nonblocking )
|
//if( !data->nonblocking )
|
||||||
acquire_sem_etc( data->input_wait , 1 , B_CAN_INTERRUPT , 0 );
|
acquire_sem_etc( data->input_wait , 1 , B_CAN_INTERRUPT , 0 );
|
||||||
|
|
||||||
|
restart:
|
||||||
|
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
|
||||||
if ( READ_8( Command ) & BUFE )
|
if ( READ_8( Command ) & BUFE )
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx read_hook: Nothing to read!!!\n" );
|
TRACE( "rtl8139_nielx read_hook: Nothing to read!!!\n" );
|
||||||
|
unlock( former );
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,45 +643,43 @@ read_hook (void* cookie, off_t position, void *buf, size_t* num_bytes)
|
|||||||
// 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 )
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx read_hook: The transfer is not yet finished!!!\n" );
|
TRACE( "rtl8139_nielx read_hook: The transfer is not yet finished!!!\n" );
|
||||||
return B_IO_ERROR;
|
unlock( former );
|
||||||
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check for an error: if needed: resetrx, length may not be bigger than 1514 + 4 CRC
|
//Check for an error: if needed: resetrx, length may not be bigger than 1514 + 4 CRC
|
||||||
if ( !( packet_header->bits & 0x1 ) || packet_header->length > 1518 )
|
if ( !( packet_header->bits & 0x1 ) || packet_header->length > 1518 )
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx read_hook: Error in package reception: bits: %u length %u!!!\n" , packet_header->bits , packet_header->length);
|
TRACE( "rtl8139_nielx read_hook: Error in package reception: bits: %u length %u!!!\n" , packet_header->bits , packet_header->length);
|
||||||
return B_IO_ERROR;
|
unlock ( former );
|
||||||
|
rtl8139_reset( data );
|
||||||
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintf( "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;
|
*num_bytes = packet_header->length - 4;
|
||||||
if ( data->receivebufferoffset + *num_bytes > 65536 )
|
if ( data->receivebufferoffset + *num_bytes > 65536 )
|
||||||
{
|
{
|
||||||
//Packet wraps around , copy last bits except header ( = +4 )
|
//Packet wraps around , copy last bits except header ( = +4 )
|
||||||
memcpy( buf , 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( buf + 0x10000 - ( data->receivebufferoffset + 4 ) , data->receivebufferlog , *num_bytes - (0x10000 - ( data->receivebufferoffset + 4 ) ) );
|
memcpy( (void *) ( (uint32)buf + 0x10000 - ( data->receivebufferoffset + 4 ) ) , data->receivebufferlog , *num_bytes - (0x10000 - ( data->receivebufferoffset + 4 ) ) );
|
||||||
dprintf( "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 , 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 ), packet_header->length - 4); //length-4 because we don't want to copy the 4 bytes CRC
|
||||||
|
|
||||||
//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;
|
||||||
|
|
||||||
WRITE_16( CAPR , data->receivebufferoffset - 16 ); //-16, avoid overflow
|
WRITE_16( CAPR , data->receivebufferoffset - 16 ); //-16, avoid overflow
|
||||||
|
TRACE( "rtl8139_nielx read_hook(): CBP %u CAPR %u \n" , READ_16( CBR ) , READ_16( CAPR ) );
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx read_hook(): CBP %u CAPR %u \n" , READ_16( CBR ) , READ_16( CAPR ) );
|
unlock( former );
|
||||||
|
|
||||||
// Re-enable interrupts
|
|
||||||
WRITE_16( ISR , ReceiveOk );
|
|
||||||
WRITE_16( IMR ,
|
|
||||||
ReceiveOk | ReceiveError | TransmitOk | TransmitError |
|
|
||||||
ReceiveOverflow | ReceiveUnderflow | ReceiveFIFOOverrun |
|
|
||||||
TimeOut | SystemError );
|
|
||||||
return packet_header->length - 4;
|
return packet_header->length - 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,54 +695,48 @@ write_hook (void* cookie, off_t position, const void* buffer, size_t* num_bytes)
|
|||||||
int buflen = *num_bytes;
|
int buflen = *num_bytes;
|
||||||
int transmitid = 0;
|
int transmitid = 0;
|
||||||
uint32 transmitdescription = 0;
|
uint32 transmitdescription = 0;
|
||||||
|
cpu_status former;
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx write_hook()\n" );
|
TRACE( "rtl8139_nielx write_hook()\n" );
|
||||||
|
|
||||||
acquire_sem_etc( data->lock , 1 , B_CAN_INTERRUPT, 0);
|
acquire_sem( data->lock );
|
||||||
|
|
||||||
|
//Get spinlock
|
||||||
|
WRITE_16( IMR , 0 );
|
||||||
|
former = lock();
|
||||||
|
|
||||||
if ( data->writes == 4 )
|
if ( data->writes == 4 )
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx write_hook(): already doing four writes\n" );
|
dprintf( "rtl8139_nielx write_hook(): already doing four writes\n" );
|
||||||
|
unlock( former );
|
||||||
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
||||||
return B_INTERRUPTED;
|
return B_INTERRUPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( buflen > 1792 ) //Maximum of 1792 bytes
|
if ( buflen > 1792 ) //Maximum of 1792 bytes
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx write_hook(): packet is too long\n" );
|
TRACE( "rtl8139_nielx write_hook(): packet is too long\n" );
|
||||||
|
unlock( former );
|
||||||
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to determine a free transmit descriptor
|
// We need to determine a free transmit descriptor
|
||||||
if ( data->transmitstatus[ data->nexttransmitstatus ] == 1 )
|
transmitid = data->queued_packets % 4;
|
||||||
|
if ( data->transmitstatus[ transmitid ] == 1 )
|
||||||
{
|
{
|
||||||
//No free descriptor]
|
//No free descriptor]
|
||||||
|
unlock( former );
|
||||||
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Update our current transmit id
|
|
||||||
transmitid = data->nexttransmitstatus;
|
|
||||||
if ( data->nexttransmitstatus == 3 )
|
|
||||||
data->nexttransmitstatus = 0;
|
|
||||||
else
|
|
||||||
data->nexttransmitstatus++;
|
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx write_hook(): TransmitID: %u Packagelen: %u Register: %lx\n" , transmitid , buflen , TSD0 + (sizeof(uint32) * transmitid ) );
|
dprintf( "rtl8139_nielx write_hook(): TransmitID: %u Packagelen: %u Register: %lx\n" , transmitid , buflen , TSD0 + (sizeof(uint32) * transmitid ) );
|
||||||
|
|
||||||
if ( transmitid == -1 )
|
|
||||||
{
|
|
||||||
dprintf( "rtl8139_nielx_write_hook(): no free buffer ?!?\n" );
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->writes++;
|
data->writes++;
|
||||||
// Set the buffer as used
|
// Set the buffer as used
|
||||||
data->transmitstatus[transmitid] = 1;
|
data->transmitstatus[transmitid] = 1;
|
||||||
|
|
||||||
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
|
||||||
|
|
||||||
//Copy the packet into the buffer
|
//Copy the packet into the buffer
|
||||||
memcpy( data->transmitbufferlog[transmitid] , buffer , buflen );
|
memcpy( data->transmitbufferlog[transmitid] , buffer , buflen );
|
||||||
|
|
||||||
@ -658,10 +745,18 @@ write_hook (void* cookie, off_t position, const void* buffer, size_t* num_bytes)
|
|||||||
|
|
||||||
//Clear OWN and start transfer Create transmit description with early Tx FIFO, size
|
//Clear OWN and start transfer Create transmit description with early Tx FIFO, size
|
||||||
transmitdescription = ( buflen | 0x80000 | transmitdescription ) ^OWN; //0x80000 = early tx treshold
|
transmitdescription = ( buflen | 0x80000 | transmitdescription ) ^OWN; //0x80000 = early tx treshold
|
||||||
dprintf( "rtl8139_nielx write: transmitdescription = %lu\n" , transmitdescription );
|
TRACE( "rtl8139_nielx write: transmitdescription = %lu\n" , transmitdescription );
|
||||||
WRITE_32( TSD0 + (sizeof(uint32) * transmitid ) , transmitdescription );
|
WRITE_32( TSD0 + (sizeof(uint32) * transmitid ) , transmitdescription );
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx write: TSAD: %u\n" , READ_16( TSAD ) );
|
TRACE( "rtl8139_nielx write: TSAD: %u\n" , READ_16( TSAD ) );
|
||||||
|
data->queued_packets++;
|
||||||
|
|
||||||
|
unlock( former );
|
||||||
|
WRITE_16( IMR ,
|
||||||
|
ReceiveOk | ReceiveError | TransmitOk | TransmitError |
|
||||||
|
ReceiveOverflow | ReceiveUnderflow | ReceiveFIFOOverrun |
|
||||||
|
TimeOut | SystemError );
|
||||||
|
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
||||||
|
|
||||||
//Done
|
//Done
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@ -677,20 +772,20 @@ control_hook (void* cookie, uint32 op, void* arg, size_t len)
|
|||||||
{
|
{
|
||||||
rtl8139_properties_t *data = (rtl8139_properties_t *)cookie;
|
rtl8139_properties_t *data = (rtl8139_properties_t *)cookie;
|
||||||
ether_address_t address;
|
ether_address_t address;
|
||||||
dprintf( "rtl8139_nielx control_hook()\n" );
|
TRACE( "rtl8139_nielx control_hook()\n" );
|
||||||
|
|
||||||
|
|
||||||
switch ( op )
|
switch ( op )
|
||||||
{
|
{
|
||||||
case ETHER_INIT:
|
case ETHER_INIT:
|
||||||
dprintf( "rtl8139_nielx control_hook(): Wants us to init... ;-)\n" );
|
TRACE( "rtl8139_nielx control_hook(): Wants us to init... ;-)\n" );
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
|
|
||||||
case ETHER_GETADDR:
|
case ETHER_GETADDR:
|
||||||
if ( data == NULL )
|
if ( data == NULL )
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx control_hook(): Wants our address...\n" );
|
TRACE( "rtl8139_nielx control_hook(): Wants our address...\n" );
|
||||||
memcpy( arg , (void *) &(data->address) , sizeof( ether_address_t ) );
|
memcpy( arg , (void *) &(data->address) , sizeof( ether_address_t ) );
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
@ -701,9 +796,9 @@ control_hook (void* cookie, uint32 op, void* arg, size_t len)
|
|||||||
if ( data->multiset == 8 )
|
if ( data->multiset == 8 )
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx control_hook(): Add multicast...\n" );
|
TRACE( "rtl8139_nielx control_hook(): Add multicast...\n" );
|
||||||
memcpy( &address , arg , sizeof( address ) );
|
memcpy( &address , arg , sizeof( address ) );
|
||||||
dprintf( "Multicast address: %i %i %i %i %i %i \n" , address.ebyte[0] ,
|
TRACE( "Multicast address: %i %i %i %i %i %i \n" , address.ebyte[0] ,
|
||||||
address.ebyte[1] , address.ebyte[2] , address.ebyte[3] , address.ebyte[4] ,
|
address.ebyte[1] , address.ebyte[2] , address.ebyte[3] , address.ebyte[4] ,
|
||||||
address.ebyte[5] );
|
address.ebyte[5] );
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@ -712,20 +807,20 @@ control_hook (void* cookie, uint32 op, void* arg, size_t len)
|
|||||||
if ( data == NULL )
|
if ( data == NULL )
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx control_hook(): Wants to set block/nonblock\n" );
|
TRACE( "rtl8139_nielx control_hook(): Wants to set block/nonblock\n" );
|
||||||
memcpy( &data->nonblocking , arg , sizeof( data->nonblocking ) );
|
memcpy( &data->nonblocking , arg , sizeof( data->nonblocking ) );
|
||||||
return B_NO_ERROR;
|
return B_NO_ERROR;
|
||||||
|
|
||||||
case ETHER_REMMULTI:
|
case ETHER_REMMULTI:
|
||||||
dprintf( "rtl8139_nielx control_hook(): Wants REMMULTI\n" );
|
TRACE( "rtl8139_nielx control_hook(): Wants REMMULTI\n" );
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
case ETHER_SETPROMISC:
|
case ETHER_SETPROMISC:
|
||||||
dprintf("rtl8139_nielx control_hook(): Wants PROMISC\n" );
|
TRACE("rtl8139_nielx control_hook(): Wants PROMISC\n" );
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
case ETHER_GETFRAMESIZE:
|
case ETHER_GETFRAMESIZE:
|
||||||
dprintf("rtl8139_nielx control_hook(): Wants GETFRAMESIZE\n" ) ;
|
TRACE("rtl8139_nielx control_hook(): Wants GETFRAMESIZE\n" ) ;
|
||||||
*( (unsigned int *)arg ) = 1514;
|
*( (unsigned int *)arg ) = 1514;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@ -742,100 +837,127 @@ rtl8139_interrupt( void *cookie )
|
|||||||
rtl8139_properties_t *data = (rtl8139_properties_t *)cookie;
|
rtl8139_properties_t *data = (rtl8139_properties_t *)cookie;
|
||||||
uint8 temp8;
|
uint8 temp8;
|
||||||
uint16 isr_contents;
|
uint16 isr_contents;
|
||||||
uint16 isr_write = 0;
|
|
||||||
uint32 txstatus;
|
|
||||||
int32 retval = B_UNHANDLED_INTERRUPT;
|
int32 retval = B_UNHANDLED_INTERRUPT;
|
||||||
cpu_status status;
|
cpu_status status;
|
||||||
|
|
||||||
status = lock();
|
status = lock();
|
||||||
|
WRITE_16( IMR , 0 ); //Disable interrupts
|
||||||
|
|
||||||
isr_contents = READ_16( ISR );
|
for (;;)
|
||||||
dprintf( "NIELX INTERRUPT: %u \n" , isr_contents );
|
|
||||||
if( isr_contents & ReceiveOk )
|
|
||||||
{
|
{
|
||||||
dprintf( "rtl8139_nielx interrupt ReceiveOk\n" );
|
isr_contents = READ_16( ISR );
|
||||||
release_sem_etc( data->input_wait , 1 , B_DO_NOT_RESCHEDULE );
|
if ( isr_contents == 0 )
|
||||||
// First, disable all interrupts until the read hook is finished. It will re-enable them.
|
break;
|
||||||
WRITE_16( IMR , 0 );
|
else
|
||||||
retval = B_INVOKE_SCHEDULER;
|
WRITE_16( ISR , isr_contents );
|
||||||
}
|
|
||||||
|
|
||||||
if (isr_contents & ReceiveError )
|
|
||||||
{
|
|
||||||
//Do something
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isr_contents & TransmitOk )
|
|
||||||
{
|
|
||||||
// Check each status descriptor
|
|
||||||
for (temp8 = 0 ; temp8 < 4 ; temp8++)
|
|
||||||
{
|
|
||||||
// If a register isn't used, continue next run
|
|
||||||
if ( data->transmitstatus[temp8] != 1 )
|
|
||||||
continue;
|
|
||||||
txstatus = READ_32( TSD0 + temp8 * sizeof( int32 ) );
|
|
||||||
dprintf( "run: %u txstatus: %lu Register: %lx\n" , temp8 , txstatus , TSD0 + temp8 * sizeof( int32 ) );
|
|
||||||
|
|
||||||
if ( ( txstatus & TOK ) )
|
TRACE( "NIELX INTERRUPT: %u \n" , isr_contents );
|
||||||
{
|
if( isr_contents & ReceiveOk )
|
||||||
//this one is the one!
|
{
|
||||||
dprintf( "NIELX INTERRUPT: TXOK, clearing register %u\n" , temp8 );
|
TRACE( "rtl8139_nielx interrupt ReceiveOk\n" );
|
||||||
data->transmitstatus[temp8] = 0; //That's all there is to it
|
release_sem_etc( data->input_wait , 1 , B_DO_NOT_RESCHEDULE );
|
||||||
data->writes--;
|
retval = B_INVOKE_SCHEDULER;
|
||||||
//update next transmitid
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
isr_write |= TransmitOk;
|
|
||||||
retval = B_HANDLED_INTERRUPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( isr_contents & TransmitError )
|
if (isr_contents & ReceiveError )
|
||||||
{
|
{
|
||||||
//
|
//Do something
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isr_contents & ReceiveOverflow )
|
if (isr_contents & TransmitOk )
|
||||||
{
|
{
|
||||||
// Discard all the current packages to be processed -- newos driver
|
uint32 checks = data->queued_packets - data->finished_packets;
|
||||||
WRITE_16( CAPR , ( READ_16( CBR ) + 16 ) % 0x1000 );
|
uint32 txstatus;
|
||||||
isr_write |= ReceiveOverflow;
|
// Check each status descriptor
|
||||||
retval = B_HANDLED_INTERRUPT;
|
while( checks > 0 )
|
||||||
}
|
{
|
||||||
|
// If a register isn't used, continue next run
|
||||||
if( isr_contents & ReceiveUnderflow )
|
temp8 = data->finished_packets % 4 ;
|
||||||
{
|
txstatus = READ_32( TSD0 + temp8 * sizeof( int32 ) );
|
||||||
// Most probably a link change -> TODO CHECK!
|
dprintf( "run: %u txstatus: %lu Register: %lx\n" , temp8 , txstatus , TSD0 + temp8 * sizeof( int32 ) );
|
||||||
isr_write |= ReceiveUnderflow;
|
|
||||||
dprintf( "rtl8139_nielx interrupt(): BMCR: 0x%x BMSR: 0x%x\n" ,
|
if ( !( txstatus & ( TOK | TUN | TABT ) ) )
|
||||||
READ_16( BMCR ) ,
|
{
|
||||||
READ_16( BMSR ) );
|
dprintf( "NOT FINISHED\n" );
|
||||||
retval = B_HANDLED_INTERRUPT;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isr_contents & ReceiveFIFOOverrun )
|
if ( txstatus & ( TABT | OWC ) )
|
||||||
{
|
{
|
||||||
//
|
dprintf( "MAJOR ERROR\n" );
|
||||||
;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isr_contents & TimeOut )
|
if ( txstatus &( TUN ) )
|
||||||
{
|
{
|
||||||
//
|
dprintf( "TRANSMIT UNDERRUN\n" );
|
||||||
;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isr_contents & SystemError )
|
if ( ( txstatus & TOK ) )
|
||||||
{
|
{
|
||||||
//
|
//this one is the one!
|
||||||
;
|
dprintf( "NIELX INTERRUPT: TXOK, clearing register %u\n" , temp8 );
|
||||||
}
|
data->transmitstatus[temp8] = 0; //That's all there is to it
|
||||||
|
data->writes--;
|
||||||
WRITE_16( ISR , isr_write );
|
data->finished_packets++;
|
||||||
|
checks--;
|
||||||
|
//update next transmitid
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
retval = B_HANDLED_INTERRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isr_contents & TransmitError )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isr_contents & ReceiveOverflow )
|
||||||
|
{
|
||||||
|
// Discard all the current packages to be processed -- newos driver
|
||||||
|
WRITE_16( CAPR , ( READ_16( CBR ) + 16 ) % 0x1000 );
|
||||||
|
retval = B_HANDLED_INTERRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isr_contents & ReceiveUnderflow )
|
||||||
|
{
|
||||||
|
// Most probably a link change -> TODO CHECK!
|
||||||
|
TRACE( "rtl8139_nielx interrupt(): BMCR: 0x%x BMSR: 0x%x\n" ,
|
||||||
|
READ_16( BMCR ) ,
|
||||||
|
READ_16( BMSR ) );
|
||||||
|
retval = B_HANDLED_INTERRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isr_contents & ReceiveFIFOOverrun )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isr_contents & TimeOut )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isr_contents & SystemError )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Re-enable interrupts
|
||||||
|
WRITE_16( IMR ,
|
||||||
|
ReceiveOk | ReceiveError | TransmitOk | TransmitError |
|
||||||
|
ReceiveOverflow | ReceiveUnderflow | ReceiveFIFOOverrun |
|
||||||
|
TimeOut | SystemError );
|
||||||
|
|
||||||
unlock( status );
|
unlock( status );
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
@ -857,15 +979,15 @@ close_hook (void* cookie)
|
|||||||
|
|
||||||
|
|
||||||
/* -----
|
/* -----
|
||||||
rtl8139_free - called after the last device is closed, and after
|
free_hook - called after the last device is closed, and after
|
||||||
all i/o is complete.
|
all i/o is complete.
|
||||||
----- */
|
----- */
|
||||||
static status_t
|
static status_t
|
||||||
rtl8139_free (void* cookie)
|
free_hook (void* cookie)
|
||||||
{
|
{
|
||||||
rtl8139_properties_t *data = (rtl8139_properties_t *) cookie;
|
rtl8139_properties_t *data = (rtl8139_properties_t *) cookie;
|
||||||
|
|
||||||
dprintf( "rtl8139_nielx free_hook()\n" );
|
TRACE( "rtl8139_nielx free_hook()\n" );
|
||||||
|
|
||||||
//Remove interrupt handler
|
//Remove interrupt handler
|
||||||
remove_io_interrupt_handler( data->pcii->u.h0.interrupt_line ,
|
remove_io_interrupt_handler( data->pcii->u.h0.interrupt_line ,
|
||||||
@ -875,6 +997,9 @@ rtl8139_free (void* cookie)
|
|||||||
delete_area( data->receivebuffer );
|
delete_area( data->receivebuffer );
|
||||||
delete_area( data->transmitbuffer[0] );
|
delete_area( data->transmitbuffer[0] );
|
||||||
delete_area( data->transmitbuffer[2] );
|
delete_area( data->transmitbuffer[2] );
|
||||||
|
delete_area( data->ioarea ); //Only does something on ppc
|
||||||
|
|
||||||
|
m_openmask &= ~(1L << data->device_id);
|
||||||
|
|
||||||
//Finally, free the cookie
|
//Finally, free the cookie
|
||||||
free( data );
|
free( data );
|
||||||
@ -882,9 +1007,6 @@ rtl8139_free (void* cookie)
|
|||||||
//Put the pci module
|
//Put the pci module
|
||||||
put_module( B_PCI_MODULE_NAME );
|
put_module( B_PCI_MODULE_NAME );
|
||||||
|
|
||||||
//To conclude: set the status of the device to closed
|
|
||||||
m_isopen = 0;
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -896,7 +1018,7 @@ rtl8139_free (void* cookie)
|
|||||||
device_hooks rtl8139_hooks = {
|
device_hooks rtl8139_hooks = {
|
||||||
open_hook, /* -> open entry point */
|
open_hook, /* -> open entry point */
|
||||||
close_hook, /* -> close entry point */
|
close_hook, /* -> close entry point */
|
||||||
rtl8139_free, /* -> free cookie */
|
free_hook, /* -> free cookie */
|
||||||
control_hook, /* -> control entry point */
|
control_hook, /* -> control entry point */
|
||||||
read_hook, /* -> read entry point */
|
read_hook, /* -> read entry point */
|
||||||
write_hook /* -> write entry point */
|
write_hook /* -> write entry point */
|
||||||
@ -910,7 +1032,7 @@ device_hooks rtl8139_hooks = {
|
|||||||
const char**
|
const char**
|
||||||
publish_devices()
|
publish_devices()
|
||||||
{
|
{
|
||||||
return rtl8139_name;
|
return (const char **)rtl8139_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
|
@ -101,10 +101,10 @@ area_id map_mem(void **log, void *phy, size_t size, const char *name)
|
|||||||
dprintf("mapping physical address %p with %#lx bytes for %s\n",phy,size,name);
|
dprintf("mapping physical address %p with %#lx bytes for %s\n",phy,size,name);
|
||||||
|
|
||||||
offset = (uint32)phy & (B_PAGE_SIZE - 1);
|
offset = (uint32)phy & (B_PAGE_SIZE - 1);
|
||||||
phyadr = phy - offset;
|
phyadr = (void *) ( (uint32)phy - offset );
|
||||||
size = round_to_pagesize(size + offset);
|
size = round_to_pagesize(size + offset);
|
||||||
area = map_physical_memory(name, phyadr, size, B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA, &mapadr);
|
area = map_physical_memory(name, phyadr, size, B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA, &mapadr);
|
||||||
*log = mapadr + offset;
|
*log = (void *) ( (uint32)mapadr + offset );
|
||||||
|
|
||||||
dprintf("physical = %p, logical = %p, offset = %#lx, phyadr = %p, mapadr = %p, size = %#lx, area = %#lx\n",
|
dprintf("physical = %p, logical = %p, offset = %#lx, phyadr = %p, mapadr = %p, size = %#lx, area = %#lx\n",
|
||||||
phy, *log, offset, phyadr, mapadr, size, area);
|
phy, *log, offset, phyadr, mapadr, size, area);
|
||||||
|
Loading…
Reference in New Issue
Block a user