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