dpeth: use new libnetdriver
Change-Id: Ic389e54817c5b241dad851c89ef1cf16c015a79b
This commit is contained in:
parent
3913e49004
commit
91c4db251e
11 changed files with 463 additions and 1229 deletions
|
@ -10,7 +10,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/com.h>
|
#include <minix/netdriver.h>
|
||||||
#include <net/gen/ether.h>
|
#include <net/gen/ether.h>
|
||||||
#include <net/gen/eth_io.h>
|
#include <net/gen/eth_io.h>
|
||||||
#include "dp.h"
|
#include "dp.h"
|
||||||
|
@ -23,17 +23,17 @@ static unsigned char StationAddress[SA_ADDR_LEN] = {0, 0, 0, 0, 0, 0,};
|
||||||
static buff_t *TxBuff = NULL;
|
static buff_t *TxBuff = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el1_getstats(dpeth_t *dep)
|
** Name: el1_getstats
|
||||||
** Function: Reads statistics counters from board.
|
** Function: Reads statistics counters from board.
|
||||||
**/
|
**/
|
||||||
static void el1_getstats(dpeth_t * dep)
|
static void el1_getstats(dpeth_t * dep)
|
||||||
{
|
{
|
||||||
|
|
||||||
return; /* Nothing to do */
|
/* Nothing to do */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el1_reset(dpeth_t *dep)
|
** Name: el1_reset
|
||||||
** Function: Reset function specific for Etherlink hardware.
|
** Function: Reset function specific for Etherlink hardware.
|
||||||
*/
|
*/
|
||||||
static void el1_reset(dpeth_t * dep)
|
static void el1_reset(dpeth_t * dep)
|
||||||
|
@ -49,7 +49,6 @@ static void el1_reset(dpeth_t * dep)
|
||||||
for (ix = EL1_ADDRESS; ix < SA_ADDR_LEN; ix += 1)
|
for (ix = EL1_ADDRESS; ix < SA_ADDR_LEN; ix += 1)
|
||||||
outb_el1(dep, ix, StationAddress[ix]);
|
outb_el1(dep, ix, StationAddress[ix]);
|
||||||
|
|
||||||
lock();
|
|
||||||
/* Enable DMA/Interrupt, gain control of Buffer */
|
/* Enable DMA/Interrupt, gain control of Buffer */
|
||||||
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
||||||
/* Clear RX packet area */
|
/* Clear RX packet area */
|
||||||
|
@ -60,22 +59,19 @@ static void el1_reset(dpeth_t * dep)
|
||||||
inb_el1(dep, EL1_RECV);
|
inb_el1(dep, EL1_RECV);
|
||||||
inb_el1(dep, EL1_XMIT);
|
inb_el1(dep, EL1_XMIT);
|
||||||
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
||||||
unlock();
|
|
||||||
return; /* Done */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el1_dumpstats(dpeth_t *dep, int port, vir_bytes size)
|
** Name: el1_dumpstats
|
||||||
** Function: Dumps counter on screen (support for console display).
|
** Function: Dumps counter on screen (support for console display).
|
||||||
*/
|
*/
|
||||||
static void el1_dumpstats(dpeth_t * UNUSED(dep))
|
static void el1_dumpstats(dpeth_t * UNUSED(dep))
|
||||||
{
|
{
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el1_mode_init(dpeth_t *dep)
|
** Name: el1_mode_init
|
||||||
** Function: Initializes receicer mode
|
** Function: Initializes receicer mode
|
||||||
*/
|
*/
|
||||||
static void el1_mode_init(dpeth_t * dep)
|
static void el1_mode_init(dpeth_t * dep)
|
||||||
|
@ -95,125 +91,93 @@ static void el1_mode_init(dpeth_t * dep)
|
||||||
}
|
}
|
||||||
outb_el1(dep, EL1_RECV, dep->de_recv_mode);
|
outb_el1(dep, EL1_RECV, dep->de_recv_mode);
|
||||||
inb_el1(dep, EL1_RECV);
|
inb_el1(dep, EL1_RECV);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el1_recv(dpeth_t *dep, int from, int size)
|
** Name: el1_recv
|
||||||
** Function: Receive function. Called from interrupt handler to
|
** Function: Receive function. Called from interrupt handler to
|
||||||
** unload recv. buffer or from main (packet to client)
|
** unload recv. buffer or from main (packet to client)
|
||||||
*/
|
*/
|
||||||
static void el1_recv(dpeth_t * dep, int from, int size)
|
static ssize_t el1_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
|
||||||
{
|
{
|
||||||
buff_t *rxptr;
|
buff_t *rxptr;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
while ((dep->de_flags & DEF_READING) && (rxptr = dep->de_recvq_head)) {
|
if ((rxptr = dep->de_recvq_head) == NULL)
|
||||||
|
return SUSPEND;
|
||||||
|
|
||||||
/* Remove buffer from queue and free buffer */
|
/* Remove buffer from queue and free buffer */
|
||||||
lock();
|
|
||||||
if (dep->de_recvq_tail == dep->de_recvq_head)
|
if (dep->de_recvq_tail == dep->de_recvq_head)
|
||||||
dep->de_recvq_head = dep->de_recvq_tail = NULL;
|
dep->de_recvq_head = dep->de_recvq_tail = NULL;
|
||||||
else
|
else
|
||||||
dep->de_recvq_head = rxptr->next;
|
dep->de_recvq_head = rxptr->next;
|
||||||
unlock();
|
|
||||||
|
|
||||||
/* Copy buffer to user area */
|
/* Copy buffer to user area */
|
||||||
mem2user(dep, rxptr);
|
size = MIN(rxptr->size, max);
|
||||||
|
|
||||||
/* Reply information */
|
netdriver_copyout(data, 0, rxptr->buffer, size);
|
||||||
dep->de_read_s = rxptr->size;
|
|
||||||
dep->de_flags |= DEF_ACK_RECV;
|
|
||||||
dep->de_flags &= NOT(DEF_READING);
|
|
||||||
|
|
||||||
/* Return buffer to the idle pool */
|
/* Return buffer to the idle pool */
|
||||||
free_buff(dep, rxptr);
|
free_buff(dep, rxptr);
|
||||||
}
|
|
||||||
return;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el1_send(dpeth_t *dep, int from_int, int pktsize)
|
** Name: el1_send
|
||||||
** Function: Send function. Called from main to transit a packet or
|
** Function: Send function.
|
||||||
** from interrupt handler when a new packet was queued.
|
|
||||||
*/
|
*/
|
||||||
static void el1_send(dpeth_t * dep, int from_int, int pktsize)
|
static int el1_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
|
||||||
{
|
{
|
||||||
buff_t *txbuff;
|
buff_t *txbuff;
|
||||||
clock_t now;
|
clock_t now;
|
||||||
|
|
||||||
if (from_int == FALSE) {
|
if (dep->de_flags & DEF_XMIT_BUSY) {
|
||||||
|
|
||||||
if ((txbuff = alloc_buff(dep, pktsize + sizeof(buff_t))) != NULL) {
|
|
||||||
|
|
||||||
/* Fill transmit buffer from user area */
|
|
||||||
txbuff->next = NULL;
|
|
||||||
txbuff->size = pktsize;
|
|
||||||
txbuff->client = dep->de_client;
|
|
||||||
user2mem(dep, txbuff);
|
|
||||||
} else
|
|
||||||
panic("out of memory for Tx");
|
|
||||||
|
|
||||||
} else if ((txbuff = dep->de_xmitq_head) != NULL) {
|
|
||||||
|
|
||||||
/* Get first packet in queue */
|
|
||||||
lock();
|
|
||||||
if (dep->de_xmitq_tail == dep->de_xmitq_head)
|
|
||||||
dep->de_xmitq_head = dep->de_xmitq_tail = NULL;
|
|
||||||
else
|
|
||||||
dep->de_xmitq_head = txbuff->next;
|
|
||||||
unlock();
|
|
||||||
pktsize = txbuff->size;
|
|
||||||
|
|
||||||
} else
|
|
||||||
panic("should not be sending ");
|
|
||||||
|
|
||||||
if ((dep->de_flags & DEF_XMIT_BUSY)) {
|
|
||||||
if (from_int) panic("should not be sending ");
|
|
||||||
getticks(&now);
|
getticks(&now);
|
||||||
if ((now - dep->de_xmit_start) > 4) {
|
if ((now - dep->de_xmit_start) > 4) {
|
||||||
/* Transmitter timed out */
|
/* Transmitter timed out */
|
||||||
DEBUG(printf("3c501: transmitter timed out ... \n"));
|
DEBUG(printf("3c501: transmitter timed out ... \n"));
|
||||||
dep->de_stat.ets_sendErr += 1;
|
dep->de_stat.ets_sendErr += 1;
|
||||||
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
||||||
el1_reset(dep);
|
/* Try sending anyway. */
|
||||||
|
} else
|
||||||
|
return SUSPEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Queue packet */
|
/* Since we may have to retransmit, we need a local copy. */
|
||||||
lock(); /* Queue packet to receive queue */
|
if ((txbuff = alloc_buff(dep, size + sizeof(buff_t))) == NULL)
|
||||||
if (dep->de_xmitq_head == NULL)
|
panic("out of memory");
|
||||||
dep->de_xmitq_head = txbuff;
|
|
||||||
else
|
/* Fill transmit buffer from user area */
|
||||||
dep->de_xmitq_tail->next = txbuff;
|
txbuff->next = NULL;
|
||||||
dep->de_xmitq_tail = txbuff;
|
txbuff->size = size;
|
||||||
unlock();
|
|
||||||
} else {
|
netdriver_copyin(data, 0, txbuff->buffer, size);
|
||||||
|
|
||||||
/* Save for retransmission */
|
/* Save for retransmission */
|
||||||
TxBuff = txbuff;
|
TxBuff = txbuff;
|
||||||
dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND);
|
dep->de_flags |= DEF_XMIT_BUSY;
|
||||||
|
|
||||||
/* Setup board for packet loading */
|
/* Setup board for packet loading */
|
||||||
lock(); /* Buffer to processor */
|
|
||||||
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
||||||
inb_el1(dep, EL1_RECV); /* Clears any spurious interrupt */
|
inb_el1(dep, EL1_RECV); /* Clears any spurious interrupt */
|
||||||
inb_el1(dep, EL1_XMIT);
|
inb_el1(dep, EL1_XMIT);
|
||||||
outw_el1(dep, EL1_RECVPTR, 0); /* Clears RX packet area */
|
outw_el1(dep, EL1_RECVPTR, 0); /* Clears RX packet area */
|
||||||
|
|
||||||
/* Loads packet */
|
/* Loads packet */
|
||||||
outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - pktsize));
|
outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - size));
|
||||||
outsb(dep->de_data_port, SELF, txbuff->buffer, pktsize);
|
outsb(dep->de_data_port, txbuff->buffer, size);
|
||||||
/* Starts transmitter */
|
/* Starts transmitter */
|
||||||
outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - pktsize));
|
outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - size));
|
||||||
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_XMIT); /* There it goes... */
|
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_XMIT); /* There it goes... */
|
||||||
unlock();
|
|
||||||
|
|
||||||
getticks(&dep->de_xmit_start);
|
getticks(&dep->de_xmit_start);
|
||||||
dep->de_flags &= NOT(DEF_SENDING);
|
|
||||||
}
|
return OK;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el1_stop(dpeth_t *dep)
|
** Name: el1_stop
|
||||||
** Function: Stops board and disable interrupts.
|
** Function: Stops board and disable interrupts.
|
||||||
*/
|
*/
|
||||||
static void el1_stop(dpeth_t * dep)
|
static void el1_stop(dpeth_t * dep)
|
||||||
|
@ -225,11 +189,10 @@ static void el1_stop(dpeth_t * dep)
|
||||||
outb_el1(dep, EL1_CSR, ECSR_RESET);
|
outb_el1(dep, EL1_CSR, ECSR_RESET);
|
||||||
outb_el1(dep, EL1_CSR, ECSR_SYS);
|
outb_el1(dep, EL1_CSR, ECSR_SYS);
|
||||||
sys_irqdisable(&dep->de_hook); /* Disable interrupt */
|
sys_irqdisable(&dep->de_hook); /* Disable interrupt */
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el1_interrupt(dpeth_t *dep)
|
** Name: el1_interrupt
|
||||||
** Function: Interrupt handler. Acknwledges transmit interrupts
|
** Function: Interrupt handler. Acknwledges transmit interrupts
|
||||||
** or unloads receive buffer to memory queue.
|
** or unloads receive buffer to memory queue.
|
||||||
*/
|
*/
|
||||||
|
@ -264,7 +227,6 @@ static void el1_interrupt(dpeth_t * dep)
|
||||||
}
|
}
|
||||||
DEBUG(printf("3c501: got xmit interrupt (0x%02X)\n", isr));
|
DEBUG(printf("3c501: got xmit interrupt (0x%02X)\n", isr));
|
||||||
el1_reset(dep);
|
el1_reset(dep);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/** if (inw_el1(dep, EL1_XMITPTR) == EL1_BFRSIZ) **/
|
/** if (inw_el1(dep, EL1_XMITPTR) == EL1_BFRSIZ) **/
|
||||||
/* Packet transmitted successfully */
|
/* Packet transmitted successfully */
|
||||||
|
@ -272,13 +234,10 @@ static void el1_interrupt(dpeth_t * dep)
|
||||||
dep->bytes_Tx += (long) (TxBuff->size);
|
dep->bytes_Tx += (long) (TxBuff->size);
|
||||||
free_buff(dep, TxBuff);
|
free_buff(dep, TxBuff);
|
||||||
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
||||||
if ((dep->de_flags & DEF_SENDING) && dep->de_xmitq_head) {
|
netdriver_send();
|
||||||
/* Pending transmit request available in queue */
|
if (dep->de_flags & DEF_XMIT_BUSY)
|
||||||
el1_send(dep, TRUE, 0);
|
|
||||||
if (dep->de_flags & (DEF_XMIT_BUSY | DEF_ACK_SEND))
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else if ((csr & (ECSR_RECV | ECSR_XMTBSY)) == (ECSR_RECV | ECSR_XMTBSY)) {
|
} else if ((csr & (ECSR_RECV | ECSR_XMTBSY)) == (ECSR_RECV | ECSR_XMTBSY)) {
|
||||||
|
|
||||||
|
@ -301,21 +260,20 @@ static void el1_interrupt(dpeth_t * dep)
|
||||||
/* Got a good packet. Read it from buffer */
|
/* Got a good packet. Read it from buffer */
|
||||||
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
|
||||||
outw_el1(dep, EL1_XMITPTR, 0);
|
outw_el1(dep, EL1_XMITPTR, 0);
|
||||||
insb(dep->de_data_port, SELF, rxptr->buffer, pktsize);
|
insb(dep->de_data_port, rxptr->buffer, pktsize);
|
||||||
rxptr->next = NULL;
|
rxptr->next = NULL;
|
||||||
rxptr->size = pktsize;
|
rxptr->size = pktsize;
|
||||||
dep->de_stat.ets_packetR += 1;
|
dep->de_stat.ets_packetR += 1;
|
||||||
dep->bytes_Rx += (long) pktsize;
|
dep->bytes_Rx += (long) pktsize;
|
||||||
lock(); /* Queue packet to receive queue */
|
/* Queue packet to receive queue */
|
||||||
if (dep->de_recvq_head == NULL)
|
if (dep->de_recvq_head == NULL)
|
||||||
dep->de_recvq_head = rxptr;
|
dep->de_recvq_head = rxptr;
|
||||||
else
|
else
|
||||||
dep->de_recvq_tail->next = rxptr;
|
dep->de_recvq_tail->next = rxptr;
|
||||||
dep->de_recvq_tail = rxptr;
|
dep->de_recvq_tail = rxptr;
|
||||||
unlock();
|
|
||||||
|
|
||||||
/* Reply to pending Receive requests, if any */
|
/* Reply to pending Receive requests, if any */
|
||||||
el1_recv(dep, TRUE, 0);
|
netdriver_recv();
|
||||||
}
|
}
|
||||||
} else { /* Nasty condition, should never happen */
|
} else { /* Nasty condition, should never happen */
|
||||||
DEBUG(
|
DEBUG(
|
||||||
|
@ -337,11 +295,10 @@ static void el1_interrupt(dpeth_t * dep)
|
||||||
/* Be sure that interrupts are cleared */
|
/* Be sure that interrupts are cleared */
|
||||||
inb_el1(dep, EL1_RECV);
|
inb_el1(dep, EL1_RECV);
|
||||||
inb_el1(dep, EL1_XMIT);
|
inb_el1(dep, EL1_XMIT);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el1_init(dpeth_t *dep)
|
** Name: el1_init
|
||||||
** Function: Initalizes board hardware and driver data structures.
|
** Function: Initalizes board hardware and driver data structures.
|
||||||
*/
|
*/
|
||||||
static void el1_init(dpeth_t * dep)
|
static void el1_init(dpeth_t * dep)
|
||||||
|
@ -376,12 +333,10 @@ static void el1_init(dpeth_t * dep)
|
||||||
dep->de_getstatsf = el1_getstats;
|
dep->de_getstatsf = el1_getstats;
|
||||||
dep->de_dumpstatsf = el1_dumpstats;
|
dep->de_dumpstatsf = el1_dumpstats;
|
||||||
dep->de_interruptf = el1_interrupt;
|
dep->de_interruptf = el1_interrupt;
|
||||||
|
|
||||||
return; /* Done */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: int el1_probe(dpeth_t *dep)
|
** Name: el1_probe
|
||||||
** Function: Checks for presence of the board.
|
** Function: Checks for presence of the board.
|
||||||
*/
|
*/
|
||||||
int el1_probe(dpeth_t * dep)
|
int el1_probe(dpeth_t * dep)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
|
#include <minix/netdriver.h>
|
||||||
#include <net/gen/ether.h>
|
#include <net/gen/ether.h>
|
||||||
#include <net/gen/eth_io.h>
|
#include <net/gen/eth_io.h>
|
||||||
#include "dp.h"
|
#include "dp.h"
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
#include "3c503.h"
|
#include "3c503.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el2_init(dpeth_t *dep);
|
** Name: el2_init
|
||||||
** Function: Initalize hardware and data structures.
|
** Function: Initalize hardware and data structures.
|
||||||
*/
|
*/
|
||||||
static void el2_init(dpeth_t * dep)
|
static void el2_init(dpeth_t * dep)
|
||||||
|
@ -97,11 +98,10 @@ static void el2_init(dpeth_t * dep)
|
||||||
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
|
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
|
||||||
printf("%02X%c", dep->de_address.ea_addr[ix],
|
printf("%02X%c", dep->de_address.ea_addr[ix],
|
||||||
ix < SA_ADDR_LEN - 1 ? ':' : '\n');
|
ix < SA_ADDR_LEN - 1 ? ':' : '\n');
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el2_stop(dpeth_t *dep);
|
** Name: el2_stop
|
||||||
** Function: Stops board by disabling interrupts.
|
** Function: Stops board by disabling interrupts.
|
||||||
*/
|
*/
|
||||||
static void el2_stop(dpeth_t * dep)
|
static void el2_stop(dpeth_t * dep)
|
||||||
|
@ -109,11 +109,10 @@ static void el2_stop(dpeth_t * dep)
|
||||||
|
|
||||||
outb_el2(dep, EL2_CFGR, ECFGR_IRQOFF);
|
outb_el2(dep, EL2_CFGR, ECFGR_IRQOFF);
|
||||||
sys_irqdisable(&dep->de_hook); /* disable interrupts */
|
sys_irqdisable(&dep->de_hook); /* disable interrupts */
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el2_probe(dpeth_t *dep);
|
** Name: el2_probe
|
||||||
** Function: Probe for the presence of an EtherLink II card.
|
** Function: Probe for the presence of an EtherLink II card.
|
||||||
** Initialize memory addressing if card detected.
|
** Initialize memory addressing if card detected.
|
||||||
*/
|
*/
|
||||||
|
@ -132,9 +131,9 @@ int el2_probe(dpeth_t * dep)
|
||||||
|
|
||||||
/* Resets board */
|
/* Resets board */
|
||||||
outb_el2(dep, EL2_CNTR, ECNTR_RESET | thin);
|
outb_el2(dep, EL2_CNTR, ECNTR_RESET | thin);
|
||||||
milli_delay(1);
|
micro_delay(1000);
|
||||||
outb_el2(dep, EL2_CNTR, thin);
|
outb_el2(dep, EL2_CNTR, thin);
|
||||||
milli_delay(5);
|
micro_delay(5000);
|
||||||
|
|
||||||
/* Map the address PROM to lower I/O address range */
|
/* Map the address PROM to lower I/O address range */
|
||||||
outb_el2(dep, EL2_CNTR, ECNTR_SAPROM | thin);
|
outb_el2(dep, EL2_CNTR, ECNTR_SAPROM | thin);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/com.h>
|
#include <minix/netdriver.h>
|
||||||
#include <net/gen/ether.h>
|
#include <net/gen/ether.h>
|
||||||
#include <net/gen/eth_io.h>
|
#include <net/gen/eth_io.h>
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ static const char *const IfNamesMsg[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_update_stats(dpeth_t *dep)
|
** Name: el3_update_stats
|
||||||
** Function: Reads statistic counters from board
|
** Function: Reads statistic counters from board
|
||||||
** and updates local counters.
|
** and updates local counters.
|
||||||
*/
|
*/
|
||||||
|
@ -52,36 +52,30 @@ static void el3_update_stats(dpeth_t * dep)
|
||||||
/* Goes back to operating window and enables statistics */
|
/* Goes back to operating window and enables statistics */
|
||||||
SetWindow(WNO_Operating);
|
SetWindow(WNO_Operating);
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_StatsEnable);
|
outw_el3(dep, REG_CmdStatus, CMD_StatsEnable);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_getstats(dpeth_t *dep)
|
** Name: el3_getstats
|
||||||
** Function: Reads statistics counters from board.
|
** Function: Reads statistics counters from board.
|
||||||
*/
|
*/
|
||||||
static void el3_getstats(dpeth_t * dep)
|
static void el3_getstats(dpeth_t * dep)
|
||||||
{
|
{
|
||||||
|
|
||||||
lock();
|
|
||||||
el3_update_stats(dep);
|
el3_update_stats(dep);
|
||||||
unlock();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_dodump(dpeth_t *dep)
|
** Name: el3_dodump
|
||||||
** Function: Dumps counter on screen (support for console display).
|
** Function: Dumps counter on screen (support for console display).
|
||||||
*/
|
*/
|
||||||
static void el3_dodump(dpeth_t * dep)
|
static void el3_dodump(dpeth_t * dep)
|
||||||
{
|
{
|
||||||
|
|
||||||
el3_getstats(dep);
|
el3_getstats(dep);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_rx_mode(dpeth_t *dep)
|
** Name: el3_rx_mode
|
||||||
** Function: Initializes receiver mode
|
** Function: Initializes receiver mode
|
||||||
*/
|
*/
|
||||||
static void el3_rx_mode(dpeth_t * dep)
|
static void el3_rx_mode(dpeth_t * dep)
|
||||||
|
@ -95,85 +89,49 @@ static void el3_rx_mode(dpeth_t * dep)
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_RxReset);
|
outw_el3(dep, REG_CmdStatus, CMD_RxReset);
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_SetRxFilter | dep->de_recv_mode);
|
outw_el3(dep, REG_CmdStatus, CMD_SetRxFilter | dep->de_recv_mode);
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_RxEnable);
|
outw_el3(dep, REG_CmdStatus, CMD_RxEnable);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_reset(dpeth_t *dep)
|
** Name: el3_reset
|
||||||
** Function: Reset function specific for Etherlink hardware.
|
** Function: Reset function specific for Etherlink hardware.
|
||||||
*/
|
*/
|
||||||
static void el3_reset(dpeth_t * UNUSED(dep))
|
static void el3_reset(dpeth_t * UNUSED(dep))
|
||||||
{
|
{
|
||||||
|
|
||||||
return; /* Done */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_write_fifo(dpeth_t * dep, int pktsize);
|
** Name: el3_recv
|
||||||
** Function: Writes a packet from user area to board.
|
|
||||||
** Remark: Writing a word/dword at a time may result faster
|
|
||||||
** but is a lot more complicated. Let's go simpler way.
|
|
||||||
*/
|
|
||||||
static void el3_write_fifo(dpeth_t * dep, int pktsize)
|
|
||||||
{
|
|
||||||
int bytes, ix = 0;
|
|
||||||
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
|
||||||
int r, padding = pktsize;
|
|
||||||
|
|
||||||
do { /* Writes chuncks of packet from user buffers */
|
|
||||||
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
|
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
|
||||||
/* Writes from user buffer to Tx FIFO */
|
|
||||||
r= sys_safe_outsb(dep->de_data_port, iovp->iod_proc_nr,
|
|
||||||
iovp->iod_iovec[ix].iov_grant, 0, bytes);
|
|
||||||
if (r != OK)
|
|
||||||
panic("el3_write_fifo: sys_safe_outsb failed: %d", r);
|
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
|
||||||
dp_next_iovec(iovp);
|
|
||||||
ix = 0;
|
|
||||||
}
|
|
||||||
/* Till packet done */
|
|
||||||
} while ((pktsize -= bytes) > 0);
|
|
||||||
while ((padding++ % sizeof(long)) != 0) outb(dep->de_data_port, 0x00);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: void el3_recv(dpeth_t *dep, int fromint, int size)
|
|
||||||
** Function: Receive function. Called from interrupt handler or
|
** Function: Receive function. Called from interrupt handler or
|
||||||
** from main to unload recv. buffer (packet to client)
|
** from main to unload recv. buffer (packet to client)
|
||||||
*/
|
*/
|
||||||
static void el3_recv(dpeth_t *dep, int fromint, int size)
|
static ssize_t el3_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
|
||||||
{
|
{
|
||||||
buff_t *rxptr;
|
buff_t *rxptr;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
while ((dep->de_flags & DEF_READING) && (rxptr = dep->de_recvq_head)) {
|
if ((rxptr = dep->de_recvq_head) == NULL)
|
||||||
|
return SUSPEND;
|
||||||
|
|
||||||
lock(); /* Remove buffer from queue */
|
/* Remove buffer from queue */
|
||||||
if (dep->de_recvq_tail == dep->de_recvq_head)
|
if (dep->de_recvq_tail == dep->de_recvq_head)
|
||||||
dep->de_recvq_head = dep->de_recvq_tail = NULL;
|
dep->de_recvq_head = dep->de_recvq_tail = NULL;
|
||||||
else
|
else
|
||||||
dep->de_recvq_head = rxptr->next;
|
dep->de_recvq_head = rxptr->next;
|
||||||
unlock();
|
|
||||||
|
|
||||||
/* Copy buffer to user area and free it */
|
/* Copy buffer to user area and free it */
|
||||||
mem2user(dep, rxptr);
|
size = MIN(rxptr->size, max);
|
||||||
|
|
||||||
dep->de_read_s = rxptr->size;
|
netdriver_copyout(data, 0, rxptr->buffer, size);
|
||||||
dep->de_flags |= DEF_ACK_RECV;
|
|
||||||
dep->de_flags &= NOT(DEF_READING);
|
|
||||||
|
|
||||||
/* Return buffer to the idle pool */
|
/* Return buffer to the idle pool */
|
||||||
free_buff(dep, rxptr);
|
free_buff(dep, rxptr);
|
||||||
}
|
|
||||||
return;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_rx_complete(dpeth_t * dep);
|
** Name: el3_rx_complete
|
||||||
** Function: Upon receiving a packet, provides status checks
|
** Function: Upon receiving a packet, provides status checks
|
||||||
** and if packet is OK copies it to local buffer.
|
** and if packet is OK copies it to local buffer.
|
||||||
*/
|
*/
|
||||||
|
@ -205,38 +163,36 @@ static void el3_rx_complete(dpeth_t * dep)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Good packet. Read it from FIFO */
|
/* Good packet. Read it from FIFO */
|
||||||
insb(dep->de_data_port, SELF, rxptr->buffer, pktsize);
|
insb(dep->de_data_port, rxptr->buffer, pktsize);
|
||||||
rxptr->next = NULL;
|
rxptr->next = NULL;
|
||||||
rxptr->size = pktsize;
|
rxptr->size = pktsize;
|
||||||
|
|
||||||
lock(); /* Queue packet to receive queue */
|
/* Queue packet to receive queue */
|
||||||
if (dep->de_recvq_head == NULL)
|
if (dep->de_recvq_head == NULL)
|
||||||
dep->de_recvq_head = rxptr;
|
dep->de_recvq_head = rxptr;
|
||||||
else
|
else
|
||||||
dep->de_recvq_tail->next = rxptr;
|
dep->de_recvq_tail->next = rxptr;
|
||||||
dep->de_recvq_tail = rxptr;
|
dep->de_recvq_tail = rxptr;
|
||||||
unlock();
|
|
||||||
|
|
||||||
/* Reply to pending Receive requests, if any */
|
/* Reply to pending Receive requests, if any */
|
||||||
el3_recv(dep, TRUE, pktsize);
|
netdriver_recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discard top packet from queue */
|
/* Discard top packet from queue */
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_RxDiscard);
|
outw_el3(dep, REG_CmdStatus, CMD_RxDiscard);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_send(dpeth_t *dep, int count)
|
** Name: el3_send
|
||||||
** Function: Send function. Called from main to transit a packet or
|
** Function: Send function. Called from main to transit a packet or
|
||||||
** from interrupt handler when Tx FIFO gets available.
|
** from interrupt handler when Tx FIFO gets available.
|
||||||
*/
|
*/
|
||||||
static void el3_send(dpeth_t * dep, int from_int, int count)
|
static int el3_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
|
||||||
{
|
{
|
||||||
clock_t now;
|
clock_t now;
|
||||||
int ix;
|
int ix;
|
||||||
short int TxStatus;
|
short int TxStatus;
|
||||||
|
size_t padding;
|
||||||
|
|
||||||
getticks(&now);
|
getticks(&now);
|
||||||
if ((dep->de_flags & DEF_XMIT_BUSY) &&
|
if ((dep->de_flags & DEF_XMIT_BUSY) &&
|
||||||
|
@ -249,24 +205,26 @@ static void el3_send(dpeth_t * dep, int from_int, int count)
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_TxEnable);
|
outw_el3(dep, REG_CmdStatus, CMD_TxEnable);
|
||||||
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
||||||
}
|
}
|
||||||
if (!(dep->de_flags & DEF_XMIT_BUSY)) {
|
if (dep->de_flags & DEF_XMIT_BUSY)
|
||||||
|
return SUSPEND;
|
||||||
|
|
||||||
/* Writes Transmitter preamble 1st Word (packet len, no ints) */
|
/* Writes Transmitter preamble 1st Word (packet len, no ints) */
|
||||||
outw_el3(dep, REG_TxFIFO, count);
|
outw_el3(dep, REG_TxFIFO, size);
|
||||||
/* Writes Transmitter preamble 2nd Word (all zero) */
|
/* Writes Transmitter preamble 2nd Word (all zero) */
|
||||||
outw_el3(dep, REG_TxFIFO, 0);
|
outw_el3(dep, REG_TxFIFO, 0);
|
||||||
/* Writes packet */
|
/* Writes packet */
|
||||||
el3_write_fifo(dep, count);
|
netdriver_portoutb(data, 0, dep->de_data_port, size);
|
||||||
|
padding = size;
|
||||||
|
while ((padding++ % sizeof(long)) != 0) outb(dep->de_data_port, 0x00);
|
||||||
|
|
||||||
getticks(&dep->de_xmit_start);
|
getticks(&dep->de_xmit_start);
|
||||||
dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND);
|
dep->de_flags |= DEF_XMIT_BUSY;
|
||||||
if (inw_el3(dep, REG_TxFree) > ETH_MAX_PACK_SIZE) {
|
if (inw_el3(dep, REG_TxFree) > ETH_MAX_PACK_SIZE) {
|
||||||
/* Tx has enough room for a packet of maximum size */
|
/* Tx has enough room for a packet of maximum size */
|
||||||
dep->de_flags &= NOT(DEF_XMIT_BUSY | DEF_SENDING);
|
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
||||||
} else {
|
} else {
|
||||||
/* Interrupt driver when enough room is available */
|
/* Interrupt driver when enough room is available */
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_SetTxAvailable | ETH_MAX_PACK_SIZE);
|
outw_el3(dep, REG_CmdStatus, CMD_SetTxAvailable | ETH_MAX_PACK_SIZE);
|
||||||
dep->de_flags &= NOT(DEF_SENDING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pops Tx status stack */
|
/* Pops Tx status stack */
|
||||||
|
@ -278,12 +236,12 @@ static void el3_send(dpeth_t * dep, int from_int, int count)
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_TxEnable);
|
outw_el3(dep, REG_CmdStatus, CMD_TxEnable);
|
||||||
outb_el3(dep, REG_TxStatus, 0);
|
outb_el3(dep, REG_TxStatus, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_close(dpeth_t *dep)
|
** Name: el3_close
|
||||||
** Function: Stops board and makes it ready to shut down.
|
** Function: Stops board and makes it ready to shut down.
|
||||||
*/
|
*/
|
||||||
static void el3_close(dpeth_t * dep)
|
static void el3_close(dpeth_t * dep)
|
||||||
|
@ -296,24 +254,22 @@ static void el3_close(dpeth_t * dep)
|
||||||
|
|
||||||
if (dep->de_if_port == BNC_XCVR) {
|
if (dep->de_if_port == BNC_XCVR) {
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_StopIntXcvr);
|
outw_el3(dep, REG_CmdStatus, CMD_StopIntXcvr);
|
||||||
/* milli_delay(5); */
|
/* micro_delay(5000); */
|
||||||
|
|
||||||
} else if (dep->de_if_port == TP_XCVR) {
|
} else if (dep->de_if_port == TP_XCVR) {
|
||||||
SetWindow(WNO_Diagnostics);
|
SetWindow(WNO_Diagnostics);
|
||||||
outw_el3(dep, REG_MediaStatus, inw_el3(dep, REG_MediaStatus) &
|
outw_el3(dep, REG_MediaStatus, inw_el3(dep, REG_MediaStatus) &
|
||||||
NOT((MediaLBeatEnable | MediaJabberEnable)));
|
NOT((MediaLBeatEnable | MediaJabberEnable)));
|
||||||
/* milli_delay(5); */
|
/* micro_delay(5000); */
|
||||||
}
|
}
|
||||||
DEBUG(printf("%s: stopping Etherlink ... \n", dep->de_name));
|
DEBUG(printf("%s: stopping Etherlink ... \n", dep->de_name));
|
||||||
/* Issues a global reset
|
/* Issues a global reset
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_GlobalReset); */
|
outw_el3(dep, REG_CmdStatus, CMD_GlobalReset); */
|
||||||
sys_irqdisable(&dep->de_hook); /* Disable interrupt */
|
sys_irqdisable(&dep->de_hook); /* Disable interrupt */
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_interrupt(dpeth_t *dep)
|
** Name: el3_interrupt
|
||||||
** Function: Interrupt handler. Acknwledges transmit interrupts
|
** Function: Interrupt handler. Acknwledges transmit interrupts
|
||||||
** or unloads receive buffer to memory queue.
|
** or unloads receive buffer to memory queue.
|
||||||
*/
|
*/
|
||||||
|
@ -332,8 +288,7 @@ static void el3_interrupt(dpeth_t * dep)
|
||||||
DEBUG(printf("3c509: got Tx interrupt, Status=0x%04x\n", isr);)
|
DEBUG(printf("3c509: got Tx interrupt, Status=0x%04x\n", isr);)
|
||||||
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
dep->de_flags &= NOT(DEF_XMIT_BUSY);
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | INT_TxAvailable);
|
outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | INT_TxAvailable);
|
||||||
if (dep->de_flags & DEF_SENDING) /* Send pending */
|
netdriver_send();
|
||||||
el3_send(dep, TRUE, dep->de_send_s);
|
|
||||||
}
|
}
|
||||||
if (isr & (INT_AdapterFail | INT_RxEarly | INT_UpdateStats)) {
|
if (isr & (INT_AdapterFail | INT_RxEarly | INT_UpdateStats)) {
|
||||||
|
|
||||||
|
@ -354,11 +309,10 @@ static void el3_interrupt(dpeth_t * dep)
|
||||||
/* Acknowledge interrupt */
|
/* Acknowledge interrupt */
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | (INT_Latch | INT_Requested));
|
outw_el3(dep, REG_CmdStatus, CMD_Acknowledge | (INT_Latch | INT_Requested));
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: unsigned el3_read_eeprom(port_t port, unsigned address);
|
** Name: el3_read_eeprom
|
||||||
** Function: Reads the EEPROM at specified address
|
** Function: Reads the EEPROM at specified address
|
||||||
*/
|
*/
|
||||||
static unsigned el3_read_eeprom(port_t port, unsigned address)
|
static unsigned el3_read_eeprom(port_t port, unsigned address)
|
||||||
|
@ -368,7 +322,7 @@ static unsigned el3_read_eeprom(port_t port, unsigned address)
|
||||||
|
|
||||||
address |= EL3_READ_EEPROM;
|
address |= EL3_READ_EEPROM;
|
||||||
outb(port, address);
|
outb(port, address);
|
||||||
milli_delay(5); /* Allows EEPROM reads */
|
micro_delay(5000); /* Allows EEPROM reads */
|
||||||
for (result = 0, bit = 16; bit > 0; bit -= 1) {
|
for (result = 0, bit = 16; bit > 0; bit -= 1) {
|
||||||
result = (result << 1) | (inb(port) & 0x0001);
|
result = (result << 1) | (inb(port) & 0x0001);
|
||||||
}
|
}
|
||||||
|
@ -376,7 +330,7 @@ static unsigned el3_read_eeprom(port_t port, unsigned address)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_read_StationAddress(dpeth_t *dep)
|
** Name: el3_read_StationAddress
|
||||||
** Function: Reads station address from board
|
** Function: Reads station address from board
|
||||||
*/
|
*/
|
||||||
static void el3_read_StationAddress(dpeth_t * dep)
|
static void el3_read_StationAddress(dpeth_t * dep)
|
||||||
|
@ -390,11 +344,10 @@ static void el3_read_StationAddress(dpeth_t * dep)
|
||||||
dep->de_address.ea_addr[ix++] = (rc >> 8) & 0xFF;
|
dep->de_address.ea_addr[ix++] = (rc >> 8) & 0xFF;
|
||||||
dep->de_address.ea_addr[ix++] = rc & 0xFF;
|
dep->de_address.ea_addr[ix++] = rc & 0xFF;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_open(dpeth_t *dep)
|
** Name: el3_open
|
||||||
** Function: Initalizes board hardware and driver data structures.
|
** Function: Initalizes board hardware and driver data structures.
|
||||||
*/
|
*/
|
||||||
static void el3_open(dpeth_t * dep)
|
static void el3_open(dpeth_t * dep)
|
||||||
|
@ -440,7 +393,7 @@ static void el3_open(dpeth_t * dep)
|
||||||
if (dep->de_if_port == BNC_XCVR) {
|
if (dep->de_if_port == BNC_XCVR) {
|
||||||
/* Start internal transceiver for Coaxial cable */
|
/* Start internal transceiver for Coaxial cable */
|
||||||
outw_el3(dep, REG_CmdStatus, CMD_StartIntXcvr);
|
outw_el3(dep, REG_CmdStatus, CMD_StartIntXcvr);
|
||||||
milli_delay(5);
|
micro_delay(5000);
|
||||||
|
|
||||||
} else if (dep->de_if_port == TP_XCVR) {
|
} else if (dep->de_if_port == TP_XCVR) {
|
||||||
/* Start internal transceiver for Twisted pair cable */
|
/* Start internal transceiver for Twisted pair cable */
|
||||||
|
@ -497,12 +450,10 @@ static void el3_open(dpeth_t * dep)
|
||||||
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
|
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
|
||||||
printf("%02X%c", dep->de_address.ea_addr[ix],
|
printf("%02X%c", dep->de_address.ea_addr[ix],
|
||||||
ix < SA_ADDR_LEN - 1 ? ':' : '\n');
|
ix < SA_ADDR_LEN - 1 ? ':' : '\n');
|
||||||
|
|
||||||
return; /* Done */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: unsigned int el3_checksum(port_t port);
|
** Name: int el3_checksum
|
||||||
** Function: Reads EEPROM and computes checksum.
|
** Function: Reads EEPROM and computes checksum.
|
||||||
*/
|
*/
|
||||||
static unsigned short el3_checksum(port_t port)
|
static unsigned short el3_checksum(port_t port)
|
||||||
|
@ -534,7 +485,7 @@ static unsigned short el3_checksum(port_t port)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void el3_write_id(port_t port);
|
** Name: el3_write_id
|
||||||
** Function: Writes the ID sequence to the board.
|
** Function: Writes the ID sequence to the board.
|
||||||
*/
|
*/
|
||||||
static void el3_write_id(port_t port)
|
static void el3_write_id(port_t port)
|
||||||
|
@ -548,11 +499,10 @@ static void el3_write_id(port_t port)
|
||||||
pattern <<= 1;
|
pattern <<= 1;
|
||||||
pattern = (pattern & 0x0100) ? pattern ^ 0xCF : pattern;
|
pattern = (pattern & 0x0100) ? pattern ^ 0xCF : pattern;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: int el3_probe(dpeth_t *dep)
|
** Name: el3_probe
|
||||||
** Function: Checks for presence of the board.
|
** Function: Checks for presence of the board.
|
||||||
*/
|
*/
|
||||||
int el3_probe(dpeth_t * dep)
|
int el3_probe(dpeth_t * dep)
|
||||||
|
@ -572,10 +522,10 @@ int el3_probe(dpeth_t * dep)
|
||||||
|
|
||||||
el3_write_id(id_port);
|
el3_write_id(id_port);
|
||||||
outb(id_port, EL3_ID_GLOBAL_RESET); /* Reset the board */
|
outb(id_port, EL3_ID_GLOBAL_RESET); /* Reset the board */
|
||||||
milli_delay(5); /* Technical reference says 162 micro sec. */
|
micro_delay(5000); /* Technical reference says 162 micro sec. */
|
||||||
el3_write_id(id_port);
|
el3_write_id(id_port);
|
||||||
outb(id_port, EL3_SET_TAG_REGISTER);
|
outb(id_port, EL3_SET_TAG_REGISTER);
|
||||||
milli_delay(5);
|
micro_delay(5000);
|
||||||
|
|
||||||
dep->de_id_port = id_port; /* Stores ID port No. */
|
dep->de_id_port = id_port; /* Stores ID port No. */
|
||||||
dep->de_ramsize = /* RAM size is meaningless */
|
dep->de_ramsize = /* RAM size is meaningless */
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include <assert.h>
|
|
||||||
/*
|
/*
|
||||||
** File: 8390.c May 02, 2000
|
** File: 8390.c May 02, 2000
|
||||||
**
|
**
|
||||||
|
@ -12,32 +11,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/com.h>
|
#include <minix/netdriver.h>
|
||||||
#include <net/gen/ether.h>
|
#include <net/gen/ether.h>
|
||||||
#include <net/gen/eth_io.h>
|
#include <net/gen/eth_io.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "dp.h"
|
#include "dp.h"
|
||||||
|
|
||||||
#if (ENABLE_DP8390 == 1)
|
#if (ENABLE_DP8390 == 1)
|
||||||
|
|
||||||
#define PIO16 0 /* NOTE: pio 16 functions missing */
|
|
||||||
|
|
||||||
#include "8390.h"
|
#include "8390.h"
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define sys_nic2mem(srcOffs,dstProc,dstOffs,length) \
|
|
||||||
sys_vircopy(SELF,dep->de_memsegm,(vir_bytes)(srcOffs),\
|
|
||||||
(dstProc),D,(vir_bytes)(dstOffs),length)
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
#define sys_user2nic_s(srcProc,grant,dstOffs,length) \
|
|
||||||
sys_safecopyfrom((srcProc),(grant),0, \
|
|
||||||
(vir_bytes)(dstOffs),length,dep->de_memsegm)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static char RdmaErrMsg[] = "remote dma failed to complete";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_rw_setup(dpeth_t *dep, int mode, int size, u16_t offset);
|
** Name: ns_rw_setup
|
||||||
** Function: Sets the board for reading/writing.
|
** Function: Sets the board for reading/writing.
|
||||||
*/
|
*/
|
||||||
static void ns_rw_setup(const dpeth_t *dep, int mode, int size, u16_t offset)
|
static void ns_rw_setup(const dpeth_t *dep, int mode, int size, u16_t offset)
|
||||||
|
@ -50,11 +35,10 @@ static void ns_rw_setup(const dpeth_t *dep, int mode, int size, u16_t offset)
|
||||||
outb_reg0(dep, DP_RSAR1, (offset >> 8) & 0xFF);
|
outb_reg0(dep, DP_RSAR1, (offset >> 8) & 0xFF);
|
||||||
mode |= (CR_PS_P0 | CR_STA);
|
mode |= (CR_PS_P0 | CR_STA);
|
||||||
outb_reg0(dep, DP_CR, mode);
|
outb_reg0(dep, DP_CR, mode);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_start_xmit(dpeth_t *dep, int size, int pageno);
|
** Name: ns_start_xmit
|
||||||
** Function: Sets the board for for transmitting and fires it.
|
** Function: Sets the board for for transmitting and fires it.
|
||||||
*/
|
*/
|
||||||
static void ns_start_xmit(const dpeth_t * dep, int size, int pageno)
|
static void ns_start_xmit(const dpeth_t * dep, int size, int pageno)
|
||||||
|
@ -64,110 +48,58 @@ static void ns_start_xmit(const dpeth_t * dep, int size, int pageno)
|
||||||
outb_reg0(dep, DP_TBCR1, size >> 8);
|
outb_reg0(dep, DP_TBCR1, size >> 8);
|
||||||
outb_reg0(dep, DP_TBCR0, size & 0xFF);
|
outb_reg0(dep, DP_TBCR0, size & 0xFF);
|
||||||
outb_reg0(dep, DP_CR, CR_NO_DMA | CR_STA | CR_TXP); /* Fires transmission */
|
outb_reg0(dep, DP_CR, CR_NO_DMA | CR_STA | CR_TXP); /* Fires transmission */
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void mem_getblock(dpeth_t *dep, u16_t offset,
|
** Name: mem_getblock
|
||||||
** int size, void *dst)
|
|
||||||
** Function: Reads a block of packet from board (shared memory).
|
** Function: Reads a block of packet from board (shared memory).
|
||||||
*/
|
*/
|
||||||
static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
|
static void mem_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
|
||||||
{
|
{
|
||||||
panic("mem_getblock: not converted to safecopies");
|
|
||||||
#if 0
|
assert(offset + size <= dep->de_ramsize);
|
||||||
sys_nic2mem(dep->de_linmem + offset, SELF, dst, size);
|
|
||||||
return;
|
memcpy(dst, dep->de_locmem + offset, size);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void mem_nic2user(dpeth_t *dep, int pageno, int pktsize);
|
** Name: mem_nic2user
|
||||||
** Function: Copies a packet from board to user area (shared memory).
|
** Function: Copies a packet from board to user area (shared memory).
|
||||||
*/
|
*/
|
||||||
static void mem_nic2user(dpeth_t * dep, int pageno, int pktsize)
|
static void mem_nic2user(dpeth_t *dep, int pageno, struct netdriver_data *data,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
panic("mem_nic2user: not converted to safecopies");
|
size_t offset, left;
|
||||||
#if 0
|
|
||||||
phys_bytes offset;
|
|
||||||
iovec_dat_s_t *iovp = &dep->de_read_iovec;
|
|
||||||
int bytes, ix = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* Computes shared memory address (skipping receive header) */
|
/* Computes shared memory address (skipping receive header) */
|
||||||
offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
|
offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
|
||||||
|
|
||||||
do { /* Reads chuncks of packet into user area */
|
if (offset + size > dep->de_stoppage * DP_PAGESIZE) {
|
||||||
|
left = dep->de_stoppage * DP_PAGESIZE - offset;
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of a chunck */
|
netdriver_copyout(data, 0, dep->de_locmem + offset, left);
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
|
||||||
|
|
||||||
/* Reads from board to user area */
|
|
||||||
if ((offset + bytes) > (dep->de_stoppage * DP_PAGESIZE)) {
|
|
||||||
|
|
||||||
/* Circular buffer wrap-around */
|
|
||||||
bytes = dep->de_stoppage * DP_PAGESIZE - offset;
|
|
||||||
sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr,
|
|
||||||
iovp->iod_iovec[ix].iov_grant, bytes);
|
|
||||||
pktsize -= bytes;
|
|
||||||
phys_user += bytes;
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size - bytes;
|
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
|
||||||
offset = dep->de_startpage * DP_PAGESIZE;
|
offset = dep->de_startpage * DP_PAGESIZE;
|
||||||
}
|
netdriver_copyout(data, left, dep->de_locmem + offset, size - left);
|
||||||
sys_nic2mem_s(dep->de_linmem + offset, iovp->iod_proc_nr,
|
} else
|
||||||
iovp->iod_iovec[ix].iov_grant, bytes);
|
netdriver_copyout(data, 0, dep->de_locmem + offset, size);
|
||||||
offset += bytes;
|
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
|
||||||
dp_next_iovec(iovp);
|
|
||||||
ix = 0;
|
|
||||||
}
|
|
||||||
/* Till packet done */
|
|
||||||
} while ((pktsize -= bytes) > 0);
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
** Name: mem_user2nic
|
||||||
** Function: Copies a packet from user area to board (shared memory).
|
** Function: Copies a packet from user area to board (shared memory).
|
||||||
*/
|
*/
|
||||||
static void mem_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
static void mem_user2nic(dpeth_t *dep, int pageno, struct netdriver_data *data,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
#if 1
|
size_t offset;
|
||||||
panic("mem_user2nic: not converted to safecopies");
|
|
||||||
#else
|
|
||||||
phys_bytes offset, phys_user;
|
|
||||||
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
|
||||||
int bytes, ix = 0;
|
|
||||||
|
|
||||||
/* Computes shared memory address */
|
/* Computes shared memory address */
|
||||||
offset = pageno * DP_PAGESIZE;
|
offset = pageno * DP_PAGESIZE;
|
||||||
|
|
||||||
do { /* Reads chuncks of packet from user area */
|
netdriver_copyin(data, 0, dep->de_locmem + offset, size);
|
||||||
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of chunck */
|
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
|
||||||
|
|
||||||
/* Reads from user area to board (shared memory) */
|
|
||||||
sys_user2nic_s(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant,
|
|
||||||
dep->de_linmem + offset, bytes);
|
|
||||||
offset += bytes;
|
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
|
||||||
dp_next_iovec(iovp);
|
|
||||||
ix = 0;
|
|
||||||
}
|
|
||||||
/* Till packet done */
|
|
||||||
} while ((pktsize -= bytes) > 0);
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void pio_getblock(dpeth_t *dep, u16_t offset,
|
** Name: pio_getblock
|
||||||
** int size, void *dst)
|
|
||||||
** Function: Reads a block of packet from board (Prog. I/O).
|
** Function: Reads a block of packet from board (Prog. I/O).
|
||||||
*/
|
*/
|
||||||
static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
|
static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
|
||||||
|
@ -176,110 +108,72 @@ static void pio_getblock(dpeth_t *dep, u16_t offset, int size, void *dst)
|
||||||
/* Sets up board for reading */
|
/* Sets up board for reading */
|
||||||
ns_rw_setup(dep, CR_DM_RR, size, offset);
|
ns_rw_setup(dep, CR_DM_RR, size, offset);
|
||||||
|
|
||||||
#if PIO16 == 0
|
if (dep->de_16bit == TRUE)
|
||||||
insb(dep->de_data_port, SELF, dst, size);
|
|
||||||
#else
|
|
||||||
if (dep->de_16bit == TRUE) {
|
|
||||||
insw(dep->de_data_port, dst, size);
|
insw(dep->de_data_port, dst, size);
|
||||||
} else {
|
else
|
||||||
insb(dep->de_data_port, dst, size);
|
insb(dep->de_data_port, dst, size);
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
|
** Name: pio_nic2user
|
||||||
** Function: Copies a packet from board to user area (Prog. I/O).
|
** Function: Copies a packet from board to user area (Prog. I/O).
|
||||||
*/
|
*/
|
||||||
static void pio_nic2user(dpeth_t *dep, int pageno, int pktsize)
|
static void pio_nic2user(dpeth_t *dep, int pageno, struct netdriver_data *data,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
iovec_dat_s_t *iovp = &dep->de_read_iovec;
|
size_t offset, left;
|
||||||
unsigned offset, iov_offset; int r, bytes, ix = 0;
|
|
||||||
|
|
||||||
/* Computes memory address (skipping receive header) */
|
/* Computes memory address (skipping receive header) */
|
||||||
offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
|
offset = pageno * DP_PAGESIZE + sizeof(dp_rcvhdr_t);
|
||||||
/* Sets up board for reading */
|
|
||||||
ns_rw_setup(dep, CR_DM_RR, ((offset + pktsize) > (dep->de_stoppage * DP_PAGESIZE)) ?
|
|
||||||
(dep->de_stoppage * DP_PAGESIZE) - offset : pktsize, offset);
|
|
||||||
|
|
||||||
iov_offset= 0;
|
if (offset + size > dep->de_stoppage * DP_PAGESIZE) {
|
||||||
do { /* Reads chuncks of packet into user area */
|
left = dep->de_stoppage * DP_PAGESIZE - offset;
|
||||||
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of a chunck */
|
ns_rw_setup(dep, CR_DM_RR, left, offset);
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
|
||||||
|
|
||||||
if ((offset + bytes) > (dep->de_stoppage * DP_PAGESIZE)) {
|
if (dep->de_16bit)
|
||||||
|
netdriver_portinw(data, 0, dep->de_data_port, left);
|
||||||
|
else
|
||||||
|
netdriver_portinb(data, 0, dep->de_data_port, left);
|
||||||
|
|
||||||
/* Circular buffer wrap-around */
|
|
||||||
bytes = dep->de_stoppage * DP_PAGESIZE - offset;
|
|
||||||
r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr,
|
|
||||||
iovp->iod_iovec[ix].iov_grant, iov_offset, bytes);
|
|
||||||
if (r != OK) {
|
|
||||||
panic("pio_nic2user: sys_safe_insb failed: %d", r);
|
|
||||||
}
|
|
||||||
pktsize -= bytes;
|
|
||||||
iov_offset += bytes;
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size - bytes;
|
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
|
||||||
offset = dep->de_startpage * DP_PAGESIZE;
|
offset = dep->de_startpage * DP_PAGESIZE;
|
||||||
ns_rw_setup(dep, CR_DM_RR, pktsize, offset);
|
} else
|
||||||
}
|
left = 0;
|
||||||
r= sys_safe_insb(dep->de_data_port, iovp->iod_proc_nr,
|
|
||||||
iovp->iod_iovec[ix].iov_grant, iov_offset, bytes);
|
|
||||||
if (r != OK)
|
|
||||||
panic("pio_nic2user: sys_safe_insb failed: %d", r);
|
|
||||||
offset += bytes;
|
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
ns_rw_setup(dep, CR_DM_RR, size - left, offset);
|
||||||
dp_next_iovec(iovp);
|
|
||||||
ix = 0;
|
if (dep->de_16bit)
|
||||||
}
|
netdriver_portinw(data, left, dep->de_data_port, size - left);
|
||||||
iov_offset= 0;
|
else
|
||||||
/* Till packet done */
|
netdriver_portinb(data, left, dep->de_data_port, size - left);
|
||||||
} while ((pktsize -= bytes) > 0);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
** Name: pio_user2nic
|
||||||
** Function: Copies a packet from user area to board (Prog. I/O).
|
** Function: Copies a packet from user area to board (Prog. I/O).
|
||||||
*/
|
*/
|
||||||
static void pio_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
static void pio_user2nic(dpeth_t *dep, int pageno, struct netdriver_data *data,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
int ix;
|
||||||
int r, bytes, ix = 0;
|
|
||||||
|
|
||||||
/* Sets up board for writing */
|
/* Sets up board for writing */
|
||||||
ns_rw_setup(dep, CR_DM_RW, pktsize, pageno * DP_PAGESIZE);
|
ns_rw_setup(dep, CR_DM_RW, size, pageno * DP_PAGESIZE);
|
||||||
|
|
||||||
do { /* Reads chuncks of packet from user area */
|
if (dep->de_16bit)
|
||||||
|
netdriver_portoutw(data, 0, dep->de_data_port, size);
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of chunck */
|
else
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
netdriver_portoutb(data, 0, dep->de_data_port, size);
|
||||||
r= sys_safe_outsb(dep->de_data_port, iovp->iod_proc_nr,
|
|
||||||
iovp->iod_iovec[ix].iov_grant, 0, bytes);
|
|
||||||
if (r != OK)
|
|
||||||
panic("pio_user2nic: sys_safe_outsb failed: %d", r);
|
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */
|
|
||||||
dp_next_iovec(iovp);
|
|
||||||
ix = 0;
|
|
||||||
}
|
|
||||||
/* Till packet done */
|
|
||||||
} while ((pktsize -= bytes) > 0);
|
|
||||||
|
|
||||||
for (ix = 0; ix < 100; ix += 1) {
|
for (ix = 0; ix < 100; ix += 1) {
|
||||||
if (inb_reg0(dep, DP_ISR) & ISR_RDC) break;
|
if (inb_reg0(dep, DP_ISR) & ISR_RDC) break;
|
||||||
}
|
}
|
||||||
if (ix == 100) {
|
if (ix == 100)
|
||||||
panic("%s", RdmaErrMsg);
|
panic("remote dma failed to complete");
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_stats(dpeth_t * dep)
|
** Name: ns_stats
|
||||||
** Function: Updates counters reading from device
|
** Function: Updates counters reading from device
|
||||||
*/
|
*/
|
||||||
static void ns_stats(dpeth_t * dep)
|
static void ns_stats(dpeth_t * dep)
|
||||||
|
@ -288,22 +182,20 @@ static void ns_stats(dpeth_t * dep)
|
||||||
dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
|
dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
|
||||||
dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1);
|
dep->de_stat.ets_recvErr += inb_reg0(dep, DP_CNTR1);
|
||||||
dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2);
|
dep->de_stat.ets_fifoOver += inb_reg0(dep, DP_CNTR2);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_dodump(dpeth_t * dep)
|
** Name: ns_dodump
|
||||||
** Function: Displays statistics (a request from F5 key).
|
** Function: Displays statistics (a request from a function key).
|
||||||
*/
|
*/
|
||||||
static void ns_dodump(dpeth_t * dep)
|
static void ns_dodump(dpeth_t * dep)
|
||||||
{
|
{
|
||||||
|
|
||||||
ns_stats(dep); /* Forces reading fo counters from board */
|
ns_stats(dep); /* Forces reading of counters from board */
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_reinit(dpeth_t *dep)
|
** Name: ns_reinit
|
||||||
** Function: Updates receiver configuration.
|
** Function: Updates receiver configuration.
|
||||||
*/
|
*/
|
||||||
static void ns_reinit(dpeth_t * dep)
|
static void ns_reinit(dpeth_t * dep)
|
||||||
|
@ -315,26 +207,24 @@ static void ns_reinit(dpeth_t * dep)
|
||||||
if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM;
|
if (dep->de_flags & DEF_MULTI) dp_reg |= RCR_AM;
|
||||||
outb_reg0(dep, DP_CR, CR_PS_P0);
|
outb_reg0(dep, DP_CR, CR_PS_P0);
|
||||||
outb_reg0(dep, DP_RCR, dp_reg);
|
outb_reg0(dep, DP_RCR, dp_reg);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_send(dpeth_t * dep, int from_int, int size)
|
** Name: ns_send
|
||||||
** Function: Transfers packet to device and starts sending.
|
** Function: Transfers packet to device and starts sending.
|
||||||
*/
|
*/
|
||||||
static void ns_send(dpeth_t * dep, int from_int, int size)
|
static int ns_send(dpeth_t *dep, struct netdriver_data *data, size_t size)
|
||||||
{
|
{
|
||||||
int queue;
|
int queue;
|
||||||
|
|
||||||
if (queue = dep->de_sendq_head, dep->de_sendq[queue].sq_filled) {
|
queue = dep->de_sendq_head;
|
||||||
if (from_int) panic("should not be sending ");
|
if (dep->de_sendq[queue].sq_filled)
|
||||||
dep->de_send_s = size;
|
return SUSPEND;
|
||||||
return;
|
|
||||||
}
|
(dep->de_user2nicf)(dep, dep->de_sendq[queue].sq_sendpage, data, size);
|
||||||
(dep->de_user2nicf) (dep, dep->de_sendq[queue].sq_sendpage, size);
|
|
||||||
dep->bytes_Tx += (long) size;
|
dep->bytes_Tx += (long) size;
|
||||||
dep->de_sendq[queue].sq_filled = TRUE;
|
dep->de_sendq[queue].sq_filled = TRUE;
|
||||||
dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND);
|
dep->de_flags |= DEF_XMIT_BUSY;
|
||||||
if (dep->de_sendq_tail == queue) { /* there it goes.. */
|
if (dep->de_sendq_tail == queue) { /* there it goes.. */
|
||||||
ns_start_xmit(dep, size, dep->de_sendq[queue].sq_sendpage);
|
ns_start_xmit(dep, size, dep->de_sendq[queue].sq_sendpage);
|
||||||
} else
|
} else
|
||||||
|
@ -342,13 +232,12 @@ static void ns_send(dpeth_t * dep, int from_int, int size)
|
||||||
|
|
||||||
if (++queue == dep->de_sendq_nr) queue = 0;
|
if (++queue == dep->de_sendq_nr) queue = 0;
|
||||||
dep->de_sendq_head = queue;
|
dep->de_sendq_head = queue;
|
||||||
dep->de_flags &= NOT(DEF_SENDING);
|
|
||||||
|
|
||||||
return;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_reset(dpeth_t *dep)
|
** Name: ns_reset
|
||||||
** Function: Resets device.
|
** Function: Resets device.
|
||||||
*/
|
*/
|
||||||
static void ns_reset(dpeth_t * dep)
|
static void ns_reset(dpeth_t * dep)
|
||||||
|
@ -359,14 +248,14 @@ static void ns_reset(dpeth_t * dep)
|
||||||
outb_reg0(dep, DP_CR, CR_STP | CR_NO_DMA);
|
outb_reg0(dep, DP_CR, CR_STP | CR_NO_DMA);
|
||||||
outb_reg0(dep, DP_RBCR0, 0);
|
outb_reg0(dep, DP_RBCR0, 0);
|
||||||
outb_reg0(dep, DP_RBCR1, 0);
|
outb_reg0(dep, DP_RBCR1, 0);
|
||||||
for (ix = 0; ix < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); ix += 1)
|
for (ix = 0; ix < 0x1000 && (inb_reg0(dep, DP_ISR) & ISR_RST) == 0; ix += 1)
|
||||||
/* Do nothing */ ;
|
/* Do nothing */ ;
|
||||||
outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST);
|
outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST);
|
||||||
outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA);
|
outb_reg0(dep, DP_CR, CR_STA | CR_NO_DMA);
|
||||||
outb_reg0(dep, DP_TCR, TCR_NORMAL | TCR_OFST);
|
outb_reg0(dep, DP_TCR, TCR_NORMAL | TCR_OFST);
|
||||||
|
|
||||||
/* Acknowledge the ISR_RDC (remote dma) interrupt. */
|
/* Acknowledge the ISR_RDC (remote dma) interrupt. */
|
||||||
for (ix = 0; ix < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); ix += 1)
|
for (ix = 0; ix < 0x1000 && (inb_reg0(dep, DP_ISR) & ISR_RDC) == 0; ix += 1)
|
||||||
/* Do nothing */ ;
|
/* Do nothing */ ;
|
||||||
outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & NOT(ISR_RDC));
|
outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & NOT(ISR_RDC));
|
||||||
|
|
||||||
|
@ -376,19 +265,18 @@ static void ns_reset(dpeth_t * dep)
|
||||||
dep->de_sendq_head = dep->de_sendq_tail = 0;
|
dep->de_sendq_head = dep->de_sendq_tail = 0;
|
||||||
for (ix = 0; ix < dep->de_sendq_nr; ix++)
|
for (ix = 0; ix < dep->de_sendq_nr; ix++)
|
||||||
dep->de_sendq[ix].sq_filled = FALSE;
|
dep->de_sendq[ix].sq_filled = FALSE;
|
||||||
ns_send(dep, TRUE, dep->de_send_s);
|
netdriver_send();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_recv(dpeth_t *dep, int fromint, int size)
|
** Name: ns_recv
|
||||||
** Function: Gets a packet from device
|
** Function: Gets a packet from device
|
||||||
*/
|
*/
|
||||||
static void ns_recv(dpeth_t *dep, int fromint, int size)
|
static ssize_t ns_recv(dpeth_t *dep, struct netdriver_data *data, size_t max)
|
||||||
{
|
{
|
||||||
dp_rcvhdr_t header;
|
dp_rcvhdr_t header;
|
||||||
unsigned pageno, curr, next;
|
unsigned pageno, curr, next;
|
||||||
vir_bytes length;
|
size_t length;
|
||||||
int packet_processed = FALSE;
|
int packet_processed = FALSE;
|
||||||
#ifdef ETH_IGN_PROTO
|
#ifdef ETH_IGN_PROTO
|
||||||
u16_t eth_type;
|
u16_t eth_type;
|
||||||
|
@ -403,17 +291,21 @@ static void ns_recv(dpeth_t *dep, int fromint, int size)
|
||||||
curr = inb_reg1(dep, DP_CURR);
|
curr = inb_reg1(dep, DP_CURR);
|
||||||
outb_reg0(dep, DP_CR, CR_PS_P0 | CR_NO_DMA | CR_STA);
|
outb_reg0(dep, DP_CR, CR_PS_P0 | CR_NO_DMA | CR_STA);
|
||||||
|
|
||||||
if (curr == pageno) break;
|
if (curr == pageno)
|
||||||
|
return SUSPEND;
|
||||||
|
|
||||||
(dep->de_getblockf) (dep, pageno * DP_PAGESIZE, sizeof(header), &header);
|
(dep->de_getblockf)(dep, pageno * DP_PAGESIZE, sizeof(header),
|
||||||
|
&header);
|
||||||
#ifdef ETH_IGN_PROTO
|
#ifdef ETH_IGN_PROTO
|
||||||
(dep->de_getblockf) (dep, pageno * DP_PAGESIZE + sizeof(header) + 2 * sizeof(ether_addr_t), sizeof(eth_type), ð_type);
|
(dep->de_getblockf)(dep, pageno * DP_PAGESIZE + sizeof(header) +
|
||||||
|
2 * sizeof(ether_addr_t), sizeof(eth_type), ð_type);
|
||||||
#endif
|
#endif
|
||||||
length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t);
|
length = (header.dr_rbcl | (header.dr_rbch << 8)) -
|
||||||
|
sizeof(dp_rcvhdr_t);
|
||||||
next = header.dr_next;
|
next = header.dr_next;
|
||||||
|
|
||||||
if (length < ETH_MIN_PACK_SIZE || length > ETH_MAX_PACK_SIZE) {
|
if (length < ETH_MIN_PACK_SIZE || length > max) {
|
||||||
printf("%s: packet with strange length arrived: %ld\n",
|
printf("%s: packet with strange length arrived: %zu\n",
|
||||||
dep->de_name, length);
|
dep->de_name, length);
|
||||||
dep->de_stat.ets_recvErr += 1;
|
dep->de_stat.ets_recvErr += 1;
|
||||||
next = curr;
|
next = curr;
|
||||||
|
@ -422,50 +314,40 @@ static void ns_recv(dpeth_t *dep, int fromint, int size)
|
||||||
printf("%s: strange next page\n", dep->de_name);
|
printf("%s: strange next page\n", dep->de_name);
|
||||||
dep->de_stat.ets_recvErr += 1;
|
dep->de_stat.ets_recvErr += 1;
|
||||||
next = curr;
|
next = curr;
|
||||||
|
|
||||||
#ifdef ETH_IGN_PROTO
|
#ifdef ETH_IGN_PROTO
|
||||||
} else if (eth_type == eth_ign_proto) {
|
} else if (eth_type == eth_ign_proto) {
|
||||||
/* Hack: ignore packets of a given protocol */
|
/* Hack: ignore packets of a given protocol */
|
||||||
static int first = TRUE;
|
static int first = TRUE;
|
||||||
if (first) {
|
if (first) {
|
||||||
first = FALSE;
|
first = FALSE;
|
||||||
printf("%s: dropping proto %04x packet\n", dep->de_name, ntohs(eth_ign_proto));
|
printf("%s: dropping proto %04x packet\n",
|
||||||
|
dep->de_name, ntohs(eth_ign_proto));
|
||||||
}
|
}
|
||||||
next = curr;
|
next = curr;
|
||||||
#endif
|
#endif
|
||||||
} else if (header.dr_status & RSR_FO) {
|
} else if (header.dr_status & RSR_FO) {
|
||||||
/* This is very serious, issue a warning and reset buffers */
|
/* This is very serious, issue a warning and reset buffers */
|
||||||
printf("%s: fifo overrun, resetting receive buffer\n", dep->de_name);
|
printf("%s: fifo overrun, resetting receive buffer\n",
|
||||||
|
dep->de_name);
|
||||||
dep->de_stat.ets_fifoOver += 1;
|
dep->de_stat.ets_fifoOver += 1;
|
||||||
next = curr;
|
next = curr;
|
||||||
|
|
||||||
} else if ((header.dr_status & RSR_PRX) && (dep->de_flags & DEF_ENABLED)) {
|
} else if (header.dr_status & RSR_PRX) {
|
||||||
|
(dep->de_nic2userf)(dep, pageno, data, length);
|
||||||
if (!(dep->de_flags & DEF_READING)) break;
|
|
||||||
|
|
||||||
(dep->de_nic2userf) (dep, pageno, length);
|
|
||||||
dep->de_read_s = length;
|
|
||||||
dep->de_flags |= DEF_ACK_RECV;
|
|
||||||
dep->de_flags &= NOT(DEF_READING);
|
|
||||||
packet_processed = TRUE;
|
packet_processed = TRUE;
|
||||||
}
|
}
|
||||||
dep->bytes_Rx += (long) length;
|
dep->bytes_Rx += (long) length;
|
||||||
dep->de_stat.ets_packetR += 1;
|
dep->de_stat.ets_packetR += 1;
|
||||||
outb_reg0(dep, DP_BNRY, (next == dep->de_startpage ? dep->de_stoppage : next) - 1);
|
outb_reg0(dep, DP_BNRY,
|
||||||
|
(next == dep->de_startpage ? dep->de_stoppage : next) - 1);
|
||||||
pageno = next;
|
pageno = next;
|
||||||
|
|
||||||
} while (!packet_processed);
|
} while (!packet_processed);
|
||||||
#if 0
|
|
||||||
if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED))
|
return length;
|
||||||
/* The chip is stopped, and all arrived packets delivered */
|
|
||||||
(*dep->de_resetf) (dep);
|
|
||||||
dep->de_flags &= NOT(DEF_STOPPED);
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_interrupt(dpeth_t * dep)
|
** Name: ns_interrupt
|
||||||
** Function: Handles interrupt.
|
** Function: Handles interrupt.
|
||||||
*/
|
*/
|
||||||
static void ns_interrupt(dpeth_t * dep)
|
static void ns_interrupt(dpeth_t * dep)
|
||||||
|
@ -487,13 +369,15 @@ static void ns_interrupt(dpeth_t * dep)
|
||||||
dep->de_stat.ets_fifoUnder++;
|
dep->de_stat.ets_fifoUnder++;
|
||||||
}
|
}
|
||||||
if ((isr & ISR_TXE) || (tsr & (TSR_CRS | TSR_CDH | TSR_OWC))) {
|
if ((isr & ISR_TXE) || (tsr & (TSR_CRS | TSR_CDH | TSR_OWC))) {
|
||||||
printf("%s: got send Error (0x%02X)\n", dep->de_name, tsr);
|
printf("%s: got send Error (0x%02X)\n",
|
||||||
|
dep->de_name, tsr);
|
||||||
dep->de_stat.ets_sendErr++;
|
dep->de_stat.ets_sendErr++;
|
||||||
}
|
}
|
||||||
queue = dep->de_sendq_tail;
|
queue = dep->de_sendq_tail;
|
||||||
|
|
||||||
if (!(dep->de_sendq[queue].sq_filled)) { /* Hardware bug? */
|
if (!(dep->de_sendq[queue].sq_filled)) { /* Hardware bug? */
|
||||||
printf("%s: transmit interrupt, but not sending\n", dep->de_name);
|
printf("%s: transmit interrupt, but not sending\n",
|
||||||
|
dep->de_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
dep->de_sendq[queue].sq_filled = FALSE;
|
dep->de_sendq[queue].sq_filled = FALSE;
|
||||||
|
@ -503,15 +387,14 @@ static void ns_interrupt(dpeth_t * dep)
|
||||||
ns_start_xmit(dep, dep->de_sendq[queue].sq_size,
|
ns_start_xmit(dep, dep->de_sendq[queue].sq_size,
|
||||||
dep->de_sendq[queue].sq_sendpage);
|
dep->de_sendq[queue].sq_sendpage);
|
||||||
}
|
}
|
||||||
if (dep->de_flags & DEF_SENDING) {
|
netdriver_send();
|
||||||
ns_send(dep, TRUE, dep->de_send_s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (isr & ISR_PRX) {
|
if (isr & ISR_PRX) {
|
||||||
ns_recv(dep, TRUE, 0);
|
netdriver_recv();
|
||||||
}
|
}
|
||||||
if (isr & ISR_RXE) {
|
if (isr & ISR_RXE) {
|
||||||
printf("%s: got recv Error (0x%04X)\n", dep->de_name, inb_reg0(dep, DP_RSR));
|
printf("%s: got recv Error (0x%04X)\n",
|
||||||
|
dep->de_name, inb_reg0(dep, DP_RSR));
|
||||||
dep->de_stat.ets_recvErr++;
|
dep->de_stat.ets_recvErr++;
|
||||||
}
|
}
|
||||||
if (isr & ISR_CNT) {
|
if (isr & ISR_CNT) {
|
||||||
|
@ -526,26 +409,21 @@ static void ns_interrupt(dpeth_t * dep)
|
||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
}
|
}
|
||||||
if (isr & ISR_RST) {
|
if (isr & ISR_RST) {
|
||||||
/* This means we got an interrupt but the ethernet
|
/* This means we got an interrupt but the ethernet chip is shut
|
||||||
* chip is shutdown. We set the flag DEF_STOPPED, and
|
* down. We reset the chip right away, possibly losing received
|
||||||
* continue processing arrived packets. When the
|
* packets in the process. There used to be a more elaborate
|
||||||
* receive buffer is empty, we reset the dp8390. */
|
* approach of resetting only after all pending packets had
|
||||||
|
* been accepted, but it was broken and this is simpler anyway.
|
||||||
|
*/
|
||||||
printf("%s: network interface stopped\n", dep->de_name);
|
printf("%s: network interface stopped\n", dep->de_name);
|
||||||
dep->de_flags |= DEF_STOPPED;
|
ns_reset(dep);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED)) {
|
|
||||||
|
|
||||||
/* The chip is stopped, and all arrived packets delivered */
|
|
||||||
ns_reset(dep);
|
|
||||||
dep->de_flags &= NOT(DEF_STOPPED);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ns_init(dpeth_t *dep)
|
** Name: ns_init
|
||||||
** Function: Initializes the NS 8390
|
** Function: Initializes the NS 8390
|
||||||
*/
|
*/
|
||||||
void ns_init(dpeth_t * dep)
|
void ns_init(dpeth_t * dep)
|
||||||
|
@ -555,12 +433,8 @@ void ns_init(dpeth_t * dep)
|
||||||
|
|
||||||
/* NS8390 initialization (as recommended in National Semiconductor specs) */
|
/* NS8390 initialization (as recommended in National Semiconductor specs) */
|
||||||
outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_NO_DMA); /* 0x21 */
|
outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_NO_DMA); /* 0x21 */
|
||||||
#if PIO16 == 0
|
|
||||||
outb_reg0(dep, DP_DCR, (DCR_BYTEWIDE | DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS));
|
|
||||||
#else
|
|
||||||
outb_reg0(dep, DP_DCR, (((dep->de_16bit) ? DCR_WORDWIDE : DCR_BYTEWIDE) |
|
outb_reg0(dep, DP_DCR, (((dep->de_16bit) ? DCR_WORDWIDE : DCR_BYTEWIDE) |
|
||||||
DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS));
|
DCR_LTLENDIAN | DCR_8BYTES | DCR_BMS));
|
||||||
#endif
|
|
||||||
outb_reg0(dep, DP_RBCR0, 0);
|
outb_reg0(dep, DP_RBCR0, 0);
|
||||||
outb_reg0(dep, DP_RBCR1, 0);
|
outb_reg0(dep, DP_RBCR1, 0);
|
||||||
outb_reg0(dep, DP_RCR, RCR_MON); /* Sets Monitor mode */
|
outb_reg0(dep, DP_RCR, RCR_MON); /* Sets Monitor mode */
|
||||||
|
@ -609,13 +483,9 @@ void ns_init(dpeth_t * dep)
|
||||||
dep->de_nic2userf = mem_nic2user;
|
dep->de_nic2userf = mem_nic2user;
|
||||||
dep->de_getblockf = mem_getblock;
|
dep->de_getblockf = mem_getblock;
|
||||||
} else {
|
} else {
|
||||||
#if PIO16 == 0
|
|
||||||
dep->de_user2nicf = pio_user2nic;
|
dep->de_user2nicf = pio_user2nic;
|
||||||
dep->de_nic2userf = pio_nic2user;
|
dep->de_nic2userf = pio_nic2user;
|
||||||
dep->de_getblockf = pio_getblock;
|
dep->de_getblockf = pio_getblock;
|
||||||
#else
|
|
||||||
#error Missing I/O functions for pio 16 bits
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
dep->de_recvf = ns_recv;
|
dep->de_recvf = ns_recv;
|
||||||
dep->de_sendf = ns_send;
|
dep->de_sendf = ns_send;
|
||||||
|
@ -624,135 +494,8 @@ void ns_init(dpeth_t * dep)
|
||||||
dep->de_getstatsf = ns_stats;
|
dep->de_getstatsf = ns_stats;
|
||||||
dep->de_dumpstatsf = ns_dodump;
|
dep->de_dumpstatsf = ns_dodump;
|
||||||
dep->de_interruptf = ns_interrupt;
|
dep->de_interruptf = ns_interrupt;
|
||||||
|
|
||||||
return; /* Done */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PIO16 == 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
|
||||||
** Function: Copies a packet from user area to board (Prog. I/O, 16bits).
|
|
||||||
*/
|
|
||||||
static void dp_pio16_user2nic(dpeth_t *dep, int pageno, int pktsize)
|
|
||||||
{
|
|
||||||
u8_t two_bytes[2];
|
|
||||||
phys_bytes phys_user, phys_2bytes = vir2phys(two_bytes);
|
|
||||||
vir_bytes ecount = (pktsize + 1) & NOT(0x0001);
|
|
||||||
int bytes, ix = 0, odd_byte = 0;
|
|
||||||
iovec_dat_t *iovp = &dep->de_write_iovec;
|
|
||||||
|
|
||||||
outb_reg0(dep, DP_ISR, ISR_RDC);
|
|
||||||
dp_read_setup(dep, ecount, pageno * DP_PAGESIZE);
|
|
||||||
|
|
||||||
do {
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size;
|
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
|
||||||
|
|
||||||
phys_user = numap(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_addr, bytes);
|
|
||||||
if (!phys_user) panic(UmapErrMsg);
|
|
||||||
|
|
||||||
if (odd_byte) {
|
|
||||||
phys_copy(phys_user, phys_2bytes + 1, (phys_bytes) 1);
|
|
||||||
out_word(dep->de_data_port, *(u16_t *)two_bytes);
|
|
||||||
pktsize--;
|
|
||||||
bytes--;
|
|
||||||
phys_user++;
|
|
||||||
odd_byte = 0;
|
|
||||||
if (!bytes) continue;
|
|
||||||
}
|
|
||||||
ecount = bytes & NOT(0x0001);
|
|
||||||
if (ecount != 0) {
|
|
||||||
phys_outsw(dep->de_data_port, phys_user, ecount);
|
|
||||||
pktsize -= ecount;
|
|
||||||
bytes -= ecount;
|
|
||||||
phys_user += ecount;
|
|
||||||
}
|
|
||||||
if (bytes) {
|
|
||||||
phys_copy(phys_user, phys_2bytes, (phys_bytes) 1);
|
|
||||||
pktsize--;
|
|
||||||
bytes--;
|
|
||||||
phys_user++;
|
|
||||||
odd_byte = 1;
|
|
||||||
}
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of I/O vector */
|
|
||||||
dp_next_iovec(iovp);
|
|
||||||
ix = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (bytes > 0);
|
|
||||||
|
|
||||||
if (odd_byte) out_word(dep->de_data_port, *(u16_t *) two_bytes);
|
|
||||||
for (ix = 0; ix < 100; ix++) {
|
|
||||||
if (inb_reg0(dep, DP_ISR) & ISR_RDC) break;
|
|
||||||
}
|
|
||||||
if (ix == 100) {
|
|
||||||
panic(RdmaErrMsg);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: void dp_pio16_nic2user(dpeth_t *dep, int pageno, int pktsize)
|
|
||||||
** Function: Copies a packet from board to user area (Prog. I/O, 16bits).
|
|
||||||
*/
|
|
||||||
static void dp_pio16_nic2user(dpeth_t * dep, int nic_addr, int count)
|
|
||||||
{
|
|
||||||
phys_bytes phys_user;
|
|
||||||
vir_bytes ecount;
|
|
||||||
int bytes, i;
|
|
||||||
u8_t two_bytes[2];
|
|
||||||
phys_bytes phys_2bytes;
|
|
||||||
int odd_byte;
|
|
||||||
|
|
||||||
ecount = (count + 1) & ~1;
|
|
||||||
phys_2bytes = vir2phys(two_bytes);
|
|
||||||
odd_byte = 0;
|
|
||||||
|
|
||||||
dp_read_setup(dep, ecount, nic_addr);
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (count > 0) {
|
|
||||||
if (i >= IOVEC_NR) {
|
|
||||||
dp_next_iovec(iovp);
|
|
||||||
i = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bytes = iovp->iod_iovec[i].iov_size;
|
|
||||||
if (bytes > count) bytes = count;
|
|
||||||
|
|
||||||
phys_user = numap(iovp->iod_proc_nr,
|
|
||||||
iovp->iod_iovec[i].iov_addr, bytes);
|
|
||||||
if (!phys_user) panic(UmapErrMsg);
|
|
||||||
if (odd_byte) {
|
|
||||||
phys_copy(phys_2bytes + 1, phys_user, (phys_bytes) 1);
|
|
||||||
count--;
|
|
||||||
bytes--;
|
|
||||||
phys_user++;
|
|
||||||
odd_byte = 0;
|
|
||||||
if (!bytes) continue;
|
|
||||||
}
|
|
||||||
ecount = bytes & ~1;
|
|
||||||
if (ecount != 0) {
|
|
||||||
phys_insw(dep->de_data_port, phys_user, ecount);
|
|
||||||
count -= ecount;
|
|
||||||
bytes -= ecount;
|
|
||||||
phys_user += ecount;
|
|
||||||
}
|
|
||||||
if (bytes) {
|
|
||||||
*(u16_t *) two_bytes = in_word(dep->de_data_port);
|
|
||||||
phys_copy(phys_2bytes, phys_user, (phys_bytes) 1);
|
|
||||||
count--;
|
|
||||||
bytes--;
|
|
||||||
phys_user++;
|
|
||||||
odd_byte = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* PIO16 == 1 */
|
|
||||||
|
|
||||||
#endif /* ENABLE_DP8390 */
|
#endif /* ENABLE_DP8390 */
|
||||||
|
|
||||||
/** end 8390.c **/
|
/** end 8390.c **/
|
||||||
|
|
|
@ -5,6 +5,6 @@ SRCS= 3c501.c 3c509.c 3c503.c ne.c wd.c 8390.c devio.c netbuff.c dp.c
|
||||||
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
|
DPADD+= ${LIBNETDRIVER} ${LIBSYS}
|
||||||
LDADD+= -lnetdriver -lsys
|
LDADD+= -lnetdriver -lsys
|
||||||
|
|
||||||
CPPFLAGS+= -Ddebug=0
|
CPPFLAGS+= -DVERBOSE=0
|
||||||
|
|
||||||
.include <minix.service.mk>
|
.include <minix.service.mk>
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
**
|
**
|
||||||
** Author: Giovanni Falzoni <gfalzoni@inwind.it>
|
** Author: Giovanni Falzoni <gfalzoni@inwind.it>
|
||||||
**
|
**
|
||||||
** This file contains the routines for readind/writing
|
** This file contains the routines for reading/writing
|
||||||
** from/to the device registers.
|
** from/to the device registers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
|
#include <minix/netdriver.h>
|
||||||
#include <net/gen/ether.h>
|
#include <net/gen/ether.h>
|
||||||
#include <net/gen/eth_io.h>
|
#include <net/gen/eth_io.h>
|
||||||
#include "dp.h"
|
#include "dp.h"
|
||||||
|
@ -18,11 +19,10 @@ static void warning(const char *type, int err)
|
||||||
{
|
{
|
||||||
|
|
||||||
printf("Warning: eth#0 sys_%s failed (%d)\n", type, err);
|
printf("Warning: eth#0 sys_%s failed (%d)\n", type, err);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: unsigned int inb(unsigned short int port);
|
** Name: inb
|
||||||
** Function: Reads a byte from specified i/o port.
|
** Function: Reads a byte from specified i/o port.
|
||||||
*/
|
*/
|
||||||
unsigned int inb(unsigned short port)
|
unsigned int inb(unsigned short port)
|
||||||
|
@ -35,7 +35,7 @@ unsigned int inb(unsigned short port)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: unsigned int inw(unsigned short int port);
|
** Name: inw
|
||||||
** Function: Reads a word from specified i/o port.
|
** Function: Reads a word from specified i/o port.
|
||||||
*/
|
*/
|
||||||
unsigned int inw(unsigned short port)
|
unsigned int inw(unsigned short port)
|
||||||
|
@ -48,22 +48,31 @@ unsigned int inw(unsigned short port)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: unsigned int insb(unsigned short int port, int proc_nr, void *buffer, int count);
|
** Name: insb
|
||||||
** Function: Reads a sequence of bytes from specified i/o port to user space buffer.
|
** Function: Reads a sequence of bytes from an i/o port.
|
||||||
*/
|
*/
|
||||||
void insb(unsigned short int port, endpoint_t proc_nr,
|
void insb(unsigned short int port, void *buffer, int count)
|
||||||
void *buffer, int count)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ((rc = sys_insb(port, proc_nr, buffer, count)) != OK)
|
if ((rc = sys_insb(port, SELF, buffer, count)) != OK)
|
||||||
warning("insb", rc);
|
warning("insb", rc);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Name: insw
|
||||||
|
** Function: Reads a sequence of words from an i/o port.
|
||||||
|
*/
|
||||||
|
void insw(unsigned short int port, void *buffer, int count)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ((rc = sys_insw(port, SELF, buffer, count)) != OK)
|
||||||
|
warning("insw", rc);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void outb(unsigned short int port, unsigned long value);
|
** Name: outb
|
||||||
** Function: Writes a byte to specified i/o port.
|
** Function: Writes a byte to specified i/o port.
|
||||||
*/
|
*/
|
||||||
void outb(unsigned short port, unsigned long value)
|
void outb(unsigned short port, unsigned long value)
|
||||||
|
@ -71,11 +80,10 @@ void outb(unsigned short port, unsigned long value)
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ((rc = sys_outb(port, value)) != OK) warning("outb", rc);
|
if ((rc = sys_outb(port, value)) != OK) warning("outb", rc);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void outw(unsigned short int port, unsigned long value);
|
** Name: outw
|
||||||
** Function: Writes a word to specified i/o port.
|
** Function: Writes a word to specified i/o port.
|
||||||
*/
|
*/
|
||||||
void outw(unsigned short port, unsigned long value)
|
void outw(unsigned short port, unsigned long value)
|
||||||
|
@ -83,20 +91,18 @@ void outw(unsigned short port, unsigned long value)
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ((rc = sys_outw(port, value)) != OK) warning("outw", rc);
|
if ((rc = sys_outw(port, value)) != OK) warning("outw", rc);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void outsb(unsigned short int port, int proc_nr, void *buffer, int count);
|
** Name: outsb
|
||||||
** Function: Writes a sequence of bytes from user space to specified i/o port.
|
** Function: Writes a sequence of bytes to an i/o port.
|
||||||
*/
|
*/
|
||||||
void outsb(unsigned short port, endpoint_t proc_nr, void *buffer, int count)
|
void outsb(unsigned short port, void *buffer, int count)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ((rc = sys_outsb(port, proc_nr, buffer, count)) != OK)
|
if ((rc = sys_outsb(port, SELF, buffer, count)) != OK)
|
||||||
warning("outsb", rc);
|
warning("outsb", rc);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -14,9 +14,10 @@
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
#include <minix/netdriver.h>
|
#include <minix/netdriver.h>
|
||||||
#include <minix/endpoint.h>
|
#include <minix/endpoint.h>
|
||||||
#include <minix/ds.h>
|
|
||||||
#include <net/gen/ether.h>
|
#include <net/gen/ether.h>
|
||||||
#include <net/gen/eth_io.h>
|
#include <net/gen/eth_io.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "dp.h"
|
#include "dp.h"
|
||||||
|
|
||||||
|
@ -24,7 +25,6 @@
|
||||||
** Local data
|
** Local data
|
||||||
*/
|
*/
|
||||||
static dpeth_t de_state;
|
static dpeth_t de_state;
|
||||||
static int de_instance;
|
|
||||||
|
|
||||||
typedef struct dp_conf { /* Configuration description structure */
|
typedef struct dp_conf { /* Configuration description structure */
|
||||||
port_t dpc_port;
|
port_t dpc_port;
|
||||||
|
@ -41,90 +41,43 @@ static dp_conf_t dp_conf[DP_CONF_NR] = {
|
||||||
{ 0x000, 0, 0x00000, },
|
{ 0x000, 0, 0x00000, },
|
||||||
};
|
};
|
||||||
|
|
||||||
static char CopyErrMsg[] = "unable to read/write user data";
|
static int do_init(unsigned int instance, ether_addr_t *addr);
|
||||||
static char RecvErrMsg[] = "netdriver_receive failed";
|
static void do_stop(void);
|
||||||
static char SendErrMsg[] = "send failed";
|
static void do_mode(unsigned int mode);
|
||||||
static char SizeErrMsg[] = "illegal packet size";
|
static int do_send(struct netdriver_data *data, size_t size);
|
||||||
static char TypeErrMsg[] = "illegal message type";
|
static ssize_t do_recv(struct netdriver_data *data, size_t max);
|
||||||
static char DevName[] = "eth#?";
|
static void do_stat(eth_stat_t *stat);
|
||||||
|
static void do_intr(unsigned int mask);
|
||||||
|
static void do_other(const message *m_ptr, int ipc_status);
|
||||||
|
|
||||||
|
static const struct netdriver dp_table = {
|
||||||
|
.ndr_init = do_init,
|
||||||
|
.ndr_stop = do_stop,
|
||||||
|
.ndr_mode = do_mode,
|
||||||
|
.ndr_recv = do_recv,
|
||||||
|
.ndr_send = do_send,
|
||||||
|
.ndr_stat = do_stat,
|
||||||
|
.ndr_intr = do_intr,
|
||||||
|
.ndr_other = do_other
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void reply(dpeth_t *dep, int err, int m_type)
|
** Name: update_conf
|
||||||
** Function: Fills a reply message and sends it.
|
|
||||||
*/
|
|
||||||
static void reply(dpeth_t * dep)
|
|
||||||
{
|
|
||||||
message reply;
|
|
||||||
int r, flags;
|
|
||||||
|
|
||||||
flags = DL_NOFLAGS;
|
|
||||||
if (dep->de_flags & DEF_ACK_SEND) flags |= DL_PACK_SEND;
|
|
||||||
if (dep->de_flags & DEF_ACK_RECV) flags |= DL_PACK_RECV;
|
|
||||||
|
|
||||||
reply.m_type = DL_TASK_REPLY;
|
|
||||||
reply.m_netdrv_net_dl_task.flags = flags;
|
|
||||||
reply.m_netdrv_net_dl_task.count = dep->de_read_s;
|
|
||||||
|
|
||||||
DEBUG(printf("\t reply %d (%lx)\n", reply.m_type,
|
|
||||||
reply.m_netdrv_net_dl_task.flags));
|
|
||||||
|
|
||||||
if ((r = ipc_send(dep->de_client, &reply)) != OK)
|
|
||||||
panic(SendErrMsg, r);
|
|
||||||
|
|
||||||
dep->de_read_s = 0;
|
|
||||||
dep->de_flags &= NOT(DEF_ACK_SEND | DEF_ACK_RECV);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: void dp_confaddr(dpeth_t *dep)
|
|
||||||
** Function: Checks environment for a User defined ethernet address.
|
|
||||||
*/
|
|
||||||
static void dp_confaddr(dpeth_t * dep)
|
|
||||||
{
|
|
||||||
static char ea_fmt[] = "x:x:x:x:x:x";
|
|
||||||
char ea_key[16];
|
|
||||||
int ix;
|
|
||||||
long val;
|
|
||||||
|
|
||||||
strlcpy(ea_key, "DPETH0_EA", sizeof(ea_key));
|
|
||||||
ea_key[5] += de_instance;
|
|
||||||
|
|
||||||
for (ix = 0; ix < SA_ADDR_LEN; ix++) {
|
|
||||||
val = dep->de_address.ea_addr[ix];
|
|
||||||
if (env_parse(ea_key, ea_fmt, ix, &val, 0x00L, 0xFFL) != EP_SET)
|
|
||||||
break;
|
|
||||||
dep->de_address.ea_addr[ix] = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ix != 0 && ix != SA_ADDR_LEN)
|
|
||||||
/* It's all or nothing, force a panic */
|
|
||||||
env_parse(ea_key, "?", 0, &val, 0L, 0L);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: void update_conf(dpeth_t *dep, dp_conf_t *dcp)
|
|
||||||
** Function: Gets the default settings from 'dp_conf' table and
|
** Function: Gets the default settings from 'dp_conf' table and
|
||||||
** modifies them from the environment.
|
** modifies them from the environment.
|
||||||
*/
|
*/
|
||||||
static void update_conf(dpeth_t * dep, const dp_conf_t * dcp)
|
static void update_conf(dpeth_t * dep, const dp_conf_t * dcp,
|
||||||
|
unsigned int instance)
|
||||||
{
|
{
|
||||||
static char dpc_fmt[] = "x:d:x";
|
static char dpc_fmt[] = "x:d:x";
|
||||||
char ec_key[16];
|
char ec_key[16];
|
||||||
long val;
|
long val;
|
||||||
|
|
||||||
strlcpy(ec_key, "DPETH0", sizeof(ec_key));
|
strlcpy(ec_key, "DPETH0", sizeof(ec_key));
|
||||||
ec_key[5] += de_instance;
|
ec_key[5] += instance;
|
||||||
|
|
||||||
dep->de_mode = DEM_SINK;
|
|
||||||
val = dcp->dpc_port; /* Get I/O port address */
|
val = dcp->dpc_port; /* Get I/O port address */
|
||||||
switch (env_parse(ec_key, dpc_fmt, 0, &val, 0x000L, 0x3FFL)) {
|
env_parse(ec_key, dpc_fmt, 0, &val, 0x000L, 0x3FFL);
|
||||||
case EP_OFF: dep->de_mode = DEM_DISABLED; break;
|
|
||||||
case EP_ON:
|
|
||||||
case EP_SET: dep->de_mode = DEM_ENABLED; break;
|
|
||||||
}
|
|
||||||
dep->de_base_port = val;
|
dep->de_base_port = val;
|
||||||
|
|
||||||
val = dcp->dpc_irq | DEI_DEFAULT; /* Get Interrupt line (IRQ) */
|
val = dcp->dpc_irq | DEI_DEFAULT; /* Get Interrupt line (IRQ) */
|
||||||
|
@ -134,15 +87,13 @@ static void update_conf(dpeth_t * dep, const dp_conf_t * dcp)
|
||||||
val = dcp->dpc_mem; /* Get shared memory address */
|
val = dcp->dpc_mem; /* Get shared memory address */
|
||||||
env_parse(ec_key, dpc_fmt, 2, &val, 0L, LONG_MAX);
|
env_parse(ec_key, dpc_fmt, 2, &val, 0L, LONG_MAX);
|
||||||
dep->de_linmem = val;
|
dep->de_linmem = val;
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void do_dump(message *mp)
|
** Name: do_dump
|
||||||
** Function: Displays statistics on screen (SFx key from console)
|
** Function: Displays statistics on screen (SFx key from console)
|
||||||
*/
|
*/
|
||||||
static void do_dump(const message *mp)
|
static void do_dump(void)
|
||||||
{
|
{
|
||||||
dpeth_t *dep;
|
dpeth_t *dep;
|
||||||
|
|
||||||
|
@ -150,14 +101,12 @@ static void do_dump(const message *mp)
|
||||||
|
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
|
|
||||||
if (dep->de_mode == DEM_DISABLED) return;
|
|
||||||
|
|
||||||
printf("%s statistics:\t\t", dep->de_name);
|
printf("%s statistics:\t\t", dep->de_name);
|
||||||
|
|
||||||
/* Network interface status */
|
/* Network interface status */
|
||||||
printf("Status: 0x%04x (%d)\n\n", dep->de_flags, dep->de_int_pending);
|
printf("Status: 0x%04x\n\n", dep->de_flags);
|
||||||
|
|
||||||
(*dep->de_dumpstatsf) (dep);
|
(*dep->de_dumpstatsf)(dep);
|
||||||
|
|
||||||
/* Transmitted/received bytes */
|
/* Transmitted/received bytes */
|
||||||
printf("Tx bytes:%10ld\t", dep->bytes_Tx);
|
printf("Tx bytes:%10ld\t", dep->bytes_Tx);
|
||||||
|
@ -178,40 +127,31 @@ static void do_dump(const message *mp)
|
||||||
/* Transmit collisions/receive CRC errors */
|
/* Transmit collisions/receive CRC errors */
|
||||||
printf("Tx Coll: %8ld\t", dep->de_stat.ets_collision);
|
printf("Tx Coll: %8ld\t", dep->de_stat.ets_collision);
|
||||||
printf("Rx CRC: %8ld\n", dep->de_stat.ets_CRCerr);
|
printf("Rx CRC: %8ld\n", dep->de_stat.ets_CRCerr);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void get_userdata_s(int user_proc, vir_bytes user_addr, int count, void *loc_addr)
|
** Name: do_first_init
|
||||||
** Function: Copies data from user area.
|
|
||||||
*/
|
|
||||||
static void get_userdata_s(int user_proc, cp_grant_id_t grant,
|
|
||||||
vir_bytes offset, int count, void *loc_addr)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
vir_bytes len;
|
|
||||||
|
|
||||||
len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t);
|
|
||||||
if ((rc = sys_safecopyfrom(user_proc, grant, 0, (vir_bytes)loc_addr, len)) != OK)
|
|
||||||
panic(CopyErrMsg, rc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: void do_first_init(dpeth_t *dep, dp_conf_t *dcp);
|
|
||||||
** Function: Init action to setup task
|
** Function: Init action to setup task
|
||||||
*/
|
*/
|
||||||
static void do_first_init(dpeth_t *dep, const dp_conf_t *dcp)
|
static void do_first_init(dpeth_t *dep, const dp_conf_t *dcp)
|
||||||
{
|
{
|
||||||
|
|
||||||
dep->de_linmem = 0xFFFF0000;
|
dep->de_linmem = 0xFFFF0000; /* FIXME: this overrides update_conf, why? */
|
||||||
|
|
||||||
/* Make sure statisics are cleared */
|
/* Make sure statisics are cleared */
|
||||||
memset((void *) &(dep->de_stat), 0, sizeof(eth_stat_t));
|
memset(&dep->de_stat, 0, sizeof(dep->de_stat));
|
||||||
|
|
||||||
/* Device specific initialization */
|
/* Device specific initialization */
|
||||||
(*dep->de_initf) (dep);
|
(*dep->de_initf)(dep);
|
||||||
|
|
||||||
|
/* Map memory if requested */
|
||||||
|
if (dep->de_linmem != 0) {
|
||||||
|
assert(dep->de_ramsize > 0);
|
||||||
|
dep->de_locmem =
|
||||||
|
vm_map_phys(SELF, (void *)dep->de_linmem, dep->de_ramsize);
|
||||||
|
if (dep->de_locmem == MAP_FAILED)
|
||||||
|
panic("unable to map memory");
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the interrupt handler policy. Request interrupts not to be reenabled
|
/* Set the interrupt handler policy. Request interrupts not to be reenabled
|
||||||
* automatically. Return the IRQ line number when an interrupt occurs.
|
* automatically. Return the IRQ line number when an interrupt occurs.
|
||||||
|
@ -219,402 +159,160 @@ static void do_first_init(dpeth_t *dep, const dp_conf_t *dcp)
|
||||||
dep->de_hook = dep->de_irq;
|
dep->de_hook = dep->de_irq;
|
||||||
if (sys_irqsetpolicy(dep->de_irq, 0 /*IRQ_REENABLE*/, &dep->de_hook) != OK)
|
if (sys_irqsetpolicy(dep->de_irq, 0 /*IRQ_REENABLE*/, &dep->de_hook) != OK)
|
||||||
panic("unable to set IRQ policy");
|
panic("unable to set IRQ policy");
|
||||||
dep->de_int_pending = FALSE;
|
|
||||||
sys_irqenable(&dep->de_hook);
|
sys_irqenable(&dep->de_hook);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void do_init(message *mp)
|
** Name: do_init
|
||||||
** Function: Checks for hardware presence.
|
** Function: Checks for hardware presence.
|
||||||
** Provides initialization of hardware and data structures
|
** Initialize hardware and data structures.
|
||||||
|
** Return status and ethernet address.
|
||||||
*/
|
*/
|
||||||
static void do_init(const message * mp)
|
static int do_init(unsigned int instance, ether_addr_t *addr)
|
||||||
{
|
{
|
||||||
dpeth_t *dep;
|
dpeth_t *dep;
|
||||||
dp_conf_t *dcp;
|
dp_conf_t *dcp;
|
||||||
message reply_mess;
|
int confnr, fkeys, sfkeys;
|
||||||
int r, confnr;
|
|
||||||
|
|
||||||
dep = &de_state;
|
dep = &de_state;
|
||||||
|
|
||||||
|
strlcpy(dep->de_name, "dpeth#?", sizeof(dep->de_name));
|
||||||
|
dep->de_name[4] = '0' + instance;
|
||||||
|
|
||||||
/* Pick a default configuration for this instance. */
|
/* Pick a default configuration for this instance. */
|
||||||
confnr = MIN(de_instance, DP_CONF_NR-1);
|
confnr = MIN(instance, DP_CONF_NR-1);
|
||||||
|
|
||||||
dcp = &dp_conf[confnr];
|
dcp = &dp_conf[confnr];
|
||||||
strlcpy(dep->de_name, DevName, sizeof(dep->de_name));
|
|
||||||
dep->de_name[4] = '0' + de_instance;
|
|
||||||
|
|
||||||
if (dep->de_mode == DEM_DISABLED) {
|
update_conf(dep, dcp, instance);
|
||||||
|
|
||||||
update_conf(dep, dcp); /* First time thru */
|
if (!el1_probe(dep) && /* Probe for 3c501 */
|
||||||
if (dep->de_mode == DEM_ENABLED &&
|
|
||||||
!el1_probe(dep) && /* Probe for 3c501 */
|
|
||||||
!wdeth_probe(dep) && /* Probe for WD80x3 */
|
!wdeth_probe(dep) && /* Probe for WD80x3 */
|
||||||
!ne_probe(dep) && /* Probe for NEx000 */
|
!ne_probe(dep) && /* Probe for NEx000 */
|
||||||
!el2_probe(dep) && /* Probe for 3c503 */
|
!el2_probe(dep) && /* Probe for 3c503 */
|
||||||
!el3_probe(dep)) { /* Probe for 3c509 */
|
!el3_probe(dep)) { /* Probe for 3c509 */
|
||||||
printf("%s: warning no ethernet card found at 0x%04X\n",
|
printf("%s: warning no ethernet card found at 0x%04X\n",
|
||||||
dep->de_name, dep->de_base_port);
|
dep->de_name, dep->de_base_port);
|
||||||
dep->de_mode = DEM_DISABLED;
|
return ENXIO;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = OK;
|
|
||||||
|
|
||||||
/* 'de_mode' may change if probe routines fail, test again */
|
|
||||||
switch (dep->de_mode) {
|
|
||||||
|
|
||||||
case DEM_DISABLED:
|
|
||||||
/* Device is configured OFF or hardware probe failed */
|
|
||||||
r = ENXIO;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEM_ENABLED:
|
|
||||||
/* Device is present and probed */
|
|
||||||
if (dep->de_flags == DEF_EMPTY) {
|
|
||||||
/* These actions only the first time */
|
|
||||||
do_first_init(dep, dcp);
|
do_first_init(dep, dcp);
|
||||||
dep->de_flags |= DEF_ENABLED;
|
|
||||||
}
|
/* Request function key for debug dumps */
|
||||||
|
fkeys = sfkeys = 0; bit_set(sfkeys, 7);
|
||||||
|
if (fkey_map(&fkeys, &sfkeys) != OK)
|
||||||
|
printf("%s: couldn't bind Shift+F7 key (%d)\n", dep->de_name, errno);
|
||||||
|
|
||||||
|
memcpy(addr, dep->de_address.ea_addr, sizeof(*addr));
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Name: de_mode
|
||||||
|
** Function: Sets packet receipt mode.
|
||||||
|
*/
|
||||||
|
static void do_mode(unsigned int mode)
|
||||||
|
{
|
||||||
|
dpeth_t *dep;
|
||||||
|
|
||||||
|
dep = &de_state;
|
||||||
|
|
||||||
dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
|
dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
|
||||||
if (mp->m_net_netdrv_dl_conf.mode & DL_PROMISC_REQ)
|
if (mode & NDEV_PROMISC)
|
||||||
dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
|
dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
|
||||||
if (mp->m_net_netdrv_dl_conf.mode & DL_MULTI_REQ)
|
if (mode & NDEV_MULTI)
|
||||||
dep->de_flags |= DEF_MULTI;
|
dep->de_flags |= DEF_MULTI;
|
||||||
if (mp->m_net_netdrv_dl_conf.mode & DL_BROAD_REQ)
|
if (mode & NDEV_BROAD)
|
||||||
dep->de_flags |= DEF_BROAD;
|
dep->de_flags |= DEF_BROAD;
|
||||||
(*dep->de_flagsf) (dep);
|
(*dep->de_flagsf)(dep);
|
||||||
break;
|
|
||||||
|
|
||||||
case DEM_SINK:
|
|
||||||
/* Device not present (sink mode) */
|
|
||||||
memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t));
|
|
||||||
dp_confaddr(dep); /* Station address from env. */
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
reply_mess.m_type = DL_CONF_REPLY;
|
|
||||||
reply_mess.m_netdrv_net_dl_conf.stat = r;
|
|
||||||
if (r == OK)
|
|
||||||
memcpy(reply_mess.m_netdrv_net_dl_conf.hw_addr, dep->de_address.ea_addr,
|
|
||||||
sizeof(reply_mess.m_netdrv_net_dl_conf.hw_addr));
|
|
||||||
DEBUG(printf("\t reply %d\n", reply_mess.m_type));
|
|
||||||
if (ipc_send(mp->m_source, &reply_mess) != OK) /* Can't send */
|
|
||||||
panic(SendErrMsg, mp->m_source);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void dp_next_iovec(iovec_dat_t *iovp)
|
** Name: do_send
|
||||||
** Function: Retrieves data from next iovec element.
|
** Function: Send a packet, if possible.
|
||||||
*/
|
*/
|
||||||
void dp_next_iovec(iovec_dat_s_t * iovp)
|
static int do_send(struct netdriver_data *data, size_t size)
|
||||||
{
|
{
|
||||||
|
|
||||||
iovp->iod_iovec_s -= IOVEC_NR;
|
|
||||||
iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_t);
|
|
||||||
get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, iovp->iod_iovec_offset,
|
|
||||||
iovp->iod_iovec_s, iovp->iod_iovec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: int calc_iovec_size(iovec_dat_t *iovp)
|
|
||||||
** Function: Compute the size of a request.
|
|
||||||
*/
|
|
||||||
static int calc_iovec_size(iovec_dat_s_t * iovp)
|
|
||||||
{
|
|
||||||
int size, ix;
|
|
||||||
|
|
||||||
size = ix = 0;
|
|
||||||
do {
|
|
||||||
size += iovp->iod_iovec[ix].iov_size;
|
|
||||||
if (++ix >= IOVEC_NR) {
|
|
||||||
dp_next_iovec(iovp);
|
|
||||||
ix = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Till all vectors added */
|
|
||||||
} while (ix < iovp->iod_iovec_s);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: void do_vwrite_s(message *mp)
|
|
||||||
** Function:
|
|
||||||
*/
|
|
||||||
static void do_vwrite_s(const message * mp)
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
dpeth_t *dep;
|
dpeth_t *dep;
|
||||||
|
|
||||||
dep = &de_state;
|
dep = &de_state;
|
||||||
|
|
||||||
dep->de_client = mp->m_source;
|
return (*dep->de_sendf)(dep, data, size);
|
||||||
|
|
||||||
if (dep->de_mode == DEM_ENABLED) {
|
|
||||||
|
|
||||||
if (dep->de_flags & DEF_SENDING) /* Is sending in progress? */
|
|
||||||
panic("send already in progress ");
|
|
||||||
|
|
||||||
dep->de_write_iovec.iod_proc_nr = mp->m_source;
|
|
||||||
get_userdata_s(mp->m_source, mp->m_net_netdrv_dl_writev_s.grant, 0,
|
|
||||||
mp->m_net_netdrv_dl_writev_s.count, dep->de_write_iovec.iod_iovec);
|
|
||||||
dep->de_write_iovec.iod_iovec_s = mp->m_net_netdrv_dl_writev_s.count;
|
|
||||||
dep->de_write_iovec.iod_grant = mp->m_net_netdrv_dl_writev_s.grant;
|
|
||||||
dep->de_write_iovec.iod_iovec_offset = 0;
|
|
||||||
size = calc_iovec_size(&dep->de_write_iovec);
|
|
||||||
if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE)
|
|
||||||
panic(SizeErrMsg, size);
|
|
||||||
|
|
||||||
dep->de_flags |= DEF_SENDING;
|
|
||||||
(*dep->de_sendf) (dep, FALSE, size);
|
|
||||||
|
|
||||||
} else if (dep->de_mode == DEM_SINK)
|
|
||||||
dep->de_flags |= DEF_ACK_SEND;
|
|
||||||
|
|
||||||
reply(dep);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void do_vread_s(message *mp, int vectored)
|
** Name: do_recv
|
||||||
** Function:
|
** Function: Receive a packet, if possible.
|
||||||
*/
|
*/
|
||||||
static void do_vread_s(const message * mp)
|
static ssize_t do_recv(struct netdriver_data *data, size_t max)
|
||||||
{
|
{
|
||||||
int size;
|
|
||||||
dpeth_t *dep;
|
dpeth_t *dep;
|
||||||
|
|
||||||
dep = &de_state;
|
dep = &de_state;
|
||||||
|
|
||||||
dep->de_client = mp->m_source;
|
return (*dep->de_recvf)(dep, data, max);
|
||||||
|
|
||||||
if (dep->de_mode == DEM_ENABLED) {
|
|
||||||
|
|
||||||
if (dep->de_flags & DEF_READING) /* Reading in progress */
|
|
||||||
panic("read already in progress");
|
|
||||||
|
|
||||||
dep->de_read_iovec.iod_proc_nr = mp->m_source;
|
|
||||||
get_userdata_s(mp->m_source, mp->m_net_netdrv_dl_readv_s.grant, 0,
|
|
||||||
mp->m_net_netdrv_dl_readv_s.count, dep->de_read_iovec.iod_iovec);
|
|
||||||
dep->de_read_iovec.iod_iovec_s = mp->m_net_netdrv_dl_readv_s.count;
|
|
||||||
dep->de_read_iovec.iod_grant = mp->m_net_netdrv_dl_readv_s.grant;
|
|
||||||
dep->de_read_iovec.iod_iovec_offset = 0;
|
|
||||||
size = calc_iovec_size(&dep->de_read_iovec);
|
|
||||||
if (size < ETH_MAX_PACK_SIZE) panic(SizeErrMsg, size);
|
|
||||||
|
|
||||||
dep->de_flags |= DEF_READING;
|
|
||||||
(*dep->de_recvf) (dep, FALSE, size);
|
|
||||||
#if 0
|
|
||||||
if ((dep->de_flags & (DEF_READING | DEF_STOPPED)) == (DEF_READING | DEF_STOPPED))
|
|
||||||
/* The chip is stopped, and all arrived packets delivered */
|
|
||||||
(*dep->de_resetf) (dep);
|
|
||||||
dep->de_flags &= NOT(DEF_STOPPED);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
reply(dep);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void do_getstat_s(message *mp)
|
** Name: do_stat
|
||||||
** Function: Reports device statistics.
|
** Function: Reports device statistics.
|
||||||
*/
|
*/
|
||||||
static void do_getstat_s(const message * mp)
|
static void do_stat(eth_stat_t *stat)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
dpeth_t *dep;
|
|
||||||
message reply_mess;
|
|
||||||
|
|
||||||
dep = &de_state;
|
memcpy(stat, &de_state.de_stat, sizeof(*stat));
|
||||||
|
|
||||||
if (dep->de_mode == DEM_ENABLED) (*dep->de_getstatsf) (dep);
|
|
||||||
if ((rc = sys_safecopyto(mp->m_source, mp->m_net_netdrv_dl_getstat_s.grant, 0,
|
|
||||||
(vir_bytes)&dep->de_stat,
|
|
||||||
(vir_bytes)sizeof(dep->de_stat))) != OK)
|
|
||||||
panic(CopyErrMsg, rc);
|
|
||||||
|
|
||||||
reply_mess.m_type = DL_STAT_REPLY;
|
|
||||||
rc= ipc_send(mp->m_source, &reply_mess);
|
|
||||||
if (rc != OK)
|
|
||||||
panic("do_getname: ipc_send failed: %d", rc);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void dp_stop(dpeth_t *dep)
|
** Name: do_stop
|
||||||
** Function: Stops network interface.
|
** Function: Stops network interface.
|
||||||
*/
|
*/
|
||||||
static void dp_stop(dpeth_t * dep)
|
static void do_stop(void)
|
||||||
{
|
{
|
||||||
|
dpeth_t *dep;
|
||||||
|
|
||||||
if (dep->de_mode == DEM_ENABLED && (dep->de_flags & DEF_ENABLED)) {
|
dep = &de_state;
|
||||||
|
|
||||||
/* Stop device */
|
/* Stop device */
|
||||||
(dep->de_stopf) (dep);
|
(dep->de_stopf)(dep);
|
||||||
dep->de_flags = DEF_EMPTY;
|
|
||||||
dep->de_mode = DEM_DISABLED;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_watchdog(const void *UNUSED(message))
|
/*
|
||||||
{
|
** Name: do_intr
|
||||||
|
** Function; Handles interrupts.
|
||||||
DEBUG(printf("\t no reply"));
|
*/
|
||||||
return;
|
static void do_intr(unsigned int __unused mask)
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_hw_intr(void)
|
|
||||||
{
|
{
|
||||||
dpeth_t *dep;
|
dpeth_t *dep;
|
||||||
|
|
||||||
dep = &de_state;
|
dep = &de_state;
|
||||||
|
|
||||||
/* If device is enabled and interrupt pending */
|
/* If device is enabled and interrupt pending */
|
||||||
if (dep->de_mode == DEM_ENABLED) {
|
(*dep->de_interruptf)(dep);
|
||||||
dep->de_int_pending = TRUE;
|
|
||||||
(*dep->de_interruptf) (dep);
|
|
||||||
if (dep->de_flags & (DEF_ACK_SEND | DEF_ACK_RECV))
|
|
||||||
reply(dep);
|
|
||||||
dep->de_int_pending = FALSE;
|
|
||||||
sys_irqenable(&dep->de_hook);
|
sys_irqenable(&dep->de_hook);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SEF functions and variables. */
|
/*
|
||||||
static void sef_local_startup(void);
|
** Name: do_other
|
||||||
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
** Function: Processes miscellaneous messages.
|
||||||
static void sef_cb_signal_handler(int signo);
|
*/
|
||||||
|
static void do_other(const message *m_ptr, int ipc_status)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (is_ipc_notify(ipc_status) && m_ptr->m_source == TTY_PROC_NR)
|
||||||
|
do_dump();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: int dpeth_task(void)
|
** Name: main
|
||||||
** Function: Main entry for dp task
|
** Function: Main entry for dp task
|
||||||
*/
|
*/
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
message m;
|
|
||||||
int ipc_status;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* SEF local startup. */
|
|
||||||
env_setargs(argc, argv);
|
env_setargs(argc, argv);
|
||||||
sef_local_startup();
|
|
||||||
|
|
||||||
while (TRUE) {
|
netdriver_task(&dp_table);
|
||||||
if ((rc = netdriver_receive(ANY, &m, &ipc_status)) != OK){
|
|
||||||
panic(RecvErrMsg, rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(printf("eth: got message %d, ", m.m_type));
|
return 0;
|
||||||
|
|
||||||
if (is_ipc_notify(ipc_status)) {
|
|
||||||
switch(_ENDPOINT_P(m.m_source)) {
|
|
||||||
case CLOCK:
|
|
||||||
/* to be defined */
|
|
||||||
do_watchdog(&m);
|
|
||||||
break;
|
|
||||||
case HARDWARE:
|
|
||||||
/* Interrupt from device */
|
|
||||||
handle_hw_intr();
|
|
||||||
break;
|
|
||||||
case TTY_PROC_NR:
|
|
||||||
/* Function key pressed */
|
|
||||||
do_dump(&m);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Invalid message type */
|
|
||||||
panic(TypeErrMsg, m.m_type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* message processed, get another one */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (m.m_type) {
|
|
||||||
case DL_WRITEV_S: /* Write message to device */
|
|
||||||
do_vwrite_s(&m);
|
|
||||||
break;
|
|
||||||
case DL_READV_S: /* Read message from device */
|
|
||||||
do_vread_s(&m);
|
|
||||||
break;
|
|
||||||
case DL_CONF: /* Initialize device */
|
|
||||||
do_init(&m);
|
|
||||||
break;
|
|
||||||
case DL_GETSTAT_S: /* Get device statistics */
|
|
||||||
do_getstat_s(&m);
|
|
||||||
break;
|
|
||||||
default: /* Invalid message type */
|
|
||||||
panic(TypeErrMsg, m.m_type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return OK; /* Never reached, but keeps compiler happy */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* sef_local_startup *
|
|
||||||
*===========================================================================*/
|
|
||||||
static void sef_local_startup()
|
|
||||||
{
|
|
||||||
/* Register init callbacks. */
|
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
|
||||||
sef_setcb_init_lu(sef_cb_init_fresh);
|
|
||||||
sef_setcb_init_restart(sef_cb_init_fresh);
|
|
||||||
|
|
||||||
/* Register live update callbacks. */
|
|
||||||
sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
|
|
||||||
sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree);
|
|
||||||
|
|
||||||
/* Register signal callbacks. */
|
|
||||||
sef_setcb_signal_handler(sef_cb_signal_handler);
|
|
||||||
|
|
||||||
/* Let SEF perform startup. */
|
|
||||||
sef_startup();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* sef_cb_init_fresh *
|
|
||||||
*===========================================================================*/
|
|
||||||
static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
|
|
||||||
{
|
|
||||||
/* Initialize the dpeth driver. */
|
|
||||||
int fkeys, sfkeys;
|
|
||||||
long v;
|
|
||||||
|
|
||||||
/* Request function key for debug dumps */
|
|
||||||
fkeys = sfkeys = 0; bit_set(sfkeys, 8);
|
|
||||||
if ((fkey_map(&fkeys, &sfkeys)) != OK)
|
|
||||||
printf("%s: couldn't program Shift+F8 key (%d)\n", DevName, errno);
|
|
||||||
|
|
||||||
v = 0;
|
|
||||||
(void) env_parse("instance", "d", 0, &v, 0, 255);
|
|
||||||
de_instance = (int) v;
|
|
||||||
|
|
||||||
/* Announce we are up! */
|
|
||||||
netdriver_announce();
|
|
||||||
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* sef_cb_signal_handler *
|
|
||||||
*===========================================================================*/
|
|
||||||
static void sef_cb_signal_handler(int signo)
|
|
||||||
{
|
|
||||||
/* Only check for termination signal, ignore anything else. */
|
|
||||||
if (signo != SIGTERM) return;
|
|
||||||
|
|
||||||
if (de_state.de_mode == DEM_ENABLED)
|
|
||||||
dp_stop(&de_state);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** dp.c **/
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
#define NOT(x) (~(x))
|
#define NOT(x) (~(x))
|
||||||
|
|
||||||
#if debug == 1
|
#if VERBOSE == 1
|
||||||
# define DEBUG(statm) statm
|
# define DEBUG(statm) statm
|
||||||
#else
|
#else
|
||||||
# define DEBUG(statm)
|
# define DEBUG(statm)
|
||||||
|
@ -70,26 +70,19 @@ typedef struct _buff_t { /* Receive/Transmit buffer header */
|
||||||
} buff_t;
|
} buff_t;
|
||||||
|
|
||||||
struct dpeth;
|
struct dpeth;
|
||||||
struct iovec_dat;
|
typedef void (*dp_eth_t)(struct dpeth *);
|
||||||
typedef void (*dp_eth_t) (struct dpeth *);
|
typedef int (*dp_send_t)(struct dpeth *, struct netdriver_data *, size_t);
|
||||||
typedef void (*dp_send_recv_t) (struct dpeth *, int, int);
|
typedef ssize_t (*dp_recv_t)(struct dpeth *, struct netdriver_data *, size_t);
|
||||||
|
|
||||||
#if ENABLE_DP8390 == 1
|
#if ENABLE_DP8390 == 1
|
||||||
typedef void (*dp_user2nicf_t) (struct dpeth *, int, int);
|
typedef void (*dp_user2nicf_t)(struct dpeth *, int, struct netdriver_data *,
|
||||||
typedef void (*dp_nic2userf_t) (struct dpeth *, int, int);
|
size_t);
|
||||||
typedef void (*dp_getblock_t) (struct dpeth *, u16_t, int, void *);
|
typedef void (*dp_nic2userf_t)(struct dpeth *, int, struct netdriver_data *,
|
||||||
|
size_t);
|
||||||
|
typedef void (*dp_getblock_t)(struct dpeth *, u16_t, int, void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SENDQ_NR 2 /* Size of the send queue */
|
#define SENDQ_NR 2 /* Size of the send queue */
|
||||||
#define IOVEC_NR 16 /* Number of IOVEC entries at a time */
|
|
||||||
|
|
||||||
typedef struct iovec_dat_s {
|
|
||||||
iovec_s_t iod_iovec[IOVEC_NR];
|
|
||||||
int iod_iovec_s;
|
|
||||||
endpoint_t iod_proc_nr;
|
|
||||||
cp_grant_id_t iod_grant;
|
|
||||||
vir_bytes iod_iovec_offset;
|
|
||||||
} iovec_dat_s_t;
|
|
||||||
|
|
||||||
typedef struct dpeth {
|
typedef struct dpeth {
|
||||||
/* The de_base_port field is the starting point of the probe. The
|
/* The de_base_port field is the starting point of the probe. The
|
||||||
|
@ -109,7 +102,6 @@ typedef struct dpeth {
|
||||||
port_t de_data_port; /* For boards using Prog. I/O for xmit/recv */
|
port_t de_data_port; /* For boards using Prog. I/O for xmit/recv */
|
||||||
|
|
||||||
int de_irq;
|
int de_irq;
|
||||||
int de_int_pending;
|
|
||||||
int de_hook; /* interrupt hook at kernel */
|
int de_hook; /* interrupt hook at kernel */
|
||||||
|
|
||||||
char de_name[8];
|
char de_name[8];
|
||||||
|
@ -117,7 +109,7 @@ typedef struct dpeth {
|
||||||
#define DEI_DEFAULT 0x8000
|
#define DEI_DEFAULT 0x8000
|
||||||
|
|
||||||
phys_bytes de_linmem; /* For boards using shared memory */
|
phys_bytes de_linmem; /* For boards using shared memory */
|
||||||
vir_bytes de_memoffs;
|
char *de_locmem; /* Locally mapped (virtual) address */
|
||||||
int de_ramsize; /* Size of on board memory */
|
int de_ramsize; /* Size of on board memory */
|
||||||
int de_offset_page; /* Offset of shared memory page */
|
int de_offset_page; /* Offset of shared memory page */
|
||||||
|
|
||||||
|
@ -129,8 +121,8 @@ typedef struct dpeth {
|
||||||
dp_eth_t de_getstatsf;
|
dp_eth_t de_getstatsf;
|
||||||
dp_eth_t de_dumpstatsf;
|
dp_eth_t de_dumpstatsf;
|
||||||
dp_eth_t de_interruptf;
|
dp_eth_t de_interruptf;
|
||||||
dp_send_recv_t de_recvf;
|
dp_recv_t de_recvf;
|
||||||
dp_send_recv_t de_sendf;
|
dp_send_t de_sendf;
|
||||||
|
|
||||||
ether_addr_t de_address; /* Ethernet Address */
|
ether_addr_t de_address; /* Ethernet Address */
|
||||||
eth_stat_t de_stat; /* Ethernet Statistics */
|
eth_stat_t de_stat; /* Ethernet Statistics */
|
||||||
|
@ -141,35 +133,12 @@ typedef struct dpeth {
|
||||||
|
|
||||||
int de_flags; /* Send/Receive mode (Configuration) */
|
int de_flags; /* Send/Receive mode (Configuration) */
|
||||||
|
|
||||||
#define DEF_EMPTY 0x0000
|
#define DEF_EMPTY 0x00
|
||||||
#define DEF_READING 0x0001
|
#define DEF_XMIT_BUSY 0x01
|
||||||
#define DEF_RECV_BUSY 0x0002
|
#define DEF_PROMISC 0x02
|
||||||
#define DEF_ACK_RECV 0x0004
|
#define DEF_MULTI 0x04
|
||||||
#define DEF_SENDING 0x0010
|
#define DEF_BROAD 0x08
|
||||||
#define DEF_XMIT_BUSY 0x0020
|
|
||||||
#define DEF_ACK_SEND 0x0040
|
|
||||||
#define DEF_PROMISC 0x0100
|
|
||||||
#define DEF_MULTI 0x0200
|
|
||||||
#define DEF_BROAD 0x0400
|
|
||||||
#define DEF_ENABLED 0x2000
|
|
||||||
#define DEF_STOPPED 0x4000
|
|
||||||
|
|
||||||
int de_mode; /* Status of the Interface */
|
|
||||||
|
|
||||||
#define DEM_DISABLED 0x0000
|
|
||||||
#define DEM_SINK 0x0001
|
|
||||||
#define DEM_ENABLED 0x0002
|
|
||||||
|
|
||||||
/* Temporary storage for RECV/SEND requests */
|
|
||||||
iovec_dat_s_t de_read_iovec;
|
|
||||||
iovec_dat_s_t de_write_iovec;
|
|
||||||
vir_bytes de_read_s;
|
|
||||||
vir_bytes de_send_s;
|
|
||||||
int de_client;
|
|
||||||
/*
|
|
||||||
message de_sendmsg;
|
|
||||||
iovec_dat_t de_tmp_iovec;
|
|
||||||
*/
|
|
||||||
#if ENABLE_DP8390 == 1
|
#if ENABLE_DP8390 == 1
|
||||||
/* For use by NS DP8390 driver */
|
/* For use by NS DP8390 driver */
|
||||||
port_t de_dp8390_port;
|
port_t de_dp8390_port;
|
||||||
|
@ -203,8 +172,6 @@ typedef struct dpeth {
|
||||||
/* For use by 3Com Etherlink (3c501 and 3c509) driver */
|
/* For use by 3Com Etherlink (3c501 and 3c509) driver */
|
||||||
buff_t *de_recvq_head;
|
buff_t *de_recvq_head;
|
||||||
buff_t *de_recvq_tail;
|
buff_t *de_recvq_tail;
|
||||||
buff_t *de_xmitq_head;
|
|
||||||
buff_t *de_xmitq_tail;
|
|
||||||
u16_t de_recv_mode;
|
u16_t de_recv_mode;
|
||||||
clock_t de_xmit_start;
|
clock_t de_xmit_start;
|
||||||
#endif
|
#endif
|
||||||
|
@ -215,29 +182,23 @@ typedef struct dpeth {
|
||||||
* Function definitions
|
* Function definitions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* dp.c */
|
|
||||||
void dp_next_iovec(iovec_dat_s_t * iovp);
|
|
||||||
|
|
||||||
/* devio.c */
|
/* devio.c */
|
||||||
#if defined USE_IOPL
|
#if defined USE_IOPL
|
||||||
#include <machine/portio.h>
|
#include <machine/portio.h>
|
||||||
#else
|
#else
|
||||||
unsigned int inb(unsigned short int);
|
unsigned int inb(unsigned short int);
|
||||||
unsigned int inw(unsigned short int);
|
unsigned int inw(unsigned short int);
|
||||||
void insb(unsigned short int, endpoint_t, void *, int);
|
void insb(unsigned short int, void *, int);
|
||||||
void insw(unsigned short int, int, void *, int);
|
void insw(unsigned short int, void *, int);
|
||||||
void outb(unsigned short int, unsigned long);
|
void outb(unsigned short int, unsigned long);
|
||||||
void outw(unsigned short int, unsigned long);
|
void outw(unsigned short int, unsigned long);
|
||||||
void outsb(unsigned short int, endpoint_t, void *, int);
|
void outsb(unsigned short int, void *, int);
|
||||||
void outsw(unsigned short int, int, void *, int);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* netbuff.c */
|
/* netbuff.c */
|
||||||
void *alloc_buff(dpeth_t *, int);
|
void *alloc_buff(dpeth_t *, int);
|
||||||
void free_buff(dpeth_t *, void *);
|
void free_buff(dpeth_t *, void *);
|
||||||
void init_buff(dpeth_t *, buff_t **);
|
void init_buff(dpeth_t *, buff_t **);
|
||||||
void mem2user(dpeth_t *, buff_t *);
|
|
||||||
void user2mem(dpeth_t *, buff_t *);
|
|
||||||
|
|
||||||
/* 3c501.c */
|
/* 3c501.c */
|
||||||
#if ENABLE_3C501 == 1
|
#if ENABLE_3C501 == 1
|
||||||
|
@ -274,8 +235,4 @@ int wdeth_probe(dpeth_t * dep);
|
||||||
#define wdeth_probe(x) (0)
|
#define wdeth_probe(x) (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define lock() (++dep->de_int_pending,sys_irqdisable(&dep->de_hook))
|
|
||||||
#define unlock() do{int i=(--dep->de_int_pending)?0:sys_irqenable(&dep->de_hook);(void) i;}while(0)
|
|
||||||
#define milli_delay(t) tickdelay(1)
|
|
||||||
|
|
||||||
/** dp.h **/
|
/** dp.h **/
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
|
#include <minix/netdriver.h>
|
||||||
#include <net/gen/ether.h>
|
#include <net/gen/ether.h>
|
||||||
#include <net/gen/eth_io.h>
|
#include <net/gen/eth_io.h>
|
||||||
#include "dp.h"
|
#include "dp.h"
|
||||||
|
@ -23,7 +24,7 @@
|
||||||
#include "ne.h"
|
#include "ne.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ne_reset(dpeth_t * dep);
|
** Name: ne_reset
|
||||||
** Function: Resets the board and checks if reset cycle completes
|
** Function: Resets the board and checks if reset cycle completes
|
||||||
*/
|
*/
|
||||||
static int ne_reset(dpeth_t * dep)
|
static int ne_reset(dpeth_t * dep)
|
||||||
|
@ -34,13 +35,13 @@ static int ne_reset(dpeth_t * dep)
|
||||||
outb_ne(dep, NE_RESET, inb_ne(dep, NE_RESET));
|
outb_ne(dep, NE_RESET, inb_ne(dep, NE_RESET));
|
||||||
do {
|
do {
|
||||||
if (++count > 10) return FALSE; /* 20 mSecs. timeout */
|
if (++count > 10) return FALSE; /* 20 mSecs. timeout */
|
||||||
milli_delay(2);
|
micro_delay(2000);
|
||||||
} while ((inb_ne(dep, DP_ISR) & ISR_RST) == 0);
|
} while ((inb_ne(dep, DP_ISR) & ISR_RST) == 0);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ne_close(dpeth_t * dep);
|
** Name: ne_close
|
||||||
** Function: Stops the board by resetting it and masking interrupts.
|
** Function: Stops the board by resetting it and masking interrupts.
|
||||||
*/
|
*/
|
||||||
static void ne_close(dpeth_t * dep)
|
static void ne_close(dpeth_t * dep)
|
||||||
|
@ -49,11 +50,10 @@ static void ne_close(dpeth_t * dep)
|
||||||
(void)ne_reset(dep);
|
(void)ne_reset(dep);
|
||||||
outb_ne(dep, DP_ISR, 0xFF);
|
outb_ne(dep, DP_ISR, 0xFF);
|
||||||
sys_irqdisable(&dep->de_hook);
|
sys_irqdisable(&dep->de_hook);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void ne_init(dpeth_t * dep);
|
** Name: ne_init
|
||||||
** Function: Initialize the board making it ready to work.
|
** Function: Initialize the board making it ready to work.
|
||||||
*/
|
*/
|
||||||
static void ne_init(dpeth_t * dep)
|
static void ne_init(dpeth_t * dep)
|
||||||
|
@ -90,12 +90,12 @@ static void ne_init(dpeth_t * dep)
|
||||||
dep->de_ramsize / 1024,
|
dep->de_ramsize / 1024,
|
||||||
dep->de_base_port, dep->de_irq);
|
dep->de_base_port, dep->de_irq);
|
||||||
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
|
for (ix = 0; ix < SA_ADDR_LEN; ix += 1)
|
||||||
printf("%02X%c", dep->de_address.ea_addr[ix], ix < SA_ADDR_LEN - 1 ? ':' : '\n');
|
printf("%02X%c", dep->de_address.ea_addr[ix],
|
||||||
return;
|
ix < SA_ADDR_LEN - 1 ? ':' : '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: int ne_probe(dpeth_t * dep);
|
** Name: ne_probe
|
||||||
** Function: Probe for the presence of a NE*000 card by testing
|
** Function: Probe for the presence of a NE*000 card by testing
|
||||||
** whether the board is reachable through the dp8390.
|
** whether the board is reachable through the dp8390.
|
||||||
** Note that the NE1000 is an 8bit card and has a memory
|
** Note that the NE1000 is an 8bit card and has a memory
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
|
#include <minix/netdriver.h>
|
||||||
#include <net/gen/ether.h>
|
#include <net/gen/ether.h>
|
||||||
#include <net/gen/eth_io.h>
|
#include <net/gen/eth_io.h>
|
||||||
#include "dp.h"
|
#include "dp.h"
|
||||||
|
@ -18,7 +19,7 @@ static m_hdr_t *allocptr = NULL;
|
||||||
static char tx_rx_buff[8192];
|
static char tx_rx_buff[8192];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void *alloc_buff(dpeth_t *dep, int size)
|
** Name: alloc_buff
|
||||||
** Function: Allocates a buffer from the common pool.
|
** Function: Allocates a buffer from the common pool.
|
||||||
*/
|
*/
|
||||||
void *alloc_buff(dpeth_t *dep, int size)
|
void *alloc_buff(dpeth_t *dep, int size)
|
||||||
|
@ -26,7 +27,6 @@ void *alloc_buff(dpeth_t *dep, int size)
|
||||||
m_hdr_t *ptr, *wrk = allocptr;
|
m_hdr_t *ptr, *wrk = allocptr;
|
||||||
int units = ((size + sizeof(m_hdr_t) - 1) / sizeof(m_hdr_t)) + 1;
|
int units = ((size + sizeof(m_hdr_t) - 1) / sizeof(m_hdr_t)) + 1;
|
||||||
|
|
||||||
lock();
|
|
||||||
for (ptr = wrk->next;; wrk = ptr, ptr = ptr->next) {
|
for (ptr = wrk->next;; wrk = ptr, ptr = ptr->next) {
|
||||||
if (ptr->size >= units) {
|
if (ptr->size >= units) {
|
||||||
/* Memory is available, carve requested size from pool */
|
/* Memory is available, carve requested size from pool */
|
||||||
|
@ -39,24 +39,22 @@ void *alloc_buff(dpeth_t *dep, int size)
|
||||||
ptr->size = units;
|
ptr->size = units;
|
||||||
}
|
}
|
||||||
allocptr = wrk;
|
allocptr = wrk;
|
||||||
unlock();
|
|
||||||
return ptr + 1;
|
return ptr + 1;
|
||||||
}
|
}
|
||||||
if (ptr == allocptr) break;
|
if (ptr == allocptr) break;
|
||||||
}
|
}
|
||||||
unlock();
|
|
||||||
return NULL; /* No memory available */
|
return NULL; /* No memory available */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void free_buff(dpeth_t *dep, void *blk)
|
** Name: free_buff
|
||||||
** Function: Returns a buffer to the common pool.
|
** Function: Returns a buffer to the common pool.
|
||||||
*/
|
*/
|
||||||
void free_buff(dpeth_t *dep, void *blk)
|
void free_buff(dpeth_t *dep, void *blk)
|
||||||
{
|
{
|
||||||
m_hdr_t *wrk, *ptr = (m_hdr_t *) blk - 1;
|
m_hdr_t *wrk, *ptr = (m_hdr_t *) blk - 1;
|
||||||
|
|
||||||
lock(); /* Scan linked list for the correct place */
|
/* Scan linked list for the correct place */
|
||||||
for (wrk = allocptr; !(ptr > wrk && ptr < wrk->next); wrk = wrk->next)
|
for (wrk = allocptr; !(ptr > wrk && ptr < wrk->next); wrk = wrk->next)
|
||||||
if (wrk >= wrk->next && (ptr > wrk || ptr < wrk->next)) break;
|
if (wrk >= wrk->next && (ptr > wrk || ptr < wrk->next)) break;
|
||||||
|
|
||||||
|
@ -72,12 +70,10 @@ void free_buff(dpeth_t *dep, void *blk)
|
||||||
} else
|
} else
|
||||||
wrk->next = ptr;
|
wrk->next = ptr;
|
||||||
allocptr = wrk; /* Point allocptr to block just released */
|
allocptr = wrk; /* Point allocptr to block just released */
|
||||||
unlock();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Name: void init_buff(dpeth_t *dep, buff_t **tx_buff)
|
** Name: init_buff
|
||||||
** Function: Initalizes driver data structures.
|
** Function: Initalizes driver data structures.
|
||||||
*/
|
*/
|
||||||
void init_buff(dpeth_t *dep, buff_t **tx_buff)
|
void init_buff(dpeth_t *dep, buff_t **tx_buff)
|
||||||
|
@ -98,69 +94,6 @@ void init_buff(dpeth_t *dep, buff_t **tx_buff)
|
||||||
(*tx_buff)->size = 0;
|
(*tx_buff)->size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return; /* Done */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: void mem2user(dpeth_t *dep, buff_t *rxbuff);
|
|
||||||
** Function: Copies a packet from local buffer to user area.
|
|
||||||
*/
|
|
||||||
void mem2user(dpeth_t *dep, buff_t *rxbuff)
|
|
||||||
{
|
|
||||||
int bytes, ix = 0;
|
|
||||||
iovec_dat_s_t *iovp = &dep->de_read_iovec;
|
|
||||||
int r, pktsize = rxbuff->size;
|
|
||||||
char *buffer = rxbuff->buffer;
|
|
||||||
|
|
||||||
do { /* Reads chuncks of packet into user buffers */
|
|
||||||
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
|
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
|
||||||
|
|
||||||
/* Reads from Rx buffer to user area */
|
|
||||||
r= sys_safecopyto(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0,
|
|
||||||
(vir_bytes)buffer, bytes);
|
|
||||||
if (r != OK)
|
|
||||||
panic("mem2user: sys_safecopyto failed: %d", r);
|
|
||||||
buffer += bytes;
|
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
|
||||||
dp_next_iovec(iovp);
|
|
||||||
ix = 0;
|
|
||||||
}
|
|
||||||
/* Till packet done */
|
|
||||||
} while ((pktsize -= bytes) > 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Name: void user2mem(dpeth_t *dep, buff_t *txbuff)
|
|
||||||
** Function: Copies a packet from user area to local buffer.
|
|
||||||
*/
|
|
||||||
void user2mem(dpeth_t *dep, buff_t *txbuff)
|
|
||||||
{
|
|
||||||
int bytes, ix = 0;
|
|
||||||
iovec_dat_s_t *iovp = &dep->de_write_iovec;
|
|
||||||
int r, pktsize = txbuff->size;
|
|
||||||
char *buffer = txbuff->buffer;
|
|
||||||
|
|
||||||
do { /* Reads chuncks of packet from user buffers */
|
|
||||||
|
|
||||||
bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
|
|
||||||
if (bytes > pktsize) bytes = pktsize;
|
|
||||||
r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant,
|
|
||||||
0, (vir_bytes)buffer, bytes);
|
|
||||||
if (r != OK)
|
|
||||||
panic("user2mem: sys_safecopyfrom failed: %d", r);
|
|
||||||
buffer += bytes;
|
|
||||||
|
|
||||||
if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
|
|
||||||
dp_next_iovec(iovp);
|
|
||||||
ix = 0;
|
|
||||||
}
|
|
||||||
/* Till packet done */
|
|
||||||
} while ((pktsize -= bytes) > 0);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_BUFFERS */
|
#endif /* HAVE_BUFFERS */
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <minix/drivers.h>
|
#include <minix/drivers.h>
|
||||||
|
#include <minix/netdriver.h>
|
||||||
#include <net/gen/ether.h>
|
#include <net/gen/ether.h>
|
||||||
#include <net/gen/eth_io.h>
|
#include <net/gen/eth_io.h>
|
||||||
#include "dp.h"
|
#include "dp.h"
|
||||||
|
@ -43,8 +44,7 @@ static int we_ultra(dpeth_t * dep);
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* wdeth_probe *
|
* wdeth_probe *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int wdeth_probe(dep)
|
int wdeth_probe(dpeth_t *dep)
|
||||||
dpeth_t *dep;
|
|
||||||
{
|
{
|
||||||
int sum;
|
int sum;
|
||||||
|
|
||||||
|
@ -67,8 +67,7 @@ dpeth_t *dep;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* we_init *
|
* we_init *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static void we_init(dep)
|
static void we_init(dpeth_t *dep)
|
||||||
dpeth_t *dep;
|
|
||||||
{
|
{
|
||||||
int i, int_indx, int_nr;
|
int i, int_indx, int_nr;
|
||||||
int tlb, rambit, revision;
|
int tlb, rambit, revision;
|
||||||
|
@ -212,8 +211,7 @@ dpeth_t *dep;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* we_stop *
|
* we_stop *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static void we_stop(dep)
|
static void we_stop(dpeth_t *dep)
|
||||||
dpeth_t *dep;
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (dep->de_16bit) outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_LAN16E);
|
if (dep->de_16bit) outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_LAN16E);
|
||||||
|
@ -226,8 +224,7 @@ dpeth_t *dep;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* we_aliasing *
|
* we_aliasing *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int we_aliasing(dep)
|
static int we_aliasing(dpeth_t *dep)
|
||||||
dpeth_t *dep;
|
|
||||||
{
|
{
|
||||||
/* Determine whether wd8003 hardware performs register aliasing. This implies
|
/* Determine whether wd8003 hardware performs register aliasing. This implies
|
||||||
* an old WD8003E board. */
|
* an old WD8003E board. */
|
||||||
|
@ -243,8 +240,7 @@ dpeth_t *dep;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* we_interface_chip *
|
* we_interface_chip *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int we_interface_chip(dep)
|
static int we_interface_chip(dpeth_t *dep)
|
||||||
dpeth_t *dep;
|
|
||||||
{
|
{
|
||||||
/* Determine if the board has an interface chip. */
|
/* Determine if the board has an interface chip. */
|
||||||
|
|
||||||
|
@ -258,8 +254,7 @@ dpeth_t *dep;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* we_16bitboard *
|
* we_16bitboard *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int we_16bitboard(dep)
|
static int we_16bitboard(dpeth_t *dep)
|
||||||
dpeth_t *dep;
|
|
||||||
{
|
{
|
||||||
/* Determine whether the board is capable of doing 16 bit memory moves.
|
/* Determine whether the board is capable of doing 16 bit memory moves.
|
||||||
* If the 16 bit enable bit is unchangable by software we'll assume an
|
* If the 16 bit enable bit is unchangable by software we'll assume an
|
||||||
|
@ -286,8 +281,7 @@ dpeth_t *dep;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* we_16bitslot *
|
* we_16bitslot *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int we_16bitslot(dep)
|
static int we_16bitslot(dpeth_t *dep)
|
||||||
dpeth_t *dep;
|
|
||||||
{
|
{
|
||||||
/* Determine if the 16 bit board in plugged into a 16 bit slot. */
|
/* Determine if the 16 bit board in plugged into a 16 bit slot. */
|
||||||
|
|
||||||
|
@ -297,8 +291,7 @@ dpeth_t *dep;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* we_ultra *
|
* we_ultra *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
static int we_ultra(dep)
|
static int we_ultra(dpeth_t *dep)
|
||||||
dpeth_t *dep;
|
|
||||||
{
|
{
|
||||||
/* Determine if we has an '790 chip. */
|
/* Determine if we has an '790 chip. */
|
||||||
u8_t tlb;
|
u8_t tlb;
|
||||||
|
|
Loading…
Reference in a new issue