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