1139749Simp/*- 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$ 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#include <sys/rman.h> 3964777Snyan#include <machine/resource.h> 4064777Snyan 4164777Snyan#include <net/ethernet.h> 4264777Snyan#include <net/if.h> 4364777Snyan#include <net/if_arp.h> 44149609Simp#include <net/if_media.h> 4564777Snyan#include <net/if_mib.h> 4664777Snyan 4764777Snyan#include <isa/isavar.h> 4864777Snyan 4964777Snyan#include <dev/ed/if_edvar.h> 5064777Snyan#include <dev/ed/if_edreg.h> 5164777Snyan#include <dev/ed/if_ed98.h> 5264777Snyan 53141550Simpstatic int ed98_alloc_port(device_t, int); 54141550Simpstatic int ed98_alloc_memory(device_t, int); 55141550Simpstatic int ed_pio_testmem(struct ed_softc *, int, int, int); 56141550Simpstatic int ed_probe_CNET98(device_t, int, int); 57141550Simpstatic int ed_probe_CNET98EL(device_t, int, int); 58154924Simpstatic int ed_probe_EZ98(device_t, int, int); 59141550Simpstatic int ed_probe_NEC77(device_t, int, int); 60141550Simpstatic int ed_probe_NW98X(device_t, int, int); 61141550Simpstatic int ed_probe_SB98(device_t, int, int); 62154924Simpstatic int ed_probe_SIC98(device_t, int, int); 63141550Simpstatic int ed98_probe_Novell(device_t, int, int); 64141550Simpstatic int ed98_probe_generic8390(struct ed_softc *); 65141550Simpstatic void ed_reset_CNET98(struct ed_softc *, int); 66141550Simpstatic void ed_winsel_CNET98(struct ed_softc *, u_short); 67141550Simpstatic void ed_get_SB98(struct ed_softc *); 6864777Snyan 69141550Simpstatic int ed_cbus_probe(device_t); 70141550Simpstatic int ed_cbus_attach(device_t); 7164777Snyan 7264777Snyanstatic struct isa_pnp_id ed_ids[] = { 7364777Snyan/* TODO - list up PnP boards for PC-98 */ 7464777Snyan { 0, NULL } 7564777Snyan}; 7664777Snyan 7764777Snyanstatic int 78141550Simped_cbus_probe(device_t dev) 7964777Snyan{ 8064777Snyan struct ed_softc *sc = device_get_softc(dev); 8164777Snyan int flags = device_get_flags(dev); 8264777Snyan int error = 0; 8364777Snyan 8464777Snyan sc->type = ED_TYPE98(flags); 8564777Snyan#ifdef ED_DEBUG 86141550Simp device_printf(dev, "ed_cbus_probe: sc->type=%x\n", sc->type); 8764777Snyan#endif 8864777Snyan 8964777Snyan /* Check isapnp ids */ 9064777Snyan error = ISA_PNP_PROBE(device_get_parent(dev), dev, ed_ids); 9164777Snyan#ifdef ED_DEBUG 92141550Simp device_printf(dev, "ed_cbus_probe: ISA_PNP_PROBE returns %d\n", error); 9364777Snyan#endif 9464777Snyan 9564777Snyan /* If the card had a PnP ID that didn't match any we know about */ 96141552Simp if (error == ENXIO) 9764777Snyan goto end; 9864777Snyan 9964777Snyan /* If we had some other problem. */ 100141552Simp if (!(error == 0 || error == ENOENT)) 10164777Snyan goto end; 10264777Snyan 10364777Snyan /* Heuristic probes */ 10464777Snyan#ifdef ED_DEBUG 105141550Simp device_printf(dev, "ed_cbus_probe: Heuristic probes start\n"); 10664777Snyan#endif 10764777Snyan switch (sc->type) { 10864777Snyan case ED_TYPE98_GENERIC: 10964777Snyan /* 11064777Snyan * CAUTION! 11164777Snyan * sc->type of these boards are overwritten by PC/AT's value. 11264777Snyan */ 11364777Snyan 11464777Snyan /* 11564777Snyan * SMC EtherEZ98 11664777Snyan */ 11764777Snyan error = ed_probe_EZ98(dev, 0, flags); 118141552Simp if (error == 0) 11964777Snyan goto end; 12064777Snyan 12164777Snyan ed_release_resources(dev); 12264777Snyan 12364777Snyan /* 12464777Snyan * Allied Telesis CenterCom LA-98-T 12564777Snyan */ 12664777Snyan error = ed_probe_Novell(dev, 0, flags); 127141932Simp if (error == 0) { 128141932Simp ed_Novell_read_mac(sc); 12964777Snyan goto end; 130141932Simp } 13164777Snyan break; 13264777Snyan 13364777Snyan /* 13464777Snyan * NE2000-like boards probe routine 13564777Snyan */ 13664777Snyan case ED_TYPE98_BDN: 13764777Snyan /* 13864777Snyan * ELECOM LANEED LD-BDN 13964777Snyan * PLANET SMART COM 98 EN-2298 14064777Snyan */ 14164777Snyan case ED_TYPE98_LGY: 14264777Snyan /* 14364777Snyan * MELCO LGY-98, IND-SP, IND-SS 14464777Snyan * MACNICA NE2098 14564777Snyan */ 14664777Snyan case ED_TYPE98_ICM: 14764777Snyan /* 14864777Snyan * ICM DT-ET-25, DT-ET-T5, IF-2766ET, IF-2771ET 14964777Snyan * D-Link DE-298P, DE-298 15064777Snyan */ 15164777Snyan case ED_TYPE98_EGY: 15264777Snyan /* 15364777Snyan * MELCO EGY-98 15464777Snyan * Contec C-NET(98)E-A, C-NET(98)L-A 15564777Snyan */ 15664777Snyan case ED_TYPE98_108: 15764777Snyan /* 15864777Snyan * NEC PC-9801-107,108 15964777Snyan */ 16064777Snyan case ED_TYPE98_NC5098: 16164777Snyan /* 16264777Snyan * NextCom NC5098 16364777Snyan */ 16464777Snyan error = ed98_probe_Novell(dev, 0, flags); 16564777Snyan break; 16664777Snyan 16764777Snyan /* 16864777Snyan * other boards with special probe routine 16964777Snyan */ 17064777Snyan case ED_TYPE98_SIC: 17164777Snyan /* 17264777Snyan * Allied Telesis SIC-98 17364777Snyan */ 17464777Snyan error = ed_probe_SIC98(dev, 0, flags); 17564777Snyan break; 17664777Snyan 17764777Snyan case ED_TYPE98_CNET98EL: 17864777Snyan /* 17964777Snyan * Contec C-NET(98)E/L 18064777Snyan */ 18164777Snyan error = ed_probe_CNET98EL(dev, 0, flags); 18264777Snyan break; 18364777Snyan 18464777Snyan case ED_TYPE98_CNET98: 18564777Snyan /* 18664777Snyan * Contec C-NET(98) 18764777Snyan */ 18864777Snyan error = ed_probe_CNET98(dev, 0, flags); 18964777Snyan break; 19064777Snyan 19164777Snyan case ED_TYPE98_LA98: 19264777Snyan /* 19364777Snyan * IO-DATA LA/T-98 19464777Snyan * NEC PC-9801-77,78 19564777Snyan */ 19664777Snyan error = ed_probe_NEC77(dev, 0, flags); 19764777Snyan break; 19864777Snyan 19964777Snyan case ED_TYPE98_NW98X: 20064777Snyan /* 20164777Snyan * Networld EC/EP-98X 20264777Snyan */ 20364777Snyan error = ed_probe_NW98X(dev, 0, flags); 20464777Snyan break; 20564777Snyan 20664777Snyan case ED_TYPE98_SB98: 20764777Snyan /* 20864777Snyan * Soliton SB-9801 20964777Snyan * Fujikura FN-9801 21064777Snyan */ 21164777Snyan error = ed_probe_SB98(dev, 0, flags); 21264777Snyan break; 21364777Snyan } 21464777Snyan 21564777Snyanend: 21664777Snyan#ifdef ED_DEBUG 217141550Simp device_printf(dev, "ed_cbus_probe: end, error=%d\n", error); 21864777Snyan#endif 21964777Snyan if (error == 0) 22064777Snyan error = ed_alloc_irq(dev, 0, 0); 22164777Snyan 22264777Snyan ed_release_resources(dev); 22364777Snyan return (error); 22464777Snyan} 22564777Snyan 22664777Snyanstatic int 227141550Simped_cbus_attach(dev) 22864777Snyan device_t dev; 22964777Snyan{ 23064777Snyan struct ed_softc *sc = device_get_softc(dev); 23164777Snyan int flags = device_get_flags(dev); 23264777Snyan int error; 23364777Snyan 23464777Snyan if (sc->port_used > 0) { 235141552Simp if (ED_TYPE98(flags) == ED_TYPE98_GENERIC) 236191299Simp ed_alloc_port(dev, 0, sc->port_used); 237141552Simp else 238191299Simp ed98_alloc_port(dev, 0); 23964777Snyan } 24064777Snyan if (sc->mem_used) 241191299Simp ed_alloc_memory(dev, 0, sc->mem_used); 24264777Snyan 243191299Simp ed_alloc_irq(dev, 0, 0); 24464777Snyan 245191234Simp if (sc->sc_media_ioctl == NULL) 246191234Simp ed_gen_ifmedia_init(sc); 247191234Simp error = ed_attach(dev); 24864777Snyan if (error) { 24964777Snyan ed_release_resources(dev); 25064777Snyan return (error); 25164777Snyan } 252191234Simp error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, 253191234Simp NULL, edintr, sc, &sc->irq_handle); 254191234Simp if (error) 255191234Simp ed_release_resources(dev); 256191234Simp return (error); 25764777Snyan} 25864777Snyan 25964777Snyan/* 26064777Snyan * Interrupt conversion table for EtherEZ98 26164777Snyan */ 262141495Simpstatic uint16_t ed_EZ98_intr_val[] = { 26364777Snyan 0, 26464777Snyan 3, 26564777Snyan 5, 26664777Snyan 6, 26764777Snyan 0, 26864777Snyan 9, 26964777Snyan 12, 27064777Snyan 13 27164777Snyan}; 27264777Snyan 27364777Snyanstatic int 274141550Simped_probe_EZ98(device_t dev, int port_rid, int flags) 27564777Snyan{ 27664777Snyan struct ed_softc *sc = device_get_softc(dev); 27764777Snyan int error; 27864777Snyan static unsigned short *intr_vals[] = {NULL, ed_EZ98_intr_val}; 27964777Snyan 28064777Snyan error = ed_alloc_port(dev, port_rid, ED_EZ98_IO_PORTS); 28164777Snyan if (error) { 28264777Snyan return (error); 28364777Snyan } 28464777Snyan 28564777Snyan sc->asic_offset = ED_EZ98_ASIC_OFFSET; 28664777Snyan sc->nic_offset = ED_EZ98_NIC_OFFSET; 28764777Snyan 28864777Snyan return ed_probe_WD80x3_generic(dev, flags, intr_vals); 28964777Snyan} 29064777Snyan 29164777Snyan/* 29264777Snyan * I/O conversion tables 29364777Snyan */ 29464777Snyan 29564777Snyan/* LGY-98, ICM, C-NET(98)E/L */ 29664777Snyanstatic bus_addr_t ed98_ioaddr_generic[] = { 29764777Snyan 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 29864777Snyan}; 29964777Snyan 30064777Snyan/* 30164777Snyan * Definitions for Contec C-NET(98)E/L 30264777Snyan */ 30364777Snyan#define ED_CNET98EL_ICR 2 /* Interrupt Configuration Register */ 30464777Snyan 30564777Snyan#define ED_CNET98EL_ICR_IRQ3 0x01 30664777Snyan#define ED_CNET98EL_ICR_IRQ5 0x02 30764777Snyan#define ED_CNET98EL_ICR_IRQ6 0x04 30864777Snyan#define ED_CNET98EL_ICR_IRQ12 0x20 30964777Snyan 31064777Snyan#define ED_CNET98EL_IMR 4 /* Interrupt Mask Register */ 31164777Snyan#define ED_CNET98EL_ISR 5 /* Interrupt Status Register */ 31264777Snyan 31364777Snyan/* EGY-98 */ 31464777Snyanstatic bus_addr_t ed98_ioaddr_egy98[] = { 31564777Snyan 0, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 31664777Snyan 0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e 31764777Snyan}; 31864777Snyan 31964777Snyan/* SIC-98 */ 32064777Snyanstatic bus_addr_t ed98_ioaddr_sic98[] = { 32164777Snyan 0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00, 0x0c00, 0x0e00, 32264777Snyan 0x1000, 0x1200, 0x1400, 0x1600, 0x1800, 0x1a00, 0x1c00, 0x1e00 32364777Snyan}; 32464777Snyan 32564777Snyan/* LA/T-98, LD-BDN, PC-9801-77, SB-9801 */ 32664777Snyanstatic bus_addr_t ed98_ioaddr_la98[] = { 32764777Snyan 0x0000, 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 32864777Snyan 0x8000, 0x9000, 0xa000, 0xb000, 0xc000, 0xd000, 0xe000, 0xf000, 32964777Snyan 0x0100 /* for NEC 77(see below) */ 33064777Snyan}; 33164777Snyan 33264777Snyan/* 33364777Snyan * Definitions for NEC PC-9801-77 33464777Snyan */ 33564777Snyan#define ED_NEC77_IRQ 16 /* Interrupt Configuration Register */ 33664777Snyan 33764777Snyan#define ED_NEC77_IRQ3 0x04 33864777Snyan#define ED_NEC77_IRQ5 0x06 33964777Snyan#define ED_NEC77_IRQ6 0x08 34064777Snyan#define ED_NEC77_IRQ12 0x0a 34164777Snyan#define ED_NEC77_IRQ13 0x02 34264777Snyan 34364777Snyan/* 34464777Snyan * Definitions for Soliton SB-9801 34564777Snyan */ 34664777Snyan#define ED_SB98_CFG 1 /* Board configuration */ 34764777Snyan 34864777Snyan#define ED_SB98_CFG_IRQ3 0x00 34964777Snyan#define ED_SB98_CFG_IRQ5 0x04 35064777Snyan#define ED_SB98_CFG_IRQ6 0x08 35164777Snyan#define ED_SB98_CFG_IRQ12 0x0c 35264777Snyan#define ED_SB98_CFG_ALTPORT 0x40 /* use EXTERNAL media */ 35364777Snyan#define ED_SB98_CFG_ENABLE 0xa0 /* enable configuration */ 35464777Snyan 35564777Snyan#define ED_SB98_EEPENA 2 /* EEPROM access enable */ 35664777Snyan 35764777Snyan#define ED_SB98_EEPENA_DISABLE 0x00 35864777Snyan#define ED_SB98_EEPENA_ENABLE 0x01 35964777Snyan 36064777Snyan#define ED_SB98_EEP 3 /* EEPROM access */ 36164777Snyan 36264777Snyan#define ED_SB98_EEP_SDA 0x01 /* Serial Data */ 36364777Snyan#define ED_SB98_EEP_SCL 0x02 /* Serial Clock */ 36464777Snyan#define ED_SB98_EEP_READ 0x01 /* Read Command */ 36564777Snyan 36664777Snyan#define ED_SB98_EEP_DELAY 300 36764777Snyan 36864777Snyan#define ED_SB98_ADDRESS 0x01 /* Station Address(1-6) */ 36964777Snyan 37064777Snyan#define ED_SB98_POLARITY 4 /* Polarity */ 37164777Snyan 37264777Snyan/* PC-9801-108 */ 37364777Snyanstatic bus_addr_t ed98_ioaddr_nec108[] = { 37464777Snyan 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 37564777Snyan 0x1000, 0x1002, 0x1004, 0x1006, 0x1008, 0x100a, 0x100c, 0x100e 37664777Snyan}; 37764777Snyan 37864777Snyan/* C-NET(98) */ 37964777Snyanstatic bus_addr_t ed98_ioaddr_cnet98[] = { 38064777Snyan 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 38164777Snyan 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e 38264777Snyan}; 38364777Snyan 38464777Snyan/* 38564777Snyan * Definitions for Contec C-NET(98) 38664777Snyan */ 38764777Snyan#define ED_CNET98_MAP_REG0L 0 /* MAPPING register0 Low */ 38864777Snyan#define ED_CNET98_MAP_REG1L 1 /* MAPPING register1 Low */ 38964777Snyan#define ED_CNET98_MAP_REG2L 2 /* MAPPING register2 Low */ 39064777Snyan#define ED_CNET98_MAP_REG3L 3 /* MAPPING register3 Low */ 39164777Snyan#define ED_CNET98_MAP_REG0H 4 /* MAPPING register0 Hi */ 39264777Snyan#define ED_CNET98_MAP_REG1H 5 /* MAPPING register1 Hi */ 39364777Snyan#define ED_CNET98_MAP_REG2H 6 /* MAPPING register2 Hi */ 39464777Snyan#define ED_CNET98_MAP_REG3H 7 /* MAPPING register3 Hi */ 39564777Snyan#define ED_CNET98_WIN_REG 8 /* Window register */ 39664777Snyan#define ED_CNET98_INT_LEV 9 /* Init level register */ 39764777Snyan 39864777Snyan#define ED_CNET98_INT_IRQ3 0x01 /* INT 0 */ 39964777Snyan#define ED_CNET98_INT_IRQ5 0x02 /* INT 1 */ 40064777Snyan#define ED_CNET98_INT_IRQ6 0x04 /* INT 2 */ 40164777Snyan#define ED_CNET98_INT_IRQ9 0x08 /* INT 3 */ 40264777Snyan#define ED_CNET98_INT_IRQ12 0x20 /* INT 5 */ 40364777Snyan#define ED_CNET98_INT_IRQ13 0x40 /* INT 6 */ 40464777Snyan 40564777Snyan#define ED_CNET98_INT_REQ 10 /* Init request register */ 40664777Snyan#define ED_CNET98_INT_MASK 11 /* Init mask register */ 40764777Snyan#define ED_CNET98_INT_STAT 12 /* Init status register */ 40864777Snyan#define ED_CNET98_INT_CLR 12 /* Init clear register */ 40964777Snyan#define ED_CNET98_RESERVE1 13 41064777Snyan#define ED_CNET98_RESERVE2 14 41164777Snyan#define ED_CNET98_RESERVE3 15 41264777Snyan 41364777Snyan/* EC/EP-98X, NC5098 */ 41464777Snyanstatic bus_addr_t ed98_ioaddr_nw98x[] = { 41564777Snyan 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, 41664777Snyan 0x0800, 0x0900, 0x0a00, 0x0b00, 0x0c00, 0x0d00, 0x0e00, 0x0f00, 41764777Snyan 0x1000 /* for EC/EP-98X(see below) */ 41864777Snyan}; 41964777Snyan 42064777Snyan/* 42164777Snyan * Definitions for Networld EC/EP-98X 42264777Snyan */ 42364777Snyan#define ED_NW98X_IRQ 16 /* Interrupt Configuration Register */ 42464777Snyan 42564777Snyan#define ED_NW98X_IRQ3 0x04 42664777Snyan#define ED_NW98X_IRQ5 0x06 42764777Snyan#define ED_NW98X_IRQ6 0x08 42864777Snyan#define ED_NW98X_IRQ12 0x0a 42964777Snyan#define ED_NW98X_IRQ13 0x02 43064777Snyan 43164777Snyan/* NC5098 ASIC */ 43264777Snyanstatic bus_addr_t ed98_asic_nc5098[] = { 43364777Snyan/* DATA ENADDR RESET */ 43464777Snyan 0x0000, 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x4000, 43564777Snyan 0, 0, 0, 0, 0, 0, 0, 0 43664777Snyan}; 43764777Snyan 43864777Snyan/* 43964777Snyan * Definitions for NextCom NC5098 44064777Snyan */ 44164777Snyan#define ED_NC5098_ENADDR 1 /* Station Address(1-6) */ 44264777Snyan 44364777Snyan/* 44464777Snyan * Allocate a port resource with the given resource id. 44564777Snyan */ 44664777Snyanstatic int 447141550Simped98_alloc_port(device_t dev, int rid) 44864777Snyan{ 44964777Snyan struct ed_softc *sc = device_get_softc(dev); 45064777Snyan struct resource *res; 45164777Snyan int error; 45264777Snyan bus_addr_t *io_nic, *io_asic, adj; 45364777Snyan static bus_addr_t io_res[ED_NOVELL_IO_PORTS + 1]; 45464777Snyan int i, n; 45564777Snyan int offset, reset, data; 45664777Snyan 45764777Snyan /* Set i/o table for resource manager */ 45864777Snyan io_nic = io_asic = ed98_ioaddr_generic; 45964777Snyan offset = ED_NOVELL_ASIC_OFFSET; 46064777Snyan reset = ED_NOVELL_RESET; 46164777Snyan data = ED_NOVELL_DATA; 46264777Snyan n = ED_NOVELL_IO_PORTS; 46364777Snyan 46464777Snyan switch (sc->type) { 46564777Snyan case ED_TYPE98_LGY: 46664777Snyan io_asic = ed98_ioaddr_egy98; /* XXX - Yes, we use egy98 */ 46764777Snyan offset = 0x0200; 46864777Snyan reset = 8; 46964777Snyan break; 47064777Snyan 47164777Snyan case ED_TYPE98_EGY: 47264777Snyan io_nic = io_asic = ed98_ioaddr_egy98; 47364777Snyan offset = 0x0200; 47464777Snyan reset = 8; 47564777Snyan break; 47664777Snyan 47764777Snyan case ED_TYPE98_ICM: 47864777Snyan offset = 0x0100; 47964777Snyan break; 48064777Snyan 48164777Snyan case ED_TYPE98_BDN: 48264777Snyan io_nic = io_asic = ed98_ioaddr_la98; 48364777Snyan offset = 0x0100; 48464777Snyan reset = 0x0c; 48564777Snyan break; 48664777Snyan 48764777Snyan case ED_TYPE98_SIC: 48864777Snyan io_nic = io_asic = ed98_ioaddr_sic98; 48964777Snyan offset = 0x2000; 49064777Snyan n = 16+1; 49164777Snyan break; 49264777Snyan 49364777Snyan case ED_TYPE98_108: 49464777Snyan io_nic = io_asic = ed98_ioaddr_nec108; 49564777Snyan offset = 0x0888; /* XXX - overwritten after */ 49664777Snyan reset = 1; 49764777Snyan n = 16; /* XXX - does not set ASIC i/o here */ 49864777Snyan break; 49964777Snyan 50064777Snyan case ED_TYPE98_LA98: 50164777Snyan io_nic = io_asic = ed98_ioaddr_la98; 50264777Snyan offset = 0x0100; 50364777Snyan break; 50464777Snyan 50564777Snyan case ED_TYPE98_CNET98EL: 50664777Snyan offset = 0x0400; 50764777Snyan data = 0x0e; 50864777Snyan break; 50964777Snyan 51064777Snyan case ED_TYPE98_CNET98: 51164777Snyan /* XXX - Yes, we use generic i/o here */ 51264777Snyan offset = 0x0400; 51364777Snyan break; 51464777Snyan 51564777Snyan case ED_TYPE98_NW98X: 51664777Snyan io_nic = io_asic = ed98_ioaddr_nw98x; 51764777Snyan offset = 0x1000; 51864777Snyan break; 51964777Snyan 52064777Snyan case ED_TYPE98_SB98: 52164777Snyan io_nic = io_asic = ed98_ioaddr_la98; 52264777Snyan offset = 0x0400; 52364777Snyan reset = 7; 52464777Snyan break; 52564777Snyan 52664777Snyan case ED_TYPE98_NC5098: 52764777Snyan io_nic = ed98_ioaddr_nw98x; 52864777Snyan io_asic = ed98_asic_nc5098; 52964777Snyan offset = 0x2000; 53064777Snyan reset = 7; 53164777Snyan n = 16+8; /* XXX */ 53264777Snyan break; 53364777Snyan } 53464777Snyan 53564777Snyan bcopy(io_nic, io_res, sizeof(io_nic[0]) * ED_NOVELL_ASIC_OFFSET); 536141552Simp for (i = ED_NOVELL_ASIC_OFFSET; i < ED_NOVELL_IO_PORTS; i++) 53764777Snyan io_res[i] = io_asic[i - ED_NOVELL_ASIC_OFFSET] + offset; 53864777Snyan 539141552Simp res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, io_res, n, 540141552Simp RF_ACTIVE); 541141552Simp if (!res) 54264777Snyan return (ENOENT); 54364777Snyan 54464777Snyan sc->port_res = res; 54564777Snyan sc->port_used = n; 546155874Snyan sc->port_bst = rman_get_bustag(res); 547155874Snyan sc->port_bsh = rman_get_bushandle(res); 54864777Snyan 54964777Snyan /* Re-map i/o table if needed */ 55064777Snyan switch (sc->type) { 55164777Snyan case ED_TYPE98_LA98: 55264777Snyan case ED_TYPE98_NW98X: 55364777Snyan io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset; 55464777Snyan n++; 55564777Snyan break; 55664777Snyan 55764777Snyan case ED_TYPE98_108: 55864777Snyan adj = (rman_get_start(res) & 0xf000) / 2; 55964777Snyan offset = (offset | adj) - rman_get_start(res); 56064777Snyan 561141552Simp for (n = ED_NOVELL_ASIC_OFFSET; n < ED_NOVELL_IO_PORTS; n++) 56264777Snyan io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset; 56364777Snyan break; 56464777Snyan 56564777Snyan case ED_TYPE98_CNET98: 56664777Snyan io_nic = io_asic = ed98_ioaddr_cnet98; 56764777Snyan offset = 1; 56864777Snyan 56964777Snyan bcopy(io_nic, io_res, sizeof(io_nic[0]) * ED_NOVELL_ASIC_OFFSET); 570141552Simp for (n = ED_NOVELL_ASIC_OFFSET; n < ED_NOVELL_IO_PORTS; n++) 57164777Snyan io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset; 57264777Snyan break; 57364777Snyan 57464777Snyan case ED_TYPE98_NC5098: 57564777Snyan n = ED_NOVELL_IO_PORTS; 57664777Snyan break; 57764777Snyan } 57864777Snyan 579141552Simp if (reset != ED_NOVELL_RESET) 58064777Snyan io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_RESET] = 58164777Snyan io_res[ED_NOVELL_ASIC_OFFSET + reset]; 58264777Snyan if (data != ED_NOVELL_DATA) { 58364777Snyan io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_DATA] = 58464777Snyan io_res[ED_NOVELL_ASIC_OFFSET + data]; 58564777Snyan#if 0 58664777Snyan io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_DATA + 1] = 58764777Snyan io_res[ED_NOVELL_ASIC_OFFSET + data + 1]; 58864777Snyan#endif 58964777Snyan } 59064777Snyan 59164777Snyan error = isa_load_resourcev(res, io_res, n); 592141552Simp if (error != 0) 59364777Snyan return (ENOENT); 59464777Snyan#ifdef ED_DEBUG 59564777Snyan device_printf(dev, "ed98_alloc_port: i/o ports = %d\n", n); 596141552Simp for (i = 0; i < n; i++) 59764777Snyan printf("%x,", io_res[i]); 59864777Snyan printf("\n"); 59964777Snyan#endif 60064777Snyan return (0); 60164777Snyan} 60264777Snyan 60364777Snyanstatic int 60464777Snyaned98_alloc_memory(dev, rid) 60564777Snyan device_t dev; 60664777Snyan int rid; 60764777Snyan{ 60864777Snyan struct ed_softc *sc = device_get_softc(dev); 60964777Snyan int error; 610294883Sjhibbits rman_res_t conf_maddr, conf_msize; 61164777Snyan 612141552Simp error = bus_get_resource(dev, SYS_RES_MEMORY, 0, &conf_maddr, 613141552Simp &conf_msize); 614141552Simp if (error) 61564777Snyan return (error); 61664777Snyan 617141552Simp if ((conf_maddr == 0) || (conf_msize == 0)) 61864777Snyan return (ENXIO); 61964777Snyan 62064777Snyan error = ed_alloc_memory(dev, rid, (int) conf_msize); 621141552Simp if (error) 62264777Snyan return (error); 62364777Snyan 624149558Simp sc->mem_start = 0; 62564777Snyan sc->mem_size = conf_msize; 62664777Snyan 62764777Snyan return (0); 62864777Snyan} 62964777Snyan 63064777Snyan/* 63164777Snyan * Generic probe routine for testing for the existance of a DS8390. 63264777Snyan * Must be called after the NIC has just been reset. This routine 63364777Snyan * works by looking at certain register values that are guaranteed 63464777Snyan * to be initialized a certain way after power-up or reset. Seems 63564777Snyan * not to currently work on the 83C690. 63664777Snyan * 63764777Snyan * Specifically: 63864777Snyan * 63964777Snyan * Register reset bits set bits 64064777Snyan * Command Register (CR) TXP, STA RD2, STP 64164777Snyan * Interrupt Status (ISR) RST 64264777Snyan * Interrupt Mask (IMR) All bits 64364777Snyan * Data Control (DCR) LAS 64464777Snyan * Transmit Config. (TCR) LB1, LB0 64564777Snyan * 64664777Snyan * XXX - We only check the CR register. 64764777Snyan * 64864777Snyan * Return 1 if 8390 was found, 0 if not. 64964777Snyan */ 65064777Snyan 65164777Snyanstatic int 652141550Simped98_probe_generic8390(struct ed_softc *sc) 65364777Snyan{ 65464777Snyan u_char tmp = ed_nic_inb(sc, ED_P0_CR); 65564777Snyan#ifdef DIAGNOSTIC 65664777Snyan printf("ed?: inb(ED_P0_CR)=%x\n", tmp); 65764777Snyan#endif 65864777Snyan if ((tmp & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) != 659141552Simp (ED_CR_RD2 | ED_CR_STP)) 66064777Snyan return (0); 66164777Snyan 66264777Snyan (void) ed_nic_inb(sc, ED_P0_ISR); 66364777Snyan 66464777Snyan return (1); 66564777Snyan} 66664777Snyan 66764777Snyanstatic int 668141550Simped98_probe_Novell(device_t dev, int port_rid, int flags) 66964777Snyan{ 67064777Snyan struct ed_softc *sc = device_get_softc(dev); 67164777Snyan int error; 67264777Snyan int n; 67364777Snyan u_char romdata[ETHER_ADDR_LEN * 2], tmp; 67464777Snyan 67564777Snyan#ifdef ED_DEBUG 67664777Snyan device_printf(dev, "ed98_probe_Novell: start\n"); 67764777Snyan#endif 67864777Snyan error = ed98_alloc_port(dev, port_rid); 679141552Simp if (error) 68064777Snyan return (error); 68164777Snyan 68264777Snyan sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 68364777Snyan sc->nic_offset = ED_NOVELL_NIC_OFFSET; 68464777Snyan 68564777Snyan /* Reset the board */ 68664777Snyan#ifdef ED_DEBUG 68764777Snyan device_printf(dev, "ed98_probe_Novell: reset\n"); 68864777Snyan#endif 68964777Snyan switch (sc->type) { 69064777Snyan#if 1 /* XXX - I'm not sure this is really necessary... */ 69164777Snyan case ED_TYPE98_BDN: 69264777Snyan tmp = ed_asic_inb(sc, ED_NOVELL_RESET); 69364777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, (tmp & 0xf0) | 0x08); 69464777Snyan ed_nic_outb(sc, 0x04, tmp); 69564777Snyan (void) ed_asic_inb(sc, 0x08); 69664777Snyan ed_asic_outb(sc, 0x08, tmp); 69764777Snyan ed_asic_outb(sc, 0x08, tmp & 0x7f); 69864777Snyan break; 69964777Snyan#endif 70064777Snyan case ED_TYPE98_NC5098: 70164777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, 0x00); 70264777Snyan DELAY(5000); 70364777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, 0x01); 70464777Snyan break; 70564777Snyan 70664777Snyan default: 70764777Snyan tmp = ed_asic_inb(sc, ED_NOVELL_RESET); 70864777Snyan 70964777Snyan /* 71064777Snyan * I don't know if this is necessary; probably cruft leftover from 71164777Snyan * Clarkson packet driver code. Doesn't do a thing on the boards I've 712108533Sschweikh * tested. -DG [note that an outb(0x84, 0) seems to work here, and is 71364777Snyan * non-invasive...but some boards don't seem to reset and I don't have 71464777Snyan * complete documentation on what the 'right' thing to do is...so we 71564777Snyan * do the invasive thing for now. Yuck.] 71664777Snyan */ 71764777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, tmp); 71864777Snyan break; 71964777Snyan } 72064777Snyan DELAY(5000); 72164777Snyan 72264777Snyan /* 72364777Snyan * This is needed because some NE clones apparently don't reset the 72464777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 72564777Snyan * - this makes the probe invasive! ...Done against my better 72664777Snyan * judgement. -DLG 72764777Snyan */ 72864777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 72964777Snyan DELAY(5000); 73064777Snyan 73164777Snyan /* Make sure that we really have an 8390 based board */ 732141552Simp if (!ed98_probe_generic8390(sc)) 73364777Snyan return (ENXIO); 73464777Snyan 73564777Snyan /* Test memory via PIO */ 73664777Snyan#ifdef ED_DEBUG 73764777Snyan device_printf(dev, "ed98_probe_Novell: test memory\n"); 73864777Snyan#endif 73964777Snyan sc->cr_proto = ED_CR_RD2; 740141552Simp if (!ed_pio_testmem(sc, 8192, 0, flags) && 741141552Simp !ed_pio_testmem(sc, 16384, 1, flags)) 74264777Snyan return (ENXIO); 74364777Snyan 74464777Snyan /* Setup the board type */ 74564777Snyan#ifdef ED_DEBUG 74664777Snyan device_printf(dev, "ed98_probe_Novell: board type\n"); 74764777Snyan#endif 74864777Snyan switch (sc->type) { 74964777Snyan case ED_TYPE98_BDN: 75064777Snyan sc->type_str = "LD-BDN"; 75164777Snyan break; 75264777Snyan case ED_TYPE98_EGY: 75364777Snyan sc->type_str = "EGY-98"; 75464777Snyan break; 75564777Snyan case ED_TYPE98_LGY: 75664777Snyan sc->type_str = "LGY-98"; 75764777Snyan break; 75864777Snyan case ED_TYPE98_ICM: 75964777Snyan sc->type_str = "ICM"; 76064777Snyan break; 76164777Snyan case ED_TYPE98_108: 76264777Snyan sc->type_str = "PC-9801-108"; 76364777Snyan break; 76464777Snyan case ED_TYPE98_LA98: 76564777Snyan sc->type_str = "LA-98"; 76664777Snyan break; 76764777Snyan case ED_TYPE98_NW98X: 76864777Snyan sc->type_str = "NW98X"; 76964777Snyan break; 77064777Snyan case ED_TYPE98_NC5098: 77164777Snyan sc->type_str = "NC5098"; 77264777Snyan break; 77364777Snyan default: 77464777Snyan sc->type_str = NULL; 77564777Snyan break; 77664777Snyan } 77764777Snyan 77864777Snyan /* Get station address */ 77964777Snyan switch (sc->type) { 78064777Snyan case ED_TYPE98_NC5098: 781141552Simp for (n = 0; n < ETHER_ADDR_LEN; n++) 782147256Sbrooks sc->enaddr[n] = ed_asic_inb(sc, ED_NC5098_ENADDR + n); 78364777Snyan break; 78464777Snyan 78564777Snyan default: 78664777Snyan ed_pio_readmem(sc, 0, romdata, sizeof(romdata)); 787141552Simp for (n = 0; n < ETHER_ADDR_LEN; n++) 788147256Sbrooks sc->enaddr[n] = romdata[n * (sc->isa16bit + 1)]; 78964777Snyan break; 79064777Snyan } 79164777Snyan 79264777Snyan /* clear any pending interrupts that might have occurred above */ 79364777Snyan ed_nic_outb(sc, ED_P0_ISR, 0xff); 79464777Snyan 795154924Simp sc->sc_write_mbufs = ed_pio_write_mbufs; 79664777Snyan return (0); 79764777Snyan} 79864777Snyan 79964777Snyan/* 80064777Snyan * Probe and vendor-specific initialization routine for SIC-98 boards 80164777Snyan */ 80264777Snyanstatic int 803141550Simped_probe_SIC98(device_t dev, int port_rid, int flags) 80464777Snyan{ 80564777Snyan struct ed_softc *sc = device_get_softc(dev); 80664777Snyan int error; 80764777Snyan int i; 80864777Snyan u_char sum; 80964777Snyan 81064777Snyan /* 81164777Snyan * Setup card RAM and I/O address 81264777Snyan * Kernel Virtual to segment C0000-DFFFF???? 81364777Snyan */ 81464777Snyan error = ed98_alloc_port(dev, port_rid); 815141552Simp if (error) 81664777Snyan return (error); 81764777Snyan 818121118Sshiba sc->asic_offset = ED_SIC_ASIC_OFFSET; 819121118Sshiba sc->nic_offset = ED_SIC_NIC_OFFSET; 82064777Snyan 82164777Snyan error = ed98_alloc_memory(dev, 0); 822141552Simp if (error) 82364777Snyan return (error); 82464777Snyan 82564777Snyan /* Reset card to force it into a known state. */ 82664777Snyan ed_asic_outb(sc, 0, 0x00); 82764777Snyan DELAY(100); 82864777Snyan if (ED_TYPE98SUB(flags) == 0) { 82964777Snyan /* SIC-98/SIU-98 */ 83064777Snyan ed_asic_outb(sc, 0, 0x94); 83164777Snyan DELAY(100); 83264777Snyan ed_asic_outb(sc, 0, 0x94); 83364777Snyan } else { 83464777Snyan /* SIU-98-D */ 83564777Snyan ed_asic_outb(sc, 0, 0x80); 83664777Snyan DELAY(100); 83764777Snyan ed_asic_outb(sc, 0, 0x94); 83864777Snyan DELAY(100); 83964777Snyan ed_asic_outb(sc, 0, 0x9e); 84064777Snyan } 84164777Snyan DELAY(100); 84264777Snyan 84364777Snyan /* 84464777Snyan * Here we check the card ROM, if the checksum passes, and the 84564777Snyan * type code and ethernet address check out, then we know we have 84664777Snyan * an SIC card. 84764777Snyan */ 848149558Simp sum = bus_space_read_1(sc->mem_bst, sc->mem_bsh, 6 * 2); 849141552Simp for (i = 0; i < ETHER_ADDR_LEN; i++) 850149558Simp sum ^= (sc->enaddr[i] = 851149558Simp bus_space_read_1(sc->mem_bst, sc->mem_bsh, i * 2)); 85264777Snyan#ifdef ED_DEBUG 85364777Snyan device_printf(dev, "ed_probe_sic98: got address %6D\n", 854147256Sbrooks sc->enaddr, ":"); 85564777Snyan#endif 856141552Simp if (sum != 0) 85764777Snyan return (ENXIO); 858147256Sbrooks if ((sc->enaddr[0] | sc->enaddr[1] | sc->enaddr[2]) == 0) 85964777Snyan return (ENXIO); 86064777Snyan 861121118Sshiba sc->vendor = ED_VENDOR_SIC; 86264777Snyan sc->type_str = "SIC98"; 86364777Snyan sc->isa16bit = 1; 86464777Snyan sc->cr_proto = 0; 86564777Snyan 86664777Snyan /* 86764777Snyan * SIC RAM page 0x0000-0x3fff(or 0x7fff) 86864777Snyan */ 869141552Simp if (ED_TYPE98SUB(flags) == 0) 87064777Snyan ed_asic_outb(sc, 0, 0x90); 871141552Simp else 87264777Snyan ed_asic_outb(sc, 0, 0x8e); 87364777Snyan DELAY(100); 87464777Snyan 875141550Simp error = ed_clear_memory(dev); 876141550Simp if (error) 877141550Simp return (error); 87864777Snyan 87964777Snyan sc->mem_shared = 1; 88064777Snyan sc->mem_end = sc->mem_start + sc->mem_size; 88164777Snyan 88264777Snyan /* 88364777Snyan * allocate one xmit buffer if < 16k, two buffers otherwise 88464777Snyan */ 885141552Simp if ((sc->mem_size < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) 88664777Snyan sc->txb_cnt = 1; 887141552Simp else 88864777Snyan sc->txb_cnt = 2; 88964777Snyan sc->tx_page_start = 0; 89064777Snyan 89164777Snyan sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE * sc->txb_cnt; 89264777Snyan sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE; 89364777Snyan 89464777Snyan sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; 89564777Snyan 896154924Simp sc->sc_write_mbufs = ed_shmem_write_mbufs; 89764777Snyan return (0); 89864777Snyan} 89964777Snyan 90064777Snyan/* 90164777Snyan * Contec C-NET(98) series support routines 90264777Snyan */ 90364777Snyanstatic void 904141550Simped_reset_CNET98(struct ed_softc *sc, int flags) 90564777Snyan{ 906118557Sbde u_int init_addr = ED_CNET98_INIT; 90764777Snyan u_char tmp; 90864777Snyan 90964777Snyan /* Choose initial register address */ 91064777Snyan if (ED_TYPE98SUB(flags) != 0) { 91164777Snyan init_addr = ED_CNET98_INIT2; 91264777Snyan } 91364777Snyan#ifdef ED_DEBUG 91464777Snyan printf("ed?: initial register=%x\n", init_addr); 91564777Snyan#endif 91664777Snyan /* 91764777Snyan * Reset the board to force it into a known state. 91864777Snyan */ 91964777Snyan outb(init_addr, 0x00); /* request */ 92064777Snyan DELAY(5000); 92164777Snyan outb(init_addr, 0x01); /* cancel */ 92264777Snyan DELAY(5000); 92364777Snyan 92464777Snyan /* 92564777Snyan * Set I/O address(A15-12) and cpu type 92664777Snyan * 92764777Snyan * AAAAIXXC(8bit) 92864777Snyan * AAAA: A15-A12, I: I/O enable, XX: reserved, C: CPU type 92964777Snyan * 93064777Snyan * CPU type is 1:80286 or higher, 0:not. 93164777Snyan * But FreeBSD runs under i386 or higher, thus it must be 1. 93264777Snyan */ 93364777Snyan tmp = (rman_get_start(sc->port_res) & 0xf000) >> 8; 93464777Snyan tmp |= (0x08 | 0x01); 93564777Snyan#ifdef ED_DEBUG 93664777Snyan printf("ed?: outb(%x, %x)\n", init_addr + 2, tmp); 93764777Snyan#endif 93864777Snyan outb(init_addr + 2, tmp); 93964777Snyan DELAY(5000); 94064777Snyan 94164777Snyan /* 94264777Snyan * This is needed because some NE clones apparently don't reset the 94364777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 94464777Snyan * - this makes the probe invasive! ...Done against my better 94564777Snyan * judgement. -DLG 94664777Snyan */ 94764777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 94864777Snyan DELAY(5000); 94964777Snyan} 95064777Snyan 95164777Snyanstatic void 952141550Simped_winsel_CNET98(struct ed_softc *sc, u_short bank) 95364777Snyan{ 954141550Simp u_char mem = (rman_get_start(sc->mem_res) >> 12) & 0xff; 95564777Snyan 95664777Snyan /* 95764777Snyan * Disable window memory 95864777Snyan * bit7 is 0:disable 95964777Snyan */ 96064777Snyan ed_asic_outb(sc, ED_CNET98_WIN_REG, mem & 0x7f); 96164777Snyan DELAY(10); 96264777Snyan 96364777Snyan /* 96464777Snyan * Select window address 96564777Snyan * FreeBSD address 0xf00xxxxx 96664777Snyan */ 96764777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG0L, bank & 0xff); 96864777Snyan DELAY(10); 96964777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG0H, (bank >> 8) & 0xff); 97064777Snyan DELAY(10); 97164777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG1L, 0x00); 97264777Snyan DELAY(10); 97364777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG1H, 0x41); 97464777Snyan DELAY(10); 97564777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG2L, 0x00); 97664777Snyan DELAY(10); 97764777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG2H, 0x42); 97864777Snyan DELAY(10); 97964777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG3L, 0x00); 98064777Snyan DELAY(10); 98164777Snyan ed_asic_outb(sc, ED_CNET98_MAP_REG3H, 0x43); 98264777Snyan DELAY(10); 98364777Snyan 98464777Snyan /* 98564777Snyan * Enable window memory(16Kbyte) 98664777Snyan * bit7 is 1:enable 98764777Snyan */ 98864777Snyan#ifdef ED_DEBUG 98964777Snyan printf("ed?: window start address=%x\n", mem); 99064777Snyan#endif 99164777Snyan ed_asic_outb(sc, ED_CNET98_WIN_REG, mem); 99264777Snyan DELAY(10); 99364777Snyan} 99464777Snyan 99564777Snyan/* 99664777Snyan * Probe and vendor-specific initialization routine for C-NET(98) boards 99764777Snyan */ 99864777Snyanstatic int 999141550Simped_probe_CNET98(device_t dev, int port_rid, int flags) 100064777Snyan{ 100164777Snyan struct ed_softc *sc = device_get_softc(dev); 100264777Snyan int error; 100364777Snyan u_char tmp; 1004294883Sjhibbits rman_res_t conf_irq, junk; 100564777Snyan#ifdef DIAGNOSTIC 100664777Snyan u_char tmp_s; 100764777Snyan#endif 100864777Snyan 100964777Snyan error = ed98_alloc_port(dev, port_rid); 1010141552Simp if (error) 101164777Snyan return (error); 101264777Snyan 101364777Snyan sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 101464777Snyan sc->nic_offset = ED_NOVELL_NIC_OFFSET; 101564777Snyan 101664777Snyan error = ed98_alloc_memory(dev, 0); 1017141552Simp if (error) 101864777Snyan return (error); 101964777Snyan 102064777Snyan /* Check I/O address. 0x[a-f]3d0 are allowed. */ 102164777Snyan if (((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0) 102264777Snyan || ((rman_get_start(sc->port_res) & 0xf000) < (u_short) 0xa000)) { 102364777Snyan#ifdef DIAGNOSTIC 1024297000Sjhibbits device_printf(dev, "Invalid i/o port configuration (0x%jx) " 102564777Snyan "must be %s for %s\n", rman_get_start(sc->port_res), 102664777Snyan "0x[a-f]3d0", "CNET98"); 102764777Snyan#endif 102864777Snyan return (ENXIO); 102964777Snyan } 103064777Snyan 103164777Snyan#ifdef DIAGNOSTIC 103264777Snyan /* Check window area address */ 1033141550Simp tmp_s = rman_get_start(sc->mem_res) >> 12; 103464777Snyan if (tmp_s < 0x80) { 1035297000Sjhibbits device_printf(dev, "Please change window address(0x%jx)\n", 1036141550Simp rman_get_start(sc->mem_res)); 103764777Snyan return (ENXIO); 103864777Snyan } 103964777Snyan 104064777Snyan tmp_s &= 0x0f; 104164777Snyan tmp = rman_get_start(sc->port_res) >> 12; 104264777Snyan if ((tmp_s <= tmp) && (tmp < (tmp_s + 4))) { 1043297000Sjhibbits device_printf(dev, "Please change iobase address(0x%jx) " 1044297000Sjhibbits "or window address(0x%jx)\n", 1045141550Simp rman_get_start(sc->port_res), 1046141550Simp rman_get_start(sc->mem_res)); 104764777Snyan return (ENXIO); 104864777Snyan } 104964777Snyan#endif 105064777Snyan /* Reset the board */ 105164777Snyan ed_reset_CNET98(sc, flags); 105264777Snyan 105364777Snyan /* 105464777Snyan * This is needed because some NE clones apparently don't reset the 105564777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 105664777Snyan * - this makes the probe invasive! ...Done against my better 105764777Snyan * judgement. -DLG 105864777Snyan */ 105964777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 106064777Snyan DELAY(5000); 106164777Snyan 106264777Snyan /* Make sure that we really have an 8390 based board */ 1063141552Simp if (!ed98_probe_generic8390(sc)) 106464777Snyan return (ENXIO); 106564777Snyan 106664777Snyan /* 106764777Snyan * Set window ethernet address area 106864777Snyan * board memory base 0x480000 data 256byte 106964777Snyan */ 107064777Snyan ed_winsel_CNET98(sc, 0x4800); 107164777Snyan 107264777Snyan /* 107364777Snyan * Get station address from on-board ROM 107464777Snyan */ 1075149558Simp bus_space_read_region_1(sc->mem_bst, sc->mem_bsh, sc->mem_start, 1076149558Simp sc->enaddr, ETHER_ADDR_LEN); 107764777Snyan 107864777Snyan sc->vendor = ED_VENDOR_MISC; 107964777Snyan sc->type_str = "CNET98"; 108064777Snyan sc->isa16bit = 0; 108164777Snyan sc->cr_proto = ED_CR_RD2; 108264777Snyan 108364777Snyan /* 108464777Snyan * Set window buffer memory area 108564777Snyan * board memory base 0x400000 data 16kbyte 108664777Snyan */ 108764777Snyan ed_winsel_CNET98(sc, 0x4000); 108864777Snyan 1089141550Simp error = ed_clear_memory(dev); 1090141550Simp if (error) 1091141550Simp return (error); 109264777Snyan 109364777Snyan sc->mem_shared = 1; 109464777Snyan sc->mem_end = sc->mem_start + sc->mem_size; 109564777Snyan 109664777Snyan sc->txb_cnt = 1; /* XXX */ 109764777Snyan sc->tx_page_start = 0; 109864777Snyan 109964777Snyan sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE; 110064777Snyan sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE; 110164777Snyan 110264777Snyan sc->mem_ring = sc->mem_start + ED_PAGE_SIZE * ED_TXBUF_SIZE; 110364777Snyan 110464777Snyan /* 110564777Snyan * Set interrupt level 110664777Snyan */ 1107141552Simp error = bus_get_resource(dev, SYS_RES_IRQ, 0, &conf_irq, &junk); 110864777Snyan if (error) 110964777Snyan return (error); 111064777Snyan 111164777Snyan switch (conf_irq) { 111264777Snyan case 3: 111364777Snyan tmp = ED_CNET98_INT_IRQ3; 111464777Snyan break; 111564777Snyan case 5: 111664777Snyan tmp = ED_CNET98_INT_IRQ5; 111764777Snyan break; 111864777Snyan case 6: 111964777Snyan tmp = ED_CNET98_INT_IRQ6; 112064777Snyan break; 112164777Snyan case 9: 112264777Snyan tmp = ED_CNET98_INT_IRQ9; 112364777Snyan break; 112464777Snyan case 12: 112564777Snyan tmp = ED_CNET98_INT_IRQ12; 112664777Snyan break; 112764777Snyan case 13: 112864777Snyan tmp = ED_CNET98_INT_IRQ13; 112964777Snyan break; 113064777Snyan default: 1131297000Sjhibbits device_printf(dev, "Invalid irq configuration (%jd) must be " 113264777Snyan "%s for %s\n", conf_irq, "3,5,6,9,12,13", "CNET98"); 113364777Snyan return (ENXIO); 113464777Snyan } 113564777Snyan ed_asic_outb(sc, ED_CNET98_INT_LEV, tmp); 113664777Snyan DELAY(1000); 113764777Snyan /* 113864777Snyan * Set interrupt mask. 113964777Snyan * bit7:1 all interrupt mask 114064777Snyan * bit1:1 timer interrupt mask 114164777Snyan * bit0:0 NS controler interrupt enable 114264777Snyan */ 114364777Snyan ed_asic_outb(sc, ED_CNET98_INT_MASK, 0x7e); 114464777Snyan DELAY(1000); 114564777Snyan 1146154924Simp sc->sc_write_mbufs = ed_shmem_write_mbufs; 114764777Snyan return (0); 114864777Snyan} 114964777Snyan 115064777Snyan/* 115164777Snyan * Probe and vendor-specific initialization routine for C-NET(98)E/L boards 115264777Snyan */ 115364777Snyanstatic int 1154141550Simped_probe_CNET98EL(device_t dev, int port_rid, int flags) 115564777Snyan{ 115664777Snyan struct ed_softc *sc = device_get_softc(dev); 115764777Snyan int error; 115864777Snyan int i; 115964777Snyan u_char romdata[ETHER_ADDR_LEN * 2], tmp; 1160294883Sjhibbits rman_res_t conf_irq, junk; 116164777Snyan 116264777Snyan error = ed98_alloc_port(dev, port_rid); 1163141552Simp if (error) 116464777Snyan return (error); 116564777Snyan 116664777Snyan sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 116764777Snyan sc->nic_offset = ED_NOVELL_NIC_OFFSET; 116864777Snyan 116964777Snyan /* Check I/O address. 0x[0-f]3d0 are allowed. */ 117064777Snyan if ((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0) { 117164777Snyan#ifdef DIAGNOSTIC 1172297000Sjhibbits device_printf(dev, "Invalid i/o port configuration (0x%jx) " 117364777Snyan "must be %s for %s\n", rman_get_start(sc->port_res), 117464777Snyan "0x?3d0", "CNET98E/L"); 117564777Snyan#endif 117664777Snyan return (ENXIO); 117764777Snyan } 117864777Snyan 117964777Snyan /* Reset the board */ 118064777Snyan ed_reset_CNET98(sc, flags); 118164777Snyan 118264777Snyan /* 118364777Snyan * This is needed because some NE clones apparently don't reset the 118464777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 118564777Snyan * - this makes the probe invasive! ...Done against my better 118664777Snyan * judgement. -DLG 118764777Snyan */ 118864777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 118964777Snyan DELAY(5000); 119064777Snyan 119164777Snyan /* Make sure that we really have an 8390 based board */ 1192141552Simp if (!ed98_probe_generic8390(sc)) 119364777Snyan return (ENXIO); 119464777Snyan 119564777Snyan /* Test memory via PIO */ 119664777Snyan sc->cr_proto = ED_CR_RD2; 1197141552Simp if (!ed_pio_testmem(sc, ED_CNET98EL_PAGE_OFFSET, 1, flags)) 119864777Snyan return (ENXIO); 119964777Snyan 120064777Snyan /* This looks like a C-NET(98)E/L board. */ 120164777Snyan sc->type_str = "CNET98E/L"; 120264777Snyan 120364777Snyan /* 120464777Snyan * Set IRQ. C-NET(98)E/L only allows a choice of irq 3,5,6. 120564777Snyan */ 1206141552Simp error = bus_get_resource(dev, SYS_RES_IRQ, 0, &conf_irq, &junk); 1207141552Simp if (error) 120864777Snyan return (error); 120964777Snyan 121064777Snyan switch (conf_irq) { 121164777Snyan case 3: 121264777Snyan tmp = ED_CNET98EL_ICR_IRQ3; 121364777Snyan break; 121464777Snyan case 5: 121564777Snyan tmp = ED_CNET98EL_ICR_IRQ5; 121664777Snyan break; 121764777Snyan case 6: 121864777Snyan tmp = ED_CNET98EL_ICR_IRQ6; 121964777Snyan break; 122064777Snyan#if 0 122164777Snyan case 12: 122264777Snyan tmp = ED_CNET98EL_ICR_IRQ12; 122364777Snyan break; 122464777Snyan#endif 122564777Snyan default: 1226297000Sjhibbits device_printf(dev, "Invalid irq configuration (%jd) must be " 122764777Snyan "%s for %s\n", conf_irq, "3,5,6", "CNET98E/L"); 122864777Snyan return (ENXIO); 122964777Snyan } 123064777Snyan ed_asic_outb(sc, ED_CNET98EL_ICR, tmp); 123164777Snyan ed_asic_outb(sc, ED_CNET98EL_IMR, 0x7e); 123264777Snyan 123364777Snyan /* Get station address from on-board ROM */ 123464777Snyan ed_pio_readmem(sc, 16384, romdata, sizeof(romdata)); 1235141552Simp for (i = 0; i < ETHER_ADDR_LEN; i++) 1236147256Sbrooks sc->enaddr[i] = romdata[i * 2]; 123764777Snyan 123864777Snyan /* clear any pending interrupts that might have occurred above */ 123964777Snyan ed_nic_outb(sc, ED_P0_ISR, 0xff); 124064777Snyan 1241154924Simp sc->sc_write_mbufs = ed_pio_write_mbufs; 124264777Snyan return (0); 124364777Snyan} 124464777Snyan 124564777Snyan/* 124664777Snyan * Probe and vendor-specific initialization routine for PC-9801-77 boards 124764777Snyan */ 124864777Snyanstatic int 1249141550Simped_probe_NEC77(device_t dev, int port_rid, int flags) 125064777Snyan{ 125164777Snyan struct ed_softc *sc = device_get_softc(dev); 125264777Snyan int error; 125364777Snyan u_char tmp; 1254294883Sjhibbits rman_res_t conf_irq, junk; 125564777Snyan 125664777Snyan error = ed98_probe_Novell(dev, port_rid, flags); 1257141552Simp if (error) 125864777Snyan return (error); 125964777Snyan 126064777Snyan /* LA/T-98 does not need IRQ setting. */ 1261141552Simp if (ED_TYPE98SUB(flags) == 0) 126264777Snyan return (0); 126364777Snyan 126464777Snyan /* 126564777Snyan * Set IRQ. PC-9801-77 only allows a choice of irq 3,5,6,12,13. 126664777Snyan */ 1267141552Simp error = bus_get_resource(dev, SYS_RES_IRQ, 0, &conf_irq, &junk); 1268141552Simp if (error) 126964777Snyan return (error); 127064777Snyan 127164777Snyan switch (conf_irq) { 127264777Snyan case 3: 127364777Snyan tmp = ED_NEC77_IRQ3; 127464777Snyan break; 127564777Snyan case 5: 127664777Snyan tmp = ED_NEC77_IRQ5; 127764777Snyan break; 127864777Snyan case 6: 127964777Snyan tmp = ED_NEC77_IRQ6; 128064777Snyan break; 128164777Snyan case 12: 128264777Snyan tmp = ED_NEC77_IRQ12; 128364777Snyan break; 128464777Snyan case 13: 128564777Snyan tmp = ED_NEC77_IRQ13; 128664777Snyan break; 128764777Snyan default: 1288297000Sjhibbits device_printf(dev, "Invalid irq configuration (%jd) must be " 128964777Snyan "%s for %s\n", conf_irq, "3,5,6,12,13", "PC-9801-77"); 129064777Snyan return (ENXIO); 129164777Snyan } 129264777Snyan ed_asic_outb(sc, ED_NEC77_IRQ, tmp); 129364777Snyan 129464777Snyan return (0); 129564777Snyan} 129664777Snyan 129764777Snyan/* 129864777Snyan * Probe and vendor-specific initialization routine for EC/EP-98X boards 129964777Snyan */ 130064777Snyanstatic int 1301141550Simped_probe_NW98X(device_t dev, int port_rid, int flags) 130264777Snyan{ 130364777Snyan struct ed_softc *sc = device_get_softc(dev); 130464777Snyan int error; 130564777Snyan u_char tmp; 1306294883Sjhibbits rman_res_t conf_irq, junk; 130764777Snyan 130864777Snyan error = ed98_probe_Novell(dev, port_rid, flags); 1309141552Simp if (error) 131064777Snyan return (error); 131164777Snyan 131264777Snyan /* Networld 98X3 does not need IRQ setting. */ 1313141552Simp if (ED_TYPE98SUB(flags) == 0) 131464777Snyan return (0); 131564777Snyan 131664777Snyan /* 131764777Snyan * Set IRQ. EC/EP-98X only allows a choice of irq 3,5,6,12,13. 131864777Snyan */ 1319141552Simp error = bus_get_resource(dev, SYS_RES_IRQ, 0, &conf_irq, &junk); 1320141552Simp if (error) 132164777Snyan return (error); 132264777Snyan 132364777Snyan switch (conf_irq) { 132464777Snyan case 3: 132564777Snyan tmp = ED_NW98X_IRQ3; 132664777Snyan break; 132764777Snyan case 5: 132864777Snyan tmp = ED_NW98X_IRQ5; 132964777Snyan break; 133064777Snyan case 6: 133164777Snyan tmp = ED_NW98X_IRQ6; 133264777Snyan break; 133364777Snyan case 12: 133464777Snyan tmp = ED_NW98X_IRQ12; 133564777Snyan break; 133664777Snyan case 13: 133764777Snyan tmp = ED_NW98X_IRQ13; 133864777Snyan break; 133964777Snyan default: 1340297000Sjhibbits device_printf(dev, "Invalid irq configuration (%jd) must be " 134164777Snyan "%s for %s\n", conf_irq, "3,5,6,12,13", "EC/EP-98X"); 134264777Snyan return (ENXIO); 134364777Snyan } 134464777Snyan ed_asic_outb(sc, ED_NW98X_IRQ, tmp); 134564777Snyan 134664777Snyan return (0); 134764777Snyan} 134864777Snyan 134964777Snyan/* 135064777Snyan * Read SB-9801 station address from Serial Two-Wire EEPROM 135164777Snyan */ 135264777Snyanstatic void 1353141550Simped_get_SB98(struct ed_softc *sc) 135464777Snyan{ 135564777Snyan int i, j; 135664777Snyan u_char mask, val; 135764777Snyan 135864777Snyan /* enable EEPROM acceess */ 135964777Snyan ed_asic_outb(sc, ED_SB98_EEPENA, ED_SB98_EEPENA_ENABLE); 136064777Snyan 136164777Snyan /* output start command */ 136264777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL); 136364777Snyan DELAY(ED_SB98_EEP_DELAY); 136464777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL); 136564777Snyan DELAY(ED_SB98_EEP_DELAY); 136664777Snyan 136764777Snyan /* output address (7bit) */ 136864777Snyan for (mask = 0x40; mask != 0; mask >>= 1) { 136964777Snyan val = 0; 137064777Snyan if (ED_SB98_ADDRESS & mask) 137164777Snyan val = ED_SB98_EEP_SDA; 137264777Snyan ed_asic_outb(sc, ED_SB98_EEP, val); 137364777Snyan DELAY(ED_SB98_EEP_DELAY); 137464777Snyan ed_asic_outb(sc, ED_SB98_EEP, val | ED_SB98_EEP_SCL); 137564777Snyan DELAY(ED_SB98_EEP_DELAY); 137664777Snyan } 137764777Snyan 137864777Snyan /* output READ command */ 137964777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_READ); 138064777Snyan DELAY(ED_SB98_EEP_DELAY); 138164777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_READ | ED_SB98_EEP_SCL); 138264777Snyan DELAY(ED_SB98_EEP_DELAY); 138364777Snyan 138464777Snyan /* read station address */ 138564777Snyan for (i = 0; i < ETHER_ADDR_LEN; i++) { 138664777Snyan /* output ACK */ 138764777Snyan ed_asic_outb(sc, ED_SB98_EEP, 0); 138864777Snyan DELAY(ED_SB98_EEP_DELAY); 138964777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL); 139064777Snyan DELAY(ED_SB98_EEP_DELAY); 139164777Snyan 139264777Snyan val = 0; 139364777Snyan for (j = 0; j < 8; j++) { 139464777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA); 139564777Snyan DELAY(ED_SB98_EEP_DELAY); 139664777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL); 139764777Snyan DELAY(ED_SB98_EEP_DELAY); 139864777Snyan val <<= 1; 139964777Snyan val |= (ed_asic_inb(sc, ED_SB98_EEP) & ED_SB98_EEP_SDA); 140064777Snyan DELAY(ED_SB98_EEP_DELAY); 140164777Snyan } 1402147256Sbrooks sc->enaddr[i] = val; 140364777Snyan } 140464777Snyan 140564777Snyan /* output Last ACK */ 140664777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA); 140764777Snyan DELAY(ED_SB98_EEP_DELAY); 140864777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL); 140964777Snyan DELAY(ED_SB98_EEP_DELAY); 141064777Snyan 141164777Snyan /* output stop command */ 141264777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL); 141364777Snyan DELAY(ED_SB98_EEP_DELAY); 141464777Snyan ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL); 141564777Snyan DELAY(ED_SB98_EEP_DELAY); 141664777Snyan 141764777Snyan /* disable EEPROM access */ 141864777Snyan ed_asic_outb(sc, ED_SB98_EEPENA, ED_SB98_EEPENA_DISABLE); 141964777Snyan} 142064777Snyan 142164777Snyan/* 142264777Snyan * Probe and vendor-specific initialization routine for SB-9801 boards 142364777Snyan */ 142464777Snyanstatic int 1425141550Simped_probe_SB98(device_t dev, int port_rid, int flags) 142664777Snyan{ 142764777Snyan struct ed_softc *sc = device_get_softc(dev); 142864777Snyan int error; 142964777Snyan u_char tmp; 1430294883Sjhibbits rman_res_t conf_irq, junk; 143164777Snyan 143264777Snyan error = ed98_alloc_port(dev, port_rid); 1433141552Simp if (error) 143464777Snyan return (error); 143564777Snyan 143664777Snyan sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 143764777Snyan sc->nic_offset = ED_NOVELL_NIC_OFFSET; 143864777Snyan 143964777Snyan /* Check I/O address. 00d[02468ace] are allowed. */ 144064777Snyan if ((rman_get_start(sc->port_res) & ~0x000e) != 0x00d0) { 144164777Snyan#ifdef DIAGNOSTIC 1442297000Sjhibbits device_printf(dev, "Invalid i/o port configuration (0x%jx) " 1443141552Simp "must be %s for %s\n", rman_get_start(sc->port_res), 1444141552Simp "0xd?", "SB9801"); 144564777Snyan#endif 144664777Snyan return (ENXIO); 144764777Snyan } 144864777Snyan 144964777Snyan /* Write I/O port address and read 4 times */ 145064777Snyan outb(ED_SB98_IO_INHIBIT, rman_get_start(sc->port_res) & 0xff); 145164777Snyan (void) inb(ED_SB98_IO_INHIBIT); DELAY(300); 145264777Snyan (void) inb(ED_SB98_IO_INHIBIT); DELAY(300); 145364777Snyan (void) inb(ED_SB98_IO_INHIBIT); DELAY(300); 145464777Snyan (void) inb(ED_SB98_IO_INHIBIT); DELAY(300); 145564777Snyan 145664777Snyan /* 145764777Snyan * Check IRQ. Soliton SB-9801 only allows a choice of 145864777Snyan * irq 3,5,6,12 145964777Snyan */ 1460141552Simp error = bus_get_resource(dev, SYS_RES_IRQ, 0, &conf_irq, &junk); 1461141552Simp if (error) 146264777Snyan return (error); 146364777Snyan 146464777Snyan switch (conf_irq) { 146564777Snyan case 3: 146664777Snyan tmp = ED_SB98_CFG_IRQ3; 146764777Snyan break; 146864777Snyan case 5: 146964777Snyan tmp = ED_SB98_CFG_IRQ5; 147064777Snyan break; 147164777Snyan case 6: 147264777Snyan tmp = ED_SB98_CFG_IRQ6; 147364777Snyan break; 147464777Snyan case 12: 147564777Snyan tmp = ED_SB98_CFG_IRQ12; 147664777Snyan break; 147764777Snyan default: 1478297000Sjhibbits device_printf(dev, "Invalid irq configuration (%jd) must be " 147964777Snyan "%s for %s\n", conf_irq, "3,5,6,12", "SB9801"); 148064777Snyan return (ENXIO); 148164777Snyan } 148264777Snyan 1483141552Simp if (flags & ED_FLAGS_DISABLE_TRANCEIVER) 148464777Snyan tmp |= ED_SB98_CFG_ALTPORT; 148564777Snyan ed_asic_outb(sc, ED_SB98_CFG, ED_SB98_CFG_ENABLE | tmp); 148664777Snyan ed_asic_outb(sc, ED_SB98_POLARITY, 0x01); 148764777Snyan 148864777Snyan /* Reset the board. */ 148964777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, 0x7a); 149064777Snyan DELAY(300); 149164777Snyan ed_asic_outb(sc, ED_NOVELL_RESET, 0x79); 149264777Snyan DELAY(300); 149364777Snyan 149464777Snyan /* 149564777Snyan * This is needed because some NE clones apparently don't reset the 149664777Snyan * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 149764777Snyan * - this makes the probe invasive! ...Done against my better 149864777Snyan * judgement. -DLG 149964777Snyan */ 150064777Snyan ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 150164777Snyan DELAY(5000); 150264777Snyan 150364777Snyan /* Make sure that we really have an 8390 based board */ 1504141552Simp if (!ed98_probe_generic8390(sc)) 150564777Snyan return (ENXIO); 150664777Snyan 150764777Snyan /* Test memory via PIO */ 150864777Snyan sc->cr_proto = ED_CR_RD2; 1509154924Simp if (!ed_pio_testmem(sc, 16384, 1, flags)) 151064777Snyan return (ENXIO); 151164777Snyan 151264777Snyan /* This looks like an SB9801 board. */ 151364777Snyan sc->type_str = "SB9801"; 151464777Snyan 151564777Snyan /* Get station address */ 151664777Snyan ed_get_SB98(sc); 151764777Snyan 151864777Snyan /* clear any pending interrupts that might have occurred above */ 151964777Snyan ed_nic_outb(sc, ED_P0_ISR, 0xff); 152064777Snyan 1521154924Simp sc->sc_write_mbufs = ed_pio_write_mbufs; 152264777Snyan return (0); 152364777Snyan} 152464777Snyan 152564777Snyan/* 152664777Snyan * Test the ability to read and write to the NIC memory. 152764777Snyan */ 152864777Snyanstatic int 1529141550Simped_pio_testmem(struct ed_softc *sc, int page_offset, int isa16bit, int flags) 153064777Snyan{ 153164777Snyan u_long memsize; 153264777Snyan static char test_pattern[32] = "THIS is A memory TEST pattern"; 153364777Snyan char test_buffer[32]; 153464777Snyan#ifdef DIAGNOSTIC 153564777Snyan int page_end; 153664777Snyan#endif 153764777Snyan 153864777Snyan sc->vendor = ED_VENDOR_NOVELL; 153964777Snyan sc->mem_shared = 0; 154064777Snyan sc->isa16bit = isa16bit; 154164777Snyan 154264777Snyan /* 8k of memory plus an additional 8k if 16bit */ 154364777Snyan memsize = (isa16bit ? 16384 : 8192); 154464777Snyan 154564777Snyan /* 154664777Snyan * This prevents packets from being stored in the NIC memory when the 154764777Snyan * readmem routine turns on the start bit in the CR. 154864777Snyan */ 154964777Snyan ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON); 155064777Snyan 155164777Snyan /* Initialize DCR for byte/word operations */ 1552141550Simp if (isa16bit) 155364777Snyan ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS); 1554141550Simp else 155564777Snyan ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS); 155664777Snyan ed_nic_outb(sc, ED_P0_PSTART, page_offset / ED_PAGE_SIZE); 155764777Snyan ed_nic_outb(sc, ED_P0_PSTOP, (page_offset + memsize) / ED_PAGE_SIZE); 155864777Snyan#ifdef ED_DEBUG 1559137531Snyan printf("ed?: ed_pio_testmem: page start=%x, end=%lx", 1560141552Simp page_offset, page_offset + memsize); 156164777Snyan#endif 156264777Snyan 156364777Snyan /* 156464777Snyan * Write a test pattern. If this fails, then we don't know 156564777Snyan * what this board is. 156664777Snyan */ 156764777Snyan ed_pio_writemem(sc, test_pattern, page_offset, sizeof(test_pattern)); 156864777Snyan ed_pio_readmem(sc, page_offset, test_buffer, sizeof(test_pattern)); 156964777Snyan 157064777Snyan if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) { 157164777Snyan#ifdef ED_DEBUG 1572141552Simp printf("ed?: ed_pio_testmem: bcmp(page %x) NG", page_offset); 157364777Snyan#endif 157464777Snyan return (0); 157564777Snyan } 157664777Snyan 157764777Snyan#ifdef DIAGNOSTIC 157864777Snyan /* Check the bottom. */ 157964777Snyan page_end = page_offset + memsize - ED_PAGE_SIZE; 158064777Snyan ed_pio_writemem(sc, test_pattern, page_end, sizeof(test_pattern)); 158164777Snyan ed_pio_readmem(sc, page_end, test_buffer, sizeof(test_pattern)); 158264777Snyan 158364777Snyan if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) { 158464777Snyan#ifdef ED_DEBUG 1585141552Simp printf("ed?: ed_pio_testmem: bcmp(page %x) NG", page_end); 158664777Snyan#endif 158764777Snyan return (0); 158864777Snyan } 158964777Snyan#endif 159064777Snyan sc->mem_size = memsize; 1591149558Simp sc->mem_start = page_offset; 159264777Snyan sc->mem_end = sc->mem_start + memsize; 159364777Snyan sc->tx_page_start = page_offset / ED_PAGE_SIZE; 159464777Snyan 159564777Snyan /* 159664777Snyan * Use one xmit buffer if < 16k, two buffers otherwise (if not told 159764777Snyan * otherwise). 159864777Snyan */ 1599141552Simp if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) 160064777Snyan sc->txb_cnt = 1; 1601141552Simp else 160264777Snyan sc->txb_cnt = 2; 160364777Snyan 160464777Snyan sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE; 160564777Snyan sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE; 160664777Snyan 160764777Snyan sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; 160864777Snyan 160964777Snyan return (1); 161064777Snyan} 161170355Simp 1612141550Simpstatic device_method_t ed_cbus_methods[] = { 161370355Simp /* Device interface */ 1614141550Simp DEVMETHOD(device_probe, ed_cbus_probe), 1615141550Simp DEVMETHOD(device_attach, ed_cbus_attach), 1616150136Sru DEVMETHOD(device_detach, ed_detach), 161770355Simp 161870355Simp { 0, 0 } 161970355Simp}; 162070355Simp 1621141550Simpstatic driver_t ed_cbus_driver = { 162270355Simp "ed", 1623141550Simp ed_cbus_methods, 162470355Simp sizeof(struct ed_softc) 162570355Simp}; 162670355Simp 1627141550SimpDRIVER_MODULE(ed, isa, ed_cbus_driver, ed_devclass, 0, 0); 1628113506SmdoddMODULE_DEPEND(ed, isa, 1, 1, 1); 1629113506SmdoddMODULE_DEPEND(ed, ether, 1, 1, 1); 1630