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