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