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