A BeOS driver for the VIA Rhine chipset, written by Richard Houle.
Released under the BSD license. =========================================== From: "Richard Houle" <[email protected]> Subject: RE: License question regarding beos via rhine driver. Date: Thu, 1 Apr 2004 08:48:02 -0500 Whoa. You talking about very old stuff. I don't even know if I kept a copy of that source code... If you have a copy of it, then you can do what you want. I don't have any objections or restrictions. For the license question, the driver was directly inspired by the FreeBSD driver's source code. Therefore, It's a BSD License. Richard Houle =========================================== git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7378 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* VIA VT86C100A Rhine-II and VIA VT3043 Rhine Based Card Driver
|
||||||
|
* for the BeOS Release 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Libraries
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver-Related Libraries
|
||||||
|
*/
|
||||||
|
#include <OS.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine Libraries
|
||||||
|
*/
|
||||||
|
#include "via-rhine.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine Commands
|
||||||
|
*/
|
||||||
|
void cmd_reset(viarhine_private *device)
|
||||||
|
{
|
||||||
|
write16(device->addr + ChipCmd, CmdReset);
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("cmd_reset\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_getmacaddr(viarhine_private *device)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
device->macaddr.ebyte[i] = read8(device->addr + StationAddr + i);
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("cmd_getmacaddr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
|
||||||
|
(unsigned char)device->macaddr.ebyte[0],
|
||||||
|
(unsigned char)device->macaddr.ebyte[1],
|
||||||
|
(unsigned char)device->macaddr.ebyte[2],
|
||||||
|
(unsigned char)device->macaddr.ebyte[3],
|
||||||
|
(unsigned char)device->macaddr.ebyte[4],
|
||||||
|
(unsigned char)device->macaddr.ebyte[5]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* VIA VT86C100A Rhine-II and VIA VT3043 Rhine Based Card Driver
|
||||||
|
* for the BeOS Release 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Libraries
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver-Related Libraries
|
||||||
|
*/
|
||||||
|
#include <OS.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine Libraries
|
||||||
|
*/
|
||||||
|
#include "via-rhine.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Driver Entry Functions
|
||||||
|
*/
|
||||||
|
__declspec(dllexport) status_t init_driver (void);
|
||||||
|
__declspec(dllexport) void uninit_driver (void);
|
||||||
|
__declspec(dllexport) const char **publish_devices(void);
|
||||||
|
__declspec(dllexport) device_hooks *find_device (const char *name);
|
||||||
|
|
||||||
|
char *pDevNameList[MAX_CARDS+1];
|
||||||
|
pci_info *pDevList [MAX_CARDS+1];
|
||||||
|
pci_module_info *pModuleInfo;
|
||||||
|
|
||||||
|
const char **publish_devices(void)
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("publish_devices\n");
|
||||||
|
#endif
|
||||||
|
return (const char **)pDevNameList;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t init_hardware(void )
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("init_hardware\n");
|
||||||
|
#endif
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t init_driver()
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
int32 entries;
|
||||||
|
char devName[64];
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("init_driver\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((status = get_module(B_PCI_MODULE_NAME, (module_info **)&pModuleInfo)) != B_OK)
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf(DevName ": init_driver: get_module failed! (%s)\n", strerror(status));
|
||||||
|
#endif
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find VIA Rhine Cards
|
||||||
|
if ((entries = pci_getlist(pDevList, MAX_CARDS)) == 0)
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf(DevName ": init_driver: Device(s) Not Found\n");
|
||||||
|
#endif
|
||||||
|
pci_freelist(pDevList);
|
||||||
|
put_module (B_PCI_MODULE_NAME);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Device Name List
|
||||||
|
for (i = 0; i < entries; i++)
|
||||||
|
{
|
||||||
|
sprintf(devName, "%s%ld", DevDir, i );
|
||||||
|
pDevNameList[i] = (char*)malloc(strlen(devName) + 1);
|
||||||
|
strcpy(pDevNameList[i], devName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pDevNameList[i] = NULL;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninit_driver(void)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
void *item;
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("uninit_driver\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Free Device Name List
|
||||||
|
for (i = 0; (item = pDevNameList[i]); i++)
|
||||||
|
free(item);
|
||||||
|
|
||||||
|
// Free Device List
|
||||||
|
pci_freelist(pDevList);
|
||||||
|
put_module (B_PCI_MODULE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_hooks *find_device(const char *name)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
char *item;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Find Device Name
|
||||||
|
for (i = 0; (item = pDevNameList[i]); i++)
|
||||||
|
{
|
||||||
|
if (strcmp(name, item) == 0)
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("find_device: Device Found (%s)\n", name);
|
||||||
|
#endif
|
||||||
|
return &pDeviceHooks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("find_device: Device (%s) Not Found\n", name);
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||||
@@ -0,0 +1,510 @@
|
|||||||
|
/*
|
||||||
|
* VIA VT86C100A Rhine-II and VIA VT3043 Rhine Based Card Driver
|
||||||
|
* for the BeOS Release 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Libraries
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver-Related Libraries
|
||||||
|
*/
|
||||||
|
#include <OS.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine Libraries
|
||||||
|
*/
|
||||||
|
#include "via-rhine.h"
|
||||||
|
|
||||||
|
int32 nOpenMask = 0;
|
||||||
|
|
||||||
|
int32 hook_interrupt(void *_device)
|
||||||
|
{
|
||||||
|
viarhine_private *device = (viarhine_private*)_device;
|
||||||
|
int32 handled = B_UNHANDLED_INTERRUPT;
|
||||||
|
int16 worklimit = 20;
|
||||||
|
uint16 reg;
|
||||||
|
uint32 i, j;
|
||||||
|
int wakeup_reader = 0;
|
||||||
|
int wakeup_writer = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
reg = read16(device->addr + IntrStatus);
|
||||||
|
|
||||||
|
// Acknowledge All of the Current Interrupt Sources ASAP.
|
||||||
|
write16(device->addr + IntrStatus, reg & 0xffff);
|
||||||
|
|
||||||
|
if (reg == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (reg & IntrRxDone)
|
||||||
|
{
|
||||||
|
wakeup_reader++;
|
||||||
|
write16(device->addr, CmdRxDemand | device->cmd);
|
||||||
|
handled = B_HANDLED_INTERRUPT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (reg & IntrTxDone)
|
||||||
|
{
|
||||||
|
wakeup_writer++;
|
||||||
|
handled = B_HANDLED_INTERRUPT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reg & (IntrRxErr | IntrRxDropped | IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf))
|
||||||
|
{
|
||||||
|
write16(device->addr, CmdRxDemand | device->cmd);
|
||||||
|
handled = B_HANDLED_INTERRUPT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (reg & IntrTxAbort)
|
||||||
|
{
|
||||||
|
/* Just restart Tx. */
|
||||||
|
write16(device->addr, CmdTxDemand | device->cmd);
|
||||||
|
handled = B_HANDLED_INTERRUPT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (reg & IntrTxUnderrun)
|
||||||
|
{
|
||||||
|
if (device->tx_thresh < 0xE0)
|
||||||
|
write8(device->addr + TxConfig, device->tx_thresh += 0x20);
|
||||||
|
write16(device->addr, CmdTxDemand | device->cmd);
|
||||||
|
handled = B_HANDLED_INTERRUPT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* if (reg & IntrTxDone)
|
||||||
|
{
|
||||||
|
if (device->tx > 0)
|
||||||
|
device->tx--;
|
||||||
|
|
||||||
|
if (device->tx > 0)
|
||||||
|
write16(device->addr, CmdTxDemand | device->cmd);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (--worklimit < 0)
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
if (wakeup_reader)
|
||||||
|
{
|
||||||
|
for (i = 0, j = 0; i < RX_BUFFERS; i++)
|
||||||
|
{
|
||||||
|
if (!(device->rx_desc[i].rx_status & DescOwn))
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device->cur_rx = j;
|
||||||
|
input_unwait(device, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wakeup_writer)
|
||||||
|
{
|
||||||
|
output_unwait(device, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t hook_open(const char *name, uint32 flags, void **cookie)
|
||||||
|
{
|
||||||
|
char *devName;
|
||||||
|
int i;
|
||||||
|
int32 devID;
|
||||||
|
int32 mask;
|
||||||
|
area_id cookieID;
|
||||||
|
status_t status;
|
||||||
|
uint32 size;
|
||||||
|
viarhine_private *device;
|
||||||
|
|
||||||
|
// Find Device Name
|
||||||
|
for (devID = 0; (devName = pDevNameList[devID]); devID++)
|
||||||
|
{
|
||||||
|
if (strcmp(name, devName) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!devName)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
// Check if the Device is Busy and Set in-use Flag if Not
|
||||||
|
mask = 1 << devID;
|
||||||
|
if (atomic_or(&nOpenMask, mask) & mask)
|
||||||
|
return B_BUSY;
|
||||||
|
|
||||||
|
// Allocate Storage for the Cookie
|
||||||
|
size = RNDUP(sizeof(viarhine_private), B_PAGE_SIZE);
|
||||||
|
cookieID = create_area( DevName " cookie",
|
||||||
|
cookie,
|
||||||
|
B_ANY_KERNEL_ADDRESS,
|
||||||
|
size,
|
||||||
|
B_FULL_LOCK,
|
||||||
|
B_READ_AREA | B_WRITE_AREA);
|
||||||
|
|
||||||
|
if (cookieID < 0)
|
||||||
|
{
|
||||||
|
status = B_NO_MEMORY;
|
||||||
|
goto Err0;
|
||||||
|
}
|
||||||
|
|
||||||
|
device = (viarhine_private*)(*cookie);
|
||||||
|
memset(device, 0, sizeof(viarhine_private));
|
||||||
|
|
||||||
|
// Setup the Cookie
|
||||||
|
device->cookieID = cookieID;
|
||||||
|
device->devID = devID;
|
||||||
|
device->pciInfo = pDevList[devID];
|
||||||
|
device->addr = device->pciInfo->u.h0.base_registers[0];
|
||||||
|
|
||||||
|
if ((status = res_allocate(device)) != B_OK)
|
||||||
|
goto Err1;
|
||||||
|
|
||||||
|
cmd_reset(device);
|
||||||
|
snooze(2000);
|
||||||
|
cmd_getmacaddr(device);
|
||||||
|
|
||||||
|
// Initialize MII Chip
|
||||||
|
if (cap_tbl[device->devID].flags & CanHaveMII)
|
||||||
|
{
|
||||||
|
int phy,
|
||||||
|
phy_idx = 0;
|
||||||
|
|
||||||
|
device->mii_phys[0] = 1; // Standard for this chip.
|
||||||
|
for (phy = 1; (phy < 32) && (phy_idx < 4); phy++)
|
||||||
|
{
|
||||||
|
int mii_status = mdio_read(device, phy, 1);
|
||||||
|
|
||||||
|
if ((mii_status != 0xffff) && (mii_status != 0x0000))
|
||||||
|
{
|
||||||
|
device->mii_phys[phy_idx++] = phy;
|
||||||
|
device->mii_advertising = mdio_read(device, phy, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
device->mii_cnt = phy_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate and Initialize Frame Buffer Rings & Descriptors
|
||||||
|
if (ring_init(device) != B_OK)
|
||||||
|
goto Err2;
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
write8(device->addr + StationAddr + i, device->macaddr.ebyte[i]);
|
||||||
|
|
||||||
|
write32(device->addr + TxRingPtr, mem_virt2phys(&device->tx_desc[0], sizeof(device->tx_desc[0])));
|
||||||
|
write32(device->addr + RxRingPtr, mem_virt2phys(&device->rx_desc[0], sizeof(device->rx_desc[0])));
|
||||||
|
|
||||||
|
// Initialize Other Registers.
|
||||||
|
write16(device->addr + PCIBusConfig, 0x0006);
|
||||||
|
|
||||||
|
// Configure the FIFO Thresholds.
|
||||||
|
device->tx_thresh = 0x20;
|
||||||
|
device->rx_thresh = 0x60; /* Written in device_rx_setmode(). */
|
||||||
|
|
||||||
|
write8(device->addr + TxConfig, 0x20);
|
||||||
|
rx_setmode(device);
|
||||||
|
|
||||||
|
// Setup Interrupt Handler
|
||||||
|
install_io_interrupt_handler(device->pciInfo->u.h0.interrupt_line, hook_interrupt, *cookie, 0);
|
||||||
|
|
||||||
|
// Enable interrupts by setting the interrupt mask.
|
||||||
|
write16(device->addr + IntrEnable,
|
||||||
|
IntrRxDone | IntrRxErr | IntrRxEmpty | IntrRxOverflow |
|
||||||
|
IntrTxDone | IntrTxAbort | IntrTxUnderrun | IntrRxDropped |
|
||||||
|
IntrPCIErr | IntrStatsMax | IntrLinkChange | IntrMIIChange);
|
||||||
|
|
||||||
|
device->cmd = CmdStart | CmdTxOn | CmdRxOn | /*CmdNoTxPoll |*/ CmdRxDemand;
|
||||||
|
|
||||||
|
if (device->duplex_lock)
|
||||||
|
device->cmd |= CmdFDuplex;
|
||||||
|
|
||||||
|
write16(device->addr + ChipCmd, device->cmd);
|
||||||
|
|
||||||
|
duplex_check(device);
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_open success!\n");
|
||||||
|
#endif
|
||||||
|
return B_NO_ERROR;
|
||||||
|
|
||||||
|
Err2:
|
||||||
|
ring_free(device);
|
||||||
|
|
||||||
|
Err1:
|
||||||
|
res_free(device);
|
||||||
|
delete_area(device->cookieID);
|
||||||
|
|
||||||
|
Err0:
|
||||||
|
atomic_and(&nOpenMask, ~mask);
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_open failed!\n");
|
||||||
|
#endif
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t hook_close(void *_data)
|
||||||
|
{
|
||||||
|
viarhine_private *device = (viarhine_private*)_data;
|
||||||
|
|
||||||
|
device->interrupted = 1;
|
||||||
|
input_unwait(device, 1);
|
||||||
|
output_unwait(device, 1);
|
||||||
|
|
||||||
|
res_free(device);
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_close\n");
|
||||||
|
#endif
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t hook_free(void *_data)
|
||||||
|
{
|
||||||
|
viarhine_private *device = (viarhine_private*)_data;
|
||||||
|
|
||||||
|
// Remove Interrupt Handler
|
||||||
|
remove_io_interrupt_handler(device->pciInfo->u.h0.interrupt_line, hook_interrupt, _data);
|
||||||
|
write16(device->addr + ChipCmd, CmdStop);
|
||||||
|
|
||||||
|
ring_free(device);
|
||||||
|
|
||||||
|
// Device is Now Available Again
|
||||||
|
atomic_and(&nOpenMask, ~(1 << device->devID));
|
||||||
|
|
||||||
|
delete_area(device->cookieID);
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_free\n");
|
||||||
|
#endif
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t hook_ioctl(void *_data, uint32 msg, void *buf, size_t len)
|
||||||
|
{
|
||||||
|
viarhine_private *device = (viarhine_private*)_data;
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case ETHER_GETADDR:
|
||||||
|
if (_data == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
memcpy(buf, &device->macaddr, 6);
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_control: getaddr\n");
|
||||||
|
#endif
|
||||||
|
return B_NO_ERROR;
|
||||||
|
|
||||||
|
case ETHER_INIT:
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_control: init\n");
|
||||||
|
#endif
|
||||||
|
return B_NO_ERROR;
|
||||||
|
|
||||||
|
case ETHER_GETFRAMESIZE:
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_control: getframesize (%u)\n", MAX_FRAME_SIZE);
|
||||||
|
#endif
|
||||||
|
*(uint32*)buf = MAX_FRAME_SIZE;
|
||||||
|
return B_NO_ERROR;
|
||||||
|
|
||||||
|
case ETHER_SETPROMISC:
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_control: setpromiscuous\n");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ETHER_NONBLOCK:
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_control: nonblock\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
memcpy(&device->nonblocking, buf, sizeof(device->nonblocking));
|
||||||
|
return B_NO_ERROR;
|
||||||
|
|
||||||
|
case ETHER_ADDMULTI:
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_control: add multicast\n");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_control: unknown msg %x\n", msg);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t hook_read(void *_data, off_t pos, void *buf, size_t *len)
|
||||||
|
{
|
||||||
|
viarhine_private *device = (viarhine_private*)_data;
|
||||||
|
ulong buflen;
|
||||||
|
int packet_len = 0;
|
||||||
|
unsigned int entry;
|
||||||
|
char *addr;
|
||||||
|
uint32 data_size;
|
||||||
|
uint32 desc_status;
|
||||||
|
|
||||||
|
buflen = *len;
|
||||||
|
atomic_add(&device->inrw, 1);
|
||||||
|
|
||||||
|
ReturnInLoop:
|
||||||
|
write16(device->addr, CmdRxDemand | device->cmd);
|
||||||
|
while ((device->cur_rx == 0) && (!device->nonblocking))
|
||||||
|
{
|
||||||
|
input_wait(device);
|
||||||
|
|
||||||
|
if (device->interrupted)
|
||||||
|
{
|
||||||
|
*len = 0;
|
||||||
|
return B_INTERRUPTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device->cur_rx != 0)
|
||||||
|
{
|
||||||
|
device->cur_rx--;
|
||||||
|
}
|
||||||
|
else if (device->nonblocking)
|
||||||
|
{
|
||||||
|
*len = 0;
|
||||||
|
atomic_add(&device->inrw, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = 0;
|
||||||
|
while (device->rx_desc[entry].rx_status & DescOwn)
|
||||||
|
{
|
||||||
|
entry++;
|
||||||
|
entry %= RX_BUFFERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc_status = device->rx_desc[entry].rx_status;
|
||||||
|
data_size = (desc_status >> 16) - 4;
|
||||||
|
|
||||||
|
if (buflen < data_size)
|
||||||
|
{
|
||||||
|
data_size = buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = &device->rx_buf[entry * BUFFER_SIZE];
|
||||||
|
|
||||||
|
if (!is_mine(device, addr))
|
||||||
|
{
|
||||||
|
device->rx_desc[entry].desc_length = 1536;
|
||||||
|
device->rx_desc[entry].rx_status = DescOwn;
|
||||||
|
goto ReturnInLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_read: received (%u)(%u) (%02x:%02x:%02x:%02x:%02x:%02x)\n",
|
||||||
|
data_size,
|
||||||
|
device->cur_rx,
|
||||||
|
(unsigned char)addr[0],
|
||||||
|
(unsigned char)addr[1],
|
||||||
|
(unsigned char)addr[2],
|
||||||
|
(unsigned char)addr[3],
|
||||||
|
(unsigned char)addr[4],
|
||||||
|
(unsigned char)addr[5]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*len = data_size;
|
||||||
|
memcpy(buf, addr, data_size);
|
||||||
|
|
||||||
|
device->rx_desc[entry].desc_length = MAX_FRAME_SIZE;
|
||||||
|
device->rx_desc[entry].rx_status = DescOwn;
|
||||||
|
|
||||||
|
atomic_add(&device->inrw, -1);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t hook_write(void *_data, off_t pos, const void *buf, size_t *len)
|
||||||
|
{
|
||||||
|
viarhine_private *device = (viarhine_private*)_data;
|
||||||
|
ulong buflen;
|
||||||
|
status_t status;
|
||||||
|
unsigned int entry;
|
||||||
|
unsigned int i, j;
|
||||||
|
void *addr;
|
||||||
|
|
||||||
|
buflen = *len;
|
||||||
|
atomic_add(&device->inrw, 1);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (device->interrupted)
|
||||||
|
{
|
||||||
|
atomic_add(&device->inrw, -1);
|
||||||
|
return B_INTERRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = output_wait(device, ETHER_TRANSMIT_TIMEOUT);
|
||||||
|
if (status < B_NO_ERROR)
|
||||||
|
{
|
||||||
|
atomic_add(&device->inrw, -1);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (device->tx_desc[device->cur_tx].tx_status & DescOwn);
|
||||||
|
|
||||||
|
entry = device->cur_tx;
|
||||||
|
device->cur_tx++;
|
||||||
|
device->cur_tx %= TX_BUFFERS;
|
||||||
|
|
||||||
|
device->tx_desc[entry].tx_status = DescOwn;
|
||||||
|
addr = &device->tx_buf[entry * BUFFER_SIZE];
|
||||||
|
memcpy(addr, buf, buflen);
|
||||||
|
|
||||||
|
if (buflen < 60)
|
||||||
|
{
|
||||||
|
buflen = 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buflen & 3)
|
||||||
|
{
|
||||||
|
buflen &= (~3);
|
||||||
|
buflen += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
device->tx_desc[entry].desc_length = 0x00E08000 | buflen;
|
||||||
|
write16(device->addr + ChipCmd, CmdTxDemand | device->cmd);
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("hook_write: sent (%u)(%u)\n", buflen, device->cur_tx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
atomic_add(&device->inrw, -1);
|
||||||
|
*len = buflen;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_hooks pDeviceHooks =
|
||||||
|
{
|
||||||
|
hook_open, // open entry point
|
||||||
|
hook_close, // close entry point
|
||||||
|
hook_free, // free entry point
|
||||||
|
hook_ioctl, // ioctl entry point
|
||||||
|
hook_read, // read entry point
|
||||||
|
hook_write, // write entry point
|
||||||
|
NULL, // select entry point
|
||||||
|
NULL, // deselect entry point
|
||||||
|
NULL, // readv entry point
|
||||||
|
NULL // writev entry point
|
||||||
|
};
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* VIA VT86C100A Rhine-II and VIA VT3043 Rhine Based Card Driver
|
||||||
|
* for the BeOS Release 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Libraries
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver-Related Libraries
|
||||||
|
*/
|
||||||
|
#include <OS.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine Libraries
|
||||||
|
*/
|
||||||
|
#include "via-rhine.h"
|
||||||
|
|
||||||
|
int mdio_read(viarhine_private *device, int phy_id, int regnum)
|
||||||
|
{
|
||||||
|
int boguscnt = 1024;
|
||||||
|
|
||||||
|
/* Wait for a previous command to complete. */
|
||||||
|
while ((read8(device->addr + MIICmd) & 0x60) && --boguscnt > 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
write8(device->addr + MIICmd, 0x00);
|
||||||
|
write8(device->addr + MIIPhyAddr, phy_id);
|
||||||
|
write8(device->addr + MIIRegAddr, regnum);
|
||||||
|
write8(device->addr + MIICmd, 0x40); /* Trigger Read */
|
||||||
|
|
||||||
|
boguscnt = 1024;
|
||||||
|
while ((read8(device->addr + MIICmd) & 0x40) && --boguscnt > 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
return read16(device->addr + MIIData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mdio_write(viarhine_private *device, int phy_id, int regnum, int value)
|
||||||
|
{
|
||||||
|
int boguscnt = 1024;
|
||||||
|
|
||||||
|
if ((phy_id == device->mii_phys[0]) && (regnum == 4))
|
||||||
|
device->mii_advertising = value;
|
||||||
|
|
||||||
|
/* Wait for a previous command to complete. */
|
||||||
|
while ((read8(device->addr + MIICmd) & 0x60) && --boguscnt > 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
write8(device->addr + MIICmd, 0x00);
|
||||||
|
write8(device->addr + MIIPhyAddr, phy_id);
|
||||||
|
write8(device->addr + MIIRegAddr, regnum);
|
||||||
|
write8(device->addr + MIIData, value);
|
||||||
|
write8(device->addr + MIICmd, 0x20); /* Trigger Write. */
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* VIA VT86C100A Rhine-II and VIA VT3043 Rhine Based Card Driver By Richard Houle
|
||||||
|
* for the BeOS Release 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Libraries
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver-Related Libraries
|
||||||
|
*/
|
||||||
|
#include <OS.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine Libraries
|
||||||
|
*/
|
||||||
|
#include "via-rhine.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PCI Information Table (VT6102/VT6103/VT6105/VT6105M added by Karina Goddard, March 04, VT6103 and VT6105 seem to work, but buggy)
|
||||||
|
*/
|
||||||
|
struct viarhine_pci_id_info pci_tbl[] =
|
||||||
|
{
|
||||||
|
{"VIA VT86C100A Rhine-II", 0x1106, 0x6100, 0xffff, PCI_command_io | PCI_command_master, 128},
|
||||||
|
{"VIA VT3042 Rhine", 0x1106, 0x3043, 0xffff, PCI_command_io | PCI_command_master, 128},
|
||||||
|
{"VIA VT6102 Rhine-II/VT6103 Tahoe 10/100M Fast Ethernet Adapter", 0x1106, 0x3065, 0xffff, PCI_command_io | PCI_command_master, 256},
|
||||||
|
{"VIA VT6105 Rhine-III Management Adapter", 0x1106, 0x3106, 0xffff, PCI_command_io | PCI_command_master, 256},
|
||||||
|
{"VIA VT6105M Rhine-III Management Adapter", 0x1106, 0x3053, 0xffff, PCI_command_io | PCI_command_master, 256},
|
||||||
|
|
||||||
|
{0}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chip Information Table
|
||||||
|
*/
|
||||||
|
struct viarhine_chip_info cap_tbl[] =
|
||||||
|
{
|
||||||
|
{128, CanHaveMII},
|
||||||
|
{128, CanHaveMII}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine PCI Functions
|
||||||
|
*/
|
||||||
|
int32 pci_getlist(pci_info *info[], int32 maxEntries)
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
int32 i, j;
|
||||||
|
int32 entries;
|
||||||
|
pci_info *item;
|
||||||
|
|
||||||
|
item = (pci_info*)malloc(sizeof(pci_info));
|
||||||
|
|
||||||
|
for (i = 0, entries = 0; entries < maxEntries; i++)
|
||||||
|
{
|
||||||
|
if ((status = pModuleInfo->get_nth_pci_info(i, item)) != B_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
while (pci_tbl[j].name != NULL)
|
||||||
|
{
|
||||||
|
if ((pci_tbl[j].vendor_id == item->vendor_id) &&
|
||||||
|
(pci_tbl[j].device_id == item->device_id))
|
||||||
|
{
|
||||||
|
// Check if the Device Really has an IRQ
|
||||||
|
if ((item->u.h0.interrupt_line == 0) ||
|
||||||
|
(item->u.h0.interrupt_line == 0xFF))
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("pci_getlist: Found with Invalid IRQ - Check IRQ Assignement\n");
|
||||||
|
#endif
|
||||||
|
goto next_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("pci_getlist: Found at IRQ %u\n", item->u.h0.interrupt_line);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pModuleInfo->write_pci_config(
|
||||||
|
item->bus,
|
||||||
|
item->device,
|
||||||
|
item->function,
|
||||||
|
PCI_command,
|
||||||
|
2,
|
||||||
|
pci_tbl[j].flags | pModuleInfo->read_pci_config(
|
||||||
|
item->bus,
|
||||||
|
item->device,
|
||||||
|
item->function,
|
||||||
|
PCI_command,
|
||||||
|
2));
|
||||||
|
|
||||||
|
if (pci_tbl[j].flags & PCI_command_master)
|
||||||
|
{
|
||||||
|
if (item->latency < MIN_PCI_LATENCY)
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("pci_getlist: latency too slow\n");
|
||||||
|
#endif
|
||||||
|
pModuleInfo->write_pci_config(
|
||||||
|
item->bus,
|
||||||
|
item->device,
|
||||||
|
item->function,
|
||||||
|
PCI_latency,
|
||||||
|
1,
|
||||||
|
MIN_PCI_LATENCY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info[entries++] = item;
|
||||||
|
item = (pci_info *)malloc(sizeof(pci_info));
|
||||||
|
goto next_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
next_entry:
|
||||||
|
}
|
||||||
|
|
||||||
|
info[entries] = NULL;
|
||||||
|
free(item);
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t pci_freelist(pci_info *info[])
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
pci_info *item;
|
||||||
|
|
||||||
|
for (i = 0; (item = info[i]); i++)
|
||||||
|
free(item);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* VIA VT86C100A Rhine-II and VIA VT3043 Rhine Based Card Driver
|
||||||
|
* for the BeOS Release 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Libraries
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver-Related Libraries
|
||||||
|
*/
|
||||||
|
#include <OS.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine Libraries
|
||||||
|
*/
|
||||||
|
#include "via-rhine.h"
|
||||||
|
|
||||||
|
status_t res_allocate(viarhine_private *device)
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("device_allocate_resources\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
device->olock = create_sem(1, "via-rhine output");
|
||||||
|
set_sem_owner(device->olock, B_SYSTEM_TEAM);
|
||||||
|
device->ilock = create_sem(0, "via-rhine input");
|
||||||
|
set_sem_owner(device->ilock, B_SYSTEM_TEAM);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void res_free(viarhine_private *device)
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf("device_free_resources\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
delete_sem(device->olock);
|
||||||
|
delete_sem(device->ilock);
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* VIA VT86C100A Rhine-II and VIA VT3043 Rhine Based Card Driver
|
||||||
|
* for the BeOS Release 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Libraries
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver-Related Libraries
|
||||||
|
*/
|
||||||
|
#include <OS.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine Libraries
|
||||||
|
*/
|
||||||
|
#include "via-rhine.h"
|
||||||
|
|
||||||
|
status_t ring_init(viarhine_private *device)
|
||||||
|
{
|
||||||
|
uint32 size;
|
||||||
|
uint16 i;
|
||||||
|
|
||||||
|
// Create Transmit Buffer Area
|
||||||
|
size = RNDUP(BUFFER_SIZE * TX_BUFFERS, B_PAGE_SIZE);
|
||||||
|
if ((device->tx_buf_area = create_area( DevName " tx buffers",
|
||||||
|
(void **)&device->tx_buf,
|
||||||
|
B_ANY_KERNEL_ADDRESS,
|
||||||
|
size,
|
||||||
|
B_FULL_LOCK,
|
||||||
|
B_READ_AREA | B_WRITE_AREA)) < 0)
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf(DevName ": Create TX Buffer Area Failed %x\n", device->tx_buf_area);
|
||||||
|
#endif
|
||||||
|
return device->tx_buf_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize TX Buffer Descriptors
|
||||||
|
for ( i = 0; i < TX_BUFFERS; i++)
|
||||||
|
{
|
||||||
|
device->tx_desc[i].tx_status = 0;
|
||||||
|
device->tx_desc[i].desc_length = 0;
|
||||||
|
device->tx_desc[i].addr = mem_virt2phys(&device->tx_buf[i * BUFFER_SIZE], BUFFER_SIZE);
|
||||||
|
device->tx_desc[i].next = mem_virt2phys(&device->tx_desc[i + 1], sizeof(device->tx_desc[0]));
|
||||||
|
}
|
||||||
|
device->tx_desc[i - 1].next = mem_virt2phys(&device->tx_desc[0], sizeof(device->tx_desc[0]));
|
||||||
|
|
||||||
|
// Create RX Buffer Area
|
||||||
|
size = RNDUP(BUFFER_SIZE * RX_BUFFERS, B_PAGE_SIZE);
|
||||||
|
if ((device->rx_buf_area = create_area( DevName " rx buffers",
|
||||||
|
(void **)&device->rx_buf,
|
||||||
|
B_ANY_KERNEL_ADDRESS,
|
||||||
|
size,
|
||||||
|
B_FULL_LOCK,
|
||||||
|
B_READ_AREA | B_WRITE_AREA)) < 0)
|
||||||
|
{
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
debug_printf(DevName ": Create RX Buffer Area Failed %x\n", device->rx_buf_area);
|
||||||
|
#endif
|
||||||
|
delete_area(device->tx_buf_area);
|
||||||
|
return device->rx_buf_area;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize RX Buffer Descriptors
|
||||||
|
for ( i = 0; i < RX_BUFFERS; i++)
|
||||||
|
{
|
||||||
|
device->rx_desc[i].rx_status = DescOwn;
|
||||||
|
device->rx_desc[i].desc_length = MAX_FRAME_SIZE;
|
||||||
|
device->rx_desc[i].addr = mem_virt2phys(&device->rx_buf[i * BUFFER_SIZE], BUFFER_SIZE);
|
||||||
|
device->rx_desc[i].next = mem_virt2phys(&device->rx_desc[i + 1], sizeof(device->rx_desc[0]));
|
||||||
|
}
|
||||||
|
device->rx_desc[i - 1].next = mem_virt2phys(&device->rx_desc[0], sizeof(device->tx_desc[0]));
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ring_free(viarhine_private *device)
|
||||||
|
{
|
||||||
|
delete_area(device->tx_buf_area);
|
||||||
|
delete_area(device->rx_buf_area);
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* VIA VT86C100A Rhine-II and VIA VT3043 Rhine Based Card Driver
|
||||||
|
* for the BeOS Release 5
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard Libraries
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver-Related Libraries
|
||||||
|
*/
|
||||||
|
#include <OS.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <Drivers.h>
|
||||||
|
#include <PCI.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VIA Rhine Libraries
|
||||||
|
*/
|
||||||
|
#include "via-rhine.h"
|
||||||
|
|
||||||
|
uint32 mem_virt2phys(void *addr, unsigned int length)
|
||||||
|
{
|
||||||
|
physical_entry tbl;
|
||||||
|
|
||||||
|
get_memory_map(addr, length, &tbl, 1);
|
||||||
|
return (uint32)tbl.address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rx_setmode(viarhine_private *device)
|
||||||
|
{
|
||||||
|
uint8 rx_mode; // Note: 0x02 = Accept Runt, 0x01 = Accept Errors
|
||||||
|
|
||||||
|
#if defined(__VIARHINE_PROMISCUOUS___)
|
||||||
|
{
|
||||||
|
rx_mode = 0x1C;
|
||||||
|
}
|
||||||
|
#elif defined(__VIARHINE_ALLOW_MULTICAST__)
|
||||||
|
{
|
||||||
|
uint32 nMCFilter[2]; /* Multicast Hash Filter */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(nMCFilter, 0, sizeof(nMCFilter);
|
||||||
|
for (i = 0; i < device->nMulti; i++)
|
||||||
|
{
|
||||||
|
#error TODO: Code Multicast Filter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_mode = 0x0C;
|
||||||
|
#else
|
||||||
|
|
||||||
|
write32(device->addr + MulticastFilter0, 0);
|
||||||
|
write32(device->addr + MulticastFilter1, 0);
|
||||||
|
rx_mode = 0x1A;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write8(device->addr + RxConfig, device->rx_thresh | rx_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void duplex_check(viarhine_private *device)
|
||||||
|
{
|
||||||
|
int mii_reg5;
|
||||||
|
int negotiated;
|
||||||
|
int duplex;
|
||||||
|
|
||||||
|
mii_reg5 = mdio_read(device, device->mii_phys[0], 5);
|
||||||
|
negotiated = mii_reg5 & device->mii_advertising;
|
||||||
|
|
||||||
|
if (device->duplex_lock || mii_reg5 == 0xffff)
|
||||||
|
return;
|
||||||
|
|
||||||
|
duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
|
||||||
|
if (device->duplex_full != duplex)
|
||||||
|
{
|
||||||
|
device->duplex_full = duplex;
|
||||||
|
|
||||||
|
if (duplex)
|
||||||
|
device->cmd |= CmdFDuplex;
|
||||||
|
else
|
||||||
|
device->cmd &= ~CmdFDuplex;
|
||||||
|
|
||||||
|
write16(device->addr + ChipCmd, device->cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_mine(viarhine_private *device, char *addr)
|
||||||
|
{
|
||||||
|
static char broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
|
if (memcmp(&device->macaddr, addr, 6) == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(broadcast, addr, 6) == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
int debug_printf(char *format, ...)
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
char c[2048];
|
||||||
|
int i;
|
||||||
|
static int f = 0;
|
||||||
|
|
||||||
|
va_start(vl, format);
|
||||||
|
i = vsprintf(c, format, vl);
|
||||||
|
va_end(vl);
|
||||||
|
|
||||||
|
if (f == 0)
|
||||||
|
f = open("/boot/via-rhine.log", O_WRONLY | O_APPEND | O_TEXT);
|
||||||
|
|
||||||
|
write(f, c, strlen(c));
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,313 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* I/O Ctls: Belongs in a Public Header File
|
||||||
|
*/
|
||||||
|
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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Driver Informations
|
||||||
|
*/
|
||||||
|
#define DevName "via-rhine"
|
||||||
|
#define DevDir "net/" DevName "/"
|
||||||
|
#define DEVNAME_LENGTH 64
|
||||||
|
#define MAX_CARDS 4
|
||||||
|
|
||||||
|
#define TX_BUFFERS 8
|
||||||
|
#define RX_BUFFERS 16
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 2048L /* Enough to hold a 1536 Frame */
|
||||||
|
#define MAX_FRAME_SIZE 1536 /* 1536 */
|
||||||
|
#define MAX_MULTI 32 /* Hardware Related, Do not change */
|
||||||
|
|
||||||
|
#define TRANSMIT_TIMEOUT ((bigtime_t)10000) /* 1/100 Second */
|
||||||
|
#define ETHER_TRANSMIT_TIMEOUT ((bigtime_t)1000000) /* One Second */
|
||||||
|
|
||||||
|
#define MIN_PCI_LATENCY 64
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PCI Communications
|
||||||
|
*/
|
||||||
|
#define IO_PORT_PCI_ACCESS true
|
||||||
|
//#define MEMORY_MAPPED_PCI_ACCESS true
|
||||||
|
|
||||||
|
#if IO_PORT_PCI_ACCESS
|
||||||
|
#define write8(address, value) (*pModuleInfo->write_io_8)((address), (value))
|
||||||
|
#define write16(address, value) (*pModuleInfo->write_io_16)((address), (value))
|
||||||
|
#define write32(address, value) (*pModuleInfo->write_io_32)((address), (value))
|
||||||
|
#define read8(address) ((*pModuleInfo->read_io_8)(address))
|
||||||
|
#define read16(address) ((*pModuleInfo->read_io_16)(address))
|
||||||
|
#define read32(address) ((*pModuleInfo->read_io_32)(address))
|
||||||
|
#else /* MEMORY_MAPPED_PCI_ACCESS */
|
||||||
|
#define read8(address) (*((volatile uint8*)(address))); __eieio()
|
||||||
|
#define read16(address) (*((volatile uint16*)(address))); __eieio()
|
||||||
|
#define read32(address) (*((volatile uint32*)(address))); __eieio()
|
||||||
|
#define write8(address, data) (*((volatile uint8 *)(address)) = data); __eieio()
|
||||||
|
#define write16(address, data) (*((volatile uint16 *)(address)) = (data)); __eieio()
|
||||||
|
#define write32(address, data) (*((volatile uint32 *)(address)) = (data)); __eieio()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Registers Offsets
|
||||||
|
*/
|
||||||
|
enum viarhine_register_offsets
|
||||||
|
{
|
||||||
|
StationAddr = 0x00,
|
||||||
|
RxConfig = 0x06,
|
||||||
|
TxConfig = 0x07,
|
||||||
|
ChipCmd = 0x08,
|
||||||
|
IntrStatus = 0x0C,
|
||||||
|
IntrEnable = 0x0E,
|
||||||
|
MulticastFilter0 = 0x10,
|
||||||
|
MulticastFilter1 = 0x14,
|
||||||
|
RxRingPtr = 0x18,
|
||||||
|
TxRingPtr = 0x1C,
|
||||||
|
MIIPhyAddr = 0x6C,
|
||||||
|
MIIStatus = 0x6D,
|
||||||
|
PCIBusConfig = 0x6E,
|
||||||
|
MIICmd = 0x70,
|
||||||
|
MIIRegAddr = 0x71,
|
||||||
|
MIIData = 0x72,
|
||||||
|
Config = 0x78,
|
||||||
|
RxMissed = 0x7C,
|
||||||
|
RxCRCErrs = 0x7E,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command Bits
|
||||||
|
*/
|
||||||
|
enum viarhine_chip_cmd_bits
|
||||||
|
{
|
||||||
|
CmdInit = 0x0001,
|
||||||
|
CmdStart = 0x0002,
|
||||||
|
CmdStop = 0x0004,
|
||||||
|
CmdRxOn = 0x0008,
|
||||||
|
CmdTxOn = 0x0010,
|
||||||
|
CmdTxDemand = 0x0020,
|
||||||
|
CmdRxDemand = 0x0040,
|
||||||
|
CmdEarlyRx = 0x0100,
|
||||||
|
CmdEarlyTx = 0x0200,
|
||||||
|
CmdFDuplex = 0x0400,
|
||||||
|
CmdNoTxPoll = 0x0800,
|
||||||
|
CmdReset = 0x8000
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interrupt Status Bits
|
||||||
|
*/
|
||||||
|
enum viarhine_intr_status_bits
|
||||||
|
{
|
||||||
|
IntrRxDone = 0x0001,
|
||||||
|
IntrRxErr = 0x0004,
|
||||||
|
IntrRxEmpty = 0x0020,
|
||||||
|
IntrTxDone = 0x0002,
|
||||||
|
IntrTxAbort = 0x0008,
|
||||||
|
IntrTxUnderrun = 0x0010,
|
||||||
|
IntrPCIErr = 0x0040,
|
||||||
|
IntrStatsMax = 0x0080,
|
||||||
|
IntrRxEarly = 0x0100,
|
||||||
|
IntrMIIChange = 0x0200,
|
||||||
|
IntrRxOverflow = 0x0400,
|
||||||
|
IntrRxDropped = 0x0800,
|
||||||
|
IntrRxNoBuf = 0x1000,
|
||||||
|
IntrTxAborted = 0x2000,
|
||||||
|
IntrLinkChange = 0x4000,
|
||||||
|
IntrRxWakeUp = 0x8000,
|
||||||
|
IntrNormalSummary = 0x0003,
|
||||||
|
IntrAbnormalSummary = 0xC260,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RX Status Bits
|
||||||
|
*/
|
||||||
|
enum viarhine_rx_status_bits
|
||||||
|
{
|
||||||
|
RxOK = 0x8000,
|
||||||
|
RxWholePkt = 0x0300,
|
||||||
|
RxErr = 0x008F
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Desc Status Bits
|
||||||
|
*/
|
||||||
|
enum viarhine_desc_status_bits
|
||||||
|
{
|
||||||
|
DescOwn = 0x80000000,
|
||||||
|
DescEndPacket = 0x4000,
|
||||||
|
DescIntr = 0x1000
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PCI ID Information
|
||||||
|
*/
|
||||||
|
struct viarhine_pci_id_info
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
uint16 vendor_id,
|
||||||
|
device_id,
|
||||||
|
device_id_mask,
|
||||||
|
flags;
|
||||||
|
int io_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chip Compatibility
|
||||||
|
*/
|
||||||
|
enum viarhine_chip_capability_flags
|
||||||
|
{
|
||||||
|
CanHaveMII = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chip Information
|
||||||
|
*/
|
||||||
|
struct viarhine_chip_info
|
||||||
|
{
|
||||||
|
int io_size;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RX Descriptor
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32 rx_status;
|
||||||
|
uint32 desc_length;
|
||||||
|
|
||||||
|
uint32 addr;
|
||||||
|
uint32 next;
|
||||||
|
} viarhine_rx_desc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TX Descriptor
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32 tx_status;
|
||||||
|
uint32 desc_length;
|
||||||
|
|
||||||
|
uint32 addr;
|
||||||
|
uint32 next;
|
||||||
|
} viarhine_tx_desc;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char ebyte[6];
|
||||||
|
} ethernet_addr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private Data
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Rings
|
||||||
|
*/
|
||||||
|
viarhine_tx_desc tx_desc[TX_BUFFERS]; /* TX Frame Descriptor */
|
||||||
|
viarhine_rx_desc rx_desc[RX_BUFFERS]; /* RX Frame Descriptor */
|
||||||
|
area_id tx_buf_area; /* Transmit Descriptor and Buffer Areas */
|
||||||
|
area_id rx_buf_area; /* Receive Descriptor and Buffer Areas */
|
||||||
|
uchar *tx_buf; /* TX Buffer */
|
||||||
|
uchar *rx_buf; /* RX Buffer */
|
||||||
|
|
||||||
|
area_id cookieID; /* Cookie Area ID */
|
||||||
|
int32 devID; /* Device ID */
|
||||||
|
uint32 addr; /* Base Address of HostRegs */
|
||||||
|
pci_info *pciInfo; /* PCI Informations */
|
||||||
|
ethernet_addr macaddr; /* Ethernet Address */
|
||||||
|
|
||||||
|
uint8 tx_thresh;
|
||||||
|
uint8 rx_thresh;
|
||||||
|
uint16 cmd;
|
||||||
|
uint8 interrupted;
|
||||||
|
|
||||||
|
unsigned char duplex_full; /* Full-Duplex Operation Requested. */
|
||||||
|
unsigned char duplex_lock;
|
||||||
|
|
||||||
|
uint8 cur_tx;
|
||||||
|
uint8 cur_rx;
|
||||||
|
int32 inrw; /* In Read or Write Function */
|
||||||
|
int nonblocking;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Semaphores
|
||||||
|
*/
|
||||||
|
sem_id ilock;
|
||||||
|
sem_id olock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MII Transceiver Section
|
||||||
|
*/
|
||||||
|
int mii_cnt; /* MII Device Addresses. */
|
||||||
|
uint16 mii_advertising; /* NWay Media Advertisement */
|
||||||
|
unsigned char mii_phys[8]; /* MII Device Addresses. */
|
||||||
|
|
||||||
|
} viarhine_private;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Semaphores Macros
|
||||||
|
*/
|
||||||
|
/* output_wait wakes up when the card is ready to transmit another packet */
|
||||||
|
#define output_wait(data, t) acquire_sem_etc(data->olock, 1, B_TIMEOUT, t)
|
||||||
|
#define output_unwait(data, c) release_sem_etc(data->olock, c, B_DO_NOT_RESCHEDULE)
|
||||||
|
|
||||||
|
/* input_wait wakes up when the card has at least one packet on it */
|
||||||
|
#define input_wait(data) acquire_sem_etc(data->ilock ,1, B_CAN_INTERRUPT, 0)
|
||||||
|
#define input_unwait(data, c) release_sem_etc(data->ilock, c, B_DO_NOT_RESCHEDULE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variables
|
||||||
|
*/
|
||||||
|
extern char *pDevNameList[MAX_CARDS+1];
|
||||||
|
extern pci_info *pDevList [MAX_CARDS+1];
|
||||||
|
extern pci_module_info *pModuleInfo;
|
||||||
|
extern device_hooks pDeviceHooks;
|
||||||
|
extern int32 nOpenMask;
|
||||||
|
|
||||||
|
extern struct viarhine_pci_id_info pci_tbl[];
|
||||||
|
extern struct viarhine_chip_info cap_tbl[];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// pci.c
|
||||||
|
int32 pci_getlist (pci_info *info[], int32 maxEntries);
|
||||||
|
status_t pci_freelist(pci_info *info[]);
|
||||||
|
|
||||||
|
// res.c
|
||||||
|
status_t res_allocate(viarhine_private *device);
|
||||||
|
void res_free (viarhine_private *device);
|
||||||
|
|
||||||
|
// misc.c
|
||||||
|
uint32 mem_virt2phys(void *addr, unsigned int length);
|
||||||
|
void rx_setmode (viarhine_private *device);
|
||||||
|
void duplex_check (viarhine_private *device);
|
||||||
|
bool is_mine (viarhine_private *device, char *addr);
|
||||||
|
|
||||||
|
// ring.c
|
||||||
|
status_t ring_init(viarhine_private *device);
|
||||||
|
void ring_free(viarhine_private *device);
|
||||||
|
|
||||||
|
// cmd.c
|
||||||
|
void cmd_reset (viarhine_private *device);
|
||||||
|
void cmd_getmacaddr(viarhine_private *device);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro
|
||||||
|
*/
|
||||||
|
#define RNDUP(x, y) (((x) + (y) - 1) & ~((y) - 1))
|
||||||
|
//#define __VIARHINE_DEBUG__
|
||||||
|
|
||||||
|
#ifdef __VIARHINE_DEBUG__
|
||||||
|
int debug_printf(char *format, ...);
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user