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