15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectEtherboot -  BOOTP/TFTP Bootstrap Program
35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectLANCE NIC driver for Etherboot
45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectLarge portions borrowed from the Linux LANCE driver by Donald Becker
55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectKen Yap, July 1997
65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project***************************************************************************/
75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * This program is free software; you can redistribute it and/or
105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * modify it under the terms of the GNU General Public License as
115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * published by the Free Software Foundation; either version 2, or (at
125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * your option) any later version.
135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* to get some global routines like printf */
165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "etherboot.h"
175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* to get the interface to the body of the program */
185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "nic.h"
195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_LANCE
205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "pci.h"
215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "cards.h"
235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Offsets from base I/O address */
255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	defined(INCLUDE_NE2100) || defined(INCLUDE_LANCE)
265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_ETH_ADDR	0x0
275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_DATA	0x10
285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_ADDR	0x12
295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_RESET	0x14
305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_BUS_IF	0x16
315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_TOTAL_SIZE	0x18
325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_NI6510
345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_ETH_ADDR	0x8
355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_DATA	0x0
365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_ADDR	0x2
375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_RESET	0x4
385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_BUS_IF	0x6
395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_TOTAL_SIZE	0x10
405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* lance_poll() now can use multiple Rx buffers to prevent packet loss. Set
435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Set LANCE_LOG_RX_BUFFERS to 0..7 for 1, 2, 4, 8, 16, 32, 64 or 128 Rx
445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * buffers. Usually 4 (=16 Rx buffers) is a good value. (Andreas Neuhaus)
455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Decreased to 2 (=4 Rx buffers) (Ken Yap, 20010305) */
465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define LANCE_LOG_RX_BUFFERS	2		/* Use 2^2=4 Rx buffers */
485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define RX_RING_SIZE		(1 << (LANCE_LOG_RX_BUFFERS))
505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define RX_RING_MOD_MASK	(RX_RING_SIZE - 1)
515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define RX_RING_LEN_BITS	((LANCE_LOG_RX_BUFFERS) << 29)
525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct lance_init_block
545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned short	mode;
565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned char	phys_addr[ETH_ALEN];
575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned long	filter[2];
585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	Address		rx_ring;
595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	Address		tx_ring;
605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct lance_rx_head
635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	union {
655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		Address		base;
665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		unsigned char	addr[4];
675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	} u;
685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	short		buf_length;	/* 2s complement */
695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	short		msg_length;
705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct lance_tx_head
735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	union {
755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		Address		base;
765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		unsigned char	addr[4];
775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	} u;
785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	short		buf_length;	/* 2s complement */
795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	short		misc;
805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct lance_interface
835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct lance_init_block	init_block;
855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct lance_rx_head	rx_ring[RX_RING_SIZE];
865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct lance_tx_head	tx_ring;
875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned char		rbuf[RX_RING_SIZE][ETH_FRAME_LEN+4];
885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned char		tbuf[ETH_FRAME_LEN];
895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/*
905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 * Do not alter the order of the struct members above;
915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 * the hardware depends on the correct alignment.
925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 */
935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int			rx_idx;
945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_MUST_PAD		0x00000001
975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_ENABLE_AUTOSELECT	0x00000002
985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_SELECT_PHONELINE	0x00000004
995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	LANCE_MUST_UNRESET	0x00000008
1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* A mapping from the chip ID number to the part number and features.
1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   These are from the datasheets -- in real life the '970 version
1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project   reportedly has the same ID as the '965. */
1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic const struct lance_chip_type
1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int	id_number;
1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	const char	*name;
1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int	flags;
1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project} chip_table[] = {
1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{0x0000, "LANCE 7990",			/* Ancient lance chip.  */
1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		LANCE_MUST_PAD + LANCE_MUST_UNRESET},
1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{0x0003, "PCnet/ISA 79C960",		/* 79C960 PCnet/ISA.  */
1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		LANCE_ENABLE_AUTOSELECT},
1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{0x2260, "PCnet/ISA+ 79C961",		/* 79C961 PCnet/ISA+, Plug-n-Play.  */
1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		LANCE_ENABLE_AUTOSELECT},
1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{0x2420, "PCnet/PCI 79C970",		/* 79C970 or 79C974 PCnet-SCSI, PCI. */
1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		LANCE_ENABLE_AUTOSELECT},
1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so just call
1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		it the PCnet32. */
1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{0x2430, "PCnet32",			/* 79C965 PCnet for VL bus. */
1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		LANCE_ENABLE_AUTOSELECT},
1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        {0x2621, "PCnet/PCI-II 79C970A",        /* 79C970A PCInetPCI II. */
1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                LANCE_ENABLE_AUTOSELECT},
1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{0x2625, "PCnet-FAST III 79C973",	/* 79C973 PCInet-FAST III. */
1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		LANCE_ENABLE_AUTOSELECT},
1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        {0x2626, "PCnet/HomePNA 79C978",
1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE},
1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{0x0, "PCnet (unknown)",
1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		LANCE_ENABLE_AUTOSELECT},
1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project};
1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* Define a macro for converting program addresses to real addresses */
1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#undef	virt_to_bus
1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define	virt_to_bus(x)		((unsigned long)x)
1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int			chip_version;
1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int			lance_version;
1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic unsigned short		ioaddr;
1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef	INCLUDE_LANCE
1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int			dma;
1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic struct lance_interface	*lp;
1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* additional 8 bytes for 8-byte alignment space */
1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	USE_LOWMEM_BUFFER
1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define lance ((char *)0x10000 - (sizeof(struct lance_interface)+8))
1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic char			lance[sizeof(struct lance_interface)+8];
1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef	INCLUDE_LANCE
1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* DMA defines and helper routines */
1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* DMA controller registers */
1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_CMD_REG		0x08	/* command register (w) */
1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_STAT_REG		0x08	/* status register (r) */
1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_REQ_REG            0x09    /* request register (w) */
1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_MASK_REG		0x0A	/* single-channel mask (w) */
1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_MODE_REG		0x0B	/* mode register (w) */
1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_CLEAR_FF_REG	0x0C	/* clear pointer flip-flop (w) */
1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_TEMP_REG           0x0D    /* Temporary Register (r) */
1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_RESET_REG		0x0D	/* Master Clear (w) */
1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_CLR_MASK_REG       0x0E    /* Clear Mask */
1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA1_MASK_ALL_REG       0x0F    /* all-channels mask (w) */
1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_CMD_REG		0xD0	/* command register (w) */
1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_STAT_REG		0xD0	/* status register (r) */
1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_REQ_REG            0xD2    /* request register (w) */
1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_MASK_REG		0xD4	/* single-channel mask (w) */
1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_MODE_REG		0xD6	/* mode register (w) */
1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_CLEAR_FF_REG	0xD8	/* clear pointer flip-flop (w) */
1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_TEMP_REG           0xDA    /* Temporary Register (r) */
1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_RESET_REG		0xDA	/* Master Clear (w) */
1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_CLR_MASK_REG       0xDC    /* Clear Mask */
1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA2_MASK_ALL_REG       0xDE    /* all-channels mask (w) */
1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA_MODE_READ	0x44	/* I/O to memory, no autoinit, increment, single mode */
1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA_MODE_WRITE	0x48	/* memory to I/O, no autoinit, increment, single mode */
1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define DMA_MODE_CASCADE 0xC0   /* pass thru DREQ->HRQ, DACK<-HLDA only */
1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* enable/disable a specific DMA channel */
1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void enable_dma(unsigned int dmanr)
1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (dmanr <= 3)
1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb_p(dmanr, DMA1_MASK_REG);
1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb_p(dmanr & 3, DMA2_MASK_REG);
1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void disable_dma(unsigned int dmanr)
1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (dmanr <= 3)
1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb_p(dmanr | 4, DMA1_MASK_REG);
1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb_p((dmanr & 3) | 4, DMA2_MASK_REG);
1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* set mode (above) for a specific DMA channel */
2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void set_dma_mode(unsigned int dmanr, char mode)
2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (dmanr <= 3)
2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb_p(mode | dmanr, DMA1_MODE_REG);
2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outb_p(mode | (dmanr&3), DMA2_MODE_REG);
2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif	/* !INCLUDE_LANCE */
2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectRESET - Reset adapter
2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project***************************************************************************/
2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void lance_reset(struct nic *nic)
2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int		i;
2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	Address		l;
2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Reset the LANCE */
2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_RESET);
2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Un-Reset the LANCE, needed only for the NE2100 */
2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (chip_table[lance_version].flags & LANCE_MUST_UNRESET)
2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outw(0, ioaddr+LANCE_RESET);
2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (chip_table[lance_version].flags & LANCE_ENABLE_AUTOSELECT)
2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* This is 79C960 specific; Turn on auto-select of media
2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		   (AUI, BNC). */
2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outw(0x2, ioaddr+LANCE_ADDR);
2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Don't touch 10base2 power bit. */
2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outw(inw(ioaddr+LANCE_BUS_IF) | 0x2, ioaddr+LANCE_BUS_IF);
2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* HomePNA cards need to explicitly pick the phoneline interface.
2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 * Some of these cards have ethernet interfaces as well, this
2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 * code might require some modification for those.
2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  	 */
2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project        if (chip_table[lance_version].flags & LANCE_SELECT_PHONELINE) {
2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                short media, check ;
2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                /* this is specific to HomePNA cards... */
2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outw(49, ioaddr+0x12) ;
2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                media = inw(ioaddr+0x16) ;
2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG
2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("media was %d\n", media) ;
2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                media &= ~3 ;
2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                media |= 1 ;
2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG
2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("media changed to %d\n", media) ;
2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                media &= ~3 ;
2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                media |= 1 ;
2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outw(49, ioaddr+0x12) ;
2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outw(media, ioaddr+0x16) ;
2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                outw(49, ioaddr+0x12) ;
2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                check = inw(ioaddr+0x16) ;
2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef DEBUG
2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project                printf("check %s, media was set properly\n",
2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			check ==  media ? "passed" : "FAILED" ) ;
2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Re-initialise the LANCE, and start it when done. */
2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Set station address */
2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i = 0; i < ETH_ALEN; ++i)
2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		lp->init_block.phys_addr[i] = nic->node_addr[i];
2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Preset the receive ring headers */
2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i=0; i<RX_RING_SIZE; i++) {
2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		lp->rx_ring[i].buf_length = -ETH_FRAME_LEN-4;
2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* OWN */
2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff;
2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* we set the top byte as the very last thing */
2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		lp->rx_ring[i].u.addr[3] = 0x80;
2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->rx_idx = 0;
2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->init_block.mode = 0x0;	/* enable Rx and Tx */
2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	l = (Address)virt_to_bus(&lp->init_block);
2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x1, ioaddr+LANCE_ADDR);
2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw((short)l, ioaddr+LANCE_DATA);
2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x2, ioaddr+LANCE_ADDR);
2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw((short)(l >> 16), ioaddr+LANCE_DATA);
2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x4, ioaddr+LANCE_ADDR);
2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x915, ioaddr+LANCE_DATA);
2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x0, ioaddr+LANCE_ADDR);
2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x4, ioaddr+LANCE_DATA);		/* stop */
2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x1, ioaddr+LANCE_DATA);		/* init */
2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i = 10000; i > 0; --i)
2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (inw(ioaddr+LANCE_DATA) & 0x100)
2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			break;
2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	DEBUG
2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (i <= 0)
2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("Init timed out\n");
2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Apparently clearing the InitDone bit here triggers a bug
2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   in the '974. (Mark Stockton) */
2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x2, ioaddr+LANCE_DATA);		/* start */
2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectPOLL - Wait for a frame
3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project***************************************************************************/
3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int lance_poll(struct nic *nic)
3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int		status;
3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	status = lp->rx_ring[lp->rx_idx].u.base >> 24;
3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (status & 0x80)
3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return (0);
3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	DEBUG
3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	printf("LANCE packet received rx_ring.u.base %X mcnt %hX csr0 %hX\n",
3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		lp->rx_ring[lp->rx_idx].u.base, lp->rx_ring[lp->rx_idx].msg_length,
3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inw(ioaddr+LANCE_DATA));
3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (status == 0x3)
3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		memcpy(nic->packet, lp->rbuf[lp->rx_idx], nic->packetlen = lp->rx_ring[lp->rx_idx].msg_length);
3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Andrew Boyd of QNX reports that some revs of the 79C765
3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	   clear the buffer length */
3185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->rx_ring[lp->rx_idx].buf_length = -ETH_FRAME_LEN-4;
3195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->rx_ring[lp->rx_idx].u.addr[3] |= 0x80;	/* prime for next receive */
3205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* I'm not sure if the following is still ok with multiple Rx buffers, but it works */
3225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x0, ioaddr+LANCE_ADDR);
3235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
3245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x500, ioaddr+LANCE_DATA);		/* clear receive + InitDone */
3255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Switch to the next Rx ring buffer */
3275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->rx_idx = (lp->rx_idx + 1) & RX_RING_MOD_MASK;
3285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return (status == 0x3);
3305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
3335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectTRANSMIT - Transmit a frame
3345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project***************************************************************************/
3355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void lance_transmit(
3365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	struct nic *nic,
3375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	const char *d,			/* Destination */
3385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned int t,			/* Type */
3395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned int s,			/* size */
3405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	const char *p)			/* Packet */
3415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned long		time;
3435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* copy the packet to ring buffer */
3455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	memcpy(lp->tbuf, d, ETH_ALEN);	/* dst */
3465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	memcpy(&lp->tbuf[ETH_ALEN], nic->node_addr, ETH_ALEN); /* src */
3475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->tbuf[ETH_ALEN+ETH_ALEN] = t >> 8;	/* type */
3485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->tbuf[ETH_ALEN+ETH_ALEN+1] = t;	/* type */
3495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	memcpy(&lp->tbuf[ETH_HLEN], p, s);
3505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	s += ETH_HLEN;
3515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (chip_table[chip_version].flags & LANCE_MUST_PAD)
3525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		while (s < ETH_ZLEN)	/* pad to min length */
3535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			lp->tbuf[s++] = 0;
3545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->tx_ring.buf_length = -s;
3555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->tx_ring.misc = 0x0;
3565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* OWN, STP, ENP */
3575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->tx_ring.u.base = virt_to_bus(lp->tbuf) & 0xffffff;
3585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* we set the top byte as the very last thing */
3595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->tx_ring.u.addr[3] = 0x83;
3605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Trigger an immediate send poll */
3615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x0, ioaddr+LANCE_ADDR);
3625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);	/* as in the datasheets... */
3635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Klaus Espenlaub: the value below was 0x48, but that enabled the
3645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 * interrupt line, causing a hang if for some reasone the interrupt
3655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 * controller had the LANCE interrupt enabled.  I have no idea why
3665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 * nobody ran into this before...  */
3675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x08, ioaddr+LANCE_DATA);
3685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* wait for transmit complete */
3695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	time = currticks() + TICKS_PER_SEC;		/* wait one second */
3705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	while (currticks() < time && (lp->tx_ring.u.base & 0x80000000) != 0)
3715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		;
3725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if ((lp->tx_ring.u.base & 0x80000000) != 0)
3735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		printf("LANCE timed out on transmit\n");
3745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
3755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x200, ioaddr+LANCE_DATA);		/* clear transmit + InitDone */
3765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	DEBUG
3775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	printf("tx_ring.u.base %X tx_ring.buf_length %hX tx_ring.misc %hX csr0 %hX\n",
3785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		lp->tx_ring.u.base, lp->tx_ring.buf_length, lp->tx_ring.misc,
3795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		inw(ioaddr+LANCE_DATA));
3805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic void lance_disable(struct nic *nic)
3845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_RESET);
3865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (chip_table[lance_version].flags & LANCE_MUST_UNRESET)
3875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outw(0, ioaddr+LANCE_RESET);
3885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0, ioaddr+LANCE_ADDR);
3905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x0004, ioaddr+LANCE_DATA);	/* stop the LANCE */
3915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef	INCLUDE_LANCE
3935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	disable_dma(dma);
3945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_LANCE
3985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int lance_probe1(struct nic *nic, struct pci_device *pci)
3995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
4005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int lance_probe1(struct nic *nic)
4015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
4035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	int			reset_val ;
4045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned int		i;
4055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	Address			l;
4065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	short			dma_channels;
4075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef	INCLUDE_LANCE
4085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	static const char	dmas[] = { 5, 6, 7, 3 };
4095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	reset_val = inw(ioaddr+LANCE_RESET);
4125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(reset_val, ioaddr+LANCE_RESET);
4135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if	1  /* Klaus Espenlaub -- was #ifdef	INCLUDE_NE2100*/
4145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x0, ioaddr+LANCE_ADDR);	/* Switch to window 0 */
4155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (inw(ioaddr+LANCE_DATA) != 0x4)
4165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return (-1);
4175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(88, ioaddr+LANCE_ADDR);	/* Get the version of the chip */
4195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (inw(ioaddr+LANCE_ADDR) != 88)
4205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		lance_version = 0;
4215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	else
4225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
4235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		chip_version = inw(ioaddr+LANCE_DATA);
4245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outw(89, ioaddr+LANCE_ADDR);
4255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		chip_version |= inw(ioaddr+LANCE_DATA) << 16;
4265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if ((chip_version & 0xfff) != 0x3)
4275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			return (-1);
4285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		chip_version = (chip_version >> 12) & 0xffff;
4295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		for (lance_version = 1; chip_table[lance_version].id_number != 0; ++lance_version)
4305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			if (chip_table[lance_version].id_number == chip_version)
4315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				break;
4325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* make sure data structure is 8-byte aligned */
4345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	l = ((Address)lance + 7) & ~7;
4355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp = (struct lance_interface *)l;
4365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->init_block.mode = 0x3;	/* disable Rx and Tx */
4375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;
4385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* using multiple Rx buffer and a single Tx buffer */
4395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->init_block.rx_ring = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
4405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	lp->init_block.tx_ring = virt_to_bus(&lp->tx_ring) & 0xffffff;
4415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	l = virt_to_bus(&lp->init_block);
4425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x1, ioaddr+LANCE_ADDR);
4435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
4445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw((unsigned short)l, ioaddr+LANCE_DATA);
4455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x2, ioaddr+LANCE_ADDR);
4465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
4475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw((unsigned short)(l >> 16), ioaddr+LANCE_DATA);
4485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x4, ioaddr+LANCE_ADDR);
4495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
4505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x915, ioaddr+LANCE_DATA);
4515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	outw(0x0, ioaddr+LANCE_ADDR);
4525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	(void)inw(ioaddr+LANCE_ADDR);
4535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* Get station address */
4545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i = 0; i < ETH_ALEN; ++i) {
4555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		nic->node_addr[i] = inb(ioaddr+LANCE_ETH_ADDR+i);
4565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef	INCLUDE_LANCE
4585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* now probe for DMA channel */
4595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0xf) |
4605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		(inb(DMA2_STAT_REG) & 0xf0);
4615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* need to fix when PCI provides DMA info */
4625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (i = 0; i < (sizeof(dmas)/sizeof(dmas[0])); ++i)
4635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
4645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		int		j;
4655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
4665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		dma = dmas[i];
4675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Don't enable a permanently busy DMA channel,
4685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		   or the machine will hang */
4695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (dma_channels & (1 << dma))
4705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			continue;
4715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outw(0x7f04, ioaddr+LANCE_DATA);	/* clear memory error bits */
4725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		set_dma_mode(dma, DMA_MODE_CASCADE);
4735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		enable_dma(dma);
4745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outw(0x1, ioaddr+LANCE_DATA);		/* init */
4755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		for (j = 100; j > 0; --j)
4765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			if (inw(ioaddr+LANCE_DATA) & 0x900)
4775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				break;
4785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (inw(ioaddr+LANCE_DATA) & 0x100)
4795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			break;
4805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		else
4815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			disable_dma(dma);
4825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (i >= (sizeof(dmas)/sizeof(dmas[0])))
4845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		dma = 0;
4855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	printf("\n%s base %#X, DMA %d, addr %!\n",
4865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		chip_table[lance_version].name, ioaddr, dma, nic->node_addr);
4875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
4885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	printf(" %s base %#hX, addr %!\n", chip_table[lance_version].name, ioaddr, nic->node_addr);
4895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
4905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (chip_table[chip_version].flags & LANCE_ENABLE_AUTOSELECT) {
4915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Turn on auto-select of media (10baseT or BNC) so that the
4925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		 * user watch the LEDs. */
4935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outw(0x0002, ioaddr+LANCE_ADDR);
4945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* Don't touch 10base2 power bit. */
4955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF);
4965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
4975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return (lance_version);
4985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
4995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/**************************************************************************
5015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source ProjectPROBE - Look for an adapter, this routine's visible to the outside
5025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project***************************************************************************/
5035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_LANCE
5055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct nic *lancepci_probe(struct nic *nic, unsigned short *probe_addrs, struct pci_device *pci)
5065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_NE2100
5085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct nic *ne2100_probe(struct nic *nic, unsigned short *probe_addrs)
5095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_NI6510
5115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstruct nic *ni6510_probe(struct nic *nic, unsigned short *probe_addrs)
5125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
5145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	unsigned short		*p;
5155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef	INCLUDE_LANCE
5165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	static unsigned short	io_addrs[] = { 0x300, 0x320, 0x340, 0x360, 0 };
5175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* if probe_addrs is 0, then routine can use a hardwired default */
5205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (probe_addrs == 0) {
5215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_LANCE
5225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return 0;
5235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
5245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		probe_addrs = io_addrs;
5255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	for (p = probe_addrs; (ioaddr = *p) != 0; ++p)
5285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
5295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		char	offset15, offset14 = inb(ioaddr + 14);
5305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		unsigned short	pci_cmd;
5315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_NE2100
5335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if ((offset14 == 0x52 || offset14 == 0x57) &&
5345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		 ((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44))
5355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			if (lance_probe1(nic) >= 0)
5365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				break;
5375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_NI6510
5395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if ((offset14 == 0x00 || offset14 == 0x52) &&
5405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		 ((offset15 = inb(ioaddr + 15)) == 0x55 || offset15 == 0x44))
5415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			if (lance_probe1(nic) >= 0)
5425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				break;
5435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef	INCLUDE_LANCE
5455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		adjust_pci_device(pci);
5465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		if (lance_probe1(nic, pci) >= 0)
5475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			break;
5485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
5495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* if board found */
5515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	if (ioaddr != 0)
5525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
5535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		/* point to NIC specific routines */
5545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		lance_reset(nic);
5555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		nic->reset = lance_reset;
5565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		nic->poll = lance_poll;
5575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		nic->transmit = lance_transmit;
5585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		nic->disable = lance_disable;
5595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		return nic;
5605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
5615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
5625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	/* no board found */
5635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	return 0;
5645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
565