12061Sjkh/* $NetBSD: wd80x3.c,v 1.9 2008/04/28 20:23:25 martin Exp $ */ 250479Speter 32061Sjkh/*- 438666Sjb * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 532427Sjb * All rights reserved. 6111131Sru * 7111131Sru * This code is derived from software contributed to The NetBSD Foundation 8217733Sbz * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9217733Sbz * NASA Ames Research Center. 1038666Sjb * 1138666Sjb * Redistribution and use in source and binary forms, with or without 1238666Sjb * modification, are permitted provided that the following conditions 13159363Strhodes * are met: 1464049Salex * 1. Redistributions of source code must retain the above copyright 1564049Salex * notice, this list of conditions and the following disclaimer. 16116679Ssimokawa * 2. Redistributions in binary form must reproduce the above copyright 1766071Smarkm * notice, this list of conditions and the following disclaimer in the 18116679Ssimokawa * documentation and/or other materials provided with the distribution. 1973504Sobrien * 20204661Simp * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21232907Sjmallett * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22158962Snetchild * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23223148Sru * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24169597Sdes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25169597Sdes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26169597Sdes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27169597Sdes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28231821Spluknet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29169597Sdes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30169597Sdes * POSSIBILITY OF SUCH DAMAGE. 31169597Sdes */ 32217815Sbz 33217815Sbz/* 34218524Sjhb * Device driver for National Semiconductor DS8390/WD83C690 based ethernet 35253002Salfred * adapters. 36253002Salfred * 37253002Salfred * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. 38253002Salfred * 39253002Salfred * Copyright (C) 1993, David Greenman. This software may be used, modified, 40253003Salfred * copied, distributed, and sold, in both source and binary form provided that 4132427Sjb * the above copyright and these terms are retained. Under no circumstances is 4238666Sjb * the author responsible for the proper functioning of this software, nor does 43108451Sschweikh * the author assume any responsibility for damages incurred with its use. 4438666Sjb */ 4538666Sjb 4638666Sjb/* 4738666Sjb * Device driver for the Western Digital/SMC 8003 and 8013 series, 4817308Speter * and the SMC Elite Ultra (8216). 49217273Simp */ 50217294Simp 5119175Sbde#include <sys/types.h> 5296205Sjwd#include <machine/pio.h> 53217297Simp 54217297Simp#include <lib/libsa/stand.h> 5538042Sbde#include <libi386.h> 5696205Sjwd 5796205Sjwd#ifdef _STANDALONE 5838042Sbde#include <lib/libkern/libkern.h> 5996205Sjwd#include <bootinfo.h> 60159363Strhodes#endif 61159363Strhodes 6217308Speter#include "etherdrv.h" 6396205Sjwd#include <dev/ic/dp8390reg.h> 6496205Sjwd#include "dp8390.h" 6517308Speter#include <dev/ic/wereg.h> 66148330Snetchild 67148330Snetchild#ifndef BASEREG 68148330Snetchild#define BASEREG 0x240 69148330Snetchild#define BASEMEM 0xd0000 70159831Sobrien#endif 71148330Snetchild 72148330Snetchild#define WD_BASEREG BASEREG 73148330Snetchild#define WD_BASEMEM BASEMEM 74251107Screes 75251107Screes#ifndef _STANDALONE 76148330Snetchildextern int mapio(void); 77148330Snetchild#endif 7896205Sjwd 7996205Sjwdu_char eth_myaddr[6]; 8096205Sjwd 81162147Srustatic uint8_t we_type; 82162147Srustatic int we_is16bit; 8398723Sdillon 8498723Sdillon#ifdef _STANDALONE 8598723Sdillonstatic struct btinfo_netif bi_netif; 8638666Sjb#endif 8738666Sjb 8817308Speterconst char * 89123311Speterwe_params(void) 90123311Speter{ 91123311Speter const char *typestr; 92123311Speter 93175833Sjhb dp8390_memsize = 8192; 94175833Sjhb 95169597Sdes we_type = inb(WD_BASEREG + WE_CARD_ID); 96169597Sdes switch (we_type) { 97169597Sdes#ifdef SUPPORT_WD80X3 98169597Sdes case WE_TYPE_WD8003S: 99219177Snwhitehorn typestr = "WD8003S"; 100219177Snwhitehorn break; 101238051Sobrien case WE_TYPE_WD8003E: 102219177Snwhitehorn typestr = "WD8003E"; 103219177Snwhitehorn break; 104158962Snetchild case WE_TYPE_WD8003EB: 105156840Sru typestr = "WD8003EB"; 106123311Speter break; 107137288Speter case WE_TYPE_WD8003W: 108209128Sraj typestr = "WD8003W"; 109209128Sraj break; 110156740Sru case WE_TYPE_WD8013EBT: 1112061Sjkh typestr = "WD8013EBT"; 11297769Sru dp8390_memsize = 16384; 11397252Sru we_is16bit = 1; 114119579Sru break; 11597252Sru case WE_TYPE_WD8013W: 11695730Sru typestr = "WD8013W"; 11795793Sru dp8390_memsize = 16384; 118111617Sru we_is16bit = 1; 11995730Sru break; 120116679Ssimokawa case WE_TYPE_WD8013EP: /* also WD8003EP */ 12195730Sru if (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) { 122116679Ssimokawa we_is16bit = 1; 12395730Sru dp8390_memsize = 16384; 124110035Sru typestr = "WD8013EP"; 125107516Sru } else 126138921Sru typestr = "WD8003EP"; 127156145Syar break; 128138921Sru case WE_TYPE_WD8013WC: 129133942Sru typestr = "WD8013WC"; 130133942Sru dp8390_memsize = 16384; 131156145Syar we_is16bit = 1; 132133942Sru break; 133253616Ssjg case WE_TYPE_WD8013EBP: 134253616Ssjg typestr = "WD8013EBP"; 135253616Ssjg dp8390_memsize = 16384; 136253616Ssjg we_is16bit = 1; 137253616Ssjg break; 138253616Ssjg case WE_TYPE_WD8013EPC: 139253616Ssjg typestr = "WD8013EPC"; 140253616Ssjg dp8390_memsize = 16384; 141253616Ssjg we_is16bit = 1; 142253616Ssjg break; 143253616Ssjg#endif 144253616Ssjg#ifdef SUPPORT_SMC_ULTRA 145253616Ssjg case WE_TYPE_SMC8216C: 146253616Ssjg case WE_TYPE_SMC8216T: 147253616Ssjg { 148253616Ssjg uint8_t hwr; 149253616Ssjg 150253616Ssjg typestr = (we_type == WE_TYPE_SMC8216C) ? 151253616Ssjg "SMC8216/SMC8216C" : "SMC8216T"; 152253616Ssjg 153253616Ssjg hwr = inb(WD_BASEREG + WE790_HWR); 154253616Ssjg outb(WD_BASEREG + WE790_HWR, hwr | WE790_HWR_SWH); 155117229Sru switch (inb(WD_BASEREG + WE790_RAR) & WE790_RAR_SZ64) { 156253616Ssjg case WE790_RAR_SZ64: 157253616Ssjg dp8390_memsize = 65536; 158253616Ssjg break; 15954324Smarcel case WE790_RAR_SZ32: 160253616Ssjg dp8390_memsize = 32768; 161253616Ssjg break; 162218130Simp case WE790_RAR_SZ16: 163218130Simp dp8390_memsize = 16384; 164233644Sjmallett break; 165218130Simp case WE790_RAR_SZ8: 166218130Simp /* 8216 has 16K shared mem -- 8416 has 8K */ 167239272Sgonzo typestr = (we_type == WE_TYPE_SMC8216C) ? 168218130Simp "SMC8416C/SMC8416BT" : "SMC8416T"; 169233644Sjmallett dp8390_memsize = 8192; 170218130Simp break; 171233644Sjmallett } 172233644Sjmallett outb(WD_BASEREG + WE790_HWR, hwr); 173233644Sjmallett 174218130Simp we_is16bit = 1; 175233644Sjmallett#ifdef SUPPORT_WD80X3 176233644Sjmallett dp8390_is790 = 1; 177218130Simp#endif 178218130Simp break; 179218130Simp } 180218130Simp#endif 181218130Simp default: 182218130Simp /* Not one we recognize. */ 183218130Simp return NULL; 184218130Simp } 185218130Simp 186218130Simp /* 187218130Simp * Make some adjustments to initial values depending on what is 188218130Simp * found in the ICR. 189218130Simp */ 190218130Simp if (we_is16bit && (we_type != WE_TYPE_WD8013EBT) && 191218130Simp (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) == 0) { 192218130Simp we_is16bit = 0; 19317308Speter dp8390_memsize = 8192; 194119519Smarcel } 195119519Smarcel 196119519Smarcel#ifdef WE_DEBUG 197119519Smarcel { 198119519Smarcel int i; 199119519Smarcel 200119579Sru printf("we_params: type = 0x%x, typestr = %s, is16bit = %d, " 201119519Smarcel "memsize = %d\n", we_type, typestr, we_is16bit, dp8390_memsize); 202119519Smarcel for (i = 0; i < 8; i++) 203119519Smarcel printf(" %d -> 0x%x\n", i, 204119519Smarcel inb(WD_BASEREG + i)); 205119519Smarcel } 206126031Sgad#endif 207126024Sgad 208126024Sgad return typestr; 209126024Sgad} 210126024Sgad 211126024Sgadint 212126024SgadEtherInit(unsigned char *myadr) 213126024Sgad{ 214227771Sgjb const char *typestr; 215126024Sgad uint8_t x; 216126024Sgad int i; 217227769Sgjb uint8_t laar_proto; 218227771Sgjb uint8_t msr_proto; 219227771Sgjb 220126024Sgad dp8390_iobase = WD_BASEREG + WE_NIC_OFFSET; 221126024Sgad dp8390_membase = WD_BASEMEM; 222126031Sgad 223126024Sgad#ifndef _STANDALONE 224126024Sgad if (mapio()) { 225126024Sgad printf("no IO access\n"); 226172744Sdelphij return 0; 227126024Sgad } 228126024Sgad#endif 229126024Sgad 230133376Sharti for (x = 0, i = 0; i < 8; i++) 231126024Sgad x += inb(WD_BASEREG + WE_PROM + i); 232126024Sgad 233172744Sdelphij if (x != WE_ROM_CHECKSUM_TOTAL) 234126024Sgad return 0; 235126024Sgad 236125885Sgad /* reset the ethernet card */ 237125885Sgad outb(WD_BASEREG + WE_MSR, WE_MSR_RST); 23838666Sjb delay(100); 23917308Speter outb(WD_BASEREG + WE_MSR, inb(WD_BASEREG + WE_MSR) & ~WE_MSR_RST); 240119519Smarcel delay(5000); 241251750Ssjg 242251750Ssjg typestr = we_params(); 243251750Ssjg if (!typestr) 244251750Ssjg return 0; 245254417Ssjg 246251750Ssjg printf("Using %s board, port 0x%x, iomem 0x%x, iosiz %d\n", 247251750Ssjg typestr, WD_BASEREG, WD_BASEMEM, dp8390_memsize); 248119579Sru 249218206Simp /* get ethernet address */ 2502302Spaul for (i = 0; i < 6; i++) 25139206Sjkh eth_myaddr[i] = myadr[i]= inb(WD_BASEREG + WE_PROM + i); 25239206Sjkh 25339206Sjkh /* 254133945Sru * Set upper address bits and 8/16 bit access to shared memory. 255240403Sobrien */ 256177609Sru if (dp8390_is790) { 257177609Sru laar_proto = inb(WD_BASEREG + WE_LAAR) & ~WE_LAAR_M16EN; 258177609Sru outb(WD_BASEREG + WE_LAAR, laar_proto | 259133945Sru (we_is16bit ? WE_LAAR_M16EN : 0)); 260132358Smarkm } else if ((we_type & WE_SOFTCONFIG) || 26117308Speter (we_type == WE_TYPE_WD8013EBT)) { 26254324Smarcel laar_proto = (WD_BASEMEM >> 19) & WE_LAAR_ADDRHI; 26354324Smarcel if (we_is16bit) 264132234Smarcel laar_proto |= WE_LAAR_L16EN; 265132234Smarcel outb(WD_BASEREG + WE_LAAR, laar_proto | 266132234Smarcel (we_is16bit ? WE_LAAR_M16EN : 0)); 267132234Smarcel } 26854324Smarcel 26954324Smarcel /* 27054324Smarcel * Set address and enable interface shared memory. 271118531Sru */ 27254324Smarcel if (dp8390_is790) { 27354324Smarcel /* XXX MAGIC CONSTANTS XXX */ 27454324Smarcel x = inb(WD_BASEREG + 0x04); 27554324Smarcel outb(WD_BASEREG + 0x04, x | 0x80); 27654324Smarcel outb(WD_BASEREG + 0x0b, 27754324Smarcel ((WD_BASEMEM >> 13) & 0x0f) | 278133376Sharti ((WD_BASEMEM >> 11) & 0x40) | 27954324Smarcel (inb(WD_BASEREG + 0x0b) & 0xb0)); 280133376Sharti outb(WD_BASEREG + 0x04, x); 281133376Sharti msr_proto = 0x00; 28254324Smarcel dp8390_cr_proto = 0x00; 28354324Smarcel } else { 28454324Smarcel msr_proto = (WD_BASEMEM >> 13) & WE_MSR_ADDR; 28554324Smarcel dp8390_cr_proto = ED_CR_RD2; 28654324Smarcel } 287133376Sharti 28854324Smarcel outb(WD_BASEREG + WE_MSR, msr_proto | WE_MSR_MENB); 28954324Smarcel delay(2); 29054324Smarcel 291118531Sru /* 292118531Sru * DCR gets: 29354324Smarcel * 294132234Smarcel * FIFO threshold to 8, No auto-init Remote DMA, 295132234Smarcel * byte order=80x86. 296132234Smarcel * 297132234Smarcel * 16-bit cards also get word-wide DMA transfers. 298132234Smarcel */ 299132588Skensmith dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (we_is16bit ? ED_DCR_WTS : 0); 300132358Smarkm 301132234Smarcel if (dp8390_config()) 302132358Smarkm return 0; 303132234Smarcel 304132234Smarcel#ifdef _STANDALONE 305132234Smarcel strncpy(bi_netif.ifname, "we", sizeof(bi_netif.ifname)); 30654324Smarcel bi_netif.bus = BI_BUS_ISA; 30754324Smarcel bi_netif.addr.iobase = WD_BASEREG; 30895730Sru 30995730Sru BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); 31095730Sru#endif 31195730Sru return 1; 31295730Sru} 31395730Sru 31495730Sru/* 31538666Sjb * Stop ethernet board 316107374Sru */ 31717308Spetervoid 318253616SsjgEtherStop(void) { 319253616Ssjg /* stop dp8390, followed by a board reset */ 320253616Ssjg dp8390_stop(); 32155678Smarcel outb(WD_BASEREG + WE_MSR, WE_MSR_RST); 322253616Ssjg outb(WD_BASEREG + WE_MSR, 0); 323253616Ssjg} 324253616Ssjg