1*433d6423SLionel Sambuc /* 2*433d6423SLionel Sambuc ne2000.c 3*433d6423SLionel Sambuc 4*433d6423SLionel Sambuc Driver for the ne2000 ethernet cards. This file contains only the ne2000 5*433d6423SLionel Sambuc specific code, the rest is in dp8390.c 6*433d6423SLionel Sambuc 7*433d6423SLionel Sambuc Created: March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com> 8*433d6423SLionel Sambuc */ 9*433d6423SLionel Sambuc 10*433d6423SLionel Sambuc #include <minix/drivers.h> 11*433d6423SLionel Sambuc 12*433d6423SLionel Sambuc #include <net/gen/ether.h> 13*433d6423SLionel Sambuc #include <net/gen/eth_io.h> 14*433d6423SLionel Sambuc #if __minix_vmd 15*433d6423SLionel Sambuc #include "config.h" 16*433d6423SLionel Sambuc #endif 17*433d6423SLionel Sambuc 18*433d6423SLionel Sambuc #include "local.h" 19*433d6423SLionel Sambuc #include "dp8390.h" 20*433d6423SLionel Sambuc #include "ne2000.h" 21*433d6423SLionel Sambuc 22*433d6423SLionel Sambuc #if ENABLE_NE2000 23*433d6423SLionel Sambuc 24*433d6423SLionel Sambuc #define N 100 25*433d6423SLionel Sambuc 26*433d6423SLionel Sambuc extern u32_t system_hz; 27*433d6423SLionel Sambuc 28*433d6423SLionel Sambuc #define MILLIS_TO_TICKS(m) (((m)*system_hz/1000)+1) 29*433d6423SLionel Sambuc 30*433d6423SLionel Sambuc typedef int(*testf_t) (dpeth_t *dep, int pos, u8_t *pat); 31*433d6423SLionel Sambuc 32*433d6423SLionel Sambuc static u8_t pat0[]= { 0x00, 0x00, 0x00, 0x00 }; 33*433d6423SLionel Sambuc static u8_t pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF }; 34*433d6423SLionel Sambuc static u8_t pat2[]= { 0xA5, 0x5A, 0x69, 0x96 }; 35*433d6423SLionel Sambuc static u8_t pat3[]= { 0x96, 0x69, 0x5A, 0xA5 }; 36*433d6423SLionel Sambuc 37*433d6423SLionel Sambuc static int test_8(dpeth_t *dep, int pos, u8_t *pat); 38*433d6423SLionel Sambuc static int test_16(dpeth_t *dep, int pos, u8_t *pat); 39*433d6423SLionel Sambuc static void ne_stop(dpeth_t *dep); 40*433d6423SLionel Sambuc static void milli_delay(unsigned long millis); 41*433d6423SLionel Sambuc 42*433d6423SLionel Sambuc /*===========================================================================* 43*433d6423SLionel Sambuc * ne_probe * 44*433d6423SLionel Sambuc *===========================================================================*/ 45*433d6423SLionel Sambuc int ne_probe(dpeth_t *dep) 46*433d6423SLionel Sambuc { 47*433d6423SLionel Sambuc int byte; 48*433d6423SLionel Sambuc int i; 49*433d6423SLionel Sambuc int loc1, loc2; 50*433d6423SLionel Sambuc testf_t f; 51*433d6423SLionel Sambuc 52*433d6423SLionel Sambuc dep->de_dp8390_port= dep->de_base_port + NE_DP8390; 53*433d6423SLionel Sambuc 54*433d6423SLionel Sambuc /* We probe for an ne1000 or an ne2000 by testing whether the 55*433d6423SLionel Sambuc * on board is reachable through the dp8390. Note that the 56*433d6423SLionel Sambuc * ne1000 is an 8bit card and has a memory region distict from 57*433d6423SLionel Sambuc * the 16bit ne2000 58*433d6423SLionel Sambuc */ 59*433d6423SLionel Sambuc 60*433d6423SLionel Sambuc for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++) 61*433d6423SLionel Sambuc { 62*433d6423SLionel Sambuc /* Reset the ethernet card */ 63*433d6423SLionel Sambuc byte= inb_ne(dep, NE_RESET); 64*433d6423SLionel Sambuc milli_delay(2); 65*433d6423SLionel Sambuc outb_ne(dep, NE_RESET, byte); 66*433d6423SLionel Sambuc milli_delay(2); 67*433d6423SLionel Sambuc 68*433d6423SLionel Sambuc /* Reset the dp8390 */ 69*433d6423SLionel Sambuc outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT); 70*433d6423SLionel Sambuc for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++) 71*433d6423SLionel Sambuc ; /* Do nothing */ 72*433d6423SLionel Sambuc 73*433d6423SLionel Sambuc /* Check if the dp8390 is really there */ 74*433d6423SLionel Sambuc if ((inb_reg0(dep, DP_CR) & (CR_STP|CR_DM_ABORT)) != 75*433d6423SLionel Sambuc (CR_STP|CR_DM_ABORT)) 76*433d6423SLionel Sambuc { 77*433d6423SLionel Sambuc return 0; 78*433d6423SLionel Sambuc } 79*433d6423SLionel Sambuc 80*433d6423SLionel Sambuc /* Disable the receiver and init TCR and DCR. */ 81*433d6423SLionel Sambuc outb_reg0(dep, DP_RCR, RCR_MON); 82*433d6423SLionel Sambuc outb_reg0(dep, DP_TCR, TCR_NORMAL); 83*433d6423SLionel Sambuc if (dep->de_16bit) 84*433d6423SLionel Sambuc { 85*433d6423SLionel Sambuc outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | 86*433d6423SLionel Sambuc DCR_BMS); 87*433d6423SLionel Sambuc } 88*433d6423SLionel Sambuc else 89*433d6423SLionel Sambuc { 90*433d6423SLionel Sambuc outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | 91*433d6423SLionel Sambuc DCR_BMS); 92*433d6423SLionel Sambuc } 93*433d6423SLionel Sambuc 94*433d6423SLionel Sambuc if (dep->de_16bit) 95*433d6423SLionel Sambuc { 96*433d6423SLionel Sambuc loc1= NE2000_START; 97*433d6423SLionel Sambuc loc2= NE2000_START + NE2000_SIZE - 4; 98*433d6423SLionel Sambuc f= test_16; 99*433d6423SLionel Sambuc } 100*433d6423SLionel Sambuc else 101*433d6423SLionel Sambuc { 102*433d6423SLionel Sambuc loc1= NE1000_START; 103*433d6423SLionel Sambuc loc2= NE1000_START + NE1000_SIZE - 4; 104*433d6423SLionel Sambuc f= test_8; 105*433d6423SLionel Sambuc } 106*433d6423SLionel Sambuc if (f(dep, loc1, pat0) && f(dep, loc1, pat1) && 107*433d6423SLionel Sambuc f(dep, loc1, pat2) && f(dep, loc1, pat3) && 108*433d6423SLionel Sambuc f(dep, loc2, pat0) && f(dep, loc2, pat1) && 109*433d6423SLionel Sambuc f(dep, loc2, pat2) && f(dep, loc2, pat3)) 110*433d6423SLionel Sambuc { 111*433d6423SLionel Sambuc /* We don't need a memory segment */ 112*433d6423SLionel Sambuc dep->de_linmem= 0; 113*433d6423SLionel Sambuc if (!dep->de_pci) 114*433d6423SLionel Sambuc dep->de_initf= ne_init; 115*433d6423SLionel Sambuc dep->de_stopf= ne_stop; 116*433d6423SLionel Sambuc dep->de_prog_IO= 1; 117*433d6423SLionel Sambuc return 1; 118*433d6423SLionel Sambuc } 119*433d6423SLionel Sambuc } 120*433d6423SLionel Sambuc return 0; 121*433d6423SLionel Sambuc } 122*433d6423SLionel Sambuc 123*433d6423SLionel Sambuc /*===========================================================================* 124*433d6423SLionel Sambuc * ne_init * 125*433d6423SLionel Sambuc *===========================================================================*/ 126*433d6423SLionel Sambuc void ne_init(dep) 127*433d6423SLionel Sambuc dpeth_t *dep; 128*433d6423SLionel Sambuc { 129*433d6423SLionel Sambuc int i; 130*433d6423SLionel Sambuc int word, sendq_nr; 131*433d6423SLionel Sambuc 132*433d6423SLionel Sambuc /* Setup a transfer to get the ethernet address. */ 133*433d6423SLionel Sambuc if (dep->de_16bit) 134*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR0, 6*2); 135*433d6423SLionel Sambuc else 136*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR0, 6); 137*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR1, 0); 138*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR0, 0); 139*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR1, 0); 140*433d6423SLionel Sambuc outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 141*433d6423SLionel Sambuc 142*433d6423SLionel Sambuc for (i= 0; i<6; i++) 143*433d6423SLionel Sambuc { 144*433d6423SLionel Sambuc if (dep->de_16bit) 145*433d6423SLionel Sambuc { 146*433d6423SLionel Sambuc word= inw_ne(dep, NE_DATA); 147*433d6423SLionel Sambuc dep->de_address.ea_addr[i]= word; 148*433d6423SLionel Sambuc } 149*433d6423SLionel Sambuc else 150*433d6423SLionel Sambuc { 151*433d6423SLionel Sambuc dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA); 152*433d6423SLionel Sambuc } 153*433d6423SLionel Sambuc } 154*433d6423SLionel Sambuc dep->de_data_port= dep->de_base_port + NE_DATA; 155*433d6423SLionel Sambuc if (dep->de_16bit) 156*433d6423SLionel Sambuc { 157*433d6423SLionel Sambuc dep->de_ramsize= NE2000_SIZE; 158*433d6423SLionel Sambuc dep->de_offset_page= NE2000_START / DP_PAGESIZE; 159*433d6423SLionel Sambuc } 160*433d6423SLionel Sambuc else 161*433d6423SLionel Sambuc { 162*433d6423SLionel Sambuc dep->de_ramsize= NE1000_SIZE; 163*433d6423SLionel Sambuc dep->de_offset_page= NE1000_START / DP_PAGESIZE; 164*433d6423SLionel Sambuc } 165*433d6423SLionel Sambuc 166*433d6423SLionel Sambuc /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */ 167*433d6423SLionel Sambuc sendq_nr= dep->de_ramsize / 0x2000; 168*433d6423SLionel Sambuc if (sendq_nr < 1) 169*433d6423SLionel Sambuc sendq_nr= 1; 170*433d6423SLionel Sambuc else if (sendq_nr > SENDQ_NR) 171*433d6423SLionel Sambuc sendq_nr= SENDQ_NR; 172*433d6423SLionel Sambuc dep->de_sendq_nr= sendq_nr; 173*433d6423SLionel Sambuc for (i= 0; i<sendq_nr; i++) 174*433d6423SLionel Sambuc { 175*433d6423SLionel Sambuc dep->de_sendq[i].sq_sendpage= dep->de_offset_page + 176*433d6423SLionel Sambuc i*SENDQ_PAGES; 177*433d6423SLionel Sambuc } 178*433d6423SLionel Sambuc 179*433d6423SLionel Sambuc dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES; 180*433d6423SLionel Sambuc dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE; 181*433d6423SLionel Sambuc 182*433d6423SLionel Sambuc /* Can't override the default IRQ. */ 183*433d6423SLionel Sambuc dep->de_irq &= ~DEI_DEFAULT; 184*433d6423SLionel Sambuc 185*433d6423SLionel Sambuc if (!debug) 186*433d6423SLionel Sambuc { 187*433d6423SLionel Sambuc printf("%s: NE%d000 at %X:%d\n", 188*433d6423SLionel Sambuc dep->de_name, dep->de_16bit ? 2 : 1, 189*433d6423SLionel Sambuc dep->de_base_port, dep->de_irq); 190*433d6423SLionel Sambuc } 191*433d6423SLionel Sambuc else 192*433d6423SLionel Sambuc { 193*433d6423SLionel Sambuc printf("%s: Novell NE%d000 ethernet card at I/O address " 194*433d6423SLionel Sambuc "0x%X, memory size 0x%X, irq %d\n", 195*433d6423SLionel Sambuc dep->de_name, dep->de_16bit ? 2 : 1, 196*433d6423SLionel Sambuc dep->de_base_port, dep->de_ramsize, dep->de_irq); 197*433d6423SLionel Sambuc } 198*433d6423SLionel Sambuc } 199*433d6423SLionel Sambuc 200*433d6423SLionel Sambuc /*===========================================================================* 201*433d6423SLionel Sambuc * test_8 * 202*433d6423SLionel Sambuc *===========================================================================*/ 203*433d6423SLionel Sambuc static int test_8(dep, pos, pat) 204*433d6423SLionel Sambuc dpeth_t *dep; 205*433d6423SLionel Sambuc int pos; 206*433d6423SLionel Sambuc u8_t *pat; 207*433d6423SLionel Sambuc { 208*433d6423SLionel Sambuc u8_t buf[4]; 209*433d6423SLionel Sambuc int i; 210*433d6423SLionel Sambuc int r; 211*433d6423SLionel Sambuc 212*433d6423SLionel Sambuc outb_reg0(dep, DP_ISR, 0xFF); 213*433d6423SLionel Sambuc 214*433d6423SLionel Sambuc /* Setup a transfer to put the pattern. */ 215*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR0, 4); 216*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR1, 0); 217*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR0, pos & 0xFF); 218*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR1, pos >> 8); 219*433d6423SLionel Sambuc outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 220*433d6423SLionel Sambuc 221*433d6423SLionel Sambuc for (i= 0; i<4; i++) 222*433d6423SLionel Sambuc outb_ne(dep, NE_DATA, pat[i]); 223*433d6423SLionel Sambuc 224*433d6423SLionel Sambuc for (i= 0; i<N; i++) 225*433d6423SLionel Sambuc { 226*433d6423SLionel Sambuc if (inb_reg0(dep, DP_ISR) & ISR_RDC) 227*433d6423SLionel Sambuc break; 228*433d6423SLionel Sambuc } 229*433d6423SLionel Sambuc if (i == N) 230*433d6423SLionel Sambuc { 231*433d6423SLionel Sambuc if (debug) 232*433d6423SLionel Sambuc { 233*433d6423SLionel Sambuc printf("%s: NE1000 remote DMA test failed\n", 234*433d6423SLionel Sambuc dep->de_name); 235*433d6423SLionel Sambuc } 236*433d6423SLionel Sambuc return 0; 237*433d6423SLionel Sambuc } 238*433d6423SLionel Sambuc 239*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR0, 4); 240*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR1, 0); 241*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR0, pos & 0xFF); 242*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR1, pos >> 8); 243*433d6423SLionel Sambuc outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 244*433d6423SLionel Sambuc 245*433d6423SLionel Sambuc for (i= 0; i<4; i++) 246*433d6423SLionel Sambuc buf[i]= inb_ne(dep, NE_DATA); 247*433d6423SLionel Sambuc 248*433d6423SLionel Sambuc r= (memcmp(buf, pat, 4) == 0); 249*433d6423SLionel Sambuc return r; 250*433d6423SLionel Sambuc } 251*433d6423SLionel Sambuc 252*433d6423SLionel Sambuc /*===========================================================================* 253*433d6423SLionel Sambuc * test_16 * 254*433d6423SLionel Sambuc *===========================================================================*/ 255*433d6423SLionel Sambuc static int test_16(dep, pos, pat) 256*433d6423SLionel Sambuc dpeth_t *dep; 257*433d6423SLionel Sambuc int pos; 258*433d6423SLionel Sambuc u8_t *pat; 259*433d6423SLionel Sambuc { 260*433d6423SLionel Sambuc u8_t buf[4]; 261*433d6423SLionel Sambuc int i; 262*433d6423SLionel Sambuc int r; 263*433d6423SLionel Sambuc 264*433d6423SLionel Sambuc outb_reg0(dep, DP_ISR, 0xFF); 265*433d6423SLionel Sambuc 266*433d6423SLionel Sambuc /* Setup a transfer to put the pattern. */ 267*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR0, 4); 268*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR1, 0); 269*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR0, pos & 0xFF); 270*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR1, pos >> 8); 271*433d6423SLionel Sambuc outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 272*433d6423SLionel Sambuc 273*433d6423SLionel Sambuc for (i= 0; i<4; i += 2) 274*433d6423SLionel Sambuc { 275*433d6423SLionel Sambuc outw_ne(dep, NE_DATA, *(u16_t *)(pat+i)); 276*433d6423SLionel Sambuc } 277*433d6423SLionel Sambuc 278*433d6423SLionel Sambuc for (i= 0; i<N; i++) 279*433d6423SLionel Sambuc { 280*433d6423SLionel Sambuc if (inb_reg0(dep, DP_ISR) & ISR_RDC) 281*433d6423SLionel Sambuc break; 282*433d6423SLionel Sambuc } 283*433d6423SLionel Sambuc if (i == N) 284*433d6423SLionel Sambuc { 285*433d6423SLionel Sambuc if (debug) 286*433d6423SLionel Sambuc { 287*433d6423SLionel Sambuc printf("%s: NE2000 remote DMA test failed\n", 288*433d6423SLionel Sambuc dep->de_name); 289*433d6423SLionel Sambuc } 290*433d6423SLionel Sambuc return 0; 291*433d6423SLionel Sambuc } 292*433d6423SLionel Sambuc 293*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR0, 4); 294*433d6423SLionel Sambuc outb_reg0(dep, DP_RBCR1, 0); 295*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR0, pos & 0xFF); 296*433d6423SLionel Sambuc outb_reg0(dep, DP_RSAR1, pos >> 8); 297*433d6423SLionel Sambuc outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 298*433d6423SLionel Sambuc 299*433d6423SLionel Sambuc for (i= 0; i<4; i += 2) 300*433d6423SLionel Sambuc { 301*433d6423SLionel Sambuc *(u16_t *)(buf+i)= inw_ne(dep, NE_DATA); 302*433d6423SLionel Sambuc } 303*433d6423SLionel Sambuc 304*433d6423SLionel Sambuc r= (memcmp(buf, pat, 4) == 0); 305*433d6423SLionel Sambuc return r; 306*433d6423SLionel Sambuc } 307*433d6423SLionel Sambuc 308*433d6423SLionel Sambuc /*===========================================================================* 309*433d6423SLionel Sambuc * ne_stop * 310*433d6423SLionel Sambuc *===========================================================================*/ 311*433d6423SLionel Sambuc static void ne_stop(dep) 312*433d6423SLionel Sambuc dpeth_t *dep; 313*433d6423SLionel Sambuc { 314*433d6423SLionel Sambuc int byte; 315*433d6423SLionel Sambuc 316*433d6423SLionel Sambuc /* Reset the ethernet card */ 317*433d6423SLionel Sambuc byte= inb_ne(dep, NE_RESET); 318*433d6423SLionel Sambuc milli_delay(2); 319*433d6423SLionel Sambuc outb_ne(dep, NE_RESET, byte); 320*433d6423SLionel Sambuc } 321*433d6423SLionel Sambuc 322*433d6423SLionel Sambuc static void milli_delay(unsigned long millis) 323*433d6423SLionel Sambuc { 324*433d6423SLionel Sambuc tickdelay(MILLIS_TO_TICKS(millis)); 325*433d6423SLionel Sambuc } 326*433d6423SLionel Sambuc 327*433d6423SLionel Sambuc #endif /* ENABLE_NE2000 */ 328*433d6423SLionel Sambuc 329*433d6423SLionel Sambuc /* 330*433d6423SLionel Sambuc * $PchId: ne2000.c,v 1.10 2004/08/03 12:03:00 philip Exp $ 331*433d6423SLionel Sambuc */ 332