1 /* $NetBSD: wd80x3.c,v 1.7 2002/02/17 19:47:41 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Device driver for National Semiconductor DS8390/WD83C690 based ethernet 42 * adapters. 43 * 44 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. 45 * 46 * Copyright (C) 1993, David Greenman. This software may be used, modified, 47 * copied, distributed, and sold, in both source and binary form provided that 48 * the above copyright and these terms are retained. Under no circumstances is 49 * the author responsible for the proper functioning of this software, nor does 50 * the author assume any responsibility for damages incurred with its use. 51 */ 52 53 /* 54 * Device driver for the Western Digital/SMC 8003 and 8013 series, 55 * and the SMC Elite Ultra (8216). 56 */ 57 58 #include <sys/types.h> 59 #include <machine/pio.h> 60 61 #include <lib/libsa/stand.h> 62 #include <libi386.h> 63 64 #ifdef _STANDALONE 65 #include <lib/libkern/libkern.h> 66 #include <bootinfo.h> 67 #endif 68 69 #include "etherdrv.h" 70 #include <dev/ic/dp8390reg.h> 71 #include "dp8390.h" 72 #include <dev/ic/wereg.h> 73 74 #ifndef BASEREG 75 #define BASEREG 0x240 76 #define BASEMEM 0xd0000 77 #endif 78 79 #define WD_BASEREG BASEREG 80 #define WD_BASEMEM BASEMEM 81 82 #ifndef _STANDALONE 83 extern int mapio __P((void)); 84 #endif 85 86 u_char eth_myaddr[6]; 87 88 static u_int8_t we_type; 89 static int we_is16bit; 90 91 #ifdef _STANDALONE 92 static struct btinfo_netif bi_netif; 93 #endif 94 95 const char * 96 we_params() 97 { 98 const char *typestr; 99 100 dp8390_memsize = 8192; 101 102 we_type = inb(WD_BASEREG + WE_CARD_ID); 103 switch (we_type) { 104 #ifdef SUPPORT_WD80X3 105 case WE_TYPE_WD8003S: 106 typestr = "WD8003S"; 107 break; 108 case WE_TYPE_WD8003E: 109 typestr = "WD8003E"; 110 break; 111 case WE_TYPE_WD8003EB: 112 typestr = "WD8003EB"; 113 break; 114 case WE_TYPE_WD8003W: 115 typestr = "WD8003W"; 116 break; 117 case WE_TYPE_WD8013EBT: 118 typestr = "WD8013EBT"; 119 dp8390_memsize = 16384; 120 we_is16bit = 1; 121 break; 122 case WE_TYPE_WD8013W: 123 typestr = "WD8013W"; 124 dp8390_memsize = 16384; 125 we_is16bit = 1; 126 break; 127 case WE_TYPE_WD8013EP: /* also WD8003EP */ 128 if (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) { 129 we_is16bit = 1; 130 dp8390_memsize = 16384; 131 typestr = "WD8013EP"; 132 } else 133 typestr = "WD8003EP"; 134 break; 135 case WE_TYPE_WD8013WC: 136 typestr = "WD8013WC"; 137 dp8390_memsize = 16384; 138 we_is16bit = 1; 139 break; 140 case WE_TYPE_WD8013EBP: 141 typestr = "WD8013EBP"; 142 dp8390_memsize = 16384; 143 we_is16bit = 1; 144 break; 145 case WE_TYPE_WD8013EPC: 146 typestr = "WD8013EPC"; 147 dp8390_memsize = 16384; 148 we_is16bit = 1; 149 break; 150 #endif 151 #ifdef SUPPORT_SMC_ULTRA 152 case WE_TYPE_SMC8216C: 153 case WE_TYPE_SMC8216T: 154 { 155 u_int8_t hwr; 156 157 typestr = (we_type == WE_TYPE_SMC8216C) ? 158 "SMC8216/SMC8216C" : "SMC8216T"; 159 160 hwr = inb(WD_BASEREG + WE790_HWR); 161 outb(WD_BASEREG + WE790_HWR, hwr | WE790_HWR_SWH); 162 switch (inb(WD_BASEREG + WE790_RAR) & WE790_RAR_SZ64) { 163 case WE790_RAR_SZ64: 164 dp8390_memsize = 65536; 165 break; 166 case WE790_RAR_SZ32: 167 dp8390_memsize = 32768; 168 break; 169 case WE790_RAR_SZ16: 170 dp8390_memsize = 16384; 171 break; 172 case WE790_RAR_SZ8: 173 /* 8216 has 16K shared mem -- 8416 has 8K */ 174 typestr = (we_type == WE_TYPE_SMC8216C) ? 175 "SMC8416C/SMC8416BT" : "SMC8416T"; 176 dp8390_memsize = 8192; 177 break; 178 } 179 outb(WD_BASEREG + WE790_HWR, hwr); 180 181 we_is16bit = 1; 182 #ifdef SUPPORT_WD80X3 183 dp8390_is790 = 1; 184 #endif 185 break; 186 } 187 #endif 188 default: 189 /* Not one we recognize. */ 190 return (NULL); 191 } 192 193 /* 194 * Make some adjustments to initial values depending on what is 195 * found in the ICR. 196 */ 197 if (we_is16bit && (we_type != WE_TYPE_WD8013EBT) && 198 (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) == 0) { 199 we_is16bit = 0; 200 dp8390_memsize = 8192; 201 } 202 203 #ifdef WE_DEBUG 204 { 205 int i; 206 207 printf("we_params: type = 0x%x, typestr = %s, is16bit = %d, " 208 "memsize = %d\n", we_type, typestr, we_is16bit, dp8390_memsize); 209 for (i = 0; i < 8; i++) 210 printf(" %d -> 0x%x\n", i, 211 inb(WD_BASEREG + i)); 212 } 213 #endif 214 215 return (typestr); 216 } 217 218 int 219 EtherInit(myadr) 220 unsigned char *myadr; 221 { 222 const char *typestr; 223 u_int8_t x; 224 int i; 225 u_int8_t laar_proto; 226 u_int8_t msr_proto; 227 228 dp8390_iobase = WD_BASEREG + WE_NIC_OFFSET; 229 dp8390_membase = WD_BASEMEM; 230 231 #ifndef _STANDALONE 232 if (mapio()) { 233 printf("no IO access\n"); 234 return(0); 235 } 236 #endif 237 238 for (x = 0, i = 0; i < 8; i++) 239 x += inb(WD_BASEREG + WE_PROM + i); 240 241 if (x != WE_ROM_CHECKSUM_TOTAL) 242 return(0); 243 244 /* reset the ethernet card */ 245 outb(WD_BASEREG + WE_MSR, WE_MSR_RST); 246 delay(100); 247 outb(WD_BASEREG + WE_MSR, inb(WD_BASEREG + WE_MSR) & ~WE_MSR_RST); 248 delay(5000); 249 250 typestr = we_params(); 251 if (!typestr) 252 return(0); 253 254 printf("Using %s board, port 0x%x, iomem 0x%x, iosiz %d\n", 255 typestr, WD_BASEREG, WD_BASEMEM, dp8390_memsize); 256 257 /* get ethernet address */ 258 for(i = 0; i < 6; i++) 259 eth_myaddr[i] = myadr[i]= inb(WD_BASEREG + WE_PROM + i); 260 261 /* 262 * Set upper address bits and 8/16 bit access to shared memory. 263 */ 264 if (dp8390_is790) { 265 laar_proto = inb(WD_BASEREG + WE_LAAR) & ~WE_LAAR_M16EN; 266 outb(WD_BASEREG + WE_LAAR, laar_proto | 267 (we_is16bit ? WE_LAAR_M16EN : 0)); 268 } else if ((we_type & WE_SOFTCONFIG) || 269 (we_type == WE_TYPE_WD8013EBT)) { 270 laar_proto = (WD_BASEMEM >> 19) & WE_LAAR_ADDRHI; 271 if (we_is16bit) 272 laar_proto |= WE_LAAR_L16EN; 273 outb(WD_BASEREG + WE_LAAR, laar_proto | 274 (we_is16bit ? WE_LAAR_M16EN : 0)); 275 } 276 277 /* 278 * Set address and enable interface shared memory. 279 */ 280 if (dp8390_is790) { 281 /* XXX MAGIC CONSTANTS XXX */ 282 x = inb(WD_BASEREG + 0x04); 283 outb(WD_BASEREG + 0x04, x | 0x80); 284 outb(WD_BASEREG + 0x0b, 285 ((WD_BASEMEM >> 13) & 0x0f) | 286 ((WD_BASEMEM >> 11) & 0x40) | 287 (inb(WD_BASEREG + 0x0b) & 0xb0)); 288 outb(WD_BASEREG + 0x04, x); 289 msr_proto = 0x00; 290 dp8390_cr_proto = 0x00; 291 } else { 292 msr_proto = (WD_BASEMEM >> 13) & WE_MSR_ADDR; 293 dp8390_cr_proto = ED_CR_RD2; 294 } 295 296 outb(WD_BASEREG + WE_MSR, msr_proto | WE_MSR_MENB); 297 delay(2); 298 299 /* 300 * DCR gets: 301 * 302 * FIFO threshold to 8, No auto-init Remote DMA, 303 * byte order=80x86. 304 * 305 * 16-bit cards also get word-wide DMA transfers. 306 */ 307 dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (we_is16bit ? ED_DCR_WTS : 0); 308 309 if (dp8390_config()) 310 return(0); 311 312 #ifdef _STANDALONE 313 strncpy(bi_netif.ifname, "we", sizeof(bi_netif.ifname)); 314 bi_netif.bus = BI_BUS_ISA; 315 bi_netif.addr.iobase = WD_BASEREG; 316 317 BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); 318 #endif 319 return(1); 320 } 321 322 /* 323 * Stop ethernet board 324 */ 325 void 326 EtherStop(void) { 327 /* stop dp8390, followed by a board reset */ 328 dp8390_stop(); 329 outb(WD_BASEREG + WE_MSR, WE_MSR_RST); 330 outb(WD_BASEREG + WE_MSR, 0); 331 } 332