Import, on behalf of Niels Reedijk (SF ID: nielx), his RTL8139 network cards driver.
Add a Jamfile to build it (thanks to Axel's sis900 jamfile). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3487 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
ef9b1b52ee
commit
dbafe172c0
@ -1,4 +1,5 @@
|
||||
SubDir OBOS_TOP src add-ons kernel drivers network ;
|
||||
|
||||
SubInclude OBOS_TOP src add-ons kernel drivers network rtl8139 ;
|
||||
SubInclude OBOS_TOP src add-ons kernel drivers network sis900 ;
|
||||
SubInclude OBOS_TOP src add-ons kernel drivers network stack ;
|
||||
|
31
src/add-ons/kernel/drivers/network/rtl8139/Jamfile
Normal file
31
src/add-ons/kernel/drivers/network/rtl8139/Jamfile
Normal file
@ -0,0 +1,31 @@
|
||||
SubDir OBOS_TOP src add-ons kernel drivers network rtl8139 ;
|
||||
|
||||
# set some additional defines
|
||||
{
|
||||
local defines ;
|
||||
|
||||
if $(DEBUG) {
|
||||
defines += DEBUG ;
|
||||
}
|
||||
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) -Wall -Wno-multichar ;
|
||||
}
|
||||
|
||||
R5KernelAddon rtl8139 : [ FDirName kernel drivers network ] :
|
||||
driver.c
|
||||
packetlist.c
|
||||
util.c
|
||||
;
|
||||
|
||||
rule InstallRTL8139
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
}
|
||||
|
||||
actions ignore InstallRTL8139
|
||||
{
|
||||
cp $(>) /boot/home/config/add-ons/kernel/drivers/bin/
|
||||
}
|
||||
|
||||
#InstallRTL8139 install : rtl8139 ;
|
6
src/add-ons/kernel/drivers/network/rtl8139/TODO
Normal file
6
src/add-ons/kernel/drivers/network/rtl8139/TODO
Normal file
@ -0,0 +1,6 @@
|
||||
- A major code cleanup
|
||||
- make sure all packets are received
|
||||
- Confirm to the Opentracker coding guidelines
|
||||
- Implement the free_hook
|
||||
- Think of a less memory intensive way
|
||||
- Hammer out the kernel panics caused by the read_hook and the packetlist.*
|
831
src/add-ons/kernel/drivers/network/rtl8139/driver.c
Normal file
831
src/add-ons/kernel/drivers/network/rtl8139/driver.c
Normal file
@ -0,0 +1,831 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, Niels S. Reedijk
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Parts of the code: Copyright (c) 1998 Be, Inc. All Rights Reserved
|
||||
|
||||
/* ++++++++++
|
||||
driver.c
|
||||
Implementation of the Realtek 8139 Chipset
|
||||
+++++ */
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <Drivers.h>
|
||||
#include <Errors.h>
|
||||
#include <PCI.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "ether_driver.h"
|
||||
#include "util.h"
|
||||
#include "packetlist.h"
|
||||
|
||||
/* ----------
|
||||
global data
|
||||
----- */
|
||||
static pci_info *m_device = 0;
|
||||
static pci_module_info *m_pcimodule = 0; //To call methods of pci
|
||||
static int16 m_isopen = 0; //Is the thing already opened?
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION; //Procedure
|
||||
|
||||
//Forward declaration
|
||||
static int32 rtl8139_interrupt(void *data); /* interrupt handler */
|
||||
|
||||
enum registers {
|
||||
IDR0 = 0x0 ,
|
||||
Command = 0x37 ,
|
||||
ChipVersion = 0x43 ,
|
||||
TxConfig = 0x40 ,
|
||||
RxConfig = 0x44 ,
|
||||
Config1 = 0x52 ,
|
||||
BMCR = 0x62 , //BAsic Mode Configuration Register
|
||||
BMSR = 0x64 ,
|
||||
RBSTART = 0x30 ,
|
||||
IMR = 0x3C , //Interrupt mask registers
|
||||
ISR = 0x3E ,
|
||||
_9346CR = 0x50 , // 9346 Configuration register
|
||||
Config4 = 0x5a ,
|
||||
TSD0 = 0x10 ,
|
||||
TSD1 = 0x14 ,
|
||||
MULINT = 0x5c , //Multiple interrupt
|
||||
TSD2 = 0x18 ,
|
||||
TSD3 = 0x1C ,
|
||||
ESRS = 0x36 ,
|
||||
TSAD0 = 0x20 ,
|
||||
TSAD1 = 0x24 ,
|
||||
TSAD2 = 0x28 ,
|
||||
TSAD3 = 0x2C ,
|
||||
TSAD = 0x60 , //Transmit Status of All Descriptors
|
||||
CAPR = 0x38 , //Tail pointer for buffer thingie
|
||||
CBR = 0x3A , //Offset in rxbuffer of next packet
|
||||
MPC = 0x4C ,
|
||||
MAR0 = 0x8 //Multicast register
|
||||
|
||||
};
|
||||
|
||||
|
||||
enum Command_actions {
|
||||
Reset = 0x10 , // 5th bit
|
||||
EnableReceive = 0x08 , // 4th bit
|
||||
EnableTransmit = 0x04 , // 3rd bit
|
||||
BUFE = 0x01
|
||||
};
|
||||
|
||||
enum Transmitter_actions {
|
||||
MXDMA_2 = 0x400 , // 11th bit
|
||||
MXDMA_1 = 0x200 , // 10th bit
|
||||
MXDMA_0 = 0x100 , // 9th bit
|
||||
IFG_1 = 0x2000000 , // 26th bit
|
||||
IFG_0 = 0x1000000 // 25th bit
|
||||
};
|
||||
|
||||
enum Receiver_actions {
|
||||
RXFTH2 = 0x8000, // 16th bit
|
||||
RXFTH1 = 0x4000, // 15th bit
|
||||
RXFTH0 = 0x2000 , // 14th bit
|
||||
RBLEN_1 = 0x1000 , // 13rd bit
|
||||
RBLEN_0 = 0x800 , // 12th bit
|
||||
// MXDMA equal to transmitter
|
||||
WRAP = 0x100 , // 8th bit
|
||||
AB = 0x8 , // 4rd bit
|
||||
AM = 0x4 , // 3rd bit
|
||||
APM = 0x2 // 2nd bit
|
||||
};
|
||||
|
||||
enum TransmitDescription {
|
||||
OWN = 0x2000 ,
|
||||
TOK = 0x8000
|
||||
};
|
||||
|
||||
|
||||
enum InterruptStatusBits {
|
||||
ReceiveOk = 0x01 ,
|
||||
ReceiveError = 0x02 ,
|
||||
TransmitOk = 0x04 ,
|
||||
TransmitError = 0x08 ,
|
||||
ReceiveOverflow = 0x10 ,
|
||||
ReceiveUnderflow = 0x20 ,
|
||||
ReceiveFIFOOverrun = 0x40 ,
|
||||
TimeOut = 0x4000 ,
|
||||
SystemError = 0x8000
|
||||
};
|
||||
|
||||
enum BMCR_Commands {
|
||||
ANE = 0x2000 , // Enable auto config
|
||||
Duplex_Mode = 0x100 ,
|
||||
Restart_Auto_Negotiation = 0x400
|
||||
};
|
||||
|
||||
typedef enum chiptype { RTL_8139_C } chiptype;
|
||||
|
||||
/* ----------
|
||||
structure that stores internal data
|
||||
---- */
|
||||
|
||||
typedef struct rtl8139_properties
|
||||
{
|
||||
pci_info *pcii; /* Pointer to PCI Info for the device */
|
||||
uint32 reg_base; /* Base address for registers */
|
||||
chiptype chip_type; /* Storage for the chip type */
|
||||
|
||||
area_id receivebuffer; /* Memoryaddress for the receive buffer */
|
||||
void *receivebufferlog; /* Logical address */
|
||||
void *receivebufferphy; /* Physical address */
|
||||
uint16 receivebufferoffset;/* Offset for the next package */
|
||||
|
||||
uint8 writes; /* Number of writes (0, maximum 4) */
|
||||
area_id transmitbuffer[4]; /* Transmitbuffers */
|
||||
void *transmitbufferlog[4]; /* Logical 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 nexttransmitstatus;
|
||||
|
||||
uint8 multiset; /* determines if multicast address is set */
|
||||
ether_address_t address; /* holds the MAC address */
|
||||
sem_id lock; /* lock this structure: still interrupt */
|
||||
sem_id input_wait; /* locked until there is a packet to be read */
|
||||
} rtl8139_properties_t;
|
||||
|
||||
typedef struct packetheader
|
||||
{
|
||||
volatile uint16 bits; /* Status bits of the packet header */
|
||||
volatile uint16 length; /* Length of the packet including header + CRC */
|
||||
volatile uint8 data[1];
|
||||
} packetheader_t;
|
||||
|
||||
static status_t close_hook( void * );
|
||||
|
||||
/* -----
|
||||
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
|
||||
----- */
|
||||
status_t
|
||||
init_hardware (void)
|
||||
{
|
||||
// Nielx: no special requirements here...
|
||||
dprintf( "rtl8139_nielx: init_hardware\n" );
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
init_driver - optional function - called every time the driver
|
||||
is loaded.
|
||||
----- */
|
||||
status_t
|
||||
init_driver (void)
|
||||
{
|
||||
status_t status; //Storage for statuses
|
||||
pci_info *item; //Storage used while looking through pci
|
||||
int32 i; //Counter
|
||||
|
||||
m_device = 0; //...
|
||||
|
||||
/*
|
||||
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)
|
||||
if( ( status = get_module( B_PCI_MODULE_NAME, (module_info **)&m_pcimodule )) != B_OK)
|
||||
{
|
||||
dprintf( "rtl8139_nielx init_driver(): Get PCI module failed! %u\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
i = 0;
|
||||
item = (pci_info *)malloc(sizeof(pci_info));
|
||||
while( true )
|
||||
{
|
||||
if ((status = m_pcimodule->get_nth_pci_info(i, item)) != B_OK)
|
||||
break;
|
||||
// Vendorid = 0x10ec and device_id = 0x8139
|
||||
if ( ( item->vendor_id == 0x10ec ) && ( item->device_id == 0x8139 ) )
|
||||
{
|
||||
//Also done in etherpci sample code
|
||||
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");
|
||||
i++; //next
|
||||
continue;
|
||||
}
|
||||
dprintf("rtl8139_nielx init_driver(): found at IRQ %u \n", item->u.h0.interrupt_line);
|
||||
m_device = item;
|
||||
break;
|
||||
}
|
||||
i++; //Look for the next one
|
||||
}
|
||||
|
||||
//Check if we have found any devices:
|
||||
if ( m_device == 0 )
|
||||
{
|
||||
dprintf( "rtl8139_nielx init_driver(): no device found\n" );
|
||||
put_module(B_PCI_MODULE_NAME ); //dereference module
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
uninit_driver - optional function - called every time the driver
|
||||
is unloaded
|
||||
----- */
|
||||
void
|
||||
uninit_driver (void)
|
||||
{
|
||||
free ( m_device );
|
||||
put_module( B_PCI_MODULE_NAME );
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
open_hook - handle open() calls
|
||||
----- */
|
||||
|
||||
static status_t
|
||||
open_hook(const char *name, uint32 flags, void** cookie)
|
||||
{
|
||||
|
||||
rtl8139_properties_t *data;
|
||||
uint8 temp8;
|
||||
uint16 temp16;
|
||||
unsigned char cmd;
|
||||
|
||||
dprintf( "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
|
||||
//are multiple calls, however, this could prevent some ugly bugs)
|
||||
m_isopen = 1;
|
||||
|
||||
//Create a structure that contains the internals
|
||||
if (!(*cookie = data = (rtl8139_properties_t *)malloc(sizeof(rtl8139_properties_t))))
|
||||
{
|
||||
dprintf( "rtl8139_nielx open_hook(): Out of memory\n" );
|
||||
m_isopen = 0;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
//Clear memory
|
||||
memset( data , 0 , sizeof( rtl8139_properties_t ) );
|
||||
|
||||
// Create lock
|
||||
data->lock = create_sem( 1 , "rtl8139_nielx data protect" );
|
||||
set_sem_owner( data->lock , B_SYSTEM_TEAM );
|
||||
data->input_wait = create_sem( 0 , "rtl8139_nielx read wait" );
|
||||
set_sem_owner( data->input_wait , B_SYSTEM_TEAM );
|
||||
set_sem( data->input_wait ); //give the packet list the sem
|
||||
|
||||
//Set up the cookie
|
||||
data->pcii = m_device;
|
||||
|
||||
//Enable the registers
|
||||
data->reg_base = data->pcii->u.h0.base_registers[0];
|
||||
|
||||
/* enable pci address access */
|
||||
cmd = m_pcimodule->read_pci_config(data->pcii->bus, data->pcii->device, data->pcii->function, PCI_command, 2);
|
||||
cmd = cmd | PCI_command_io | PCI_command_master | PCI_command_memory;
|
||||
m_pcimodule->write_pci_config(data->pcii->bus, data->pcii->device, data->pcii->function, PCI_command, 2, cmd );
|
||||
|
||||
// Check for the chipversion
|
||||
/*
|
||||
Please note the following:
|
||||
According to the documentation only some bits are set
|
||||
for the version. I will ignore this for now.
|
||||
*/
|
||||
temp8 = m_pcimodule->read_io_8( data->reg_base + ChipVersion );
|
||||
|
||||
switch ( temp8 )
|
||||
{
|
||||
case 0xFF:
|
||||
dprintf( "rtl8139_nielx open_hook(): Faulty chip\n" );
|
||||
m_isopen = 0;
|
||||
return EIO;
|
||||
|
||||
case 0x74:
|
||||
dprintf( "rtl8139_nielx open_hook(): Chip is the 8139 C\n" );
|
||||
data->chip_type = RTL_8139_C;
|
||||
break;
|
||||
|
||||
default:
|
||||
dprintf( "rtl8139_nielx open_hook(): Unknown chip, assuming 8139 C\n" );
|
||||
data->chip_type = RTL_8139_C;
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: Linux driver does power management here... */
|
||||
|
||||
/* Reset the chip -- command register;*/
|
||||
m_pcimodule->write_io_8( data->reg_base + Command , Reset );
|
||||
temp16 = 10000;
|
||||
while ( ( m_pcimodule->read_io_8( data->reg_base + Command ) & Reset ) && temp16 > 0 )
|
||||
temp16--;
|
||||
|
||||
if ( temp16 == 0 )
|
||||
{
|
||||
dprintf( "rtl8139_nielx open_hook(): Reset failed... Bailing out\n" );
|
||||
m_isopen = 0;
|
||||
free( data );
|
||||
return EIO;
|
||||
}
|
||||
dprintf( "rtl8139_nielx open_hook(): Chip reset: %u \n" , temp16 );
|
||||
|
||||
/* Enable writing to the configuration registers */
|
||||
m_pcimodule->write_io_8( data->reg_base + _9346CR , 0xc0 );
|
||||
|
||||
/* Since the reset was succesful, we can immediately open the transmit and receive registers */
|
||||
m_pcimodule->write_io_8( data->reg_base + Command , EnableReceive | EnableTransmit );
|
||||
|
||||
/* Reset Config1 register */
|
||||
m_pcimodule->write_io_8( data->reg_base + Config1 , 0 );
|
||||
|
||||
// Turn off lan-wake and set the driver-loaded bit
|
||||
m_pcimodule->write_io_8( data->reg_base + Config1, (m_pcimodule->read_io_8(data->reg_base + Config1 )& ~0x30) | 0x20);
|
||||
|
||||
// Enable FIFO auto-clear
|
||||
m_pcimodule->write_io_8( data->reg_base + Config4, m_pcimodule->read_io_8( data->reg_base + Config4) | 0x80);
|
||||
|
||||
// Go to normal operation
|
||||
m_pcimodule->write_io_8( data->reg_base + _9346CR , 0 );
|
||||
|
||||
/* Reset Rx Missed counter*/
|
||||
m_pcimodule->write_io_16( data->reg_base + MPC , 0 );
|
||||
|
||||
/* Configure the Transmit Register */
|
||||
//settings: Max DMA burst size per Tx DMA burst is 1024 ( = 110 )
|
||||
//settings: Interframe GAP time according to IEEE standard ( = 11 )
|
||||
m_pcimodule->write_io_32( data->reg_base + TxConfig ,
|
||||
(m_pcimodule->read_io_32( data->reg_base + TxConfig )) /*| IFG_1 |
|
||||
IFG_0*/ | MXDMA_2 | MXDMA_1 );
|
||||
|
||||
/* Configure the Receive Register */
|
||||
//settings: Early Rx Treshold is 1024 kB ( = 110 ) DISABLED
|
||||
//settings: Max DMA burst size per Rx DMA burst is 1024 ( = 110 )
|
||||
//settings: The Rx Buffer length is 64k + 16 bytes ( = 11 )
|
||||
//settings: continue last packet in memory if it exceeds buffer length.
|
||||
m_pcimodule->write_io_32( data->reg_base + RxConfig , /*RXFTH2 | RXFTH1 | */
|
||||
RBLEN_1 | RBLEN_0 | WRAP | MXDMA_2 | MXDMA_1 | APM | AB);
|
||||
|
||||
//Allocate the ring buffer for the receiver.
|
||||
// Size is set above: as 16k + 16 bytes + 1.5 kB--- 16 bytes for last CRC (a
|
||||
data->receivebuffer = alloc_mem( &(data->receivebufferlog) , &(data->receivebufferphy) , 1024 * 64 + 16 , "rx buffer" );
|
||||
if( data->receivebuffer == B_ERROR )
|
||||
{
|
||||
dprintf( "rtl8139_nielx open_hook(): memory allocation for ringbuffer failed\n" );
|
||||
return B_ERROR;
|
||||
}
|
||||
m_pcimodule->write_io_32( data->reg_base + RBSTART , (int32) data->receivebufferphy );
|
||||
data->receivebufferoffset = 0; //First packet starts at 0
|
||||
|
||||
//Disable all multi-interrupts
|
||||
m_pcimodule->write_io_16( data->reg_base + MULINT , 0 );
|
||||
|
||||
//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" );
|
||||
m_pcimodule->write_io_32( data->reg_base + TSAD0 , (int32)data->transmitbufferphy[0] );
|
||||
data->transmitbuffer[1] = data->transmitbuffer[0];
|
||||
data->transmitbufferlog[1] = data->transmitbufferlog[0] + 2048;
|
||||
data->transmitbufferphy[1] = data->transmitbufferlog[0] + 2048;
|
||||
m_pcimodule->write_io_32( data->reg_base + TSAD1 , (int32)data->transmitbufferphy[1] );
|
||||
|
||||
data->transmitbuffer[2] = alloc_mem( &(data->transmitbufferlog[2]) , &(data->transmitbufferphy[2]) , 4096 , "txbuffer23" );
|
||||
m_pcimodule->write_io_32( data->reg_base + TSAD2 , (int32)data->transmitbufferphy[2] );
|
||||
data->transmitbuffer[3] = data->transmitbuffer[2];
|
||||
data->transmitbufferlog[3] = data->transmitbufferlog[2] + 2048;
|
||||
data->transmitbufferphy[3] = data->transmitbufferlog[2] + 2048;
|
||||
m_pcimodule->write_io_32( data->reg_base + TSAD3 , (int32)data->transmitbufferphy[3] );
|
||||
|
||||
if( data->transmitbuffer[0] == B_ERROR || data->transmitbuffer[2] == B_ERROR )
|
||||
{
|
||||
dprintf( "rtl8139_nielx open_hook(): memory allocation for transmitbuffer failed\n" );
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
data->nexttransmitstatus = 0;
|
||||
|
||||
// Receive hardware MAC address
|
||||
// Suggestion by Marcus Overhagen: Make it a nice for loop...
|
||||
temp8 = 0;
|
||||
do
|
||||
{
|
||||
data->address.ebyte[ temp8 ] = m_pcimodule->read_io_8( data->reg_base + IDR0 + temp8 );
|
||||
temp8++;
|
||||
} while ( temp8 < 6 );
|
||||
|
||||
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[3] , data->address.ebyte[4] , data->address.ebyte[5] );
|
||||
|
||||
/* Receive physical match packets and broadcast packets */
|
||||
m_pcimodule->write_io_32( data->reg_base + RxConfig ,
|
||||
(m_pcimodule->read_io_32( data->reg_base + RxConfig )) | APM | AB );
|
||||
|
||||
//Clear multicast mask
|
||||
m_pcimodule->write_io_32( data->reg_base + MAR0 , 0 );
|
||||
m_pcimodule->write_io_32( data->reg_base + MAR0 + 4 , 0 );
|
||||
|
||||
|
||||
/* We want interrupts! */
|
||||
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" );
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
m_pcimodule->write_io_16( data->reg_base + IMR ,
|
||||
ReceiveOk | ReceiveError | TransmitOk | TransmitError |
|
||||
ReceiveOverflow | ReceiveUnderflow | ReceiveFIFOOverrun |
|
||||
TimeOut | SystemError );
|
||||
|
||||
/* Enable once more */
|
||||
m_pcimodule->write_io_8( data->reg_base + _9346CR , 0 );
|
||||
m_pcimodule->write_io_8( data->reg_base + Command , EnableReceive | EnableTransmit );
|
||||
|
||||
//Check if Tx and Rx are enabled
|
||||
if( !( m_pcimodule->read_io_8( data->reg_base + Command ) & EnableReceive ) || !( m_pcimodule->read_io_8( data->reg_base + Command ) & EnableTransmit ) )
|
||||
dprintf( "TRANSMIT AND RECEIVE NOT ENABLED!!!\n" );
|
||||
else
|
||||
dprintf( "TRANSMIT AND RECEIVE ENABLED!!!\n" );
|
||||
|
||||
dprintf( "rtl8139_nielx open_hook(): Basic Mode Status Register: 0x%x ESRS: 0x%x\n" ,
|
||||
m_pcimodule->read_io_16( data->reg_base + BMSR ) ,
|
||||
m_pcimodule->read_io_8( data->reg_base + ESRS ) );
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
read_hook - handle read() calls
|
||||
----- */
|
||||
|
||||
static status_t
|
||||
read_hook (void* cookie, off_t position, void *buf, size_t* num_bytes)
|
||||
{
|
||||
rtl8139_properties_t *data =/* (rtl8139_properties_t *)*/cookie;
|
||||
uint16 length;
|
||||
net_packet_t *packet;
|
||||
|
||||
dprintf( "rtl8139_nielx: read_hook()\n" );
|
||||
|
||||
acquire_sem_etc( data->input_wait , 1 , B_CAN_INTERRUPT , 0 );
|
||||
|
||||
packet = get_packet();
|
||||
if ( packet == 0 ) //No packets in queue
|
||||
return B_ERROR;
|
||||
|
||||
if ( packet->len > *num_bytes )
|
||||
{
|
||||
free( packet->buffer );
|
||||
free ( packet );
|
||||
return B_IO_ERROR;
|
||||
}
|
||||
|
||||
length = packet->len;
|
||||
|
||||
memcpy( buf , packet->buffer , length );
|
||||
|
||||
free( packet->buffer );
|
||||
free( packet );
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
rtl8139_write - handle write() calls
|
||||
----- */
|
||||
|
||||
static status_t
|
||||
write_hook (void* cookie, off_t position, const void* buffer, size_t* num_bytes)
|
||||
{
|
||||
rtl8139_properties_t *data =/* (rtl8139_properties_t *)*/cookie;
|
||||
int buflen = *num_bytes;
|
||||
int transmitid = 0;
|
||||
uint32 transmitdescription = 0;
|
||||
|
||||
dprintf( "rtl8139_nielx write_hook()\n" );
|
||||
|
||||
acquire_sem_etc( data->lock , 1 , B_CAN_INTERRUPT, 0);
|
||||
|
||||
if ( data->writes == 4 )
|
||||
{
|
||||
dprintf( "rtl8139_nielx write_hook(): already doing four writes\n" );
|
||||
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
||||
return B_INTERRUPTED;
|
||||
}
|
||||
|
||||
if ( buflen > 1792 ) //Maximum of 1792 bytes
|
||||
{
|
||||
dprintf( "rtl8139_nielx write_hook(): packet is too long\n" );
|
||||
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
||||
return B_IO_ERROR;
|
||||
}
|
||||
|
||||
// We need to determine a free transmit descriptor
|
||||
if ( data->transmitstatus[ data->nexttransmitstatus ] == 1 )
|
||||
{
|
||||
//No free descriptor]
|
||||
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
||||
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: %x\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++;
|
||||
// Set the buffer as used
|
||||
data->transmitstatus[transmitid] = 1;
|
||||
|
||||
release_sem_etc( data->lock , 1 , B_DO_NOT_RESCHEDULE );
|
||||
|
||||
//Copy the packet into the buffer
|
||||
memcpy( data->transmitbufferlog[transmitid] , buffer , buflen );
|
||||
|
||||
if ( buflen < 60 )
|
||||
buflen = 60;
|
||||
|
||||
//Clear OWN and start transfer Create transmit description with early Tx FIFO, size
|
||||
transmitdescription = ( buflen | 0x80000 | transmitdescription ) ^OWN; //0x80000 = early tx treshold
|
||||
dprintf( "rtl8139_nielx write: transmitdescription = %u\n" , transmitdescription );
|
||||
m_pcimodule->write_io_32( data->reg_base + TSD0 + (sizeof(uint32) * transmitid ) , transmitdescription );
|
||||
|
||||
dprintf( "rtl8139_nielx write: TSAD: %u\n" , m_pcimodule->read_io_16( data->reg_base + TSAD ) );
|
||||
|
||||
//Done
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
rtl8139_control - handle ioctl calls
|
||||
----- */
|
||||
|
||||
static status_t
|
||||
control_hook (void* cookie, uint32 op, void* arg, size_t len)
|
||||
{
|
||||
rtl8139_properties_t *data = (rtl8139_properties_t *)cookie;
|
||||
|
||||
dprintf( "rtl8139_nielx control_hook()\n" );
|
||||
|
||||
|
||||
switch ( op )
|
||||
{
|
||||
case ETHER_GETADDR:
|
||||
if ( data == NULL )
|
||||
return B_ERROR;
|
||||
|
||||
dprintf( "rtl8139_nielx control_hook(): Wants our address...\n" );
|
||||
memcpy( arg , (void *) &(data->address) , sizeof( ether_address_t ) );
|
||||
return B_OK;
|
||||
}
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
interrupt_handler - handle issued interrupts
|
||||
----- */
|
||||
|
||||
static int32
|
||||
rtl8139_interrupt( void *cookie )
|
||||
{
|
||||
rtl8139_properties_t *data = (rtl8139_properties_t *)cookie;
|
||||
uint8 temp8;
|
||||
uint16 isr_contents;
|
||||
uint16 isr_write = 0;
|
||||
uint32 txstatus;
|
||||
int32 retval = B_UNHANDLED_INTERRUPT;
|
||||
cpu_status status;
|
||||
|
||||
status = lock();
|
||||
|
||||
isr_contents = m_pcimodule->read_io_16( data->reg_base + ISR );
|
||||
dprintf( "NIELX INTERRUPT: %u \n" , isr_contents );
|
||||
if( isr_contents & ReceiveOk )
|
||||
{
|
||||
dprintf( "rtl8139_nielx interrupt ReceiveOk: %x\n" , m_pcimodule->read_io_16( data->reg_base + CBR ) );
|
||||
isr_write |= ReceiveOk;
|
||||
retval = B_HANDLED_INTERRUPT;
|
||||
//Next: check in command register if there's actually anything to be read
|
||||
while ( !( m_pcimodule->read_io_8( data->reg_base + Command ) & BUFE ) )
|
||||
{
|
||||
packetheader_t *packet_header;
|
||||
|
||||
// Retrieve the packet header
|
||||
packet_header = (packetheader_t *) ( ( uint8 *)data->receivebufferlog + data->receivebufferoffset );
|
||||
|
||||
// Check if the transfer is already done: EarlyRX THIS SHOULD NEVER HAPPEN
|
||||
if ( packet_header->length == 0xfff0 )
|
||||
{
|
||||
dprintf( "rtl8139_nielx interrupt: The transfer is not yet finished!!!\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
//Check for an error: if needed: resetrx
|
||||
if ( !( packet_header->bits & 0x1 ) || packet_header->length > 1500 )
|
||||
{
|
||||
dprintf( "rtl8139_nielx Interrupt: Error in package reception!!!\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
//Append the packet to the list
|
||||
append_packet( data->receivebufferlog + data->receivebufferoffset + 4 , packet_header->length - 4 ); //-4 -- we don't want CRC
|
||||
|
||||
//Update read pointer
|
||||
data->receivebufferoffset = ( data->receivebufferoffset + packet_header->length + 4 + 3 ) & ~3;
|
||||
m_pcimodule->write_io_16( data->reg_base + CAPR , data->receivebufferoffset - 16 ); //-16, avoid overflow
|
||||
dprintf( "rtl8139_nielx interrupt: Packet received ok!!!\n" );
|
||||
}
|
||||
}
|
||||
|
||||
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 = m_pcimodule->read_io_32( data->reg_base + TSD0 + temp8 * sizeof( int32 ) );
|
||||
dprintf( "run: %u txstatus: %u Register: %x\n" , temp8 , txstatus , TSD0 + temp8 * sizeof( int32 ) );
|
||||
|
||||
//m_pcimodule->write_io_32( data->reg_base + TSAD0 + temp8 * sizeof( int32) , (m_pcimodule->read_io_32( data->reg_base + TSAD0 + temp8 * sizeof( int32 ) ) ) | OWN ) ;
|
||||
|
||||
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--;
|
||||
//update next transmitid
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
isr_write |= TransmitOk;
|
||||
retval = B_HANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
if( isr_contents & TransmitError )
|
||||
{
|
||||
//
|
||||
;
|
||||
}
|
||||
|
||||
if( isr_contents & ReceiveOverflow )
|
||||
{
|
||||
// Discard all the current packages to be processed -- newos driver
|
||||
m_pcimodule->write_io_16( data->reg_base + CAPR , ( m_pcimodule->read_io_16( CBR ) + 16 ) % 0x1000 );
|
||||
isr_write |= ReceiveOverflow;
|
||||
retval = B_HANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
if( isr_contents & ReceiveUnderflow )
|
||||
{
|
||||
// Most probably a link change -> TODO CHECK!
|
||||
isr_write |= ReceiveUnderflow;
|
||||
dprintf( "rtl8139_nielx interrupt(): BMCR: 0x%x BMSR: 0x%x\n" ,
|
||||
m_pcimodule->read_io_16( data->reg_base + BMCR ) ,
|
||||
m_pcimodule->read_io_16( data->reg_base + BMSR ) );
|
||||
retval = B_HANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
if ( isr_contents & ReceiveFIFOOverrun )
|
||||
{
|
||||
//
|
||||
;
|
||||
}
|
||||
|
||||
if ( isr_contents & TimeOut )
|
||||
{
|
||||
//
|
||||
;
|
||||
}
|
||||
|
||||
if ( isr_contents & SystemError )
|
||||
{
|
||||
//
|
||||
;
|
||||
}
|
||||
|
||||
m_pcimodule->write_io_16( data->reg_base + ISR , isr_write );
|
||||
|
||||
unlock( status );
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
close_hook - handle close() calls
|
||||
----- */
|
||||
|
||||
static status_t
|
||||
close_hook (void* cookie)
|
||||
{
|
||||
rtl8139_properties_t * data = (rtl8139_properties_t *) cookie;
|
||||
m_pcimodule->write_io_8( data->reg_base + Command , Reset );
|
||||
m_pcimodule->write_io_16( data->reg_base + IMR , 0 );
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* -----
|
||||
rtl8139_free - called after the last device is closed, and after
|
||||
all i/o is complete.
|
||||
----- */
|
||||
static status_t
|
||||
rtl8139_free (void* cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/* -----
|
||||
function pointers for the device hooks entry points
|
||||
----- */
|
||||
|
||||
device_hooks rtl8139_hooks = {
|
||||
open_hook, /* -> open entry point */
|
||||
close_hook, /* -> close entry point */
|
||||
rtl8139_free, /* -> free cookie */
|
||||
control_hook, /* -> control entry point */
|
||||
read_hook, /* -> read entry point */
|
||||
write_hook /* -> write entry point */
|
||||
};
|
||||
|
||||
/* ----------
|
||||
publish_devices - return a null-terminated array of devices
|
||||
supported by this driver.
|
||||
----- */
|
||||
|
||||
const char**
|
||||
publish_devices()
|
||||
{
|
||||
return rtl8139_name;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
find_device - return ptr to device hooks structure for a
|
||||
given device name
|
||||
----- */
|
||||
|
||||
device_hooks*
|
||||
find_device(const char* name)
|
||||
{
|
||||
return &rtl8139_hooks;
|
||||
}
|
57
src/add-ons/kernel/drivers/network/rtl8139/ether_driver.h
Normal file
57
src/add-ons/kernel/drivers/network/rtl8139/ether_driver.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* ether_driver.h
|
||||
*
|
||||
* Ethernet driver: handles NE2000 and 3C503 cards
|
||||
*/
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
#ifndef _ETHER_DRIVER_H
|
||||
#define _ETHER_DRIVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <Drivers.h>
|
||||
|
||||
/*
|
||||
* ioctls: belongs in a public header file
|
||||
* somewhere, so that the net_server and other ethernet drivers can use.
|
||||
*/
|
||||
enum {
|
||||
ETHER_GETADDR = B_DEVICE_OP_CODES_END, /* get ethernet address */
|
||||
ETHER_INIT, /* set irq and port */
|
||||
ETHER_NONBLOCK, /* set/unset nonblocking mode */
|
||||
ETHER_ADDMULTI, /* add multicast addr */
|
||||
ETHER_REMMULTI, /* rem multicast addr */
|
||||
ETHER_SETPROMISC, /* set promiscuous */
|
||||
ETHER_GETFRAMESIZE /* get frame size */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 48-bit ethernet address, passed back from ETHER_GETADDR
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char ebyte[6];
|
||||
} ether_address_t;
|
||||
|
||||
|
||||
/*
|
||||
* info passed to ETHER_INIT
|
||||
*/
|
||||
|
||||
typedef struct ether_init_params {
|
||||
short port;
|
||||
short irq;
|
||||
unsigned long mem;
|
||||
} ether_init_params_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _ETHER_DRIVER_H */
|
57
src/add-ons/kernel/drivers/network/rtl8139/packetlist.c
Normal file
57
src/add-ons/kernel/drivers/network/rtl8139/packetlist.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include "packetlist.h"
|
||||
#include <malloc.h>
|
||||
|
||||
static net_packet_list_t *firstpacketlist = 0;
|
||||
static net_packet_list_t *lastpacketlist = 0;
|
||||
static sem_id mysem;
|
||||
|
||||
void append_packet( void *pointer , int16 size )
|
||||
{
|
||||
net_packet_list_t *temp;
|
||||
|
||||
temp = (net_packet_list_t *) malloc( sizeof( net_packet_list_t ) );
|
||||
temp->packet = (net_packet_t *) malloc( sizeof( net_packet_t ) );
|
||||
temp->next = 0;
|
||||
temp->packet->len = size;
|
||||
temp->packet->buffer = (void *) malloc( size );
|
||||
memcpy( temp->packet->buffer , pointer , size );
|
||||
|
||||
//This is the first packet
|
||||
if (firstpacketlist == 0 )
|
||||
firstpacketlist = temp;
|
||||
|
||||
if ( lastpacketlist == 0 )
|
||||
lastpacketlist = temp;
|
||||
else
|
||||
{
|
||||
lastpacketlist->next = temp;
|
||||
lastpacketlist = temp;
|
||||
}
|
||||
//Release the semaphore with 1, so with each packet read can do a run
|
||||
release_sem_etc( mysem , 1 , B_DO_NOT_RESCHEDULE );
|
||||
}
|
||||
|
||||
net_packet_t *get_packet()
|
||||
{
|
||||
net_packet_list_t *temp;
|
||||
net_packet_t *retval;
|
||||
|
||||
if ( firstpacketlist == 0 )
|
||||
return 0;
|
||||
|
||||
temp = firstpacketlist->next;
|
||||
retval = firstpacketlist->packet;
|
||||
free( firstpacketlist );
|
||||
|
||||
if ( temp == 0 ) //There are no more packets in teh queue
|
||||
{
|
||||
firstpacketlist = 0;
|
||||
lastpacketlist = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void set_sem( sem_id sem )
|
||||
{
|
||||
mysem = sem;
|
||||
}
|
21
src/add-ons/kernel/drivers/network/rtl8139/packetlist.h
Normal file
21
src/add-ons/kernel/drivers/network/rtl8139/packetlist.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* This file describes a netpacket kernel buffer */
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
typedef struct net_packet
|
||||
{
|
||||
void *buffer; /* Contains the packet without CRC */
|
||||
uint16 len; /* Contains the length of the packet */
|
||||
} net_packet_t;
|
||||
|
||||
struct net_packet_list;
|
||||
|
||||
typedef struct net_packet_list {
|
||||
net_packet_t *packet; /* Contains a pointer to the current packet */
|
||||
struct net_packet_list *next; /* Contains a pointer to the next packet -- if 0, then ther is none */
|
||||
} net_packet_list_t;
|
||||
|
||||
|
||||
net_packet_t *get_packet();
|
||||
void append_packet( void *pointer , int16 size );
|
||||
void set_sem( sem_id sem );
|
113
src/add-ons/kernel/drivers/network/rtl8139/util.c
Normal file
113
src/add-ons/kernel/drivers/network/rtl8139/util.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* BeOS Driver for Intel ICH AC'97 Link interface
|
||||
*
|
||||
* Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include <Errors.h>
|
||||
#include <OS.h>
|
||||
#include <string.h>
|
||||
|
||||
//#define DEBUG 2
|
||||
|
||||
|
||||
#include "util.h"
|
||||
|
||||
spinlock slock = 0;
|
||||
|
||||
uint32 round_to_pagesize(uint32 size);
|
||||
|
||||
cpu_status lock(void)
|
||||
{
|
||||
cpu_status status = disable_interrupts();
|
||||
acquire_spinlock(&slock);
|
||||
return status;
|
||||
}
|
||||
|
||||
void unlock(cpu_status status)
|
||||
{
|
||||
release_spinlock(&slock);
|
||||
restore_interrupts(status);
|
||||
}
|
||||
|
||||
uint32 round_to_pagesize(uint32 size)
|
||||
{
|
||||
return (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
|
||||
}
|
||||
|
||||
area_id alloc_mem(void **log, void **phy, size_t size, const char *name)
|
||||
{
|
||||
physical_entry pe;
|
||||
void * logadr;
|
||||
area_id areaid;
|
||||
status_t rv;
|
||||
|
||||
dprintf("rtl8139_nielx: allocating %d bytes for %s\n",size,name);
|
||||
|
||||
size = round_to_pagesize(size);
|
||||
areaid = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS,size,B_FULL_LOCK | B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
|
||||
if (areaid < B_OK) {
|
||||
dprintf("couldn't allocate area %s\n",name);
|
||||
return B_ERROR;
|
||||
}
|
||||
rv = get_memory_map(logadr,size,&pe,1);
|
||||
if (rv < B_OK) {
|
||||
delete_area(areaid);
|
||||
dprintf("couldn't map %s\n",name);
|
||||
return B_ERROR;
|
||||
}
|
||||
memset(logadr,0,size);
|
||||
if (log)
|
||||
*log = logadr;
|
||||
if (phy)
|
||||
*phy = pe.address;
|
||||
dprintf("area = %d, size = %d, log = %#08X, phy = %#08X\n",areaid,size,logadr,pe.address);
|
||||
return areaid;
|
||||
}
|
||||
|
||||
/* This is not the most advanced method to map physical memory for io access.
|
||||
* Perhaps using B_ANY_KERNEL_ADDRESS instead of B_ANY_KERNEL_BLOCK_ADDRESS
|
||||
* makes the whole offset calculation and relocation obsolete. But the code
|
||||
* below does work, and I can't test if using B_ANY_KERNEL_ADDRESS also works.
|
||||
*/
|
||||
area_id map_mem(void **log, void *phy, size_t size, const char *name)
|
||||
{
|
||||
uint32 offset;
|
||||
void *phyadr;
|
||||
void *mapadr;
|
||||
area_id area;
|
||||
|
||||
dprintf("mapping physical address %p with %#x bytes for %s\n",phy,size,name);
|
||||
|
||||
offset = (uint32)phy & (B_PAGE_SIZE - 1);
|
||||
phyadr = phy - 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);
|
||||
*log = mapadr + offset;
|
||||
|
||||
dprintf("physical = %p, logical = %p, offset = %#x, phyadr = %p, mapadr = %p, size = %#x, area = %#x\n",
|
||||
phy, *log, offset, phyadr, mapadr, size, area);
|
||||
|
||||
return area;
|
||||
}
|
41
src/add-ons/kernel/drivers/network/rtl8139/util.h
Normal file
41
src/add-ons/kernel/drivers/network/rtl8139/util.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* BeOS Driver for Intel ICH AC'97 Link interface
|
||||
*
|
||||
* Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
area_id alloc_mem(void **log, void **phy, size_t size, const char *name);
|
||||
area_id map_mem(void **log, void *phy, size_t size, const char *name);
|
||||
|
||||
cpu_status lock(void);
|
||||
void unlock(cpu_status status);
|
||||
|
||||
extern spinlock slock;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user