1N/A/*
1N/A * eepro100.c -- This file implements the eepro100 driver for etherboot.
1N/A *
1N/A *
1N/A * Copyright (C) AW Computer Systems.
1N/A * written by R.E.Wolff -- R.E.Wolff@BitWizard.nl
1N/A *
1N/A *
1N/A * AW Computer Systems is contributing to the free software community
1N/A * by paying for this driver and then putting the result under GPL.
1N/A *
1N/A * If you need a Linux device driver, please contact BitWizard for a
1N/A * quote.
1N/A *
1N/A *
1N/A * This program is free software; you can redistribute it and/or
1N/A * modify it under the terms of the GNU General Public License as
1N/A * published by the Free Software Foundation; either version 2, or (at
1N/A * your option) any later version.
1N/A *
1N/A * This program is distributed in the hope that it will be useful, but
1N/A * WITHOUT ANY WARRANTY; without even the implied warranty of
1N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1N/A * General Public License for more details.
1N/A *
1N/A * You should have received a copy of the GNU General Public License
1N/A * along with this program; if not, write to the Free Software
1N/A * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1N/A *
1N/A *
1N/A * date version by what
1N/A * Written: May 29 1997 V0.10 REW Initial revision.
1N/A * changes: May 31 1997 V0.90 REW Works!
1N/A * Jun 1 1997 V0.91 REW Cleanup
1N/A * Jun 2 1997 V0.92 REW Add some code documentation
1N/A * Jul 25 1997 V1.00 REW Tested by AW to work in a PROM
1N/A * Cleanup for publication
1N/A *
1N/A * This is the etherboot intel etherexpress Pro/100B driver.
1N/A *
1N/A * It was written from scratch, with Donald Beckers eepro100.c kernel
1N/A * driver as a guideline. Mostly the 82557 related definitions and the
1N/A * lower level routines have been cut-and-pasted into this source.
1N/A *
1N/A * The driver was finished before Intel got the NDA out of the closet.
1N/A * I still don't have the docs.
1N/A * */
1N/A
1N/A/* Philosophy of this driver.
1N/A *
1N/A * Probing:
1N/A *
1N/A * Using the pci.c functions of the Etherboot code, the 82557 chip is detected.
1N/A * It is verified that the BIOS initialized everything properly and if
1N/A * something is missing it is done now.
1N/A *
1N/A *
1N/A * Initialization:
1N/A *
1N/A *
1N/A * The chip is then initialized to "know" its ethernet address, and to
1N/A * start recieving packets. The Linux driver has a whole transmit and
1N/A * recieve ring of buffers. This is neat if you need high performance:
1N/A * you can write the buffers asynchronously to the chip reading the
1N/A * buffers and transmitting them over the network. Performance is NOT
1N/A * an issue here. We can boot a 400k kernel in about two
1N/A * seconds. (Theory: 0.4 seconds). Booting a system is going to take
1N/A * about half a minute anyway, so getting 10 times closer to the
1N/A * theoretical limit is going to make a difference of a few percent.
1N/A *
1N/A *
1N/A * Transmitting and recieving.
1N/A *
1N/A * We have only one transmit descriptor. It has two buffer descriptors:
1N/A * one for the header, and the other for the data.
1N/A * We have only one receive buffer. The chip is told to recieve packets,
1N/A * and suspend itself once it got one. The recieve (poll) routine simply
1N/A * looks at the recieve buffer to see if there is already a packet there.
1N/A * if there is, the buffer is copied, and the reciever is restarted.
1N/A *
1N/A * Caveats:
1N/A *
1N/A * The Etherboot framework moves the code to the 48k segment from
1N/A * 0x94000 to 0xa0000. There is just a little room between the end of
1N/A * this driver and the 0xa0000 address. If you compile in too many
1N/A * features, this will overflow.
1N/A * The number under "hex" in the output of size that scrolls by while
1N/A * compiling should be less than 8000. Maybe even the stack is up there,
1N/A * so that you need even more headroom.
1N/A */
1N/A
1N/A/* The etherboot authors seem to dislike the argument ordering in
1N/A * outb macros that Linux uses. I disklike the confusion that this
1N/A * has caused even more.... This file uses the Linux argument ordering. */
1N/A/* Sorry not us. It's inherited code from FreeBSD. [The authors] */
1N/A
1N/A#include "etherboot.h"
1N/A#include "nic.h"
1N/A#include "pci.h"
1N/A#include "timer.h"
1N/A
1N/Astatic int ioaddr;
1N/A
1N/Atypedef unsigned char u8;
1N/Atypedef signed char s8;
1N/Atypedef unsigned short u16;
1N/Atypedef signed short s16;
1N/Atypedef unsigned int u32;
1N/Atypedef signed int s32;
1N/A
1N/Aenum speedo_offsets {
1N/A SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */
1N/A SCBPointer = 4, /* General purpose pointer. */
1N/A SCBPort = 8, /* Misc. commands and operands. */
1N/A SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
1N/A SCBCtrlMDI = 16, /* MDI interface control. */
1N/A SCBEarlyRx = 20, /* Early receive byte count. */
1N/A};
1N/A
1N/Aenum SCBCmdBits {
1N/A SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
1N/A SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
1N/A SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
1N/A /* The rest are Rx and Tx commands. */
1N/A CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
1N/A CUCmdBase=0x0060, /* CU Base address (set to zero) . */
1N/A CUDumpStats=0x0070, /* Dump then reset stats counters. */
1N/A RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
1N/A RxResumeNoResources=0x0007,
1N/A};
1N/A
1N/Astatic int do_eeprom_cmd(int cmd, int cmd_len);
1N/Avoid hd(void *where, int n);
1N/A
1N/A/***********************************************************************/
1N/A/* I82557 related defines */
1N/A/***********************************************************************/
1N/A
1N/A/* Serial EEPROM section.
1N/A A "bit" grungy, but we work our way through bit-by-bit :->. */
1N/A/* EEPROM_Ctrl bits. */
1N/A#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
1N/A#define EE_CS 0x02 /* EEPROM chip select. */
1N/A#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
1N/A#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
1N/A#define EE_WRITE_0 0x4802
1N/A#define EE_WRITE_1 0x4806
1N/A#define EE_ENB (0x4800 | EE_CS)
1N/A
1N/A/* The EEPROM commands include the alway-set leading bit. */
1N/A#define EE_READ_CMD 6
1N/A
1N/A/* The SCB accepts the following controls for the Tx and Rx units: */
1N/A#define CU_START 0x0010
1N/A#define CU_RESUME 0x0020
1N/A#define CU_STATSADDR 0x0040
1N/A#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */
1N/A#define CU_CMD_BASE 0x0060 /* Base address to add to add CU commands. */
1N/A#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */
1N/A
1N/A#define RX_START 0x0001
1N/A#define RX_RESUME 0x0002
1N/A#define RX_ABORT 0x0004
1N/A#define RX_ADDR_LOAD 0x0006
1N/A#define RX_RESUMENR 0x0007
1N/A#define INT_MASK 0x0100
1N/A#define DRVR_INT 0x0200 /* Driver generated interrupt. */
1N/A
1N/Aenum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
1N/A S80C24, PhyUndefined, DP83840A=10, };
1N/A
1N/A/* Commands that can be put in a command list entry. */
1N/Aenum commands {
1N/A CmdNOp = 0,
1N/A CmdIASetup = 1,
1N/A CmdConfigure = 2,
1N/A CmdMulticastList = 3,
1N/A CmdTx = 4,
1N/A CmdTDR = 5,
1N/A CmdDump = 6,
1N/A CmdDiagnose = 7,
1N/A
1N/A /* And some extra flags: */
1N/A CmdSuspend = 0x4000, /* Suspend after completion. */
1N/A CmdIntr = 0x2000, /* Interrupt after completion. */
1N/A CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */
1N/A};
1N/A
1N/A/* How to wait for the command unit to accept a command.
1N/A Typically this takes 0 ticks. */
1N/Astatic inline void wait_for_cmd_done(int cmd_ioaddr)
1N/A{
1N/A int wait = 0;
1N/A int delayed_cmd;
1N/A
1N/A do
1N/A if (inb(cmd_ioaddr) == 0) return;
1N/A while(++wait <= 100);
1N/A delayed_cmd = inb(cmd_ioaddr);
1N/A do
1N/A if (inb(cmd_ioaddr) == 0) break;
1N/A while(++wait <= 10000);
1N/A printf("Command %2.2x was not immediately accepted, %d ticks!\n",
1N/A delayed_cmd, wait);
1N/A}
1N/A
1N/A/* Elements of the dump_statistics block. This block must be lword aligned. */
1N/Astatic struct speedo_stats {
1N/A u32 tx_good_frames;
1N/A u32 tx_coll16_errs;
1N/A u32 tx_late_colls;
1N/A u32 tx_underruns;
1N/A u32 tx_lost_carrier;
1N/A u32 tx_deferred;
1N/A u32 tx_one_colls;
1N/A u32 tx_multi_colls;
1N/A u32 tx_total_colls;
1N/A u32 rx_good_frames;
1N/A u32 rx_crc_errs;
1N/A u32 rx_align_errs;
1N/A u32 rx_resource_errs;
1N/A u32 rx_overrun_errs;
1N/A u32 rx_colls_errs;
1N/A u32 rx_runt_errs;
1N/A u32 done_marker;
1N/A} lstats;
1N/A
1N/A/* A speedo3 TX buffer descriptor with two buffers... */
1N/Astatic struct TxFD {
1N/A volatile s16 status;
1N/A s16 command;
1N/A u32 link; /* void * */
1N/A u32 tx_desc_addr; /* (almost) Always points to the tx_buf_addr element. */
1N/A s32 count; /* # of TBD (=2), Tx start thresh., etc. */
1N/A /* This constitutes two "TBD" entries: hdr and data */
1N/A u32 tx_buf_addr0; /* void *, header of frame to be transmitted. */
1N/A s32 tx_buf_size0; /* Length of Tx hdr. */
1N/A u32 tx_buf_addr1; /* void *, data to be transmitted. */
1N/A s32 tx_buf_size1; /* Length of Tx data. */
1N/A} txfd;
1N/A
1N/Astruct RxFD { /* Receive frame descriptor. */
1N/A volatile s16 status;
1N/A s16 command;
1N/A u32 link; /* struct RxFD * */
1N/A u32 rx_buf_addr; /* void * */
1N/A u16 count;
1N/A u16 size;
1N/A char packet[1518];
1N/A};
1N/A
1N/Astatic struct RxFD rxfd;
1N/A#define ACCESS(x) x.
1N/A
1N/Astatic int congenb = 0; /* Enable congestion control in the DP83840. */
1N/Astatic int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */
1N/Astatic int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */
1N/Astatic int txdmacount = 0; /* Tx DMA burst length, 0-127, default 0. */
1N/Astatic int rxdmacount = 0; /* Rx DMA length, 0 means no preemption. */
1N/A
1N/A/* I don't understand a byte in this structure. It was copied from the
1N/A * Linux kernel initialization for the eepro100. -- REW */
1N/Astatic struct ConfCmd {
1N/A s16 status;
1N/A s16 command;
1N/A u32 link;
1N/A unsigned char data[22];
1N/A} confcmd = {
1N/A 0, 0, 0, /* filled in later */
1N/A {22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */
1N/A 0, 0x2E, 0, 0x60, 0,
1N/A 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */
1N/A 0x3f, 0x05, }
1N/A};
1N/A
1N/A/***********************************************************************/
1N/A/* Locally used functions */
1N/A/***********************************************************************/
1N/A
1N/A/* Support function: mdio_write
1N/A *
1N/A * This probably writes to the "physical media interface chip".
1N/A * -- REW
1N/A */
1N/A
1N/Astatic int mdio_write(int phy_id, int location, int value)
1N/A{
1N/A int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
1N/A
1N/A outl(0x04000000 | (location<<16) | (phy_id<<21) | value,
1N/A ioaddr + SCBCtrlMDI);
1N/A do {
1N/A udelay(16);
1N/A
1N/A val = inl(ioaddr + SCBCtrlMDI);
1N/A if (--boguscnt < 0) {
1N/A printf(" mdio_write() timed out with val = %X.\n", val);
1N/A break;
1N/A }
1N/A } while (! (val & 0x10000000));
1N/A return val & 0xffff;
1N/A}
1N/A
1N/A/* Support function: mdio_read
1N/A *
1N/A * This probably reads a register in the "physical media interface chip".
1N/A * -- REW
1N/A */
1N/Astatic int mdio_read(int phy_id, int location)
1N/A{
1N/A int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
1N/A outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
1N/A do {
1N/A udelay(16);
1N/A
1N/A val = inl(ioaddr + SCBCtrlMDI);
1N/A
1N/A if (--boguscnt < 0) {
1N/A printf( " mdio_read() timed out with val = %X.\n", val);
1N/A break;
1N/A }
1N/A } while (! (val & 0x10000000));
1N/A return val & 0xffff;
1N/A}
1N/A
1N/A/* The fixes for the code were kindly provided by Dragan Stancevic
1N/A <visitor@valinux.com> to strictly follow Intel specifications of EEPROM
1N/A access timing.
1N/A The publicly available sheet 64486302 (sec. 3.1) specifies 1us access
1N/A interval for serial EEPROM. However, it looks like that there is an
1N/A additional requirement dictating larger udelay's in the code below.
1N/A 2000/05/24 SAW */
1N/Astatic int do_eeprom_cmd(int cmd, int cmd_len)
1N/A{
1N/A unsigned retval = 0;
1N/A long ee_addr = ioaddr + SCBeeprom;
1N/A
1N/A outw(EE_ENB, ee_addr); udelay(2);
1N/A outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
1N/A
1N/A /* Shift the command bits out. */
1N/A do {
1N/A short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
1N/A outw(dataval, ee_addr); udelay(2);
1N/A outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
1N/A retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
1N/A } while (--cmd_len >= 0);
1N/A outw(EE_ENB, ee_addr); udelay(2);
1N/A
1N/A /* Terminate the EEPROM access. */
1N/A outw(EE_ENB & ~EE_CS, ee_addr);
1N/A return retval;
1N/A}
1N/A
1N/A#if 0
1N/Astatic inline void whereami (const char *str)
1N/A{
1N/A printf ("%s\n", str);
1N/A sleep (2);
1N/A}
1N/A#else
1N/A#define whereami(s)
1N/A#endif
1N/A
1N/Astatic void eepro100_irq(struct nic *nic __unused, irq_action_t action __unused)
1N/A{
1N/A switch ( action ) {
1N/A case DISABLE :
1N/A break;
1N/A case ENABLE :
1N/A break;
1N/A case FORCE :
1N/A break;
1N/A }
1N/A}
1N/A
1N/A/* function: eepro100_transmit
1N/A * This transmits a packet.
1N/A *
1N/A * Arguments: char d[6]: destination ethernet address.
1N/A * unsigned short t: ethernet protocol type.
1N/A * unsigned short s: size of the data-part of the packet.
1N/A * char *p: the data for the packet.
1N/A * returns: void.
1N/A */
1N/A
1N/Astatic void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
1N/A{
1N/A struct eth_hdr {
1N/A unsigned char dst_addr[ETH_ALEN];
1N/A unsigned char src_addr[ETH_ALEN];
1N/A unsigned short type;
1N/A } hdr;
1N/A unsigned short status;
1N/A int s1, s2;
1N/A
1N/A status = inw(ioaddr + SCBStatus);
1N/A /* Acknowledge all of the current interrupt sources ASAP. */
1N/A outw(status & 0xfc00, ioaddr + SCBStatus);
1N/A
1N/A#ifdef DEBUG
1N/A printf ("transmitting type %hX packet (%d bytes). status = %hX, cmd=%hX\n",
1N/A t, s, status, inw (ioaddr + SCBCmd));
1N/A#endif
1N/A
1N/A memcpy (&hdr.dst_addr, d, ETH_ALEN);
1N/A memcpy (&hdr.src_addr, nic->node_addr, ETH_ALEN);
1N/A
1N/A hdr.type = htons (t);
1N/A
1N/A txfd.status = 0;
1N/A txfd.command = CmdSuspend | CmdTx | CmdTxFlex;
1N/A txfd.link = virt_to_bus (&txfd);
1N/A txfd.count = 0x02208000;
1N/A txfd.tx_desc_addr = virt_to_bus(&txfd.tx_buf_addr0);
1N/A
1N/A txfd.tx_buf_addr0 = virt_to_bus (&hdr);
1N/A txfd.tx_buf_size0 = sizeof (hdr);
1N/A
1N/A txfd.tx_buf_addr1 = virt_to_bus (p);
1N/A txfd.tx_buf_size1 = s;
1N/A
1N/A#ifdef DEBUG
1N/A printf ("txfd: \n");
1N/A hd (&txfd, sizeof (txfd));
1N/A#endif
1N/A
1N/A outl(virt_to_bus(&txfd), ioaddr + SCBPointer);
1N/A outw(INT_MASK | CU_START, ioaddr + SCBCmd);
1N/A wait_for_cmd_done(ioaddr + SCBCmd);
1N/A
1N/A s1 = inw (ioaddr + SCBStatus);
1N/A load_timer2(10*TICKS_PER_MS); /* timeout 10 ms for transmit */
1N/A while (!txfd.status && timer2_running())
1N/A /* Wait */;
1N/A s2 = inw (ioaddr + SCBStatus);
1N/A
1N/A#ifdef DEBUG
1N/A printf ("s1 = %hX, s2 = %hX.\n", s1, s2);
1N/A#endif
1N/A}
1N/A
1N/A/*
1N/A * Sometimes the receiver stops making progress. This routine knows how to
1N/A * get it going again, without losing packets or being otherwise nasty like
1N/A * a chip reset would be. Previously the driver had a whole sequence
1N/A * of if RxSuspended, if it's no buffers do one thing, if it's no resources,
1N/A * do another, etc. But those things don't really matter. Separate logic
1N/A * in the ISR provides for allocating buffers--the other half of operation
1N/A * is just making sure the receiver is active. speedo_rx_soft_reset does that.
1N/A * This problem with the old, more involved algorithm is shown up under
1N/A * ping floods on the order of 60K packets/second on a 100Mbps fdx network.
1N/A */
1N/Astatic void
1N/Aspeedo_rx_soft_reset(void)
1N/A{
1N/A wait_for_cmd_done(ioaddr + SCBCmd);
1N/A /*
1N/A * Put the hardware into a known state.
1N/A */
1N/A outb(RX_ABORT, ioaddr + SCBCmd);
1N/A
1N/A ACCESS(rxfd)rx_buf_addr = 0xffffffff;
1N/A
1N/A wait_for_cmd_done(ioaddr + SCBCmd);
1N/A
1N/A outb(RX_START, ioaddr + SCBCmd);
1N/A}
1N/A
1N/A/* function: eepro100_poll / eth_poll
1N/A * This recieves a packet from the network.
1N/A *
1N/A * Arguments: none
1N/A *
1N/A * returns: 1 if a packet was recieved.
1N/A * 0 if no pacet was recieved.
1N/A * side effects:
1N/A * returns the packet in the array nic->packet.
1N/A * returns the length of the packet in nic->packetlen.
1N/A */
1N/A
1N/Astatic int eepro100_poll(struct nic *nic, int retrieve)
1N/A{
1N/A unsigned int status;
1N/A status = inw(ioaddr + SCBStatus);
1N/A
1N/A if (!ACCESS(rxfd)status)
1N/A return 0;
1N/A
1N/A /* There is a packet ready */
1N/A if ( ! retrieve ) return 1;
1N/A
1N/A /*
1N/A * The chip may have suspended reception for various reasons.
1N/A * Check for that, and re-prime it should this be the case.
1N/A */
1N/A switch ((status >> 2) & 0xf) {
1N/A case 0: /* Idle */
1N/A break;
1N/A case 1: /* Suspended */
1N/A case 2: /* No resources (RxFDs) */
1N/A case 9: /* Suspended with no more RBDs */
1N/A case 10: /* No resources due to no RBDs */
1N/A case 12: /* Ready with no RBDs */
1N/A speedo_rx_soft_reset();
1N/A break;
1N/A case 3: case 5: case 6: case 7: case 8:
1N/A case 11: case 13: case 14: case 15:
1N/A /* these are all reserved values */
1N/A break;
1N/A }
1N/A
1N/A /* Ok. We got a packet. Now restart the reciever.... */
1N/A ACCESS(rxfd)status = 0;
1N/A ACCESS(rxfd)command = 0xc000;
1N/A outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);
1N/A outw(INT_MASK | RX_START, ioaddr + SCBCmd);
1N/A wait_for_cmd_done(ioaddr + SCBCmd);
1N/A
1N/A#ifdef DEBUG
1N/A printf ("Got a packet: Len = %d.\n", ACCESS(rxfd)count & 0x3fff);
1N/A#endif
1N/A nic->packetlen = ACCESS(rxfd)count & 0x3fff;
1N/A memcpy (nic->packet, ACCESS(rxfd)packet, nic->packetlen);
1N/A#ifdef DEBUG
1N/A hd (nic->packet, 0x30);
1N/A#endif
1N/A return 1;
1N/A}
1N/A
1N/A/* function: eepro100_disable
1N/A * resets the card. This is used to allow Etherboot or Linux
1N/A * to probe the card again from a "virginal" state....
1N/A * Arguments: none
1N/A *
1N/A * returns: void.
1N/A */
1N/Astatic void eepro100_disable(struct dev *dev __unused)
1N/A{
1N/A/* from eepro100_reset */
1N/A outl(0, ioaddr + SCBPort);
1N/A/* from eepro100_disable */
1N/A /* See if this PartialReset solves the problem with interfering with
1N/A kernel operation after Etherboot hands over. - Ken 20001102 */
1N/A outl(2, ioaddr + SCBPort);
1N/A
1N/A /* The following is from the Intel e100 driver.
1N/A * This hopefully solves the problem with hanging hard DOS images. */
1N/A
1N/A /* wait for the reset to take effect */
1N/A udelay(20);
1N/A
1N/A /* Mask off our interrupt line -- it is unmasked after reset */
1N/A {
1N/A u16 intr_status;
1N/A /* Disable interrupts on our PCI board by setting the mask bit */
1N/A outw(INT_MASK, ioaddr + SCBCmd);
1N/A intr_status = inw(ioaddr + SCBStatus);
1N/A /* ack and clear intrs */
1N/A outw(intr_status, ioaddr + SCBStatus);
1N/A inw(ioaddr + SCBStatus);
1N/A }
1N/A}
1N/A
1N/A/* exported function: eepro100_probe / eth_probe
1N/A * initializes a card
1N/A *
1N/A * side effects:
1N/A * leaves the ioaddress of the 82557 chip in the variable ioaddr.
1N/A * leaves the 82557 initialized, and ready to recieve packets.
1N/A */
1N/A
1N/Astatic int eepro100_probe(struct dev *dev, struct pci_device *p)
1N/A{
1N/A struct nic *nic = (struct nic *)dev;
1N/A unsigned short sum = 0;
1N/A int i;
1N/A int read_cmd, ee_size;
1N/A int options;
1N/A int rx_mode;
1N/A
1N/A /* we cache only the first few words of the EEPROM data
1N/A be careful not to access beyond this array */
1N/A unsigned short eeprom[16];
1N/A
1N/A if (p->ioaddr == 0)
1N/A return 0;
1N/A ioaddr = p->ioaddr & ~3; /* Mask the bit that says "this is an io addr" */
1N/A nic->ioaddr = ioaddr;
1N/A
1N/A adjust_pci_device(p);
1N/A
1N/A /* Copy IRQ from PCI information */
1N/A /* nic->irqno = pci->irq; */
1N/A nic->irqno = 0;
1N/A
1N/A if ((do_eeprom_cmd(EE_READ_CMD << 24, 27) & 0xffe0000)
1N/A == 0xffe0000) {
1N/A ee_size = 0x100;
1N/A read_cmd = EE_READ_CMD << 24;
1N/A } else {
1N/A ee_size = 0x40;
1N/A read_cmd = EE_READ_CMD << 22;
1N/A }
1N/A
1N/A for (i = 0, sum = 0; i < ee_size; i++) {
1N/A unsigned short value = do_eeprom_cmd(read_cmd | (i << 16), 27);
1N/A if (i < (int)(sizeof(eeprom)/sizeof(eeprom[0])))
1N/A eeprom[i] = value;
1N/A sum += value;
1N/A }
1N/A
1N/A for (i=0;i<ETH_ALEN;i++) {
1N/A nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
1N/A }
1N/A printf ("Ethernet addr: %!\n", nic->node_addr);
1N/A
1N/A if (sum != 0xBABA)
1N/A printf("eepro100: Invalid EEPROM checksum %#hX, "
1N/A "check settings before activating this device!\n", sum);
1N/A outl(0, ioaddr + SCBPort);
1N/A udelay (10000);
1N/A whereami ("Got eeprom.");
1N/A
1N/A /* Base = 0 */
1N/A outl(0, ioaddr + SCBPointer);
1N/A outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd);
1N/A wait_for_cmd_done(ioaddr + SCBCmd);
1N/A whereami ("set rx base addr.");
1N/A
1N/A outl(virt_to_bus(&lstats), ioaddr + SCBPointer);
1N/A outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd);
1N/A wait_for_cmd_done(ioaddr + SCBCmd);
1N/A whereami ("set stats addr.");
1N/A
1N/A /* INIT RX stuff. */
1N/A ACCESS(rxfd)status = 0x0001;
1N/A ACCESS(rxfd)command = 0x0000;
1N/A ACCESS(rxfd)link = virt_to_bus(&(ACCESS(rxfd)status));
1N/A ACCESS(rxfd)rx_buf_addr = virt_to_bus(&nic->packet);
1N/A ACCESS(rxfd)count = 0;
1N/A ACCESS(rxfd)size = 1528;
1N/A
1N/A outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);
1N/A outw(INT_MASK | RX_START, ioaddr + SCBCmd);
1N/A wait_for_cmd_done(ioaddr + SCBCmd);
1N/A
1N/A whereami ("started RX process.");
1N/A
1N/A /* Start the reciever.... */
1N/A ACCESS(rxfd)status = 0;
1N/A ACCESS(rxfd)command = 0xc000;
1N/A outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);
1N/A outw(INT_MASK | RX_START, ioaddr + SCBCmd);
1N/A
1N/A /* INIT TX stuff. */
1N/A
1N/A /* Base = 0 */
1N/A outl(0, ioaddr + SCBPointer);
1N/A outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd);
1N/A wait_for_cmd_done(ioaddr + SCBCmd);
1N/A
1N/A whereami ("set TX base addr.");
1N/A
1N/A txfd.command = (CmdIASetup);
1N/A txfd.status = 0x0000;
1N/A txfd.link = virt_to_bus (&confcmd);
1N/A
1N/A {
1N/A char *t = (char *)&txfd.tx_desc_addr;
1N/A
1N/A for (i=0;i<ETH_ALEN;i++)
1N/A t[i] = nic->node_addr[i];
1N/A }
1N/A
1N/A#ifdef DEBUG
1N/A printf ("Setup_eaddr:\n");
1N/A hd (&txfd, 0x20);
1N/A#endif
1N/A /* options = 0x40; */ /* 10mbps half duplex... */
1N/A options = 0x00; /* Autosense */
1N/A
1N/A#ifdef PROMISC
1N/A rx_mode = 3;
1N/A#elif ALLMULTI
1N/A rx_mode = 1;
1N/A#else
1N/A rx_mode = 0;
1N/A#endif
1N/A
1N/A if ( ((eeprom[6]>>8) & 0x3f) == DP83840
1N/A || ((eeprom[6]>>8) & 0x3f) == DP83840A) {
1N/A int mdi_reg23 = mdio_read(eeprom[6] & 0x1f, 23) | 0x0422;
1N/A if (congenb)
1N/A mdi_reg23 |= 0x0100;
1N/A printf(" DP83840 specific setup, setting register 23 to %hX.\n",
1N/A mdi_reg23);
1N/A mdio_write(eeprom[6] & 0x1f, 23, mdi_reg23);
1N/A }
1N/A whereami ("Done DP8340 special setup.");
1N/A if (options != 0) {
1N/A mdio_write(eeprom[6] & 0x1f, 0,
1N/A ((options & 0x20) ? 0x2000 : 0) | /* 100mbps? */
1N/A ((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */
1N/A whereami ("set mdio_register.");
1N/A }
1N/A
1N/A confcmd.command = CmdSuspend | CmdConfigure;
1N/A confcmd.status = 0x0000;
1N/A confcmd.link = virt_to_bus (&txfd);
1N/A confcmd.data[1] = (txfifo << 4) | rxfifo;
1N/A confcmd.data[4] = rxdmacount;
1N/A confcmd.data[5] = txdmacount + 0x80;
1N/A confcmd.data[15] = (rx_mode & 2) ? 0x49: 0x48;
1N/A confcmd.data[19] = (options & 0x10) ? 0xC0 : 0x80;
1N/A confcmd.data[21] = (rx_mode & 1) ? 0x0D: 0x05;
1N/A
1N/A outl(virt_to_bus(&txfd), ioaddr + SCBPointer);
1N/A outw(INT_MASK | CU_START, ioaddr + SCBCmd);
1N/A wait_for_cmd_done(ioaddr + SCBCmd);
1N/A
1N/A whereami ("started TX thingy (config, iasetup).");
1N/A
1N/A load_timer2(10*TICKS_PER_MS);
1N/A while (!txfd.status && timer2_running())
1N/A /* Wait */;
1N/A
1N/A /* Read the status register once to disgard stale data */
1N/A mdio_read(eeprom[6] & 0x1f, 1);
1N/A /* Check to see if the network cable is plugged in.
1N/A * This allows for faster failure if there is nothing
1N/A * we can do.
1N/A */
1N/A if (!(mdio_read(eeprom[6] & 0x1f, 1) & (1 << 2))) {
1N/A printf("Valid link not established\n");
1N/A eepro100_disable(dev);
1N/A return 0;
1N/A }
1N/A
1N/A dev->disable = eepro100_disable;
1N/A nic->poll = eepro100_poll;
1N/A nic->transmit = eepro100_transmit;
1N/A nic->irq = eepro100_irq;
1N/A return 1;
1N/A}
1N/A
1N/A/*********************************************************************/
1N/A
1N/A#ifdef DEBUG
1N/A
1N/A/* Hexdump a number of bytes from memory... */
1N/Avoid hd (void *where, int n)
1N/A{
1N/A int i;
1N/A
1N/A while (n > 0) {
1N/A printf ("%X ", where);
1N/A for (i=0;i < ( (n>16)?16:n);i++)
1N/A printf (" %hhX", ((char *)where)[i]);
1N/A printf ("\n");
1N/A n -= 16;
1N/A where += 16;
1N/A }
1N/A}
1N/A#endif
1N/A
1N/Astatic struct pci_id eepro100_nics[] = {
1N/APCI_ROM(0x8086, 0x1029, "id1029", "Intel EtherExpressPro100 ID1029"),
1N/APCI_ROM(0x8086, 0x1030, "id1030", "Intel EtherExpressPro100 ID1030"),
1N/APCI_ROM(0x8086, 0x1031, "82801cam", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
1N/APCI_ROM(0x8086, 0x1032, "eepro100-1032", "Intel PRO/100 VE Network Connection"),
1N/APCI_ROM(0x8086, 0x1033, "eepro100-1033", "Intel PRO/100 VM Network Connection"),
1N/APCI_ROM(0x8086, 0x1034, "eepro100-1034", "Intel PRO/100 VM Network Connection"),
1N/APCI_ROM(0x8086, 0x1035, "eepro100-1035", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
1N/APCI_ROM(0x8086, 0x1036, "eepro100-1036", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
1N/APCI_ROM(0x8086, 0x1037, "eepro100-1037", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
1N/APCI_ROM(0x8086, 0x1038, "id1038", "Intel PRO/100 VM Network Connection"),
1N/APCI_ROM(0x8086, 0x1039, "82562et", "Intel PRO100 VE 82562ET"),
1N/APCI_ROM(0x8086, 0x103a, "id103a", "Intel Corporation 82559 InBusiness 10/100"),
1N/APCI_ROM(0x8086, 0x103b, "82562etb", "Intel PRO100 VE 82562ETB"),
1N/APCI_ROM(0x8086, 0x103c, "eepro100-103c", "Intel PRO/100 VM Network Connection"),
1N/APCI_ROM(0x8086, 0x103d, "eepro100-103d", "Intel PRO/100 VE Network Connection"),
1N/APCI_ROM(0x8086, 0x103e, "eepro100-103e", "Intel PRO/100 VM Network Connection"),
1N/APCI_ROM(0x8086, 0x1059, "82551qm", "Intel PRO/100 M Mobile Connection"),
1N/APCI_ROM(0x8086, 0x1209, "82559er", "Intel EtherExpressPro100 82559ER"),
1N/APCI_ROM(0x8086, 0x1227, "82865", "Intel 82865 EtherExpress PRO/100A"),
1N/APCI_ROM(0x8086, 0x1228, "82556", "Intel 82556 EtherExpress PRO/100 Smart"),
1N/APCI_ROM(0x8086, 0x1229, "eepro100", "Intel EtherExpressPro100"),
1N/APCI_ROM(0x8086, 0x2449, "82562em", "Intel EtherExpressPro100 82562EM"),
1N/APCI_ROM(0x8086, 0x2459, "82562-1", "Intel 82562 based Fast Ethernet Connection"),
1N/APCI_ROM(0x8086, 0x245d, "82562-2", "Intel 82562 based Fast Ethernet Connection"),
1N/APCI_ROM(0x8086, 0x1050, "82562ez", "Intel 82562EZ Network Connection"),
1N/APCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent Server"),
1N/APCI_ROM(0x8086, 0x5201, "eepro100-5201", "Intel EtherExpress PRO/100 Intelligent Server"),
1N/A};
1N/A
1N/A/* Cards with device ids 0x1030 to 0x103F, 0x2449, 0x2459 or 0x245D might need
1N/A * a workaround for hardware bug on 10 mbit half duplex (see linux driver eepro100.c)
1N/A * 2003/03/17 gbaum */
1N/A
1N/A
1N/Astruct pci_driver eepro100_driver = {
1N/A .type = NIC_DRIVER,
1N/A .name = "EEPRO100",
1N/A .probe = eepro100_probe,
1N/A .ids = eepro100_nics,
1N/A .id_count = sizeof(eepro100_nics)/sizeof(eepro100_nics[0]),
1N/A .class = 0
1N/A};