324 lines
7.8 KiB
C
324 lines
7.8 KiB
C
|
/* $NetBSD: wd80x3.c,v 1.10 2008/12/14 18:46:33 christos Exp $ */
|
||
|
|
||
|
/*-
|
||
|
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||
|
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||
|
* NASA Ames Research Center.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Device driver for National Semiconductor DS8390/WD83C690 based ethernet
|
||
|
* adapters.
|
||
|
*
|
||
|
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
|
||
|
*
|
||
|
* Copyright (C) 1993, David Greenman. This software may be used, modified,
|
||
|
* copied, distributed, and sold, in both source and binary form provided that
|
||
|
* the above copyright and these terms are retained. Under no circumstances is
|
||
|
* the author responsible for the proper functioning of this software, nor does
|
||
|
* the author assume any responsibility for damages incurred with its use.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Device driver for the Western Digital/SMC 8003 and 8013 series,
|
||
|
* and the SMC Elite Ultra (8216).
|
||
|
*/
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <machine/pio.h>
|
||
|
|
||
|
#include <lib/libsa/stand.h>
|
||
|
#include <libi386.h>
|
||
|
|
||
|
#ifdef _STANDALONE
|
||
|
#include <lib/libkern/libkern.h>
|
||
|
#include <bootinfo.h>
|
||
|
#endif
|
||
|
|
||
|
#include "etherdrv.h"
|
||
|
#include <dev/ic/dp8390reg.h>
|
||
|
#include "dp8390.h"
|
||
|
#include <dev/ic/wereg.h>
|
||
|
|
||
|
#ifndef BASEREG
|
||
|
#define BASEREG 0x240
|
||
|
#define BASEMEM 0xd0000
|
||
|
#endif
|
||
|
|
||
|
#define WD_BASEREG BASEREG
|
||
|
#define WD_BASEMEM BASEMEM
|
||
|
|
||
|
#ifndef _STANDALONE
|
||
|
extern int mapio(void);
|
||
|
#endif
|
||
|
|
||
|
u_char eth_myaddr[6];
|
||
|
|
||
|
static uint8_t we_type;
|
||
|
static int we_is16bit;
|
||
|
|
||
|
#ifdef _STANDALONE
|
||
|
static struct btinfo_netif bi_netif;
|
||
|
#endif
|
||
|
|
||
|
const char *
|
||
|
we_params(void)
|
||
|
{
|
||
|
const char *typestr;
|
||
|
|
||
|
dp8390_memsize = 8192;
|
||
|
|
||
|
we_type = inb(WD_BASEREG + WE_CARD_ID);
|
||
|
switch (we_type) {
|
||
|
#ifdef SUPPORT_WD80X3
|
||
|
case WE_TYPE_WD8003S:
|
||
|
typestr = "WD8003S";
|
||
|
break;
|
||
|
case WE_TYPE_WD8003E:
|
||
|
typestr = "WD8003E";
|
||
|
break;
|
||
|
case WE_TYPE_WD8003EB:
|
||
|
typestr = "WD8003EB";
|
||
|
break;
|
||
|
case WE_TYPE_WD8003W:
|
||
|
typestr = "WD8003W";
|
||
|
break;
|
||
|
case WE_TYPE_WD8013EBT:
|
||
|
typestr = "WD8013EBT";
|
||
|
dp8390_memsize = 16384;
|
||
|
we_is16bit = 1;
|
||
|
break;
|
||
|
case WE_TYPE_WD8013W:
|
||
|
typestr = "WD8013W";
|
||
|
dp8390_memsize = 16384;
|
||
|
we_is16bit = 1;
|
||
|
break;
|
||
|
case WE_TYPE_WD8013EP: /* also WD8003EP */
|
||
|
if (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) {
|
||
|
we_is16bit = 1;
|
||
|
dp8390_memsize = 16384;
|
||
|
typestr = "WD8013EP";
|
||
|
} else
|
||
|
typestr = "WD8003EP";
|
||
|
break;
|
||
|
case WE_TYPE_WD8013WC:
|
||
|
typestr = "WD8013WC";
|
||
|
dp8390_memsize = 16384;
|
||
|
we_is16bit = 1;
|
||
|
break;
|
||
|
case WE_TYPE_WD8013EBP:
|
||
|
typestr = "WD8013EBP";
|
||
|
dp8390_memsize = 16384;
|
||
|
we_is16bit = 1;
|
||
|
break;
|
||
|
case WE_TYPE_WD8013EPC:
|
||
|
typestr = "WD8013EPC";
|
||
|
dp8390_memsize = 16384;
|
||
|
we_is16bit = 1;
|
||
|
break;
|
||
|
#endif
|
||
|
#ifdef SUPPORT_SMC_ULTRA
|
||
|
case WE_TYPE_SMC8216C:
|
||
|
case WE_TYPE_SMC8216T:
|
||
|
{
|
||
|
uint8_t hwr;
|
||
|
|
||
|
typestr = (we_type == WE_TYPE_SMC8216C) ?
|
||
|
"SMC8216/SMC8216C" : "SMC8216T";
|
||
|
|
||
|
hwr = inb(WD_BASEREG + WE790_HWR);
|
||
|
outb(WD_BASEREG + WE790_HWR, hwr | WE790_HWR_SWH);
|
||
|
switch (inb(WD_BASEREG + WE790_RAR) & WE790_RAR_SZ64) {
|
||
|
case WE790_RAR_SZ64:
|
||
|
dp8390_memsize = 65536;
|
||
|
break;
|
||
|
case WE790_RAR_SZ32:
|
||
|
dp8390_memsize = 32768;
|
||
|
break;
|
||
|
case WE790_RAR_SZ16:
|
||
|
dp8390_memsize = 16384;
|
||
|
break;
|
||
|
case WE790_RAR_SZ8:
|
||
|
/* 8216 has 16K shared mem -- 8416 has 8K */
|
||
|
typestr = (we_type == WE_TYPE_SMC8216C) ?
|
||
|
"SMC8416C/SMC8416BT" : "SMC8416T";
|
||
|
dp8390_memsize = 8192;
|
||
|
break;
|
||
|
}
|
||
|
outb(WD_BASEREG + WE790_HWR, hwr);
|
||
|
|
||
|
we_is16bit = 1;
|
||
|
#ifdef SUPPORT_WD80X3
|
||
|
dp8390_is790 = 1;
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
#endif
|
||
|
default:
|
||
|
/* Not one we recognize. */
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Make some adjustments to initial values depending on what is
|
||
|
* found in the ICR.
|
||
|
*/
|
||
|
if (we_is16bit && (we_type != WE_TYPE_WD8013EBT) &&
|
||
|
(inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) == 0) {
|
||
|
we_is16bit = 0;
|
||
|
dp8390_memsize = 8192;
|
||
|
}
|
||
|
|
||
|
#ifdef WE_DEBUG
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
printf("we_params: type = 0x%x, typestr = %s, is16bit = %d, "
|
||
|
"memsize = %d\n", we_type, typestr, we_is16bit, dp8390_memsize);
|
||
|
for (i = 0; i < 8; i++)
|
||
|
printf(" %d -> 0x%x\n", i,
|
||
|
inb(WD_BASEREG + i));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return typestr;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
EtherInit(unsigned char *myadr)
|
||
|
{
|
||
|
const char *typestr;
|
||
|
uint8_t x;
|
||
|
int i;
|
||
|
uint8_t laar_proto;
|
||
|
uint8_t msr_proto;
|
||
|
|
||
|
dp8390_iobase = WD_BASEREG + WE_NIC_OFFSET;
|
||
|
dp8390_membase = WD_BASEMEM;
|
||
|
|
||
|
#ifndef _STANDALONE
|
||
|
if (mapio()) {
|
||
|
printf("no IO access\n");
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
for (x = 0, i = 0; i < 8; i++)
|
||
|
x += inb(WD_BASEREG + WE_PROM + i);
|
||
|
|
||
|
if (x != WE_ROM_CHECKSUM_TOTAL)
|
||
|
return 0;
|
||
|
|
||
|
/* reset the ethernet card */
|
||
|
outb(WD_BASEREG + WE_MSR, WE_MSR_RST);
|
||
|
delay(100);
|
||
|
outb(WD_BASEREG + WE_MSR, inb(WD_BASEREG + WE_MSR) & ~WE_MSR_RST);
|
||
|
delay(5000);
|
||
|
|
||
|
typestr = we_params();
|
||
|
if (!typestr)
|
||
|
return 0;
|
||
|
|
||
|
printf("Using %s board, port 0x%x, iomem 0x%x, iosiz %d\n",
|
||
|
typestr, WD_BASEREG, WD_BASEMEM, dp8390_memsize);
|
||
|
|
||
|
/* get ethernet address */
|
||
|
for (i = 0; i < 6; i++)
|
||
|
eth_myaddr[i] = myadr[i]= inb(WD_BASEREG + WE_PROM + i);
|
||
|
|
||
|
/*
|
||
|
* Set upper address bits and 8/16 bit access to shared memory.
|
||
|
*/
|
||
|
if (dp8390_is790) {
|
||
|
laar_proto = inb(WD_BASEREG + WE_LAAR) & ~WE_LAAR_M16EN;
|
||
|
outb(WD_BASEREG + WE_LAAR, laar_proto |
|
||
|
(we_is16bit ? WE_LAAR_M16EN : 0));
|
||
|
} else if ((we_type & WE_SOFTCONFIG) ||
|
||
|
(we_type == WE_TYPE_WD8013EBT)) {
|
||
|
laar_proto = (WD_BASEMEM >> 19) & WE_LAAR_ADDRHI;
|
||
|
if (we_is16bit)
|
||
|
laar_proto |= WE_LAAR_L16EN;
|
||
|
outb(WD_BASEREG + WE_LAAR, laar_proto |
|
||
|
(we_is16bit ? WE_LAAR_M16EN : 0));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Set address and enable interface shared memory.
|
||
|
*/
|
||
|
if (dp8390_is790) {
|
||
|
/* XXX MAGIC CONSTANTS XXX */
|
||
|
x = inb(WD_BASEREG + 0x04);
|
||
|
outb(WD_BASEREG + 0x04, x | 0x80);
|
||
|
outb(WD_BASEREG + 0x0b,
|
||
|
((WD_BASEMEM >> 13) & 0x0f) |
|
||
|
((WD_BASEMEM >> 11) & 0x40) |
|
||
|
(inb(WD_BASEREG + 0x0b) & 0xb0));
|
||
|
outb(WD_BASEREG + 0x04, x);
|
||
|
msr_proto = 0x00;
|
||
|
dp8390_cr_proto = 0x00;
|
||
|
} else {
|
||
|
msr_proto = (WD_BASEMEM >> 13) & WE_MSR_ADDR;
|
||
|
dp8390_cr_proto = ED_CR_RD2;
|
||
|
}
|
||
|
|
||
|
outb(WD_BASEREG + WE_MSR, msr_proto | WE_MSR_MENB);
|
||
|
delay(2);
|
||
|
|
||
|
/*
|
||
|
* DCR gets:
|
||
|
*
|
||
|
* FIFO threshold to 8, No auto-init Remote DMA,
|
||
|
* byte order=80x86.
|
||
|
*
|
||
|
* 16-bit cards also get word-wide DMA transfers.
|
||
|
*/
|
||
|
dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (we_is16bit ? ED_DCR_WTS : 0);
|
||
|
|
||
|
if (dp8390_config())
|
||
|
return 0;
|
||
|
|
||
|
#ifdef _STANDALONE
|
||
|
strncpy(bi_netif.ifname, "we", sizeof(bi_netif.ifname));
|
||
|
bi_netif.bus = BI_BUS_ISA;
|
||
|
bi_netif.addr.iobase = WD_BASEREG;
|
||
|
|
||
|
BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
|
||
|
#endif
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Stop ethernet board
|
||
|
*/
|
||
|
void
|
||
|
EtherStop(void) {
|
||
|
/* stop dp8390, followed by a board reset */
|
||
|
dp8390_stop();
|
||
|
outb(WD_BASEREG + WE_MSR, WE_MSR_RST);
|
||
|
outb(WD_BASEREG + WE_MSR, 0);
|
||
|
}
|