15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectETHERBOOT -  BOOTP/TFTP Bootstrap Program
35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectAuthor: Martin Renters
55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  Date: May/94
65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project This code is based heavily on David Greenman's if_ed.c driver
85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project Copyright (C) 1993-1994, David Greenman, Martin Renters.
105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  This software may be used, modified, copied, distributed, and sold, in
115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  both source and binary form provided that the above copyright and these
125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  terms are retained. Under no circumstances are the authors responsible for
135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  the proper functioning of this software, nor do the authors assume any
145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  responsibility for damages incurred with its use.
155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectSMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project3c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98
195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectRX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)
215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "etherboot.h"
255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "nic.h"
265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "ns8390.h"
275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_NS8390
285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "pci.h"
295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "cards.h"
315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned char	eth_vendor, eth_flags, eth_laar;
335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned short	eth_nic_base, eth_asic_base;
345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned char	eth_memsize, eth_rx_start, eth_tx_start;
355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic Address		eth_bmem, eth_rmem;
365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned char	eth_drain_receiver;
375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct wd_board {
405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	const char *name;
415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	char id;
425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	char flags;
435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	char memsize;
445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} wd_boards[] = {
455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"WD8003S",	TYPE_WD8003S,	0,			MEM_8192},
465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"WD8003E",	TYPE_WD8003E,	0,			MEM_8192},
475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"WD8013EBT",	TYPE_WD8013EBT,	FLAG_16BIT,		MEM_16384},
485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"WD8003W",	TYPE_WD8003W,	0,			MEM_8192},
495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"WD8003EB",	TYPE_WD8003EB,	0,			MEM_8192},
505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"WD8013W",	TYPE_WD8013W,	FLAG_16BIT,		MEM_16384},
515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"WD8003EP/WD8013EP",
525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			TYPE_WD8013EP,	0,			MEM_8192},
535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"WD8013WC",	TYPE_WD8013WC,	FLAG_16BIT,		MEM_16384},
545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"WD8013EPC",	TYPE_WD8013EPC,	FLAG_16BIT,		MEM_16384},
555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"SMC8216T",	TYPE_SMC8216T,	FLAG_16BIT | FLAG_790,	MEM_16384},
565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"SMC8216C",	TYPE_SMC8216C,	FLAG_16BIT | FLAG_790,	MEM_16384},
575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"SMC8416T",	TYPE_SMC8416T,	FLAG_16BIT | FLAG_790,	MEM_8192},
585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"SMC8416C/BT",	TYPE_SMC8416C,	FLAG_16BIT | FLAG_790,	MEM_8192},
595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{"SMC8013EBP",	TYPE_SMC8013EBP,FLAG_16BIT,		MEM_16384},
605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{NULL,		0,		0,			0}
615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned char	t503_output;	/* AUI or internal xcvr (Thinnet) */
665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_WD)
695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	eth_probe	wd_probe
705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectError you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_3C503)
765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	eth_probe	t503_probe
775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectError you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NE)
835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	eth_probe	ne_probe
845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectError you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NS8390)
905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	eth_probe	nepci_probe
915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectError you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_3C503)
975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	ASIC_PIO	_3COM_RFMSB
985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	ASIC_PIO	NE_DATA
1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM))
1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectETH_PIO_READ - Read a frame via Programmed I/O
1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; }
1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(D8390_COMMAND_RD2 |
1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(cnt, eth_nic_base + D8390_P0_RBCR0);
1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(src, eth_nic_base + D8390_P0_RSAR0);
1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(src>>8, eth_nic_base + D8390_P0_RSAR1);
1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(D8390_COMMAND_RD0 |
1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(src & 0xff, eth_asic_base + _3COM_DALSB);
1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(src >> 8, eth_asic_base + _3COM_DAMSB);
1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT)
1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		cnt >>= 1;
1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while(cnt--) {
1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			;
1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (eth_flags & FLAG_16BIT) {
1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			*((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			dst += 2;
1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		else
1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			*(dst++) = inb(eth_asic_base + ASIC_PIO);
1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(t503_output, eth_asic_base + _3COM_CR);
1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectETH_PIO_WRITE - Write a frame via Programmed I/O
1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	COMPEX_RL2000_FIX
1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned int x;
1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif	/* COMPEX_RL2000_FIX */
1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; }
1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(D8390_COMMAND_RD2 |
1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR);
1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(cnt, eth_nic_base + D8390_P0_RBCR0);
1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1);
1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(dst, eth_nic_base + D8390_P0_RSAR0);
1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(D8390_COMMAND_RD1 |
1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);
1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT)
1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		cnt >>= 1;
1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while(cnt--)
1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			;
1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (eth_flags & FLAG_16BIT) {
1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			src += 2;
1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		else
1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(*(src++), eth_asic_base + ASIC_PIO);
1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(t503_output, eth_asic_base + _3COM_CR);
1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	COMPEX_RL2000_FIX
1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (x = 0;
1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		x < COMPEX_RL2000_TRIES &&
1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		(inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		!= D8390_ISR_RDC;
2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		++x);
2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (x >= COMPEX_RL2000_TRIES)
2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("Warning: Compex RL2000 aborted wait!\n");
2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif	/* COMPEX_RL2000_FIX */
2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		!= D8390_ISR_RDC);
2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectETH_PIO_READ - Dummy routine when NE2000 not compiled in
2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {}
2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectNS8390_RESET - Reset adapter
2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void ns8390_reset(struct nic *nic)
2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int i;
2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_drain_receiver = 0;
2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790)
2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT)
2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(0x49, eth_nic_base+D8390_P0_DCR);
2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(0x48, eth_nic_base+D8390_P0_DCR);
2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0, eth_nic_base+D8390_P0_RBCR0);
2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0, eth_nic_base+D8390_P0_RBCR1);
2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0x20, eth_nic_base+D8390_P0_RCR);	/* monitor mode */
2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(2, eth_nic_base+D8390_P0_TCR);
2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);
2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790) outb(0, eth_nic_base + 0x09);
2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP);
2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND);
2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0xFF, eth_nic_base+D8390_P0_ISR);
2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0, eth_nic_base+D8390_P0_IMR);
2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790)
2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS1 |
2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS1 |
2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i=0; i<ETH_ALEN; i++)
2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i=0; i<ETH_ALEN; i++)
2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790)
2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 |
2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 |
2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0xFF, eth_nic_base+D8390_P0_ISR);
2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0, eth_nic_base+D8390_P0_TCR);
2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(4, eth_nic_base+D8390_P0_RCR);	/* allow broadcast frames */
2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /*
2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         * No way to tell whether or not we're supposed to use
2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         * the 3Com's transceiver unless the user tells us.
2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         * 'flags' should have some compile time default value
2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         * which can be changed from the command menu.
2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         */
2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(t503_output, eth_asic_base + _3COM_CR);
2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int ns8390_poll(struct nic *nic);
2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef	INCLUDE_3C503
2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectETH_RX_OVERRUN - Bring adapter back to work after an RX overrun
2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void eth_rx_overrun(struct nic *nic)
2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int start_time;
2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790)
2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* wait for at least 1.6ms - we wait one timer tick */
3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	start_time = currticks();
3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while (currticks() - start_time <= 1)
3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Nothing */;
3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0, eth_nic_base+D8390_P0_RBCR0);	/* reset byte counter */
3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0, eth_nic_base+D8390_P0_RBCR1);
3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/*
3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 * Linux driver checks for interrupted TX here. This is not necessary,
3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 * because the transmit routine waits until the frame is sent.
3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 */
3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* enter loopback mode and restart NIC */
3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(2, eth_nic_base+D8390_P0_TCR);
3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
3185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790)
3195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
3205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
3215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
3235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
3245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* clear the RX ring, acknowledge overrun interrupt */
3265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_drain_receiver = 1;
3275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while (ns8390_poll(nic))
3285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Nothing */;
3295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_drain_receiver = 0;
3305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
3315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* leave loopback mode - no packets to be resent (see Linux driver) */
3335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0, eth_nic_base+D8390_P0_TCR);
3345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif	/* INCLUDE_3C503 */
3365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
3385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectNS8390_TRANSMIT - Transmit a frame
3395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
3405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void ns8390_transmit(
3415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct nic *nic,
3425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	const char *d,			/* Destination */
3435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned int t,			/* Type */
3445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned int s,			/* size */
3455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	const char *p)			/* Packet */
3465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
3485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (!(eth_flags & FLAG_PIO)) {
3495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                memcpy((char *)eth_bmem, d, ETH_ALEN);	/* dst */
3505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                memcpy((char *)eth_bmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
3515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                *((char *)eth_bmem+12) = t>>8;		/* type */
3525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                *((char *)eth_bmem+13) = t;
3535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                memcpy((char *)eth_bmem+ETH_HLEN, p, s);
3545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                s += ETH_HLEN;
3555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                while (s < ETH_ZLEN) *((char *)eth_bmem+(s++)) = 0;
3565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
3575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
3605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Memory interface */
3615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT) {
3625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
3635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inb(0x84);
3645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790) {
3665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
3675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inb(0x84);
3685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	inb(0x84);
3705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	memcpy((char *)eth_bmem, d, ETH_ALEN);	/* dst */
3715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	memcpy((char *)eth_bmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
3725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	*((char *)eth_bmem+12) = t>>8;		/* type */
3735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	*((char *)eth_bmem+13) = t;
3745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	memcpy((char *)eth_bmem+ETH_HLEN, p, s);
3755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	s += ETH_HLEN;
3765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while (s < ETH_ZLEN) *((char *)eth_bmem+(s++)) = 0;
3775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790) {
3785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(0, eth_asic_base + WD_MSR);
3795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inb(0x84);
3805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT) {
3825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
3835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inb(0x84);
3845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
3855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_3C503)
3885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_PIO) {
3895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM))
3915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Programmed I/O */
3925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		unsigned short type;
3935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		type = (t >> 8) | (t << 8);
3945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_pio_write(d, eth_tx_start<<8, ETH_ALEN);
3955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
3965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* bcc generates worse code without (const+const) below */
3975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
3985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_pio_write(p, (eth_tx_start<<8)+ETH_HLEN, s);
3995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		s += ETH_HLEN;
4005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (s < ETH_ZLEN) s = ETH_ZLEN;
4015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_3C503)
4035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
4075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790)
4085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 |
4095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
4105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
4115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 |
4135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
4145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR);
4155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(s, eth_nic_base+D8390_P0_TBCR0);
4165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(s>>8, eth_nic_base+D8390_P0_TBCR1);
4175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
4185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790)
4195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 |
4205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
4215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
4225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(D8390_COMMAND_PS0 |
4245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
4255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);
4265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
4275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
4295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectNS8390_POLL - Wait for a frame
4305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
4315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int ns8390_poll(struct nic *nic)
4325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
4335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int ret = 0;
4345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned char rstat, curr, next;
4355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned short len, frag;
4365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned short pktoff;
4375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned char *p;
4385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct ringbuffer pkthdr;
4395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef	INCLUDE_3C503
4415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* avoid infinite recursion: see eth_rx_overrun() */
4425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {
4435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_rx_overrun(nic);
4445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return(0);
4455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif	/* INCLUDE_3C503 */
4475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	rstat = inb(eth_nic_base+D8390_P0_RSR);
4485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (!(rstat & D8390_RSTAT_PRX)) return(0);
4495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	next = inb(eth_nic_base+D8390_P0_BOUND)+1;
4505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (next >= eth_memsize) next = eth_rx_start;
4515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);
4525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	curr = inb(eth_nic_base+D8390_P1_CURR);
4535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);
4545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (curr >= eth_memsize) curr=eth_rx_start;
4555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (curr == next) return(0);
4565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
4575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT) {
4585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
4595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inb(0x84);
4605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790) {
4625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(WD_MSR_MENB, eth_asic_base + WD_MSR);
4635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inb(0x84);
4645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	inb(0x84);
4665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	pktoff = next << 8;
4685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_PIO)
4695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_pio_read(pktoff, (char *)&pkthdr, 4);
4705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
4715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		memcpy(&pkthdr, (char *)eth_rmem + pktoff, 4);
4725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	pktoff += sizeof(pkthdr);
4735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* incoming length includes FCS so must sub 4 */
4745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	len = pkthdr.len - 4;
4755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
4765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		|| len > ETH_FRAME_LEN) {
4775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("Bogus packet, ignoring\n");
4785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return (0);
4795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else {
4815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		p = nic->packet;
4825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		nic->packetlen = len;		/* available to caller */
4835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		frag = (eth_memsize << 8) - pktoff;
4845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (len > frag) {		/* We have a wrap-around */
4855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			/* read first part */
4865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			if (eth_flags & FLAG_PIO)
4875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				eth_pio_read(pktoff, p, frag);
4885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			else
4895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				memcpy(p, (char *)eth_rmem + pktoff, frag);
4905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			pktoff = eth_rx_start << 8;
4915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			p += frag;
4925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			len -= frag;
4935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
4945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* read second part */
4955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (eth_flags & FLAG_PIO)
4965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_pio_read(pktoff, p, len);
4975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		else
4985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			memcpy(p, (char *)eth_rmem + pktoff, len);
4995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		ret = 1;
5005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
5025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790) {
5035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(0, eth_asic_base + WD_MSR);
5045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inb(0x84);
5055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT) {
5075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
5085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inb(0x84);
5095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	inb(0x84);
5115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	next = pkthdr.next;		/* frame number of next packet */
5135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (next == eth_rx_start)
5145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		next = eth_memsize;
5155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(next-1, eth_nic_base+D8390_P0_BOUND);
5165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return(ret);
5175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
5205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectNS8390_DISABLE - Turn off adapter
5215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
5225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void ns8390_disable(struct nic *nic)
5235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
5255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
5275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectETH_PROBE - Look for an adapter
5285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project**************************************************************************/
5295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_NS8390
5305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs,
5315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		      struct pci_device *pci)
5325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
5335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
5345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int i;
5375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct wd_board *brd;
5385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned short chksum;
5395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned char c;
5405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_vendor = VENDOR_NONE;
5415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_drain_receiver = 0;
5425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_WD
5445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/******************************************************************
5455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	Search for WD/SMC cards
5465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	******************************************************************/
5475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
5485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_asic_base += 0x20) {
5495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		chksum = 0;
5505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		for (i=8; i<16; i++)
5515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			chksum += inb(eth_asic_base+i);
5525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Extra checks to avoid soundcard */
5535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if ((chksum & 0xFF) == 0xFF &&
5545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			inb(eth_asic_base+8) != 0xFF &&
5555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			inb(eth_asic_base+9) != 0xFF)
5565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			break;
5575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_asic_base > WD_HIGH_BASE)
5595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return (0);
5605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* We've found a board */
5615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_vendor = VENDOR_WD;
5625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_nic_base = eth_asic_base + WD_NIC_ADDR;
5635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	c = inb(eth_asic_base+WD_BID);	/* Get board id */
5645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (brd = wd_boards; brd->name; brd++)
5655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (brd->id == c) break;
5665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (!brd->name) {
5675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("Unknown WD/SMC NIC type %hhX\n", c);
5685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return (0);	/* Unknown type */
5695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_flags = brd->flags;
5715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_memsize = brd->memsize;
5725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_tx_start = 0;
5735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	eth_rx_start = D8390_TXBUF_SIZE;
5745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if ((c == TYPE_WD8013EP) &&
5755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		(inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
5765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_flags = FLAG_16BIT;
5775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_memsize = MEM_16384;
5785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
5805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_bmem = (0x80000 |
5815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		 ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
5825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	} else
5835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_bmem = WD_DEFAULT_MEM;
5845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
5855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		*((unsigned int *)(eth_bmem + 8192)) = (unsigned int)0;
5865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (*((unsigned int *)(eth_bmem + 8192))) {
5875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			brd += 2;
5885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_memsize = brd->memsize;
5895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
5905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outb(0x80, eth_asic_base + WD_MSR);	/* Reset */
5925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i=0; i<ETH_ALEN; i++) {
5935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
5945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	printf("\n%s base %#hx, memory %#hx, addr %!\n",
5965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		brd->name, eth_asic_base, eth_bmem, nic->node_addr);
5975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_790) {
5985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
5995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb((inb(eth_asic_base+0x04) |
6005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			0x80), eth_asic_base+0x04);
6015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb((((unsigned)eth_bmem >> 13) & 0x0F) |
6025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			(((unsigned)eth_bmem >> 11) & 0x40) |
6035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			(inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
6045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb((inb(eth_asic_base+0x04) &
6055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			~0x80), eth_asic_base+0x04);
6065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	} else {
6075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb((((unsigned)eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
6085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
6095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_flags & FLAG_16BIT) {
6105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (eth_flags & FLAG_790) {
6115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_laar = inb(eth_asic_base + WD_LAAR);
6125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
6135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		} else {
6145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb((eth_laar =
6155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				WD_LAAR_L16EN | 1), eth_asic_base + WD_LAAR);
6165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
6175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	The previous line used to be
6185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
6195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	jluke@deakin.edu.au reported that removing WD_LAAR_M16EN made
6205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	it work for WD8013s.  This seems to work for my 8013 boards. I
6215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	don't know what is really happening.  I wish I had data sheets
6225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	or more time to decode the Linux driver. - Ken
6235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project*/
6245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
6255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inb(0x84);
6265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
6275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
6285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_3C503
6295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /******************************************************************
6305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        Search for 3Com 3c503 if no WD/SMC cards
6315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        ******************************************************************/
6325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_vendor == VENDOR_NONE) {
6335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		int	idx;
6345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		int	iobase_reg, membase_reg;
6355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		static unsigned short	base[] = {
6365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			0x300, 0x310, 0x330, 0x350,
6375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			0x250, 0x280, 0x2A0, 0x2E0, 0 };
6385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Loop through possible addresses checking each one */
6405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
6425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
6445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
6455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Note that we use the same settings for both 8 and 16 bit cards:
6465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * both have an 8K bank of memory at page 1 while only the 16 bit
6475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * cards have a bank at page 0.
6485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
6495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_memsize = MEM_16384;
6505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_tx_start = 32;
6515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_rx_start = 32 + D8390_TXBUF_SIZE;
6525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Check our base address. iobase and membase should */
6545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* both have a maximum of 1 bit set or be 0. */
6555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			iobase_reg = inb(eth_asic_base + _3COM_BCFR);
6575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			membase_reg = inb(eth_asic_base + _3COM_PCFR);
6585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			if ((iobase_reg & (iobase_reg - 1)) ||
6605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				(membase_reg & (membase_reg - 1)))
6615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				continue;		/* nope */
6625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Now get the shared memory address */
6645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_flags = 0;
6665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			switch (membase_reg) {
6685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				case _3COM_PCFR_DC000:
6695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					eth_bmem = 0xdc000;
6705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					break;
6715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				case _3COM_PCFR_D8000:
6725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					eth_bmem = 0xd8000;
6735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					break;
6745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				case _3COM_PCFR_CC000:
6755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					eth_bmem = 0xcc000;
6765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					break;
6775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				case _3COM_PCFR_C8000:
6785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					eth_bmem = 0xc8000;
6795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					break;
6805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				case _3COM_PCFR_PIO:
6815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					eth_flags |= FLAG_PIO;
6825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					eth_bmem = 0;
6835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					break;
6845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				default:
6855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					continue;	/* nope */
6865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				}
6875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			break;
6885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
6895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (base[idx] == 0)		/* not found */
6915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			return (0);
6925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef	T503_SHMEM
6935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_flags |= FLAG_PIO;		/* force PIO mode */
6945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_bmem = 0;
6955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
6965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_vendor = VENDOR_3COM;
6975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
6995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* Need this to make ns8390_poll() happy. */
7005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                eth_rmem = eth_bmem - 0x2000;
7025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* Reset NIC and ASIC */
7045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(_3COM_CR_RST | _3COM_CR_XSEL, eth_asic_base + _3COM_CR );
7065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR );
7075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /* Get our ethernet address */
7095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
7115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("\n3Com 3c503 base %#hx, ", eth_nic_base);
7125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                if (eth_flags & FLAG_PIO)
7135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			printf("PIO mode");
7145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                else
7155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			printf("memory %#hx", eth_bmem);
7165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                for (i=0; i<ETH_ALEN; i++) {
7175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                        nic->node_addr[i] = inb(eth_nic_base+i);
7185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                }
7195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf(", %s, addr %!\n", nic->flags ? "AUI" : "internal xcvr",
7205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			nic->node_addr);
7215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
7225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /*
7235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         * Initialize GA configuration register. Set bank and enable shared
7245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         * mem. We always use bank 1. Disable interrupts.
7255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         */
7265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(_3COM_GACFR_RSEL |
7275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			_3COM_GACFR_MBS0 | _3COM_GACFR_TCM | _3COM_GACFR_NIM, eth_asic_base + _3COM_GACFR);
7285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(0xff, eth_asic_base + _3COM_VPTR2);
7305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(0xff, eth_asic_base + _3COM_VPTR1);
7315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(0x00, eth_asic_base + _3COM_VPTR0);
7325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /*
7335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         * Clear memory and verify that it worked (we use only 8K)
7345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         */
7355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (!(eth_flags & FLAG_PIO)) {
7375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			memset((char *)eth_bmem, 0, 0x2000);
7385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			for(i = 0; i < 0x2000; ++i)
7395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				if (*(((char *)eth_bmem)+i)) {
7405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					printf ("Failed to clear 3c503 shared mem.\n");
7415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project					return (0);
7425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				}
7435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
7445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        /*
7455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         * Initialize GA page/start/stop registers.
7465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project         */
7475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
7485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outb(eth_memsize, eth_asic_base + _3COM_PSPR);
7495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        }
7505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
7515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
7525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/******************************************************************
7535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	Search for NE1000/2000 if no WD/SMC or 3com cards
7545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	******************************************************************/
7555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_vendor == VENDOR_NONE) {
7565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		char romdata[16], testbuf[32];
7575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		int idx;
7585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		static char test[] = "NE*000 memory";
7595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		static unsigned short base[] = {
7605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	NE_SCAN
7615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			NE_SCAN,
7625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
7635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			0 };
7645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* if no addresses supplied, fall back on defaults */
7655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (probe_addrs == 0 || probe_addrs[0] == 0)
7665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			probe_addrs = base;
7675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_bmem = 0;		/* No shared memory */
7685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
7695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_flags = FLAG_PIO;
7705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
7715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_memsize = MEM_16384;
7725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_tx_start = 32;
7735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_rx_start = 32 + D8390_TXBUF_SIZE;
7745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			c = inb(eth_asic_base + NE_RESET);
7755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(c, eth_asic_base + NE_RESET);
7765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			inb(0x84);
7775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(D8390_COMMAND_STP |
7785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				D8390_COMMAND_RD2, eth_nic_base + D8390_P0_COMMAND);
7795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(D8390_RCR_MON, eth_nic_base + D8390_P0_RCR);
7805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
7815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
7825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
7835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	NS8390_FORCE_16BIT
7845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_flags |= FLAG_16BIT;	/* force 16-bit mode */
7855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
7865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
7875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_pio_write(test, 8192, sizeof(test));
7885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_pio_read(8192, testbuf, sizeof(test));
7895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			if (!memcmp(test, testbuf, sizeof(test)))
7905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				break;
7915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_flags |= FLAG_16BIT;
7925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_memsize = MEM_32768;
7935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_tx_start = 64;
7945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_rx_start = 64 + D8390_TXBUF_SIZE;
7955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(D8390_DCR_WTS |
7965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
7975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(MEM_16384, eth_nic_base + D8390_P0_PSTART);
7985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			outb(MEM_32768, eth_nic_base + D8390_P0_PSTOP);
7995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_pio_write(test, 16384, sizeof(test));
8005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_pio_read(16384, testbuf, sizeof(test));
8015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			if (!memcmp(testbuf, test, sizeof(test)))
8025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				break;
8035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
8045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (eth_nic_base == 0)
8055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			return (0);
8065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (eth_nic_base > ISA_MAX_ADDR)	/* PCI probably */
8075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			eth_flags |= FLAG_16BIT;
8085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_vendor = VENDOR_NOVELL;
8095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_pio_read(0, romdata, sizeof(romdata));
8105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		for (i=0; i<ETH_ALEN; i++) {
8115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
8125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
8135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("\nNE%c000 base %#hx, addr %!\n",
8145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			(eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
8155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			nic->node_addr);
8165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
8175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
8185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (eth_vendor == VENDOR_NONE)
8195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return(0);
8205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (eth_vendor != VENDOR_3COM)
8215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		eth_rmem = eth_bmem;
8225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	ns8390_reset(nic);
8235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	nic->reset = ns8390_reset;
8245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	nic->poll = ns8390_poll;
8255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	nic->transmit = ns8390_transmit;
8265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	nic->disable = ns8390_disable;
8275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return(nic);
8285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
8295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
8305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
8315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Local variables:
8325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  c-basic-offset: 8
8335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * End:
8345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
8355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
836