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