if_ed_cbus.c revision 137531
164777Snyan/* 264777Snyan * Copyright (c) 1995, David Greenman 364777Snyan * All rights reserved. 464777Snyan * 564777Snyan * Redistribution and use in source and binary forms, with or without 664777Snyan * modification, are permitted provided that the following conditions 764777Snyan * are met: 864777Snyan * 1. Redistributions of source code must retain the above copyright 964777Snyan * notice unmodified, this list of conditions, and the following 1064777Snyan * disclaimer. 1164777Snyan * 2. Redistributions in binary form must reproduce the above copyright 1264777Snyan * notice, this list of conditions and the following disclaimer in the 1364777Snyan * documentation and/or other materials provided with the distribution. 1464777Snyan * 1564777Snyan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1664777Snyan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1764777Snyan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1864777Snyan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1964777Snyan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2064777Snyan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2164777Snyan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2264777Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2364777Snyan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2464777Snyan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2564777Snyan * SUCH DAMAGE. 2664777Snyan * 2764777Snyan * $FreeBSD: head/sys/dev/ed/if_ed_cbus.c 137531 2004-11-10 13:16:12Z nyan $ 2864777Snyan */ 2964777Snyan 3064777Snyan#include <sys/param.h> 3164777Snyan#include <sys/systm.h> 3264777Snyan#include <sys/socket.h> 3364777Snyan#include <sys/kernel.h> 3464777Snyan 3564777Snyan#include <sys/module.h> 3664777Snyan#include <sys/bus.h> 3764777Snyan#include <machine/bus.h> 3864777Snyan#ifdef PC98 3964777Snyan#include <sys/rman.h> 4064777Snyan#include <machine/resource.h> 4164777Snyan#include <machine/clock.h> 4264777Snyan#include <machine/md_var.h> 4364777Snyan#endif 4464777Snyan 4564777Snyan#include <net/ethernet.h> 4664777Snyan#include <net/if.h> 4764777Snyan#include <net/if_arp.h> 4864777Snyan#include <net/if_mib.h> 4964777Snyan 5064777Snyan#include <isa/isavar.h> 5164777Snyan 5264777Snyan#include <dev/ed/if_edvar.h> 5364777Snyan#ifdef PC98 5464777Snyan#include <dev/ed/if_edreg.h> 5564777Snyan#include <dev/ed/if_ed98.h> 5664777Snyan 5792739Salfredstatic int ed98_alloc_port (device_t, int); 5892739Salfredstatic int ed98_alloc_memory (device_t, int); 5992739Salfredstatic int ed_pio_testmem (struct ed_softc *, int, int, int); 6092739Salfredstatic int ed_probe_SIC98 (device_t, int, int); 6192739Salfredstatic int ed_probe_CNET98 (device_t, int, int); 6292739Salfredstatic int ed_probe_CNET98EL (device_t, int, int); 6392739Salfredstatic int ed_probe_NEC77 (device_t, int, int); 6492739Salfredstatic int ed_probe_NW98X (device_t, int, int); 6592739Salfredstatic int ed_probe_SB98 (device_t, int, int); 6692739Salfredstatic int ed_probe_EZ98 (device_t, int, int); 6792739Salfredstatic int ed98_probe_Novell (device_t, int, int); 6892739Salfredstatic int ed98_probe_generic8390 (struct ed_softc *); 6992739Salfredstatic void ed_reset_CNET98 (struct ed_softc *, int); 7092739Salfredstatic void ed_winsel_CNET98 (struct ed_softc *, u_short); 7192739Salfredstatic void ed_get_SB98 (struct ed_softc *); 7264777Snyan#endif 7364777Snyan 7492739Salfredstatic int ed_isa_probe (device_t); 7592739Salfredstatic int ed_isa_attach (device_t); 7664777Snyan 7764777Snyanstatic struct isa_pnp_id ed_ids[] = { 7864777Snyan#ifdef PC98 7964777Snyan/* TODO - list up PnP boards for PC-98 */ 8064777Snyan { 0, NULL } 8164777Snyan#endif 8264777Snyan}; 8364777Snyan 8464777Snyanstatic int 8564777Snyaned_isa_probe(dev) 8664777Snyan device_t dev; 8764777Snyan{ 8864777Snyan struct ed_softc *sc = device_get_softc(dev); 8964777Snyan int flags = device_get_flags(dev); 9064777Snyan int error = 0; 9164777Snyan 9264777Snyan bzero(sc, sizeof(struct ed_softc)); 9364777Snyan#ifdef PC98 9464777Snyan sc->type = ED_TYPE98(flags); 9564777Snyan#ifdef ED_DEBUG 9664777Snyan device_printf(dev, "ed_isa_probe: sc->type=%x\n", sc->type); 9764777Snyan#endif 9864777Snyan#endif 9964777Snyan 10064777Snyan /* Check isapnp ids */ 10164777Snyan error = ISA_PNP_PROBE(device_get_parent(dev), dev, ed_ids); 10264777Snyan#ifdef ED_DEBUG 10364777Snyan device_printf(dev, "ed_isa_probe: ISA_PNP_PROBE returns %d\n", error); 10464777Snyan#endif 10564777Snyan 10664777Snyan /* If the card had a PnP ID that didn't match any we know about */ 10764777Snyan if (error == ENXIO) { 10864777Snyan goto end; 10964777Snyan } 11064777Snyan 11164777Snyan /* If we had some other problem. */ 11264777Snyan if (!(error == 0 || error == ENOENT)) { 11364777Snyan goto end; 11464777Snyan } 11564777Snyan 11664777Snyan /* Heuristic probes */ 11764777Snyan#ifdef ED_DEBUG 11864777Snyan device_printf(dev, "ed_isa_probe: Heuristic probes start\n"); 11964777Snyan#endif 12064777Snyan#ifdef PC98 12164777Snyan switch (sc->type) { 12264777Snyan case ED_TYPE98_GENERIC: 12364777Snyan /* 12464777Snyan * CAUTION! 12564777Snyan * sc->type of these boards are overwritten by PC/AT's value. 12664777Snyan */ 12764777Snyan 12864777Snyan /* 12964777Snyan * SMC EtherEZ98 13064777Snyan */ 13164777Snyan error = ed_probe_EZ98(dev, 0, flags); 13264777Snyan if (error == 0) { 13364777Snyan goto end; 13464777Snyan } 13564777Snyan 13664777Snyan ed_release_resources(dev); 13764777Snyan 13864777Snyan /* 13964777Snyan * Allied Telesis CenterCom LA-98-T 14064777Snyan */ 14164777Snyan error = ed_probe_Novell(dev, 0, flags); 14264777Snyan if (error == 0) { 14364777Snyan goto end; 14464777Snyan } 14564777Snyan 14664777Snyan break; 14764777Snyan 14864777Snyan /* 14964777Snyan * NE2000-like boards probe routine 15064777Snyan */ 15164777Snyan case ED_TYPE98_BDN: 15264777Snyan /* 15364777Snyan * ELECOM LANEED LD-BDN 15464777Snyan * PLANET SMART COM 98 EN-2298 15564777Snyan */ 15664777Snyan case ED_TYPE98_LGY: 15764777Snyan /* 15864777Snyan * MELCO LGY-98, IND-SP, IND-SS 15964777Snyan * MACNICA NE2098 16064777Snyan */ 16164777Snyan case ED_TYPE98_ICM: 16264777Snyan /* 16364777Snyan * ICM DT-ET-25, DT-ET-T5, IF-2766ET, IF-2771ET 16464777Snyan * D-Link DE-298P, DE-298 16564777Snyan */ 16664777Snyan case ED_TYPE98_EGY: 16764777Snyan /* 16864777Snyan * MELCO EGY-98 16964777Snyan * Contec C-NET(98)E-A, C-NET(98)L-A 17064777Snyan */ 17164777Snyan case ED_TYPE98_108: 17264777Snyan /* 17364777Snyan * NEC PC-9801-107,108 17464777Snyan */ 17564777Snyan case ED_TYPE98_NC5098: 17664777Snyan /* 17764777Snyan * NextCom NC5098 17864777Snyan */ 17964777Snyan 18064777Snyan error = ed98_probe_Novell(dev, 0, flags); 18164777Snyan 18264777Snyan break; 18364777Snyan 18464777Snyan /* 18564777Snyan * other boards with special probe routine 18664777Snyan */ 18764777Snyan case ED_TYPE98_SIC: 18864777Snyan /* 18964777Snyan * Allied Telesis SIC-98 19064777Snyan */ 19164777Snyan error = ed_probe_SIC98(dev, 0, flags); 19264777Snyan 19364777Snyan break; 19464777Snyan 19564777Snyan case ED_TYPE98_CNET98EL: 19664777Snyan /* 19764777Snyan * Contec C-NET(98)E/L 19864777Snyan */ 19964777Snyan error = ed_probe_CNET98EL(dev, 0, flags); 20064777Snyan 20164777Snyan break; 20264777Snyan 20364777Snyan case ED_TYPE98_CNET98: 20464777Snyan /* 20564777Snyan * Contec C-NET(98) 20664777Snyan */ 20764777Snyan error = ed_probe_CNET98(dev, 0, flags); 20864777Snyan 20964777Snyan break; 21064777Snyan 21164777Snyan case ED_TYPE98_LA98: 21264777Snyan /* 21364777Snyan * IO-DATA LA/T-98 21464777Snyan * NEC PC-9801-77,78 21564777Snyan */ 21664777Snyan error = ed_probe_NEC77(dev, 0, flags); 21764777Snyan 21864777Snyan break; 21964777Snyan 22064777Snyan case ED_TYPE98_NW98X: 22164777Snyan /* 22264777Snyan * Networld EC/EP-98X 22364777Snyan */ 22464777Snyan error = ed_probe_NW98X(dev, 0, flags); 22564777Snyan 22664777Snyan break; 22764777Snyan 22864777Snyan case ED_TYPE98_SB98: 22964777Snyan /* 23064777Snyan * Soliton SB-9801 23164777Snyan * Fujikura FN-9801 23264777Snyan */ 23364777Snyan 23464777Snyan error = ed_probe_SB98(dev, 0, flags); 23564777Snyan 23664777Snyan break; 23764777Snyan } 23864777Snyan#endif 23964777Snyan 24064777Snyanend: 24164777Snyan#ifdef ED_DEBUG 24264777Snyan device_printf(dev, "ed_isa_probe: end, error=%d\n", error); 24364777Snyan#endif 24464777Snyan if (error == 0) 24564777Snyan error = ed_alloc_irq(dev, 0, 0); 24664777Snyan 24764777Snyan ed_release_resources(dev); 24864777Snyan return (error); 24964777Snyan} 25064777Snyan 25164777Snyanstatic int 25264777Snyaned_isa_attach(dev) 25364777Snyan device_t dev; 25464777Snyan{ 25564777Snyan struct ed_softc *sc = device_get_softc(dev); 25664777Snyan int flags = device_get_flags(dev); 25764777Snyan int error; 25864777Snyan 25964777Snyan if (sc->port_used > 0) { 26064777Snyan#ifdef PC98 26164777Snyan if (ED_TYPE98(flags) == ED_TYPE98_GENERIC) { 26264777Snyan ed_alloc_port(dev, sc->port_rid, sc->port_used); 26364777Snyan } else { 26464777Snyan ed98_alloc_port(dev, sc->port_rid); 26564777Snyan } 26664777Snyan#endif 26764777Snyan } 26864777Snyan if (sc->mem_used) 26964777Snyan ed_alloc_memory(dev, sc->mem_rid, sc->mem_used); 27064777Snyan 27164777Snyan ed_alloc_irq(dev, sc->irq_rid, 0); 27264777Snyan 27364777Snyan error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, 27464777Snyan edintr, sc, &sc->irq_handle); 27564777Snyan if (error) { 27664777Snyan ed_release_resources(dev); 27764777Snyan return (error); 27864777Snyan } 27964777Snyan 280121816Sbrooks return ed_attach(dev); 28164777Snyan} 28264777Snyan 28364777Snyan#ifdef PC98 28464777Snyan/* 28564777Snyan * Interrupt conversion table for EtherEZ98 28664777Snyan */ 28764777Snyanstatic unsigned short ed_EZ98_intr_val[] = { 28864777Snyan 0, 28964777Snyan 3, 29064777Snyan 5, 29164777Snyan 6, 29264777Snyan 0, 29364777Snyan 9, 29464777Snyan 12, 29564777Snyan 13 29664777Snyan}; 29764777Snyan 29864777Snyanstatic int 29964777Snyaned_probe_EZ98(dev, port_rid, flags) 30064777Snyan device_t dev; 30164777Snyan int port_rid; 30264777Snyan int flags; 30364777Snyan{ 30464777Snyan struct ed_softc *sc = device_get_softc(dev); 30564777Snyan int error; 30664777Snyan static unsigned short *intr_vals[] = {NULL, ed_EZ98_intr_val}; 30764777Snyan 30864777Snyan error = ed_alloc_port(dev, port_rid, ED_EZ98_IO_PORTS); 30964777Snyan if (error) { 31064777Snyan return (error); 31164777Snyan } 31264777Snyan 31364777Snyan sc->asic_offset = ED_EZ98_ASIC_OFFSET; 31464777Snyan sc->nic_offset = ED_EZ98_NIC_OFFSET; 31564777Snyan 31664777Snyan return ed_probe_WD80x3_generic(dev, flags, intr_vals); 31764777Snyan} 31864777Snyan 31964777Snyan/* 32064777Snyan * I/O conversion tables 32164777Snyan */ 32264777Snyan 32364777Snyan/* LGY-98, ICM, C-NET(98)E/L */ 32464777Snyanstatic bus_addr_t ed98_ioaddr_generic[] = { 32564777Snyan 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 32664777Snyan}; 32764777Snyan 32864777Snyan/* 32964777Snyan * Definitions for Contec C-NET(98)E/L 33064777Snyan */ 33164777Snyan#define ED_CNET98EL_ICR 2 /* Interrupt Configuration Register */ 33264777Snyan 33364777Snyan#define ED_CNET98EL_ICR_IRQ3 0x01 33464777Snyan#define ED_CNET98EL_ICR_IRQ5 0x02 33564777Snyan#define ED_CNET98EL_ICR_IRQ6 0x04 33664777Snyan#define ED_CNET98EL_ICR_IRQ12 0x20 33764777Snyan 33864777Snyan#define ED_CNET98EL_IMR 4 /* Interrupt Mask Register */ 33964777Snyan#define ED_CNET98EL_ISR 5 /* Interrupt Status Register */ 34064777Snyan 34164777Snyan/* EGY-98 */ 34264777Snyanstatic bus_addr_t ed98_ioaddr_egy98[] = { 34364777Snyan 0, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 34464777Snyan 0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e 34564777Snyan}; 34664777Snyan 34764777Snyan/* SIC-98 */ 34864777Snyanstatic bus_addr_t ed98_ioaddr_sic98[] = { 34964777Snyan 0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00, 0x0c00, 0x0e00, 35064777Snyan 0x1000, 0x1200, 0x1400, 0x1600, 0x1800, 0x1a00, 0x1c00, 0x1e00 35164777Snyan}; 35264777Snyan 35364777Snyan/* LA/T-98, LD-BDN, PC-9801-77, SB-9801 */ 35464777Snyanstatic bus_addr_t ed98_ioaddr_la98[] = { 35564777Snyan 0x0000, 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 35664777Snyan 0x8000, 0x9000, 0xa000, 0xb000, 0xc000, 0xd000, 0xe000, 0xf000, 35764777Snyan 0x0100 /* for NEC 77(see below) */ 35864777Snyan}; 35964777Snyan 36064777Snyan/* 36164777Snyan * Definitions for NEC PC-9801-77 36264777Snyan */ 36364777Snyan#define ED_NEC77_IRQ 16 /* Interrupt Configuration Register */ 36464777Snyan 36564777Snyan#define ED_NEC77_IRQ3 0x04 36664777Snyan#define ED_NEC77_IRQ5 0x06 36764777Snyan#define ED_NEC77_IRQ6 0x08 36864777Snyan#define ED_NEC77_IRQ12 0x0a 36964777Snyan#define ED_NEC77_IRQ13 0x02 37064777Snyan 37164777Snyan/* 37264777Snyan * Definitions for Soliton SB-9801 37364777Snyan */ 37464777Snyan#define ED_SB98_CFG 1 /* Board configuration */ 37564777Snyan 37664777Snyan#define ED_SB98_CFG_IRQ3 0x00 37764777Snyan#define ED_SB98_CFG_IRQ5 0x04 37864777Snyan#define ED_SB98_CFG_IRQ6 0x08 37964777Snyan#define ED_SB98_CFG_IRQ12 0x0c 38064777Snyan#define ED_SB98_CFG_ALTPORT 0x40 /* use EXTERNAL media */ 38164777Snyan#define ED_SB98_CFG_ENABLE 0xa0 /* enable configuration */ 38264777Snyan 38364777Snyan#define ED_SB98_EEPENA 2 /* EEPROM access enable */ 38464777Snyan 38564777Snyan#define ED_SB98_EEPENA_DISABLE 0x00 38664777Snyan#define ED_SB98_EEPENA_ENABLE 0x01 38764777Snyan 38864777Snyan#define ED_SB98_EEP 3 /* EEPROM access */ 38964777Snyan 39064777Snyan#define ED_SB98_EEP_SDA 0x01 /* Serial Data */ 39164777Snyan#define ED_SB98_EEP_SCL 0x02 /* Serial Clock */ 39264777Snyan#define ED_SB98_EEP_READ 0x01 /* Read Command */ 39364777Snyan 39464777Snyan#define ED_SB98_EEP_DELAY 300 39564777Snyan 39664777Snyan#define ED_SB98_ADDRESS 0x01 /* Station Address(1-6) */ 39764777Snyan 39864777Snyan#define ED_SB98_POLARITY 4 /* Polarity */ 39964777Snyan 40064777Snyan/* PC-9801-108 */ 40164777Snyanstatic bus_addr_t ed98_ioaddr_nec108[] = { 40264777Snyan 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 40364777Snyan 0x1000, 0x1002, 0x1004, 0x1006, 0x1008, 0x100a, 0x100c, 0x100e 40464777Snyan}; 40564777Snyan 40664777Snyan/* C-NET(98) */ 40764777Snyanstatic bus_addr_t ed98_ioaddr_cnet98[] = { 40864777Snyan 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 40964777Snyan 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e 41064777Snyan}; 41164777Snyan 41264777Snyan/* 41364777Snyan * Definitions for Contec C-NET(98) 41464777Snyan */ 41564777Snyan#define ED_CNET98_MAP_REG0L 0 /* MAPPING register0 Low */ 41664777Snyan#define ED_CNET98_MAP_REG1L 1 /* MAPPING register1 Low */ 41764777Snyan#define ED_CNET98_MAP_REG2L 2 /* MAPPING register2 Low */ 41864777Snyan#define ED_CNET98_MAP_REG3L 3 /* MAPPING register3 Low */ 41964777Snyan#define ED_CNET98_MAP_REG0H 4 /* MAPPING register0 Hi */ 42064777Snyan#define ED_CNET98_MAP_REG1H 5 /* MAPPING register1 Hi */ 42164777Snyan#define ED_CNET98_MAP_REG2H 6 /* MAPPING register2 Hi */ 42264777Snyan#define ED_CNET98_MAP_REG3H 7 /* MAPPING register3 Hi */ 42364777Snyan#define ED_CNET98_WIN_REG 8 /* Window register */ 42464777Snyan#define ED_CNET98_INT_LEV 9 /* Init level register */ 42564777Snyan 42664777Snyan#define ED_CNET98_INT_IRQ3 0x01 /* INT 0 */ 42764777Snyan#define ED_CNET98_INT_IRQ5 0x02 /* INT 1 */ 42864777Snyan#define ED_CNET98_INT_IRQ6 0x04 /* INT 2 */ 42964777Snyan#define ED_CNET98_INT_IRQ9 0x08 /* INT 3 */ 43064777Snyan#define ED_CNET98_INT_IRQ12 0x20 /* INT 5 */ 43164777Snyan#define ED_CNET98_INT_IRQ13 0x40 /* INT 6 */ 43264777Snyan 43364777Snyan#define ED_CNET98_INT_REQ 10 /* Init request register */ 43464777Snyan#define ED_CNET98_INT_MASK 11 /* Init mask register */ 43564777Snyan#define ED_CNET98_INT_STAT 12 /* Init status register */ 43664777Snyan#define ED_CNET98_INT_CLR 12 /* Init clear register */ 43764777Snyan#define ED_CNET98_RESERVE1 13 43864777Snyan#define ED_CNET98_RESERVE2 14 43964777Snyan#define ED_CNET98_RESERVE3 15 44064777Snyan 44164777Snyan/* EC/EP-98X, NC5098 */ 44264777Snyanstatic bus_addr_t ed98_ioaddr_nw98x[] = { 44364777Snyan 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 44464777Snyan 0x0800, 0x0900, 0x0a00, 0x0b00, 0x0c00, 0x0d00, 0x0e00, 0x0f00, 44564777Snyan 0x1000 /* for EC/EP-98X(see below) */ 44664777Snyan}; 44764777Snyan 44864777Snyan/* 44964777Snyan * Definitions for Networld EC/EP-98X 45064777Snyan */ 45164777Snyan#define ED_NW98X_IRQ 16 /* Interrupt Configuration Register */ 45264777Snyan 45364777Snyan#define ED_NW98X_IRQ3 0x04 45464777Snyan#define ED_NW98X_IRQ5 0x06 45564777Snyan#define ED_NW98X_IRQ6 0x08 45664777Snyan#define ED_NW98X_IRQ12 0x0a 45764777Snyan#define ED_NW98X_IRQ13 0x02 45864777Snyan 45964777Snyan/* NC5098 ASIC */ 46064777Snyanstatic bus_addr_t ed98_asic_nc5098[] = { 46164777Snyan/* DATA ENADDR RESET */ 46264777Snyan 0x0000, 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x4000, 46364777Snyan 0, 0, 0, 0, 0, 0, 0, 0 46464777Snyan}; 46564777Snyan 46664777Snyan/* 46764777Snyan * Definitions for NextCom NC5098 46864777Snyan */ 46964777Snyan#define ED_NC5098_ENADDR 1 /* Station Address(1-6) */ 47064777Snyan 47164777Snyan/* 47264777Snyan * Allocate a port resource with the given resource id. 47364777Snyan */ 47464777Snyanstatic int 47564777Snyaned98_alloc_port(dev, rid) 47664777Snyan device_t dev; 47764777Snyan int rid; 47864777Snyan{ 47964777Snyan struct ed_softc *sc = device_get_softc(dev); 48064777Snyan struct resource *res; 48164777Snyan int error; 48264777Snyan bus_addr_t *io_nic, *io_asic, adj; 48364777Snyan static bus_addr_t io_res[ED_NOVELL_IO_PORTS + 1]; 48464777Snyan int i, n; 48564777Snyan int offset, reset, data; 48664777Snyan 48764777Snyan /* Set i/o table for resource manager */ 48864777Snyan io_nic = io_asic = ed98_ioaddr_generic; 48964777Snyan offset = ED_NOVELL_ASIC_OFFSET; 49064777Snyan reset = ED_NOVELL_RESET; 49164777Snyan data = ED_NOVELL_DATA; 49264777Snyan n = ED_NOVELL_IO_PORTS; 49364777Snyan 49464777Snyan switch (sc->type) { 49564777Snyan case ED_TYPE98_LGY: 49664777Snyan io_asic = ed98_ioaddr_egy98; /* XXX - Yes, we use egy98 */ 49764777Snyan offset = 0x0200; 49864777Snyan reset = 8; 49964777Snyan break; 50064777Snyan 50164777Snyan case ED_TYPE98_EGY: 50264777Snyan io_nic = io_asic = ed98_ioaddr_egy98; 50364777Snyan offset = 0x0200; 50464777Snyan reset = 8; 50564777Snyan break; 50664777Snyan 50764777Snyan case ED_TYPE98_ICM: 50864777Snyan offset = 0x0100; 50964777Snyan break; 51064777Snyan 51164777Snyan case ED_TYPE98_BDN: 51264777Snyan io_nic = io_asic = ed98_ioaddr_la98; 51364777Snyan offset = 0x0100; 51464777Snyan reset = 0x0c; 51564777Snyan break; 51664777Snyan 51764777Snyan case ED_TYPE98_SIC: 51864777Snyan io_nic = io_asic = ed98_ioaddr_sic98; 51964777Snyan offset = 0x2000; 52064777Snyan n = 16+1; 52164777Snyan break; 52264777Snyan 52364777Snyan case ED_TYPE98_108: 52464777Snyan io_nic = io_asic = ed98_ioaddr_nec108; 52564777Snyan offset = 0x0888; /* XXX - overwritten after */ 52664777Snyan reset = 1; 52764777Snyan n = 16; /* XXX - does not set ASIC i/o here */ 52864777Snyan break; 52964777Snyan 53064777Snyan case ED_TYPE98_LA98: 53164777Snyan io_nic = io_asic = ed98_ioaddr_la98; 53264777Snyan offset = 0x0100; 53364777Snyan break; 53464777Snyan 53564777Snyan case ED_TYPE98_CNET98EL: 53664777Snyan offset = 0x0400; 53764777Snyan data = 0x0e; 53864777Snyan break; 53964777Snyan 54064777Snyan case ED_TYPE98_CNET98: 54164777Snyan /* XXX - Yes, we use generic i/o here */ 54264777Snyan offset = 0x0400; 54364777Snyan break; 54464777Snyan 54564777Snyan case ED_TYPE98_NW98X: 54664777Snyan io_nic = io_asic = ed98_ioaddr_nw98x; 54764777Snyan offset = 0x1000; 54864777Snyan break; 54964777Snyan 55064777Snyan case ED_TYPE98_SB98: 55164777Snyan io_nic = io_asic = ed98_ioaddr_la98; 55264777Snyan offset = 0x0400; 55364777Snyan reset = 7; 55464777Snyan break; 55564777Snyan 55664777Snyan case ED_TYPE98_NC5098: 55764777Snyan io_nic = ed98_ioaddr_nw98x; 55864777Snyan io_asic = ed98_asic_nc5098; 55964777Snyan offset = 0x2000; 56064777Snyan reset = 7; 56164777Snyan n = 16+8; /* XXX */ 56264777Snyan break; 56364777Snyan } 56464777Snyan 56564777Snyan bcopy(io_nic, io_res, sizeof(io_nic[0]) * ED_NOVELL_ASIC_OFFSET); 56664777Snyan for (i = ED_NOVELL_ASIC_OFFSET; i < ED_NOVELL_IO_PORTS; i++) { 56764777Snyan io_res[i] = io_asic[i - ED_NOVELL_ASIC_OFFSET] + offset; 56864777Snyan } 56964777Snyan 57064777Snyan res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, 57164777Snyan io_res, n, RF_ACTIVE); 57264777Snyan if (!res) { 57364777Snyan return (ENOENT); 57464777Snyan } 57564777Snyan 57664777Snyan sc->port_rid = rid; 57764777Snyan sc->port_res = res; 57864777Snyan sc->port_used = n; 57964777Snyan 58064777Snyan /* Re-map i/o table if needed */ 58164777Snyan switch (sc->type) { 58264777Snyan case ED_TYPE98_LA98: 58364777Snyan case ED_TYPE98_NW98X: 58464777Snyan io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset; 58564777Snyan n++; 58664777Snyan break; 58764777Snyan 58864777Snyan case ED_TYPE98_108: 58964777Snyan adj = (rman_get_start(res) & 0xf000) / 2; 59064777Snyan offset = (offset | adj) - rman_get_start(res); 59164777Snyan 59264777Snyan for (n = ED_NOVELL_ASIC_OFFSET; n < ED_NOVELL_IO_PORTS; n++) { 59364777Snyan io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset; 59464777Snyan } 59564777Snyan break; 59664777Snyan 59764777Snyan case ED_TYPE98_CNET98: 59864777Snyan io_nic = io_asic = ed98_ioaddr_cnet98; 59964777Snyan offset = 1; 60064777Snyan 60164777Snyan bcopy(io_nic, io_res, sizeof(io_nic[0]) * ED_NOVELL_ASIC_OFFSET); 60264777Snyan for (n = ED_NOVELL_ASIC_OFFSET; n < ED_NOVELL_IO_PORTS; n++) { 60364777Snyan io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset; 60464777Snyan } 60564777Snyan break; 60664777Snyan 60764777Snyan case ED_TYPE98_NC5098: 60864777Snyan n = ED_NOVELL_IO_PORTS; 60964777Snyan break; 61064777Snyan } 61164777Snyan 61264777Snyan if (reset != ED_NOVELL_RESET) { 61364777Snyan io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_RESET] = 61464777Snyan io_res[ED_NOVELL_ASIC_OFFSET + reset]; 61564777Snyan } 61664777Snyan if (data != ED_NOVELL_DATA) { 61764777Snyan io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_DATA] = 61864777Snyan io_res[ED_NOVELL_ASIC_OFFSET + data]; 61964777Snyan#if 0 62064777Snyan io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_DATA + 1] = 62164777Snyan io_res[ED_NOVELL_ASIC_OFFSET + data + 1]; 62264777Snyan#endif 62364777Snyan } 62464777Snyan 62564777Snyan error = isa_load_resourcev(res, io_res, n); 62664777Snyan if (error != 0) { 62764777Snyan return (ENOENT); 62864777Snyan } 62964777Snyan#ifdef ED_DEBUG 63064777Snyan device_printf(dev, "ed98_alloc_port: i/o ports = %d\n", n); 63164777Snyan for (i = 0; i < n; i++) { 63264777Snyan printf("%x,", io_res[i]); 63364777Snyan } 63464777Snyan printf("\n"); 63564777Snyan#endif 63664777Snyan return (0); 63764777Snyan} 63864777Snyan 63964777Snyanstatic int 64064777Snyaned98_alloc_memory(dev, rid) 64164777Snyan device_t dev; 64264777Snyan int rid; 64364777Snyan{ 64464777Snyan struct ed_softc *sc = device_get_softc(dev); 64564777Snyan int error; 64664777Snyan u_long conf_maddr, conf_msize; 64764777Snyan 64864777Snyan error = bus_get_resource(dev, SYS_RES_MEMORY, 0, 64964777Snyan &conf_maddr, &conf_msize); 65064777Snyan if (error) { 65164777Snyan return (error); 65264777Snyan } 65364777Snyan 65464777Snyan if ((conf_maddr == 0) || (conf_msize == 0)) { 65564777Snyan return (ENXIO); 65664777Snyan } 65764777Snyan 65864777Snyan error = ed_alloc_memory(dev, rid, (int) conf_msize); 65964777Snyan if (error) { 66064777Snyan return (error); 66164777Snyan } 66264777Snyan 66364777Snyan sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res); 66464777Snyan sc->mem_size = conf_msize; 66564777Snyan 66664777Snyan return (0); 66764777Snyan} 66864777Snyan 66964777Snyan/* 67064777Snyan * Generic probe routine for testing for the existance of a DS8390. 67164777Snyan * Must be called after the NIC has just been reset. This routine 67264777Snyan * works by looking at certain register values that are guaranteed 67364777Snyan * to be initialized a certain way after power-up or reset. Seems 67464777Snyan * not to currently work on the 83C690. 67564777Snyan * 67664777Snyan * Specifically: 67764777Snyan * 67864777Snyan * Register reset bits set bits 67964777Snyan * Command Register (CR) TXP, STA RD2, STP 68064777Snyan * Interrupt Status (ISR) RST 68164777Snyan * Interrupt Mask (IMR) All bits 68264777Snyan * Data Control (DCR) LAS 68364777Snyan * Transmit Config. (TCR) LB1, LB0 68464777Snyan * 68564777Snyan * XXX - We only check the CR register. 68664777Snyan * 68764777Snyan * Return 1 if 8390 was found, 0 if not. 68864777Snyan */ 68964777Snyan 69064777Snyanstatic int 69164777Snyaned98_probe_generic8390(sc) 69264777Snyan struct ed_softc *sc; 69364777Snyan{ 69464777Snyan u_char tmp = ed_nic_inb(sc, ED_P0_CR); 69564777Snyan#ifdef DIAGNOSTIC 69664777Snyan printf("ed?: inb(ED_P0_CR)=%x\n", tmp); 69764777Snyan#endif 69864777Snyan if ((tmp & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) != 69964777Snyan (ED_CR_RD2 | ED_CR_STP)) { 70064777Snyan return (0); 70164777Snyan } 70264777Snyan 70364777Snyan (void) ed_nic_inb(sc, ED_P0_ISR); 70464777Snyan 70564777Snyan return (1); 70664777Snyan} 70764777Snyan 70864777Snyanstatic int 70964777Snyaned98_probe_Novell(dev, port_rid, flags) 71064777Snyan device_t dev; 71164777Snyan int port_rid; 71264777Snyan int flags; 71364777Snyan{ 71464777Snyan struct ed_softc *sc = device_get_softc(dev); 71564777Snyan int error; 71664777Snyan int n; 71764777Snyan u_char romdata[ETHER_ADDR_LEN * 2], tmp; 71864777Snyan 71964777Snyan#ifdef ED_DEBUG 72064777Snyan device_printf(dev, "ed98_probe_Novell: start\n"); 72164777Snyan#endif 72264777Snyan error = ed98_alloc_port(dev, port_rid); 72364777Snyan if (error) { 72464777Snyan return (error); 72564777Snyan } 72664777Snyan 72764777Snyan sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 72864777Snyan sc->nic_offset = ED_NOVELL_NIC_OFFSET; 72964777Snyan 73064777Snyan /* Reset the board */ 73164777Snyan#ifdef ED_DEBUG 73264777Snyan device_printf(dev, "ed98_probe_Novell: reset\n"); 73364777Snyan#endif 73464777Snyan switch (sc->type) { 73564777Snyan#if 1 /* XXX - I'm not sure this is really necessary... */ 73664777Snyan case ED_TYPE98_BDN: 73764777Snyan tmp = ed_asic_inb(sc, ED_NOVELL_RESET); 73864777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, (tmp & 0xf0) | 0x08); 73964777Snyan ed_nic_outb(sc, 0x04, tmp); 74064777Snyan (void) ed_asic_inb(sc, 0x08); 74164777Snyan ed_asic_outb(sc, 0x08, tmp); 74264777Snyan ed_asic_outb(sc, 0x08, tmp & 0x7f); 74364777Snyan break; 74464777Snyan#endif 74564777Snyan case ED_TYPE98_NC5098: 74664777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, 0x00); 74764777Snyan DELAY(5000); 74864777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, 0x01); 74964777Snyan break; 75064777Snyan 75164777Snyan default: 75264777Snyan tmp = ed_asic_inb(sc, ED_NOVELL_RESET); 75364777Snyan 75464777Snyan /* 75564777Snyan * I don't know if this is necessary; probably cruft leftover from 75664777Snyan * Clarkson packet driver code. Doesn't do a thing on the boards I've 757108533Sschweikh * tested. -DG [note that an outb(0x84, 0) seems to work here, and is 75864777Snyan * non-invasive...but some boards don't seem to reset and I don't have 75964777Snyan * complete documentation on what the 'right' thing to do is...so we 76064777Snyan * do the invasive thing for now. Yuck.] 76164777Snyan */ 76264777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, tmp); 76364777Snyan break; 76464777Snyan } 76564777Snyan DELAY(5000); 76664777Snyan 76764777Snyan /* 76864777Snyan * This is needed because some NE clones apparently don't reset the 76964777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 77064777Snyan * - this makes the probe invasive! ...Done against my better 77164777Snyan * judgement. -DLG 77264777Snyan */ 77364777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 77464777Snyan DELAY(5000); 77564777Snyan 77664777Snyan /* Make sure that we really have an 8390 based board */ 77764777Snyan if (!ed98_probe_generic8390(sc)) { 77864777Snyan return (ENXIO); 77964777Snyan } 78064777Snyan 78164777Snyan /* Test memory via PIO */ 78264777Snyan#ifdef ED_DEBUG 78364777Snyan device_printf(dev, "ed98_probe_Novell: test memory\n"); 78464777Snyan#endif 78564777Snyan sc->cr_proto = ED_CR_RD2; 78664777Snyan if (!ed_pio_testmem(sc, 8192, 0, flags) 78764777Snyan && !ed_pio_testmem(sc, 16384, 1, flags)) { 78864777Snyan return (ENXIO); 78964777Snyan } 79064777Snyan 79164777Snyan /* Setup the board type */ 79264777Snyan#ifdef ED_DEBUG 79364777Snyan device_printf(dev, "ed98_probe_Novell: board type\n"); 79464777Snyan#endif 79564777Snyan switch (sc->type) { 79664777Snyan case ED_TYPE98_BDN: 79764777Snyan sc->type_str = "LD-BDN"; 79864777Snyan break; 79964777Snyan case ED_TYPE98_EGY: 80064777Snyan sc->type_str = "EGY-98"; 80164777Snyan break; 80264777Snyan case ED_TYPE98_LGY: 80364777Snyan sc->type_str = "LGY-98"; 80464777Snyan break; 80564777Snyan case ED_TYPE98_ICM: 80664777Snyan sc->type_str = "ICM"; 80764777Snyan break; 80864777Snyan case ED_TYPE98_108: 80964777Snyan sc->type_str = "PC-9801-108"; 81064777Snyan break; 81164777Snyan case ED_TYPE98_LA98: 81264777Snyan sc->type_str = "LA-98"; 81364777Snyan break; 81464777Snyan case ED_TYPE98_NW98X: 81564777Snyan sc->type_str = "NW98X"; 81664777Snyan break; 81764777Snyan case ED_TYPE98_NC5098: 81864777Snyan sc->type_str = "NC5098"; 81964777Snyan break; 82064777Snyan default: 82164777Snyan sc->type_str = NULL; 82264777Snyan break; 82364777Snyan } 82464777Snyan 82564777Snyan /* Get station address */ 82664777Snyan switch (sc->type) { 82764777Snyan case ED_TYPE98_NC5098: 82864777Snyan for (n = 0; n < ETHER_ADDR_LEN; n++) { 82964777Snyan sc->arpcom.ac_enaddr[n] = 83064777Snyan ed_asic_inb(sc, ED_NC5098_ENADDR + n); 83164777Snyan } 83264777Snyan break; 83364777Snyan 83464777Snyan default: 83564777Snyan ed_pio_readmem(sc, 0, romdata, sizeof(romdata)); 83664777Snyan for (n = 0; n < ETHER_ADDR_LEN; n++) { 83764777Snyan sc->arpcom.ac_enaddr[n] = 83864777Snyan romdata[n * (sc->isa16bit + 1)]; 83964777Snyan } 84064777Snyan break; 84164777Snyan } 84264777Snyan 84364777Snyan /* clear any pending interrupts that might have occurred above */ 84464777Snyan ed_nic_outb(sc, ED_P0_ISR, 0xff); 84564777Snyan 84664777Snyan return (0); 84764777Snyan} 84864777Snyan 84964777Snyan/* 85064777Snyan * Probe and vendor-specific initialization routine for SIC-98 boards 85164777Snyan */ 85264777Snyanstatic int 85364777Snyaned_probe_SIC98(dev, port_rid, flags) 85464777Snyan device_t dev; 85564777Snyan int port_rid; 85664777Snyan int flags; 85764777Snyan{ 85864777Snyan struct ed_softc *sc = device_get_softc(dev); 85964777Snyan int error; 86064777Snyan int i; 86164777Snyan u_char sum; 86264777Snyan 86364777Snyan /* 86464777Snyan * Setup card RAM and I/O address 86564777Snyan * Kernel Virtual to segment C0000-DFFFF???? 86664777Snyan */ 86764777Snyan error = ed98_alloc_port(dev, port_rid); 86864777Snyan if (error) { 86964777Snyan return (error); 87064777Snyan } 87164777Snyan 872121118Sshiba sc->asic_offset = ED_SIC_ASIC_OFFSET; 873121118Sshiba sc->nic_offset = ED_SIC_NIC_OFFSET; 87464777Snyan 87564777Snyan error = ed98_alloc_memory(dev, 0); 87664777Snyan if (error) { 87764777Snyan return (error); 87864777Snyan } 87964777Snyan 88064777Snyan /* Reset card to force it into a known state. */ 88164777Snyan ed_asic_outb(sc, 0, 0x00); 88264777Snyan DELAY(100); 88364777Snyan if (ED_TYPE98SUB(flags) == 0) { 88464777Snyan /* SIC-98/SIU-98 */ 88564777Snyan ed_asic_outb(sc, 0, 0x94); 88664777Snyan DELAY(100); 88764777Snyan ed_asic_outb(sc, 0, 0x94); 88864777Snyan } else { 88964777Snyan /* SIU-98-D */ 89064777Snyan ed_asic_outb(sc, 0, 0x80); 89164777Snyan DELAY(100); 89264777Snyan ed_asic_outb(sc, 0, 0x94); 89364777Snyan DELAY(100); 89464777Snyan ed_asic_outb(sc, 0, 0x9e); 89564777Snyan } 89664777Snyan DELAY(100); 89764777Snyan 89864777Snyan /* 89964777Snyan * Here we check the card ROM, if the checksum passes, and the 90064777Snyan * type code and ethernet address check out, then we know we have 90164777Snyan * an SIC card. 90264777Snyan */ 90364777Snyan sum = sc->mem_start[6 * 2]; 90464777Snyan for (i = 0; i < ETHER_ADDR_LEN; i++) { 90564777Snyan sum ^= (sc->arpcom.ac_enaddr[i] = sc->mem_start[i * 2]); 90664777Snyan } 90764777Snyan#ifdef ED_DEBUG 90864777Snyan device_printf(dev, "ed_probe_sic98: got address %6D\n", 90964777Snyan sc->arpcom.ac_enaddr, ":"); 91064777Snyan#endif 91164777Snyan if (sum != 0) { 91264777Snyan return (ENXIO); 91364777Snyan } 91464777Snyan if ((sc->arpcom.ac_enaddr[0] | sc->arpcom.ac_enaddr[1] | 91564777Snyan sc->arpcom.ac_enaddr[2]) == 0) { 91664777Snyan return (ENXIO); 91764777Snyan } 91864777Snyan 919121118Sshiba sc->vendor = ED_VENDOR_SIC; 92064777Snyan sc->type_str = "SIC98"; 92164777Snyan sc->isa16bit = 1; 92264777Snyan sc->cr_proto = 0; 92364777Snyan 92464777Snyan /* 92564777Snyan * SIC RAM page 0x0000-0x3fff(or 0x7fff) 92664777Snyan */ 92764777Snyan if (ED_TYPE98SUB(flags) == 0) { 92864777Snyan ed_asic_outb(sc, 0, 0x90); 92964777Snyan } else { 93064777Snyan ed_asic_outb(sc, 0, 0x8e); 93164777Snyan } 93264777Snyan DELAY(100); 93364777Snyan 93464777Snyan /* 93564777Snyan * clear interface memory, then sum to make sure its valid 93664777Snyan */ 93764777Snyan bzero(sc->mem_start, sc->mem_size); 93864777Snyan 93964777Snyan for (i = 0; i < sc->mem_size; i++) { 94064777Snyan if (sc->mem_start[i]) { 94164777Snyan device_printf(dev, "failed to clear shared memory " 942112569Sjake "at %x - check configuration\n", 94364777Snyan kvtop(sc->mem_start + i)); 94464777Snyan 94564777Snyan return (ENXIO); 94664777Snyan } 94764777Snyan } 94864777Snyan 94964777Snyan sc->mem_shared = 1; 95064777Snyan sc->mem_end = sc->mem_start + sc->mem_size; 95164777Snyan 95264777Snyan /* 95364777Snyan * allocate one xmit buffer if < 16k, two buffers otherwise 95464777Snyan */ 95564777Snyan if ((sc->mem_size < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) { 95664777Snyan sc->txb_cnt = 1; 95764777Snyan } else { 95864777Snyan sc->txb_cnt = 2; 95964777Snyan } 96064777Snyan sc->tx_page_start = 0; 96164777Snyan 96264777Snyan sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE * sc->txb_cnt; 96364777Snyan sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE; 96464777Snyan 96564777Snyan sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; 96664777Snyan 96764777Snyan return (0); 96864777Snyan} 96964777Snyan 97064777Snyan/* 97164777Snyan * Contec C-NET(98) series support routines 97264777Snyan */ 97364777Snyanstatic void 97464777Snyaned_reset_CNET98(sc, flags) 97564777Snyan struct ed_softc *sc; 97664777Snyan int flags; 97764777Snyan{ 978118557Sbde u_int init_addr = ED_CNET98_INIT; 97964777Snyan u_char tmp; 98064777Snyan 98164777Snyan /* Choose initial register address */ 98264777Snyan if (ED_TYPE98SUB(flags) != 0) { 98364777Snyan init_addr = ED_CNET98_INIT2; 98464777Snyan } 98564777Snyan#ifdef ED_DEBUG 98664777Snyan printf("ed?: initial register=%x\n", init_addr); 98764777Snyan#endif 98864777Snyan /* 98964777Snyan * Reset the board to force it into a known state. 99064777Snyan */ 99164777Snyan outb(init_addr, 0x00); /* request */ 99264777Snyan DELAY(5000); 99364777Snyan outb(init_addr, 0x01); /* cancel */ 99464777Snyan DELAY(5000); 99564777Snyan 99664777Snyan /* 99764777Snyan * Set I/O address(A15-12) and cpu type 99864777Snyan * 99964777Snyan * AAAAIXXC(8bit) 100064777Snyan * AAAA: A15-A12, I: I/O enable, XX: reserved, C: CPU type 100164777Snyan * 100264777Snyan * CPU type is 1:80286 or higher, 0:not. 100364777Snyan * But FreeBSD runs under i386 or higher, thus it must be 1. 100464777Snyan */ 100564777Snyan tmp = (rman_get_start(sc->port_res) & 0xf000) >> 8; 100664777Snyan tmp |= (0x08 | 0x01); 100764777Snyan#ifdef ED_DEBUG 100864777Snyan printf("ed?: outb(%x, %x)\n", init_addr + 2, tmp); 100964777Snyan#endif 101064777Snyan outb(init_addr + 2, tmp); 101164777Snyan DELAY(5000); 101264777Snyan 101364777Snyan /* 101464777Snyan * This is needed because some NE clones apparently don't reset the 101564777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 101664777Snyan * - this makes the probe invasive! ...Done against my better 101764777Snyan * judgement. -DLG 101864777Snyan */ 101964777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 102064777Snyan DELAY(5000); 102164777Snyan} 102264777Snyan 102364777Snyanstatic void 102464777Snyaned_winsel_CNET98(sc, bank) 102564777Snyan struct ed_softc *sc; 102664777Snyan u_short bank; 102764777Snyan{ 102864777Snyan u_char mem = (kvtop(sc->mem_start) >> 12) & 0xff; 102964777Snyan 103064777Snyan /* 103164777Snyan * Disable window memory 103264777Snyan * bit7 is 0:disable 103364777Snyan */ 103464777Snyan ed_asic_outb(sc, ED_CNET98_WIN_REG, mem & 0x7f); 103564777Snyan DELAY(10); 103664777Snyan 103764777Snyan /* 103864777Snyan * Select window address 103964777Snyan * FreeBSD address 0xf00xxxxx 104064777Snyan */ 104164777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG0L, bank & 0xff); 104264777Snyan DELAY(10); 104364777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG0H, (bank >> 8) & 0xff); 104464777Snyan DELAY(10); 104564777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG1L, 0x00); 104664777Snyan DELAY(10); 104764777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG1H, 0x41); 104864777Snyan DELAY(10); 104964777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG2L, 0x00); 105064777Snyan DELAY(10); 105164777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG2H, 0x42); 105264777Snyan DELAY(10); 105364777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG3L, 0x00); 105464777Snyan DELAY(10); 105564777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG3H, 0x43); 105664777Snyan DELAY(10); 105764777Snyan 105864777Snyan /* 105964777Snyan * Enable window memory(16Kbyte) 106064777Snyan * bit7 is 1:enable 106164777Snyan */ 106264777Snyan#ifdef ED_DEBUG 106364777Snyan printf("ed?: window start address=%x\n", mem); 106464777Snyan#endif 106564777Snyan ed_asic_outb(sc, ED_CNET98_WIN_REG, mem); 106664777Snyan DELAY(10); 106764777Snyan} 106864777Snyan 106964777Snyan/* 107064777Snyan * Probe and vendor-specific initialization routine for C-NET(98) boards 107164777Snyan */ 107264777Snyanstatic int 107364777Snyaned_probe_CNET98(dev, port_rid, flags) 107464777Snyan device_t dev; 107564777Snyan int port_rid; 107664777Snyan int flags; 107764777Snyan{ 107864777Snyan struct ed_softc *sc = device_get_softc(dev); 107964777Snyan int error; 108064777Snyan u_char tmp; 108164777Snyan u_long conf_irq, junk; 108264777Snyan int i; 108364777Snyan#ifdef DIAGNOSTIC 108464777Snyan u_char tmp_s; 108564777Snyan#endif 108664777Snyan 108764777Snyan error = ed98_alloc_port(dev, port_rid); 108864777Snyan if (error) { 108964777Snyan return (error); 109064777Snyan } 109164777Snyan 109264777Snyan sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 109364777Snyan sc->nic_offset = ED_NOVELL_NIC_OFFSET; 109464777Snyan 109564777Snyan error = ed98_alloc_memory(dev, 0); 109664777Snyan if (error) { 109764777Snyan return (error); 109864777Snyan } 109964777Snyan 110064777Snyan /* Check I/O address. 0x[a-f]3d0 are allowed. */ 110164777Snyan if (((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0) 110264777Snyan || ((rman_get_start(sc->port_res) & 0xf000) < (u_short) 0xa000)) { 110364777Snyan#ifdef DIAGNOSTIC 1104111427Snyan device_printf(dev, "Invalid i/o port configuration (0x%lx) " 110564777Snyan "must be %s for %s\n", rman_get_start(sc->port_res), 110664777Snyan "0x[a-f]3d0", "CNET98"); 110764777Snyan#endif 110864777Snyan return (ENXIO); 110964777Snyan } 111064777Snyan 111164777Snyan#ifdef DIAGNOSTIC 111264777Snyan /* Check window area address */ 111364777Snyan tmp_s = kvtop(sc->mem_start) >> 12; 111464777Snyan if (tmp_s < 0x80) { 1115112569Sjake device_printf(dev, "Please change window address(0x%x)\n", 111664777Snyan kvtop(sc->mem_start)); 111764777Snyan return (ENXIO); 111864777Snyan } 111964777Snyan 112064777Snyan tmp_s &= 0x0f; 112164777Snyan tmp = rman_get_start(sc->port_res) >> 12; 112264777Snyan if ((tmp_s <= tmp) && (tmp < (tmp_s + 4))) { 1123111427Snyan device_printf(dev, "Please change iobase address(0x%lx) " 1124112569Sjake "or window address(0x%x)\n", 112564777Snyan rman_get_start(sc->port_res), kvtop(sc->mem_start)); 112664777Snyan return (ENXIO); 112764777Snyan } 112864777Snyan#endif 112964777Snyan /* Reset the board */ 113064777Snyan ed_reset_CNET98(sc, flags); 113164777Snyan 113264777Snyan /* 113364777Snyan * This is needed because some NE clones apparently don't reset the 113464777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 113564777Snyan * - this makes the probe invasive! ...Done against my better 113664777Snyan * judgement. -DLG 113764777Snyan */ 113864777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 113964777Snyan DELAY(5000); 114064777Snyan 114164777Snyan /* Make sure that we really have an 8390 based board */ 114264777Snyan if (!ed98_probe_generic8390(sc)) { 114364777Snyan return (ENXIO); 114464777Snyan } 114564777Snyan 114664777Snyan /* 114764777Snyan * Set window ethernet address area 114864777Snyan * board memory base 0x480000 data 256byte 114964777Snyan */ 115064777Snyan ed_winsel_CNET98(sc, 0x4800); 115164777Snyan 115264777Snyan /* 115364777Snyan * Get station address from on-board ROM 115464777Snyan */ 115564777Snyan bcopy(sc->mem_start, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 115664777Snyan 115764777Snyan sc->vendor = ED_VENDOR_MISC; 115864777Snyan sc->type_str = "CNET98"; 115964777Snyan sc->isa16bit = 0; 116064777Snyan sc->cr_proto = ED_CR_RD2; 116164777Snyan 116264777Snyan /* 116364777Snyan * Set window buffer memory area 116464777Snyan * board memory base 0x400000 data 16kbyte 116564777Snyan */ 116664777Snyan ed_winsel_CNET98(sc, 0x4000); 116764777Snyan 116864777Snyan /* 116964777Snyan * clear interface memory, then sum to make sure its valid 117064777Snyan */ 117164777Snyan bzero(sc->mem_start, sc->mem_size); 117264777Snyan 117364777Snyan for (i = 0; i < sc->mem_size; i++) { 117464777Snyan if (sc->mem_start[i]) { 117564777Snyan device_printf(dev, "failed to clear shared memory " 1176112569Sjake "at %x - check configuration\n", 117764777Snyan kvtop(sc->mem_start + i)); 117864777Snyan 117964777Snyan return (ENXIO); 118064777Snyan } 118164777Snyan } 118264777Snyan 118364777Snyan sc->mem_shared = 1; 118464777Snyan sc->mem_end = sc->mem_start + sc->mem_size; 118564777Snyan 118664777Snyan sc->txb_cnt = 1; /* XXX */ 118764777Snyan sc->tx_page_start = 0; 118864777Snyan 118964777Snyan sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE; 119064777Snyan sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE; 119164777Snyan 119264777Snyan sc->mem_ring = sc->mem_start + ED_PAGE_SIZE * ED_TXBUF_SIZE; 119364777Snyan 119464777Snyan /* 119564777Snyan * Set interrupt level 119664777Snyan */ 119764777Snyan error = bus_get_resource(dev, SYS_RES_IRQ, 0, 119864777Snyan &conf_irq, &junk); 119964777Snyan if (error) 120064777Snyan return (error); 120164777Snyan 120264777Snyan switch (conf_irq) { 120364777Snyan case 3: 120464777Snyan tmp = ED_CNET98_INT_IRQ3; 120564777Snyan break; 120664777Snyan case 5: 120764777Snyan tmp = ED_CNET98_INT_IRQ5; 120864777Snyan break; 120964777Snyan case 6: 121064777Snyan tmp = ED_CNET98_INT_IRQ6; 121164777Snyan break; 121264777Snyan case 9: 121364777Snyan tmp = ED_CNET98_INT_IRQ9; 121464777Snyan break; 121564777Snyan case 12: 121664777Snyan tmp = ED_CNET98_INT_IRQ12; 121764777Snyan break; 121864777Snyan case 13: 121964777Snyan tmp = ED_CNET98_INT_IRQ13; 122064777Snyan break; 122164777Snyan default: 122264777Snyan device_printf(dev, "Invalid irq configuration (%ld) must be " 122364777Snyan "%s for %s\n", conf_irq, "3,5,6,9,12,13", "CNET98"); 122464777Snyan return (ENXIO); 122564777Snyan } 122664777Snyan ed_asic_outb(sc, ED_CNET98_INT_LEV, tmp); 122764777Snyan DELAY(1000); 122864777Snyan /* 122964777Snyan * Set interrupt mask. 123064777Snyan * bit7:1 all interrupt mask 123164777Snyan * bit1:1 timer interrupt mask 123264777Snyan * bit0:0 NS controler interrupt enable 123364777Snyan */ 123464777Snyan ed_asic_outb(sc, ED_CNET98_INT_MASK, 0x7e); 123564777Snyan DELAY(1000); 123664777Snyan 123764777Snyan return (0); 123864777Snyan} 123964777Snyan 124064777Snyan/* 124164777Snyan * Probe and vendor-specific initialization routine for C-NET(98)E/L boards 124264777Snyan */ 124364777Snyanstatic int 124464777Snyaned_probe_CNET98EL(dev, port_rid, flags) 124564777Snyan device_t dev; 124664777Snyan int port_rid; 124764777Snyan int flags; 124864777Snyan{ 124964777Snyan struct ed_softc *sc = device_get_softc(dev); 125064777Snyan int error; 125164777Snyan int i; 125264777Snyan u_char romdata[ETHER_ADDR_LEN * 2], tmp; 125364777Snyan u_long conf_irq, junk; 125464777Snyan 125564777Snyan error = ed98_alloc_port(dev, port_rid); 125664777Snyan if (error) { 125764777Snyan return (error); 125864777Snyan } 125964777Snyan 126064777Snyan sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 126164777Snyan sc->nic_offset = ED_NOVELL_NIC_OFFSET; 126264777Snyan 126364777Snyan /* Check I/O address. 0x[0-f]3d0 are allowed. */ 126464777Snyan if ((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0) { 126564777Snyan#ifdef DIAGNOSTIC 1266111427Snyan device_printf(dev, "Invalid i/o port configuration (0x%lx) " 126764777Snyan "must be %s for %s\n", rman_get_start(sc->port_res), 126864777Snyan "0x?3d0", "CNET98E/L"); 126964777Snyan#endif 127064777Snyan return (ENXIO); 127164777Snyan } 127264777Snyan 127364777Snyan /* Reset the board */ 127464777Snyan ed_reset_CNET98(sc, flags); 127564777Snyan 127664777Snyan /* 127764777Snyan * This is needed because some NE clones apparently don't reset the 127864777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 127964777Snyan * - this makes the probe invasive! ...Done against my better 128064777Snyan * judgement. -DLG 128164777Snyan */ 128264777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 128364777Snyan DELAY(5000); 128464777Snyan 128564777Snyan /* Make sure that we really have an 8390 based board */ 128664777Snyan if (!ed98_probe_generic8390(sc)) { 128764777Snyan return (ENXIO); 128864777Snyan } 128964777Snyan 129064777Snyan /* Test memory via PIO */ 129164777Snyan sc->cr_proto = ED_CR_RD2; 129264777Snyan if (!ed_pio_testmem(sc, ED_CNET98EL_PAGE_OFFSET, 1, flags)) { 129364777Snyan return (ENXIO); 129464777Snyan } 129564777Snyan 129664777Snyan /* This looks like a C-NET(98)E/L board. */ 129764777Snyan sc->type_str = "CNET98E/L"; 129864777Snyan 129964777Snyan /* 130064777Snyan * Set IRQ. C-NET(98)E/L only allows a choice of irq 3,5,6. 130164777Snyan */ 130264777Snyan error = bus_get_resource(dev, SYS_RES_IRQ, 0, 130364777Snyan &conf_irq, &junk); 130464777Snyan if (error) { 130564777Snyan return (error); 130664777Snyan } 130764777Snyan 130864777Snyan switch (conf_irq) { 130964777Snyan case 3: 131064777Snyan tmp = ED_CNET98EL_ICR_IRQ3; 131164777Snyan break; 131264777Snyan case 5: 131364777Snyan tmp = ED_CNET98EL_ICR_IRQ5; 131464777Snyan break; 131564777Snyan case 6: 131664777Snyan tmp = ED_CNET98EL_ICR_IRQ6; 131764777Snyan break; 131864777Snyan#if 0 131964777Snyan case 12: 132064777Snyan tmp = ED_CNET98EL_ICR_IRQ12; 132164777Snyan break; 132264777Snyan#endif 132364777Snyan default: 132464777Snyan device_printf(dev, "Invalid irq configuration (%ld) must be " 132564777Snyan "%s for %s\n", conf_irq, "3,5,6", "CNET98E/L"); 132664777Snyan return (ENXIO); 132764777Snyan } 132864777Snyan ed_asic_outb(sc, ED_CNET98EL_ICR, tmp); 132964777Snyan ed_asic_outb(sc, ED_CNET98EL_IMR, 0x7e); 133064777Snyan 133164777Snyan /* Get station address from on-board ROM */ 133264777Snyan ed_pio_readmem(sc, 16384, romdata, sizeof(romdata)); 133364777Snyan for (i = 0; i < ETHER_ADDR_LEN; i++) { 133464777Snyan sc->arpcom.ac_enaddr[i] = romdata[i * 2]; 133564777Snyan } 133664777Snyan 133764777Snyan /* clear any pending interrupts that might have occurred above */ 133864777Snyan ed_nic_outb(sc, ED_P0_ISR, 0xff); 133964777Snyan 134064777Snyan return (0); 134164777Snyan} 134264777Snyan 134364777Snyan/* 134464777Snyan * Probe and vendor-specific initialization routine for PC-9801-77 boards 134564777Snyan */ 134664777Snyanstatic int 134764777Snyaned_probe_NEC77(dev, port_rid, flags) 134864777Snyan device_t dev; 134964777Snyan int port_rid; 135064777Snyan int flags; 135164777Snyan{ 135264777Snyan struct ed_softc *sc = device_get_softc(dev); 135364777Snyan int error; 135464777Snyan u_char tmp; 135564777Snyan u_long conf_irq, junk; 135664777Snyan 135764777Snyan error = ed98_probe_Novell(dev, port_rid, flags); 135864777Snyan if (error) { 135964777Snyan return (error); 136064777Snyan } 136164777Snyan 136264777Snyan /* LA/T-98 does not need IRQ setting. */ 136364777Snyan if (ED_TYPE98SUB(flags) == 0) { 136464777Snyan return (0); 136564777Snyan } 136664777Snyan 136764777Snyan /* 136864777Snyan * Set IRQ. PC-9801-77 only allows a choice of irq 3,5,6,12,13. 136964777Snyan */ 137064777Snyan error = bus_get_resource(dev, SYS_RES_IRQ, 0, 137164777Snyan &conf_irq, &junk); 137264777Snyan if (error) { 137364777Snyan return (error); 137464777Snyan } 137564777Snyan 137664777Snyan switch (conf_irq) { 137764777Snyan case 3: 137864777Snyan tmp = ED_NEC77_IRQ3; 137964777Snyan break; 138064777Snyan case 5: 138164777Snyan tmp = ED_NEC77_IRQ5; 138264777Snyan break; 138364777Snyan case 6: 138464777Snyan tmp = ED_NEC77_IRQ6; 138564777Snyan break; 138664777Snyan case 12: 138764777Snyan tmp = ED_NEC77_IRQ12; 138864777Snyan break; 138964777Snyan case 13: 139064777Snyan tmp = ED_NEC77_IRQ13; 139164777Snyan break; 139264777Snyan default: 139364777Snyan device_printf(dev, "Invalid irq configuration (%ld) must be " 139464777Snyan "%s for %s\n", conf_irq, "3,5,6,12,13", "PC-9801-77"); 139564777Snyan return (ENXIO); 139664777Snyan } 139764777Snyan ed_asic_outb(sc, ED_NEC77_IRQ, tmp); 139864777Snyan 139964777Snyan return (0); 140064777Snyan} 140164777Snyan 140264777Snyan/* 140364777Snyan * Probe and vendor-specific initialization routine for EC/EP-98X boards 140464777Snyan */ 140564777Snyanstatic int 140664777Snyaned_probe_NW98X(dev, port_rid, flags) 140764777Snyan device_t dev; 140864777Snyan int port_rid; 140964777Snyan int flags; 141064777Snyan{ 141164777Snyan struct ed_softc *sc = device_get_softc(dev); 141264777Snyan int error; 141364777Snyan u_char tmp; 141464777Snyan u_long conf_irq, junk; 141564777Snyan 141664777Snyan error = ed98_probe_Novell(dev, port_rid, flags); 141764777Snyan if (error) { 141864777Snyan return (error); 141964777Snyan } 142064777Snyan 142164777Snyan /* Networld 98X3 does not need IRQ setting. */ 142264777Snyan if (ED_TYPE98SUB(flags) == 0) { 142364777Snyan return (0); 142464777Snyan } 142564777Snyan 142664777Snyan /* 142764777Snyan * Set IRQ. EC/EP-98X only allows a choice of irq 3,5,6,12,13. 142864777Snyan */ 142964777Snyan error = bus_get_resource(dev, SYS_RES_IRQ, 0, 143064777Snyan &conf_irq, &junk); 143164777Snyan if (error) { 143264777Snyan return (error); 143364777Snyan } 143464777Snyan 143564777Snyan switch (conf_irq) { 143664777Snyan case 3: 143764777Snyan tmp = ED_NW98X_IRQ3; 143864777Snyan break; 143964777Snyan case 5: 144064777Snyan tmp = ED_NW98X_IRQ5; 144164777Snyan break; 144264777Snyan case 6: 144364777Snyan tmp = ED_NW98X_IRQ6; 144464777Snyan break; 144564777Snyan case 12: 144664777Snyan tmp = ED_NW98X_IRQ12; 144764777Snyan break; 144864777Snyan case 13: 144964777Snyan tmp = ED_NW98X_IRQ13; 145064777Snyan break; 145164777Snyan default: 145264777Snyan device_printf(dev, "Invalid irq configuration (%ld) must be " 145364777Snyan "%s for %s\n", conf_irq, "3,5,6,12,13", "EC/EP-98X"); 145464777Snyan return (ENXIO); 145564777Snyan } 145664777Snyan ed_asic_outb(sc, ED_NW98X_IRQ, tmp); 145764777Snyan 145864777Snyan return (0); 145964777Snyan} 146064777Snyan 146164777Snyan/* 146264777Snyan * Read SB-9801 station address from Serial Two-Wire EEPROM 146364777Snyan */ 146464777Snyanstatic void 146564777Snyaned_get_SB98(sc) 146664777Snyan struct ed_softc *sc; 146764777Snyan{ 146864777Snyan int i, j; 146964777Snyan u_char mask, val; 147064777Snyan 147164777Snyan /* enable EEPROM acceess */ 147264777Snyan ed_asic_outb(sc, ED_SB98_EEPENA, ED_SB98_EEPENA_ENABLE); 147364777Snyan 147464777Snyan /* output start command */ 147564777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL); 147664777Snyan DELAY(ED_SB98_EEP_DELAY); 147764777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL); 147864777Snyan DELAY(ED_SB98_EEP_DELAY); 147964777Snyan 148064777Snyan /* output address (7bit) */ 148164777Snyan for (mask = 0x40; mask != 0; mask >>= 1) { 148264777Snyan val = 0; 148364777Snyan if (ED_SB98_ADDRESS & mask) 148464777Snyan val = ED_SB98_EEP_SDA; 148564777Snyan ed_asic_outb(sc, ED_SB98_EEP, val); 148664777Snyan DELAY(ED_SB98_EEP_DELAY); 148764777Snyan ed_asic_outb(sc, ED_SB98_EEP, val | ED_SB98_EEP_SCL); 148864777Snyan DELAY(ED_SB98_EEP_DELAY); 148964777Snyan } 149064777Snyan 149164777Snyan /* output READ command */ 149264777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_READ); 149364777Snyan DELAY(ED_SB98_EEP_DELAY); 149464777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_READ | ED_SB98_EEP_SCL); 149564777Snyan DELAY(ED_SB98_EEP_DELAY); 149664777Snyan 149764777Snyan /* read station address */ 149864777Snyan for (i = 0; i < ETHER_ADDR_LEN; i++) { 149964777Snyan /* output ACK */ 150064777Snyan ed_asic_outb(sc, ED_SB98_EEP, 0); 150164777Snyan DELAY(ED_SB98_EEP_DELAY); 150264777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL); 150364777Snyan DELAY(ED_SB98_EEP_DELAY); 150464777Snyan 150564777Snyan val = 0; 150664777Snyan for (j = 0; j < 8; j++) { 150764777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA); 150864777Snyan DELAY(ED_SB98_EEP_DELAY); 150964777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL); 151064777Snyan DELAY(ED_SB98_EEP_DELAY); 151164777Snyan val <<= 1; 151264777Snyan val |= (ed_asic_inb(sc, ED_SB98_EEP) & ED_SB98_EEP_SDA); 151364777Snyan DELAY(ED_SB98_EEP_DELAY); 151464777Snyan } 151564777Snyan sc->arpcom.ac_enaddr[i] = val; 151664777Snyan } 151764777Snyan 151864777Snyan /* output Last ACK */ 151964777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA); 152064777Snyan DELAY(ED_SB98_EEP_DELAY); 152164777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL); 152264777Snyan DELAY(ED_SB98_EEP_DELAY); 152364777Snyan 152464777Snyan /* output stop command */ 152564777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL); 152664777Snyan DELAY(ED_SB98_EEP_DELAY); 152764777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL); 152864777Snyan DELAY(ED_SB98_EEP_DELAY); 152964777Snyan 153064777Snyan /* disable EEPROM access */ 153164777Snyan ed_asic_outb(sc, ED_SB98_EEPENA, ED_SB98_EEPENA_DISABLE); 153264777Snyan} 153364777Snyan 153464777Snyan/* 153564777Snyan * Probe and vendor-specific initialization routine for SB-9801 boards 153664777Snyan */ 153764777Snyanstatic int 153864777Snyaned_probe_SB98(dev, port_rid, flags) 153964777Snyan device_t dev; 154064777Snyan int port_rid; 154164777Snyan int flags; 154264777Snyan{ 154364777Snyan struct ed_softc *sc = device_get_softc(dev); 154464777Snyan int error; 154564777Snyan u_char tmp; 154664777Snyan u_long conf_irq, junk; 154764777Snyan 154864777Snyan error = ed98_alloc_port(dev, port_rid); 154964777Snyan if (error) { 155064777Snyan return (error); 155164777Snyan } 155264777Snyan 155364777Snyan sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 155464777Snyan sc->nic_offset = ED_NOVELL_NIC_OFFSET; 155564777Snyan 155664777Snyan /* Check I/O address. 00d[02468ace] are allowed. */ 155764777Snyan if ((rman_get_start(sc->port_res) & ~0x000e) != 0x00d0) { 155864777Snyan#ifdef DIAGNOSTIC 1559111427Snyan device_printf(dev, "Invalid i/o port configuration (0x%lx) " 156064777Snyan "must be %s for %s\n", rman_get_start(sc->port_res), 156164777Snyan "0xd?", "SB9801"); 156264777Snyan#endif 156364777Snyan return (ENXIO); 156464777Snyan } 156564777Snyan 156664777Snyan /* Write I/O port address and read 4 times */ 156764777Snyan outb(ED_SB98_IO_INHIBIT, rman_get_start(sc->port_res) & 0xff); 156864777Snyan (void) inb(ED_SB98_IO_INHIBIT); DELAY(300); 156964777Snyan (void) inb(ED_SB98_IO_INHIBIT); DELAY(300); 157064777Snyan (void) inb(ED_SB98_IO_INHIBIT); DELAY(300); 157164777Snyan (void) inb(ED_SB98_IO_INHIBIT); DELAY(300); 157264777Snyan 157364777Snyan /* 157464777Snyan * Check IRQ. Soliton SB-9801 only allows a choice of 157564777Snyan * irq 3,5,6,12 157664777Snyan */ 157764777Snyan error = bus_get_resource(dev, SYS_RES_IRQ, 0, 157864777Snyan &conf_irq, &junk); 157964777Snyan if (error) { 158064777Snyan return (error); 158164777Snyan } 158264777Snyan 158364777Snyan switch (conf_irq) { 158464777Snyan case 3: 158564777Snyan tmp = ED_SB98_CFG_IRQ3; 158664777Snyan break; 158764777Snyan case 5: 158864777Snyan tmp = ED_SB98_CFG_IRQ5; 158964777Snyan break; 159064777Snyan case 6: 159164777Snyan tmp = ED_SB98_CFG_IRQ6; 159264777Snyan break; 159364777Snyan case 12: 159464777Snyan tmp = ED_SB98_CFG_IRQ12; 159564777Snyan break; 159664777Snyan default: 159764777Snyan device_printf(dev, "Invalid irq configuration (%ld) must be " 159864777Snyan "%s for %s\n", conf_irq, "3,5,6,12", "SB9801"); 159964777Snyan return (ENXIO); 160064777Snyan } 160164777Snyan 160264777Snyan if (flags & ED_FLAGS_DISABLE_TRANCEIVER) { 160364777Snyan tmp |= ED_SB98_CFG_ALTPORT; 160464777Snyan } 160564777Snyan ed_asic_outb(sc, ED_SB98_CFG, ED_SB98_CFG_ENABLE | tmp); 160664777Snyan ed_asic_outb(sc, ED_SB98_POLARITY, 0x01); 160764777Snyan 160864777Snyan /* Reset the board. */ 160964777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, 0x7a); 161064777Snyan DELAY(300); 161164777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, 0x79); 161264777Snyan DELAY(300); 161364777Snyan 161464777Snyan /* 161564777Snyan * This is needed because some NE clones apparently don't reset the 161664777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 161764777Snyan * - this makes the probe invasive! ...Done against my better 161864777Snyan * judgement. -DLG 161964777Snyan */ 162064777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 162164777Snyan DELAY(5000); 162264777Snyan 162364777Snyan /* Make sure that we really have an 8390 based board */ 162464777Snyan if (!ed98_probe_generic8390(sc)) { 162564777Snyan return (ENXIO); 162664777Snyan } 162764777Snyan 162864777Snyan /* Test memory via PIO */ 162964777Snyan sc->cr_proto = ED_CR_RD2; 163064777Snyan if (!ed_pio_testmem(sc, 16384, 1, flags)) { 163164777Snyan return (ENXIO); 163264777Snyan } 163364777Snyan 163464777Snyan /* This looks like an SB9801 board. */ 163564777Snyan sc->type_str = "SB9801"; 163664777Snyan 163764777Snyan /* Get station address */ 163864777Snyan ed_get_SB98(sc); 163964777Snyan 164064777Snyan /* clear any pending interrupts that might have occurred above */ 164164777Snyan ed_nic_outb(sc, ED_P0_ISR, 0xff); 164264777Snyan 164364777Snyan return (0); 164464777Snyan} 164564777Snyan 164664777Snyan/* 164764777Snyan * Test the ability to read and write to the NIC memory. 164864777Snyan */ 164964777Snyanstatic int 165064777Snyaned_pio_testmem(sc, page_offset, isa16bit, flags) 165164777Snyan struct ed_softc *sc; 165264777Snyan int page_offset; 165364777Snyan int isa16bit; 165464777Snyan int flags; 165564777Snyan{ 165664777Snyan u_long memsize; 165764777Snyan static char test_pattern[32] = "THIS is A memory TEST pattern"; 165864777Snyan char test_buffer[32]; 165964777Snyan#ifdef DIAGNOSTIC 166064777Snyan int page_end; 166164777Snyan#endif 166264777Snyan 166364777Snyan sc->vendor = ED_VENDOR_NOVELL; 166464777Snyan sc->mem_shared = 0; 166564777Snyan sc->isa16bit = isa16bit; 166664777Snyan 166764777Snyan /* 8k of memory plus an additional 8k if 16bit */ 166864777Snyan memsize = (isa16bit ? 16384 : 8192); 166964777Snyan 167064777Snyan /* 167164777Snyan * This prevents packets from being stored in the NIC memory when the 167264777Snyan * readmem routine turns on the start bit in the CR. 167364777Snyan */ 167464777Snyan ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON); 167564777Snyan 167664777Snyan /* Initialize DCR for byte/word operations */ 167764777Snyan if (isa16bit) { 167864777Snyan ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS); 167964777Snyan } else { 168064777Snyan ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS); 168164777Snyan } 168264777Snyan ed_nic_outb(sc, ED_P0_PSTART, page_offset / ED_PAGE_SIZE); 168364777Snyan ed_nic_outb(sc, ED_P0_PSTOP, (page_offset + memsize) / ED_PAGE_SIZE); 168464777Snyan#ifdef ED_DEBUG 1685137531Snyan printf("ed?: ed_pio_testmem: page start=%x, end=%lx", 168664777Snyan page_offset, page_offset + memsize); 168764777Snyan#endif 168864777Snyan 168964777Snyan /* 169064777Snyan * Write a test pattern. If this fails, then we don't know 169164777Snyan * what this board is. 169264777Snyan */ 169364777Snyan ed_pio_writemem(sc, test_pattern, page_offset, sizeof(test_pattern)); 169464777Snyan ed_pio_readmem(sc, page_offset, test_buffer, sizeof(test_pattern)); 169564777Snyan 169664777Snyan if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) { 169764777Snyan#ifdef ED_DEBUG 169864777Snyan printf("ed?: ed_pio_testmem: bcmp(page %x) NG", 169964777Snyan page_offset); 170064777Snyan#endif 170164777Snyan return (0); 170264777Snyan } 170364777Snyan 170464777Snyan#ifdef DIAGNOSTIC 170564777Snyan /* Check the bottom. */ 170664777Snyan page_end = page_offset + memsize - ED_PAGE_SIZE; 170764777Snyan ed_pio_writemem(sc, test_pattern, page_end, sizeof(test_pattern)); 170864777Snyan ed_pio_readmem(sc, page_end, test_buffer, sizeof(test_pattern)); 170964777Snyan 171064777Snyan if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) { 171164777Snyan#ifdef ED_DEBUG 171264777Snyan printf("ed?: ed_pio_testmem: bcmp(page %x) NG", 171364777Snyan page_end); 171464777Snyan#endif 171564777Snyan return (0); 171664777Snyan } 171764777Snyan#endif 171864777Snyan sc->mem_size = memsize; 171964777Snyan sc->mem_start = (char *) page_offset; 172064777Snyan sc->mem_end = sc->mem_start + memsize; 172164777Snyan sc->tx_page_start = page_offset / ED_PAGE_SIZE; 172264777Snyan 172364777Snyan /* 172464777Snyan * Use one xmit buffer if < 16k, two buffers otherwise (if not told 172564777Snyan * otherwise). 172664777Snyan */ 172764777Snyan if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) { 172864777Snyan sc->txb_cnt = 1; 172964777Snyan } else { 173064777Snyan sc->txb_cnt = 2; 173164777Snyan } 173264777Snyan 173364777Snyan sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE; 173464777Snyan sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE; 173564777Snyan 173664777Snyan sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; 173764777Snyan 173864777Snyan return (1); 173964777Snyan} 174064777Snyan#endif /* PC98 */ 174170355Simp 174270355Simpstatic device_method_t ed_isa_methods[] = { 174370355Simp /* Device interface */ 174470355Simp DEVMETHOD(device_probe, ed_isa_probe), 174570355Simp DEVMETHOD(device_attach, ed_isa_attach), 174670355Simp 174770355Simp { 0, 0 } 174870355Simp}; 174970355Simp 175070355Simpstatic driver_t ed_isa_driver = { 175170355Simp "ed", 175270355Simp ed_isa_methods, 175370355Simp sizeof(struct ed_softc) 175470355Simp}; 175570355Simp 1756113506SmdoddDRIVER_MODULE(ed, isa, ed_isa_driver, ed_devclass, 0, 0); 1757113506SmdoddMODULE_DEPEND(ed, isa, 1, 1, 1); 1758113506SmdoddMODULE_DEPEND(ed, ether, 1, 1, 1); 1759