1 /* 2 wdeth.c 3 4 Created: March 14, 1994 by Philip Homburg 5 */ 6 7 #include <minix/drivers.h> 8 #include <minix/netdriver.h> 9 10 #include <assert.h> 11 12 #include "local.h" 13 #include "dp8390.h" 14 #include "wdeth.h" 15 16 #if ENABLE_WDETH 17 18 #define WET_ETHERNET 0x01 /* Ethernet transceiver */ 19 #define WET_STARLAN 0x02 /* Starlan transceiver */ 20 #define WET_INTERF_CHIP 0x04 /* has a WD83C583 interface chip */ 21 #define WET_BRD_16BIT 0x08 /* 16 bit board */ 22 #define WET_SLT_16BIT 0x10 /* 16 bit slot */ 23 #define WET_790 0x20 /* '790 chip */ 24 25 static int we_int_table[8]= { 9, 3, 5, 7, 10, 11, 15, 4 }; 26 static int we_790int_table[8]= { 0, 9, 3, 5, 7, 10, 11, 15 }; 27 28 static void we_init(dpeth_t *dep); 29 static void we_stop(dpeth_t *dep); 30 static int we_aliasing(dpeth_t *dep); 31 static int we_interface_chip(dpeth_t *dep); 32 static int we_16bitboard(dpeth_t *dep); 33 static int we_16bitslot(dpeth_t *dep); 34 static int we_ultra(dpeth_t *dep); 35 36 /*===========================================================================* 37 * wdeth_probe * 38 *===========================================================================*/ 39 int wdeth_probe(dep) 40 dpeth_t *dep; 41 { 42 int sum; 43 44 if (dep->de_linmem == 0) 45 return 0; /* No shared memory, so no WD board */ 46 47 sum = inb_we(dep, EPL_EA0) + inb_we(dep, EPL_EA1) + 48 inb_we(dep, EPL_EA2) + inb_we(dep, EPL_EA3) + 49 inb_we(dep, EPL_EA4) + inb_we(dep, EPL_EA5) + 50 inb_we(dep, EPL_TLB) + inb_we(dep, EPL_CHKSUM); 51 if ((sum & 0xFF) != 0xFF) 52 return 0; /* No ethernet board at this address */ 53 54 dep->de_initf= we_init; 55 dep->de_stopf= we_stop; 56 dep->de_prog_IO= 0; 57 return 1; 58 } 59 60 /*===========================================================================* 61 * we_init * 62 *===========================================================================*/ 63 static void we_init(dep) 64 dpeth_t *dep; 65 { 66 int i, int_indx, int_nr; 67 int tlb, rambit, revision; 68 int icr, irr, hwr, b, gcr; 69 int we_type; 70 int sendq_nr; 71 72 dep->de_address.na_addr[0] = inb_we(dep, EPL_EA0); 73 dep->de_address.na_addr[1] = inb_we(dep, EPL_EA1); 74 dep->de_address.na_addr[2] = inb_we(dep, EPL_EA2); 75 dep->de_address.na_addr[3] = inb_we(dep, EPL_EA3); 76 dep->de_address.na_addr[4] = inb_we(dep, EPL_EA4); 77 dep->de_address.na_addr[5] = inb_we(dep, EPL_EA5); 78 79 dep->de_dp8390_port= dep->de_base_port + EPL_DP8390; 80 81 dep->de_16bit= 0; 82 83 we_type= 0; 84 we_type |= WET_ETHERNET; /* assume ethernet */ 85 if (we_ultra(dep)) 86 we_type |= WET_790; 87 if (!we_aliasing(dep)) 88 { 89 if (we_interface_chip(dep)) 90 we_type |= WET_INTERF_CHIP; 91 if (we_16bitboard(dep)) 92 { 93 we_type |= WET_BRD_16BIT; 94 if (we_16bitslot(dep)) 95 we_type |= WET_SLT_16BIT; 96 } 97 } 98 if (we_type & WET_SLT_16BIT) 99 dep->de_16bit= 1; 100 101 /* look at the on board ram size. */ 102 tlb= inb_we(dep, EPL_TLB); 103 revision= tlb & E_TLB_REV; 104 rambit= tlb & E_TLB_RAM; 105 106 if (dep->de_ramsize != 0) 107 { 108 /* size set from boot environment. */ 109 } 110 else if (revision < 2) 111 { 112 dep->de_ramsize= 0x2000; /* 8K */ 113 if (we_type & WET_BRD_16BIT) 114 dep->de_ramsize= 0x4000; /* 16K */ 115 else if ((we_type & WET_INTERF_CHIP) && 116 inb_we(dep, EPL_ICR) & E_ICR_MEMBIT) 117 { 118 dep->de_ramsize= 0x8000; /* 32K */ 119 } 120 } 121 else 122 { 123 if (we_type & WET_BRD_16BIT) 124 { 125 /* 32K or 16K */ 126 dep->de_ramsize= rambit ? 0x8000 : 0x4000; 127 } 128 else 129 { 130 /* 32K or 8K */ 131 dep->de_ramsize= rambit ? 0x8000 : 0x2000; 132 } 133 } 134 135 if (we_type & WET_790) 136 { 137 outb_we(dep, EPL_MSR, E_MSR_RESET); 138 if ((we_type & (WET_BRD_16BIT|WET_SLT_16BIT)) == 139 (WET_BRD_16BIT|WET_SLT_16BIT)) 140 { 141 outb_we(dep, EPL_LAAR, E_LAAR_LAN16E | E_LAAR_MEM16E); 142 } 143 } 144 else if (we_type & WET_BRD_16BIT) 145 { 146 if (we_type & WET_SLT_16BIT) 147 { 148 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT | 149 E_LAAR_LAN16E | E_LAAR_MEM16E); 150 } 151 else 152 { 153 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_SOFTINT | 154 E_LAAR_LAN16E); 155 } 156 } 157 158 if (we_type & WET_790) 159 { 160 outb_we(dep, EPL_MSR, E_MSR_MENABLE); 161 hwr= inb_we(dep, EPL_790_HWR); 162 outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH); 163 b= inb_we(dep, EPL_790_B); 164 outb_we(dep, EPL_790_B, ((dep->de_linmem >> 13) & 0x0f) | 165 ((dep->de_linmem >> 11) & 0x40) | (b & 0xb0)); 166 outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH); 167 } 168 else 169 { 170 outb_we(dep, EPL_MSR, E_MSR_RESET); 171 outb_we(dep, EPL_MSR, E_MSR_MENABLE | 172 ((dep->de_linmem >> 13) & E_MSR_MEMADDR)); 173 } 174 175 if ((we_type & WET_INTERF_CHIP) && !(we_type & WET_790)) 176 { 177 icr= inb_we(dep, EPL_ICR); 178 irr= inb_we(dep, EPL_IRR); 179 int_indx= (icr & E_ICR_IR2) | 180 ((irr & (E_IRR_IR0|E_IRR_IR1)) >> 5); 181 int_nr= we_int_table[int_indx]; 182 #if DEBUG 183 printf("%s: encoded irq= %d\n", netdriver_name(), int_nr); 184 #endif 185 if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr; 186 187 outb_we(dep, EPL_IRR, irr | E_IRR_IEN); 188 } 189 if (we_type & WET_790) 190 { 191 hwr= inb_we(dep, EPL_790_HWR); 192 outb_we(dep, EPL_790_HWR, hwr | E_790_HWR_SWH); 193 194 gcr= inb_we(dep, EPL_790_GCR); 195 196 outb_we(dep, EPL_790_HWR, hwr & ~E_790_HWR_SWH); 197 198 int_indx= ((gcr & E_790_GCR_IR2) >> 4) | 199 ((gcr & (E_790_GCR_IR1|E_790_GCR_IR0)) >> 2); 200 int_nr= we_790int_table[int_indx]; 201 #if DEBUG 202 printf("%s: encoded irq= %d\n", netdriver_name(), int_nr); 203 #endif 204 if (dep->de_irq & DEI_DEFAULT) dep->de_irq= int_nr; 205 206 icr= inb_we(dep, EPL_790_ICR); 207 outb_we(dep, EPL_790_ICR, icr | E_790_ICR_EIL); 208 } 209 210 /* Strip the "default flag." */ 211 dep->de_irq &= ~DEI_DEFAULT; 212 213 if (!debug) 214 { 215 printf("%s: WD80%d3 at %X:%d:%lX\n", 216 netdriver_name(), we_type & WET_BRD_16BIT ? 1 : 0, 217 dep->de_base_port, dep->de_irq, dep->de_linmem); 218 } 219 else 220 { 221 printf("%s: Western Digital %s%s card %s%s at I/O " 222 "address 0x%X, memory address 0x%lX, " 223 "memory size 0x%X, irq %d\n", 224 netdriver_name(), 225 we_type & WET_BRD_16BIT ? "16-bit " : "", 226 we_type & WET_ETHERNET ? "Ethernet" : 227 we_type & WET_STARLAN ? "Starlan" : "Network", 228 we_type & WET_INTERF_CHIP ? "with an interface chip " : "", 229 we_type & WET_SLT_16BIT ? "in a 16-bit slot " : "", 230 dep->de_base_port, dep->de_linmem, dep->de_ramsize, 231 dep->de_irq); 232 } 233 234 dep->de_offset_page= 0; /* Shared memory starts at 0 */ 235 236 /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */ 237 sendq_nr= dep->de_ramsize / 0x2000; 238 if (sendq_nr < 1) 239 sendq_nr= 1; 240 else if (sendq_nr > SENDQ_NR) 241 sendq_nr= SENDQ_NR; 242 dep->de_sendq_nr= sendq_nr; 243 for (i= 0; i<sendq_nr; i++) 244 dep->de_sendq[i].sq_sendpage= i*SENDQ_PAGES; 245 246 dep->de_startpage= i*SENDQ_PAGES; 247 dep->de_stoppage= dep->de_ramsize / DP_PAGESIZE; 248 } 249 250 /*===========================================================================* 251 * we_stop * 252 *===========================================================================*/ 253 static void we_stop(dep) 254 dpeth_t *dep; 255 { 256 if (dep->de_16bit) 257 outb_we(dep, EPL_LAAR, E_LAAR_A19 | E_LAAR_LAN16E); 258 outb_we(dep, EPL_MSR, E_MSR_RESET); 259 outb_we(dep, EPL_MSR, 0); 260 } 261 262 /*===========================================================================* 263 * we_aliasing * 264 *===========================================================================*/ 265 static int we_aliasing(dep) 266 dpeth_t *dep; 267 { 268 /* Determine whether wd8003 hardware performs register aliasing. This implies 269 * an old WD8003E board. */ 270 271 if (inb_we(dep, EPL_REG1) != inb_we(dep, EPL_EA1)) 272 return 0; 273 if (inb_we(dep, EPL_REG2) != inb_we(dep, EPL_EA2)) 274 return 0; 275 if (inb_we(dep, EPL_REG3) != inb_we(dep, EPL_EA3)) 276 return 0; 277 if (inb_we(dep, EPL_REG4) != inb_we(dep, EPL_EA4)) 278 return 0; 279 if (inb_we(dep, EPL_REG7) != inb_we(dep, EPL_CHKSUM)) 280 return 0; 281 return 1; 282 } 283 284 /*===========================================================================* 285 * we_interface_chip * 286 *===========================================================================*/ 287 static int we_interface_chip(dep) 288 dpeth_t *dep; 289 { 290 /* Determine if the board has an interface chip. */ 291 292 outb_we(dep, EPL_GP2, 0x35); 293 if (inb_we(dep, EPL_GP2) != 0x35) 294 return 0; 295 outb_we(dep, EPL_GP2, 0x3A); 296 if (inb_we(dep, EPL_GP2) != 0x3A) 297 return 0; 298 return 1; 299 } 300 301 /*===========================================================================* 302 * we_16bitboard * 303 *===========================================================================*/ 304 static int we_16bitboard(dep) 305 dpeth_t *dep; 306 { 307 /* Determine whether the board is capable of doing 16 bit memory moves. 308 * If the 16 bit enable bit is unchangable by software we'll assume an 309 * 8 bit board. 310 */ 311 int icr; 312 u8_t tlb; 313 314 icr= inb_we(dep, EPL_ICR); 315 316 outb_we(dep, EPL_ICR, icr ^ E_ICR_16BIT); 317 if (inb_we(dep, EPL_ICR) == icr) 318 { 319 tlb= inb_we(dep, EPL_TLB); 320 #if DEBUG 321 printf("%s: tlb= 0x%x\n", netdriver_name(), tlb); 322 #endif 323 return tlb == E_TLB_EB || tlb == E_TLB_E || 324 tlb == E_TLB_SMCE || tlb == E_TLB_SMC8216T || 325 tlb == E_TLB_SMC8216C; 326 } 327 outb_we(dep, EPL_ICR, icr); 328 return (icr & E_ICR_16BIT); 329 } 330 331 /*===========================================================================* 332 * we_16bitslot * 333 *===========================================================================*/ 334 static int we_16bitslot(dep) 335 dpeth_t *dep; 336 { 337 /* Determine if the 16 bit board in plugged into a 16 bit slot. */ 338 return !!(inb_we(dep, EPL_ICR) & E_ICR_16BIT); 339 } 340 341 /*===========================================================================* 342 * we_ultra * 343 *===========================================================================*/ 344 static int we_ultra(dep) 345 dpeth_t *dep; 346 { 347 /* Determine if we has an '790 chip. */ 348 u8_t tlb; 349 350 tlb= inb_we(dep, EPL_TLB); 351 return tlb == E_TLB_SMC8216T || tlb == E_TLB_SMC8216C; 352 } 353 354 #endif /* ENABLE_WDETH */ 355 356 /* 357 * $PchId: wdeth.c,v 1.10 2003/09/10 19:31:50 philip Exp $ 358 */ 359