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