Well after a fast look at the linux kernel driver of ne2k-pci cards, it seems
that the usage is same unless that the io and irq are in the PCI space config
of the ne2000 card.
So I wrote just a little part of code in the FindNE2000() function to find the
first PCI-NE2000 card which is free (not handled by the kernel).
I'm not sure that the irq handling respond ....:(
cause I've experimented some trouble in PCI cards irqs handling.
Test your pci->io device "cat/proc/pci" -> I/O at 0x6200 [0x6201]
If like this exemple , the kernel has modified the io from X to X+1 it's ok
whereas remove the io hack in the FindNe2000() function.
I havn't any pci-ne2000 card, so I can't experiment it.
but it is based on the rtl8390 chipset command like the ISA version so just
the card detection is different.
I've added too, the rt_pend_linux_irq at the end of irq handler to be compatible
with irq sharing between devices.
Send any pb ...
Good Luck.
-- Kumsta Christophe
<[EMAIL PROTECTED]>
Realtime system developper Maf-Roda
RTAI/RT-Linux <Use the source luke>
#include <linux/pci.h>
#define TX_2X_PAGES 12
#define TX_PAGES TX_2X_PAGES
/* Some generic ethernet register configurations. */
#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */
#define E8390_RX_IRQ_MASK 0x5
#define E8390_RXCONFIG 0x06
//#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */
#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */
#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */
#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */
/* Register accessed at EN_CMD, the 8390 base addr. */
#define E8390_STOP 0x01 /* Stop and reset the chip */
#define E8390_START 0x02 /* Start the chip, clear reset */
#define E8390_TRANS 0x04 /* Transmit a frame */
#define E8390_RREAD 0x08 /* Remote read */
#define E8390_RWRITE 0x10 /* Remote write */
#define E8390_NODMA 0x20 /* Remote DMA */
#define E8390_PAGE0 0x00 /* Select page chip registers */
#define E8390_PAGE1 0x40 /* using the two high-order bits */
#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
#define E8390_CMD 0x00 /* The command register (for all pages) */
/* Page 0 register offsets. */
#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
#define EN0_TSR 0x04 /* Transmit status reg RD */
#define EN0_TPSR 0x04 /* Transmit starting page WR */
#define EN0_NCR 0x05 /* Number of collision reg RD */
#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
#define EN0_FIFO 0x06 /* FIFO RD */
#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
#define EN0_ISR 0x07 /* Interrupt status reg RD WR */
#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
#define EN0_RSARLO 0x08 /* Remote start address reg 0 */
#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
#define EN0_RSARHI 0x09 /* Remote start address reg 1 */
#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
#define EN0_RSR 0x0c /* rx status reg RD */
#define EN0_RXCR 0x0c /* RX configuration reg WR */
#define EN0_TXCR 0x0d /* TX configuration reg WR */
#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
#define EN0_DCFG 0x0e /* Data configuration reg WR */
#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
#define EN0_IMR 0x0f /* Interrupt mask reg WR */
#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
/* Bits in EN0_ISR - Interrupt status register */
#define ENISR_RX 0x01 /* Receiver, no error */
#define ENISR_TX 0x02 /* Transmitter, no error */
#define ENISR_RX_ERR 0x04 /* Receiver, with error */
#define ENISR_TX_ERR 0x08 /* Transmitter, with error */
#define ENISR_OVER 0x10 /* Receiver overwrote the ring */
#define ENISR_COUNTERS 0x20 /* Counters need emptying */
#define ENISR_RDC 0x40 /* remote dma complete */
#define ENISR_RESET 0x80 /* Reset completed */
#define ENISR_ALL 0x3f /* Interrupts we will enable */
/* Bits in EN0_DCFG - Data config register */
#define ENDCFG_WTS 0x01 /* word transfer mode selection */
/* Page 1 register offsets. */
#define EN1_PHYS 0x01 /* This board's physical enet addr RD WR */
#define EN1_PHYS_SHIFT(i) i+1 /* Get and set mac address */
#define EN1_CURPAG 0x07 /* Current memory page RD WR */
#define EN1_MULT 0x08 /* Multicast filter mask array (8 bytes) RD WR */
#define EN1_MULT_SHIFT(i) 8+i /* Get and set multicast filter */
#define NE_BASE (dev.io)
#define NE_CMD 0x00
#define NE_DATAPORT 0x10
#define NE_RESET 0x1f // read to reset / write to clear
#define NE_IO_EXTENT 0x20
#define NE1SM_START_PG 0x20 // first page of TX buffer
#define NE1SM_STOP_PG 0x40 // last page+1 of RX ring
#define NESM_START_PG 0x40
#define NESM_STOP_PG 0x80
typedef struct
{
unsigned char dst[6] ; // Hardware addr of dest ethernet card
unsigned char src[6] ; // Hardware addr of source ethernet card
unsigned char proto[2] ; // neither TCP nor UDP ... just own (0x9000)
unsigned char taille ; // size of data
unsigned char data[1000] ;
} Tne2000_mess ;
volatile Tne2000_mess ne2000_buffer_get ;
volatile Tne2000_mess ne2000_buffer_send ;
typedef struct
{
int io ;
int irq ;
int wordsize ;
unsigned char tx_start_page ;
unsigned char rx_start_page ;
unsigned char start_page ;
unsigned char stop_page ;
unsigned char current_page ;
short tx1,tx2 ;
unsigned char SA_prom[32] ;
unsigned char HWaddr[6] ;
char *buffread ;
char *buffwrite ;
} TNE2000 ;
/* The 8390 specific per-packet-header format. */
typedef struct {
unsigned char status; /* status */
unsigned char next; /* pointer to next packet. */
unsigned short count; /* header + packet length in bytes */
} THeader ;
static TNE2000 NE2000dev ;
volatile static int irqtest = 0 ;
volatile static int transmit = 0 ;
static SEM ne2000_get ;
/******************************************************/
/* */
/* Gestion des ERREURS de message */
/* */
/* */
/******************************************************/
#define INT_PACKET_RECEIVED 0x01
#define INT_PACKET_TRANSMITTED 0x02
#define INT_RECEIVE_ERROR 0x04
#define INT_TRANSMIT_ERROR 0x08
#define INT_OVERWRITE_WARNING 0x10
#define INT_COUNTER_OVERFLOW 0x20
#define INT_REMOTE_DMA_COMPLETE 0x40
#define INT_RESET_STATUS 0x80
/* Bits in received packet status byte and EN0_RSR*/
#define ENRSR_RXOK 0x01 /* Received a good packet */
#define ENRSR_CRC 0x02 /* CRC error */
#define ENRSR_FAE 0x04 /* frame alignment error */
#define ENRSR_FO 0x08 /* FIFO overrun */
#define ENRSR_MPA 0x10 /* missed pkt */
#define ENRSR_PHY 0x20 /* physical/multicast address */
#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */
#define ENRSR_DEF 0x80 /* deferring */
/* Transmitted packet status, EN0_TSR. */
#define ENTSR_PTX 0x01 /* Packet transmitted without error */
#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */
#define ENTSR_COL 0x04 /* The transmit collided at least once. */
#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */
#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */
#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
/******************************************************/
/* */
/* Interrupt Handling */
/* */
/* */
/******************************************************/
//#define debugirq(x) printk("[NE2000 :0x%3.3x:#%2.2d] <IRQ_HANDLER> -> %s.\n",dev.io,dev.irq,x)
#define debugirq(x)
static void IrqHandlerNE2000()
{
unsigned char which , test ;
//printk("NE2000 :[CPU#%d] IRQ BEGIN\n",hard_cpu_id()) ;
outb_p(0x00,NE_BASE+EN0_IMR) ; // mask all
rt_disable_irq(dev.irq) ;
which = inb_p(NE_BASE+EN0_ISR) ;
irqtest = which ;
while(which)
{
if(which & INT_PACKET_RECEIVED)
{
unsigned char frame, frame_next ;
THeader header ;
which ^= INT_PACKET_RECEIVED ;
/* Get the rx page (incoming packet pointer). */
outb_p(E8390_NODMA+E8390_PAGE1, NE_BASE + E8390_CMD);
frame_next = inb_p(NE_BASE + EN1_CURPAG);
outb_p(E8390_NODMA+E8390_PAGE0, NE_BASE + E8390_CMD);
frame = dev.current_page ;
/* printk("NE2000 : RECEIVING FRAME : %i\n",dev.io,dev.irq,frame) ; */
// get HEADER of 8390
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE+ NE_CMD);
outb_p(sizeof(header) , NE_BASE + EN0_RCNTLO);
outb_p(0 , NE_BASE + EN0_RCNTHI);
outb_p(0 , NE_BASE + EN0_RSARLO); /* On page boundary */
outb_p(frame , NE_BASE + EN0_RSARHI);
outb_p(E8390_RREAD+E8390_START , NE_BASE + NE_CMD);
insb(NE_BASE + NE_DATAPORT, &header, sizeof(header));
outb_p(ENISR_RDC, NE_BASE + EN0_ISR); /* Ack intr. */
// get datas
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START , NE_BASE + NE_CMD);
outb_p((header.count-sizeof(header)) & 0xff, NE_BASE + EN0_RCNTLO);
outb_p((header.count-sizeof(header)) >> 8 , NE_BASE + EN0_RCNTHI);
outb_p(((frame<<8)+sizeof(header)) & 0xff , NE_BASE + EN0_RSARLO);
outb_p(((frame<<8)+sizeof(header)) >> 8 , NE_BASE + EN0_RSARHI);
outb_p(E8390_RREAD+E8390_START , NE_BASE + NE_CMD);
insb(NE_BASE + NE_DATAPORT, dev.buffread, header.count);
outb_p(ENISR_RDC, NE_BASE + EN0_ISR);
NE2000dev.current_page = frame_next ;
outb_p(frame,NE_BASE+EN0_BOUNDARY) ;
outb_p(E8390_RXCONFIG,NE_BASE+EN0_RXCR) ;
/* printk("NE2000 : GET TERMINATED.\n",dev.io,dev.irq) ; */
if((ne2000_buffer_get.proto[0]==0x90)&&(ne2000_buffer_get.proto[1]==0x00))
rt_sem_signal(&ne2000_get) ;
else
printk("NE2000 : ####### BAD PROTOCOL DETECTED !! ###(%2.2x%2.2x)###\n",
ne2000_buffer_get.proto[0],ne2000_buffer_get.proto[1]) ;
}
if(which & INT_RECEIVE_ERROR)
{
which ^= INT_RECEIVE_ERROR ;
test = inb_p(NE_BASE+EN0_RSR) ;
if(test & ENRSR_RXOK)
printk("NE2000 : RECEIVE STATUS : RECEIVE_OK\n") ;
if(test & ENRSR_CRC)
printk("NE2000 : RECEIVE STATUS : CRC_ERROR\n") ;
if(test & ENRSR_FAE)
printk("NE2000 : RECEIVE STATUS : FRAME_ALIGN_ERROR\n") ;
if(test & ENRSR_FO)
printk("NE2000 : RECEIVE STATUS : FIFO_OVERRUN\n") ;
if(test & ENRSR_MPA)
printk("NE2000 : RECEIVE STATUS : MISSED_PACKET\n") ;
if(test & ENRSR_PHY)
printk("NE2000 : RECEIVE STATUS : PHYS/MULTI_ADDRESS\n") ;
if(test & ENRSR_DIS)
printk("NE2000 : RECEIVE STATUS : RECEIVER_DISABLED\n") ;
if(test & ENRSR_DEF)
printk("NE2000 : RECEIVE STATUS : DEFERRING\n") ;
outb_p(E8390_RXCONFIG,NE_BASE+EN0_RXCR) ;
}
if(which & INT_PACKET_TRANSMITTED)
{
which ^= INT_PACKET_TRANSMITTED ;
//printk("NE2000 : IRQ_TRANSMIT_OK\n") ;
transmit = 0 ;
}
if(which & INT_TRANSMIT_ERROR)
{
which ^= INT_TRANSMIT_ERROR ;
test = inb_p(NE_BASE+EN0_TSR) ;
if(test & ENTSR_PTX)
printk("NE2000 : TRANSMIT STATUS : TRANSMIT_OK\n") ;
if(test & ENTSR_ND)
printk("NE2000 : TRANSMIT STATUS : NOT_DEFERRED\n") ;
if(test & ENTSR_COL)
printk("NE2000 : TRANSMIT STATUS : COLLISION\n") ;
if(test & ENTSR_ABT)
printk("NE2000 : TRANSMIT STATUS : COLLISION>16\n") ;
if(test & ENTSR_CRS)
printk("NE2000 : TRANSMIT STATUS : CARRIER_LOST\n") ;
if(test & ENTSR_FU)
printk("NE2000 : TRANSMIT STATUS : FIFO_UNDERRUN\n") ;
if(test & ENTSR_CDH)
printk("NE2000 : TRANSMIT STATUS : HEARTBEAT_LOST\n") ;
if(test & ENTSR_OWC)
printk("NE2000 : TRANSMIT STATUS : OUT_OF_WINDOW\n") ;
outb_p(E8390_TXCONFIG,NE_BASE+EN0_TXCR) ;
transmit = 0 ;
}
if(which & INT_OVERWRITE_WARNING)
{
which ^= INT_OVERWRITE_WARNING ;
debugirq("INT_OVERWRITE_WARNING") ;
}
if(which & INT_COUNTER_OVERFLOW)
{
which ^= INT_COUNTER_OVERFLOW ;
debugirq("INT_COUNTER_OVERFLOW") ;
}
if(which & INT_REMOTE_DMA_COMPLETE)
{
which ^= INT_REMOTE_DMA_COMPLETE ;
debugirq("INT_REMOTE_DMA_COMPLETE") ;
}
if(which & INT_RESET_STATUS)
{
which ^= INT_RESET_STATUS ;
debugirq("INT_RESET_STATUS") ;
}
}
outb_p(0xFF,NE_BASE+EN0_ISR) ; // acknowledge
rt_enable_irq(dev.irq) ;
outb_p(ENISR_ALL,NE_BASE+EN0_IMR) ;
// this is needed for IRQ sharing ......
rt_pend_linux_irq(dev.irq);
/* printk("<<<<IRQ END>>>>\n") ; */
}
/******************************************************/
/* */
/* Send function */
/* */
/* */
/******************************************************/
void ne2000_sender(void)
{
int mess_count ;
if(transmit==0)
{
transmit = 1 ;
mess_count = ne2000_buffer_send.taille + 15 ;
outb_p(E8390_PAGE0+E8390_START+E8390_NODMA,NE_BASE+NE_CMD) ;
outb_p(ENISR_RDC,NE_BASE+EN0_ISR) ;
outb_p(mess_count & 0xFF,NE_BASE+EN0_RCNTLO) ;
outb_p(mess_count >> 8 ,NE_BASE+EN0_RCNTHI) ;
outb_p(0x00 ,NE_BASE+EN0_RSARLO) ;
outb_p(dev.start_page ,NE_BASE+EN0_RSARHI) ;
outb_p(E8390_RWRITE+E8390_START,NE_BASE+NE_CMD) ;
outsb(NE_BASE+NE_DATAPORT,dev.buffwrite,mess_count) ;
outb_p(ENISR_RDC,NE_BASE+EN0_ISR) ;
/* paquet sending ... */
outb_p(E8390_NODMA+E8390_PAGE0, NE_BASE+E8390_CMD);
outb_p(mess_count & 0xff, NE_BASE + EN0_TCNTLO);
outb_p(mess_count >> 8, NE_BASE + EN0_TCNTHI);
outb_p(dev.start_page, NE_BASE + EN0_TPSR);
outb_p(E8390_NODMA+E8390_TRANS+E8390_START, NE_BASE+E8390_CMD);
}
}
/******************************************************/
/* */
/* Initialisation */
/* */
/* */
/******************************************************/
static void NE2000Init()
{
int i ;
// initialisation de la carte reseau ...
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP,NE_BASE+E8390_CMD) ;
outb_p(0x48,NE_BASE+EN0_DCFG) ;
// clear remote byte count regiters
outb_p(0x00,NE_BASE+EN0_RCNTLO) ;
outb_p(0x00,NE_BASE+EN0_RCNTHI) ;
// set monitor and loopback mode ... indispensable !
outb_p(E8390_RXOFF,NE_BASE+EN0_RXCR) ;
outb_p(E8390_TXOFF,NE_BASE+EN0_TXCR) ;
// set transmit page and receive ring
outb_p(dev.tx_start_page,NE_BASE+EN0_TPSR) ;
dev.tx1 = dev.tx2 = 0 ;
outb_p(dev.rx_start_page,NE_BASE+EN0_STARTPG) ;
outb_p(dev.stop_page-1,NE_BASE+EN0_BOUNDARY) ;
dev.current_page = dev.rx_start_page ;
outb_p(dev.stop_page,NE_BASE+EN0_STOPPG) ;
// clear pending irq and mask
outb_p(0xFF,NE_BASE+EN0_ISR) ;
outb_p(0x00,NE_BASE+EN0_IMR) ;
// copy of HWaddr
outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP,NE_BASE+E8390_CMD) ;
for(i=0;i<6;i++)
{
ne2000_buffer_send.src[i] = dev.HWaddr[i] ;
outb_p(dev.HWaddr[i],NE_BASE+EN1_PHYS_SHIFT(i)) ;
if(inb_p(NE_BASE+EN1_PHYS_SHIFT(i)) != dev.HWaddr[i])
printk("NE2000 : 0x%3.3x:#%2.2d -> HWaddr read/write mismap %d\n",dev.io,dev.irq,i) ;
}
ne2000_buffer_send.proto[0] = 0x90 ;
ne2000_buffer_send.proto[1] = 0x00 ;
printk("NE2000 : HWaddr [") ;
for(i=0;i<6;i++)
printk("%2.2x",inb_p(NE_BASE+EN1_PHYS_SHIFT(i))) ;
printk("]\n") ;
outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP,NE_BASE+E8390_CMD) ;
outb_p(dev.rx_start_page,NE_BASE+EN1_CURPAG) ;
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP,NE_BASE+E8390_CMD) ;
printk("NE2000 : Initialisation done.\n") ;
}
/******************************************************/
/* */
/* Starting ... */
/* */
/* */
/******************************************************/
static void NE2000Start()
{
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START,NE_BASE+E8390_CMD) ;
outb_p(0xFF,NE_BASE+EN0_ISR) ;
outb_p(E8390_TXCONFIG,NE_BASE+EN0_TXCR) ;
outb_p(E8390_RXCONFIG,NE_BASE+EN0_RXCR) ;
outb_p(ENISR_ALL,NE_BASE+EN0_IMR) ;
printk("NE2000 : Startup done.\n") ;
}
/******************************************************/
/* */
/* network card finding ... */
/* */
/* */
/******************************************************/
static struct {
unsigned short vendor, dev_id;
char *name;
}
pci_clone_list[] __initdata = {
{0x10ec, 0x8029, "RealTek RTL-8029"},
{0x1050, 0x0940, "Winbond 89C940"},
{0x11f6, 0x1401, "Compex RL2000"},
{0x8e2e, 0x3000, "KTI ET32P2"},
{0x4a14, 0x5000, "NetVin NV5000SC"},
{0x1106, 0x0926, "Via 82C926"},
{0x10bd, 0x0e34, "SureCom NE34"},
{0x1050, 0x5a5a, "Winbond"},
{0,}
}; // get from ne2k-pci.c ...
static int FindNE2000()
{
int regd,reg0 ;
// PCI config detection ...
struct pci_dev *pdev = NULL;
dev.io = 0 ;
dev.wordsize = 2 ;
while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev)) != NULL)
{
int i ;
// check the card if clone of NE2000
for (i = 0; pci_clone_list[i].vendor != 0; i++)
if (pci_clone_list[i].vendor == pdev->vendor
&& pci_clone_list[i].dev_id == pdev->device)
break;
if (pci_clone_list[i].vendor == 0)
continue;
/* Avoid already found cards from previous calls */
if (check_region(pdev->io, NE_IO_EXTENT))
continue;
dev.io = pdev->io ;
// ####### io hack #######
dev.io-- ;
// ####### io hack #######
dev.irq = pdev->irq ;
break ;
}
// preliminary check ...
if(inb_p(dev.io)==0xFF)
return -1 ;
reg0 = inb_p(dev.io) ;
outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP,dev.io+E8390_CMD) ;
regd = inb_p(dev.io+0x0d) ;
outb_p(0xff,dev.io+0x0d) ;
outb_p(E8390_NODMA+E8390_PAGE0,dev.io+E8390_CMD) ;
inb_p(dev.io+EN0_COUNTER0) ; // nettoyage du compteur en faisant une lecture ...
if(inb_p(dev.io+EN0_COUNTER0)!=0)
{
outb_p(reg0,dev.io) ;
outb_p(regd,dev.io+0x0d) ;
return -1 ;
}
printk("ne2k-pci.c: PCI NE2000 clone at I/O %#x, IRQ %d.\n", dev.io, dev.irq);
// check the SA PROM ...
{
int i ;
struct {unsigned char value, offset; }
program_seq[]=
{
{E8390_NODMA+E8390_PAGE0+E8390_STOP,E8390_CMD },
{0x48 ,EN0_DCFG },
{0x00 ,EN0_RCNTLO},
{0x00 ,EN0_RCNTHI},
{0x00 ,EN0_IMR },
{0xFF ,EN0_ISR },
{E8390_RXOFF ,EN0_RXCR },
{E8390_TXOFF ,EN0_TXCR },
{32 ,EN0_RCNTLO},
{0x00 ,EN0_RCNTHI},
{0x00 ,EN0_RSARLO},
{0x00 ,EN0_RSARHI},
{E8390_RREAD+E8390_START ,E8390_CMD },
} ;
for(i=0;i<sizeof(program_seq)/sizeof(program_seq[0]);i++)
outb_p(program_seq[i].value,dev.io+program_seq[i].offset) ;
for(i=0;i<32;i+=2)
{
dev.SA_prom[i] = inb(dev.io+NE_DATAPORT) ;
dev.SA_prom[i+1] = inb(dev.io+NE_DATAPORT) ; // lecture en word ...
if(dev.SA_prom[i] != dev.SA_prom[i+1])
dev.wordsize = 1 ;
}
if(dev.wordsize==2)
{
for(i=0;i<16;i++)
dev.SA_prom[i] = dev.SA_prom[i+i] ;
// set to word mode ...
outb_p(0x49,dev.io+EN0_DCFG) ;
dev.start_page = NESM_START_PG ;
dev.stop_page = NESM_STOP_PG ;
}
else
{
// set to byte mode ...
dev.start_page = NE1SM_START_PG ;
dev.stop_page = NE1SM_STOP_PG ;
}
if((dev.SA_prom[14]==0x57)&&(dev.SA_prom[15]==0x57))
printk("NE2000 : 0x%3.3x:#%2.2d -> Signature of NE2000 compatible found.\n",dev.io,dev.irq) ;
if((dev.SA_prom[0]==0x00)&&(dev.SA_prom[1]==0x00)&&(dev.SA_prom[2]==0x1d))
printk("NE2000 : 0x%3.3x:#%2.2d -> Signature of CTRON found.\n",dev.io,dev.irq) ;
if((dev.SA_prom[14]==0x49)&&(dev.SA_prom[15]==0x00))
printk("NE2000 : 0x%3.3x:#%2.2d -> Signature of COPAN found.\n",dev.io,dev.irq) ;
rt_reset_irq_to_sym_mode(dev.irq) ;
/* rt_assign_irq_to_cpu (dev.irq,0) ; */
if(rt_request_global_irq(dev.irq,&IrqHandlerNE2000)<0)
{
printk("NE2000 : 0x%3.3x:#%2.2d -> Attaching Irq Handler Failed !\n",dev.io,dev.irq) ;
return -1 ;
}
rt_enable_irq(dev.irq) ;
if(machine==0)
for(i=0;i<6;i++)
dev.HWaddr[i] = dev.SA_prom[i] ;
else
{
dev.HWaddr[0] = 0x63 ;
dev.HWaddr[1] = 0x63 ;
dev.HWaddr[2] = 0x27 ;
dev.HWaddr[3] = 0x70 ;
dev.HWaddr[4] = (unsigned char)(machine>>8) ;
dev.HWaddr[5] = (unsigned char)(machine) ;
}
dev.tx_start_page = dev.start_page ;
dev.rx_start_page = dev.start_page+TX_PAGES ;
dev.buffread = (unsigned char *)&ne2000_buffer_get ;
dev.buffwrite = (unsigned char *)&ne2000_buffer_send ;
return 0 ;
}
}