if_fea.c revision 49301
1/*- 2 * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. The name of the author may not be used to endorse or promote products 11 * derived from this software withough specific prior written permission 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 * $Id: if_fea.c,v 1.15 1999/07/10 19:46:08 peter Exp $ 25 */ 26 27/* 28 * DEC PDQ FDDI Controller 29 * 30 * This module support the DEFEA EISA FDDI Controller. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/kernel.h> 36#include <sys/socket.h> 37 38#include <net/if.h> 39#include <net/if_arp.h> 40 41#include <sys/module.h> 42#include <sys/bus.h> 43#include <machine/bus.h> 44#include <machine/resource.h> 45#include <sys/rman.h> 46#include <i386/eisa/eisaconf.h> 47#include <dev/pdq/pdqvar.h> 48#include <dev/pdq/pdqreg.h> 49 50static void pdq_eisa_subprobe __P((pdq_bus_t, u_int32_t, u_int32_t *, u_int32_t *, u_int32_t *)); 51static void pdq_eisa_devinit __P((pdq_softc_t *)); 52static const char * pdq_eisa_match __P((eisa_id_t)); 53static int pdq_eisa_probe __P((device_t)); 54static int pdq_eisa_attach __P((device_t)); 55void pdq_eisa_intr __P((void *)); 56static int pdq_eisa_shutdown __P((device_t)); 57 58#define DEFEA_IRQS 0x0000FBA9U 59 60#define DEFEA_INTRENABLE 0x8 /* level interrupt */ 61#define DEFEA_DECODE_IRQ(n) ((DEFEA_IRQS >> ((n) << 2)) & 0x0f) 62 63#define EISA_DEVICE_ID_DEC_DEC3001 0x10a33001 64#define EISA_DEVICE_ID_DEC_DEC3002 0x10a33002 65#define EISA_DEVICE_ID_DEC_DEC3003 0x10a33003 66#define EISA_DEVICE_ID_DEC_DEC3004 0x10a33004 67 68static void 69pdq_eisa_subprobe(bc, iobase, maddr, msize, irq) 70 pdq_bus_t bc; 71 u_int32_t iobase; 72 u_int32_t *maddr; 73 u_int32_t *msize; 74 u_int32_t *irq; 75{ 76 if (irq != NULL) 77 *irq = DEFEA_DECODE_IRQ(PDQ_OS_IORD_8(bc, iobase, PDQ_EISA_IO_CONFIG_STAT_0) & 3); 78 *maddr = (PDQ_OS_IORD_8(bc, iobase, PDQ_EISA_MEM_ADD_CMP_0) << 8) 79 | (PDQ_OS_IORD_8(bc, iobase, PDQ_EISA_MEM_ADD_CMP_1) << 16); 80 *msize = (PDQ_OS_IORD_8(bc, iobase, PDQ_EISA_MEM_ADD_MASK_0) + 4) << 8; 81 82 return; 83} 84 85static void 86pdq_eisa_devinit (sc) 87 pdq_softc_t *sc; 88{ 89 pdq_uint8_t data; 90 91 /* 92 * Do the standard initialization for the DEFEA registers. 93 */ 94 PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_FUNCTION_CTRL, 0x23); 95 PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CMP_1_1, (sc->sc_iobase >> 8) & 0xF0); 96 PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CMP_0_1, (sc->sc_iobase >> 8) & 0xF0); 97 PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_SLOT_CTRL, 0x01); 98 data = PDQ_OS_IORD_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_BURST_HOLDOFF); 99#if defined(PDQ_IOMAPPED) 100 PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_BURST_HOLDOFF, data & ~1); 101#else 102 PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_BURST_HOLDOFF, data | 1); 103#endif 104 data = PDQ_OS_IORD_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CONFIG_STAT_0); 105 PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CONFIG_STAT_0, data | DEFEA_INTRENABLE); 106 107 return; 108} 109 110static const char * 111pdq_eisa_match (type) 112 eisa_id_t type; 113{ 114 switch (type) { 115 case EISA_DEVICE_ID_DEC_DEC3001: 116 case EISA_DEVICE_ID_DEC_DEC3002: 117 case EISA_DEVICE_ID_DEC_DEC3003: 118 case EISA_DEVICE_ID_DEC_DEC3004: 119 return ("DEC FDDIcontroller/EISA Adapter"); 120 break; 121 default: 122 break; 123 } 124 return (NULL); 125} 126 127static int 128pdq_eisa_probe (dev) 129 device_t dev; 130{ 131 const char *desc; 132 u_int32_t iobase; 133 u_int32_t irq; 134 u_int32_t maddr; 135 u_int32_t msize; 136 137 u_int32_t eisa_id = eisa_get_id(dev);; 138 139 desc = pdq_eisa_match(eisa_id); 140 if (!desc) { 141 return (ENXIO); 142 } 143 144 device_set_desc(dev, desc); 145 146 iobase = eisa_get_slot(dev) * EISA_SLOT_SIZE; 147 pdq_eisa_subprobe(PDQ_BUS_EISA, iobase, &maddr, &msize, &irq); 148 149 eisa_add_iospace(dev, iobase, 0x200, RESVADDR_NONE); 150 eisa_add_mspace(dev, maddr, msize, RESVADDR_NONE); 151 eisa_add_intr(dev, irq); 152 153 return (0); 154} 155 156void 157pdq_eisa_intr(xdev) 158 void *xdev; 159{ 160 device_t dev = (device_t) xdev; 161 pdq_softc_t *sc = device_get_softc(dev); 162 (void) pdq_interrupt(sc->sc_pdq); 163 164 return; 165} 166 167static int 168pdq_eisa_attach (dev) 169 device_t dev; 170{ 171 pdq_softc_t *sc = device_get_softc(dev); 172 struct resource *io = 0; 173 struct resource *irq = 0; 174 struct resource *mspace = 0; 175 int rid; 176 void *ih; 177 u_int32_t m_addr, m_size; 178 179 rid = 0; 180 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 181 0, ~0, 1, RF_ACTIVE); 182 183 if (!io) { 184 device_printf(dev, "No I/O space?!\n"); 185 goto bad; 186 } 187 188 rid = 0; 189 mspace = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 190 0, ~0, 1, RF_ACTIVE); 191 192 if (!mspace) { 193 device_printf(dev, "No memory space?!\n"); 194 goto bad; 195 } 196 197 rid = 0; 198 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 199 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 200 201 if (!irq) { 202 device_printf(dev, "No, irq?!\n"); 203 goto bad; 204 } 205 206 m_addr = rman_get_start(mspace); 207 m_size = (rman_get_end(mspace) - rman_get_start(mspace)) + 1; 208 209 sc->sc_iobase = (pdq_bus_ioport_t) rman_get_start(io); 210 sc->sc_membase = (pdq_bus_memaddr_t) pmap_mapdev(m_addr, m_size); 211 sc->sc_if.if_name = "fea"; 212 sc->sc_if.if_unit = device_get_unit(dev); 213 214 pdq_eisa_devinit(sc); 215 sc->sc_pdq = pdq_initialize(PDQ_BUS_EISA, sc->sc_membase, 216 sc->sc_if.if_name, sc->sc_if.if_unit, 217 (void *) sc, PDQ_DEFEA); 218 if (sc->sc_pdq == NULL) { 219 device_printf(dev, "initialization failed\n"); 220 goto bad; 221 } 222 223 if (bus_setup_intr(dev, irq, INTR_TYPE_NET, pdq_eisa_intr, dev, &ih)) { 224 goto bad; 225 } 226 227 bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6); 228 pdq_ifattach(sc, NULL); 229 230 return (0); 231 232bad: 233 if (io) 234 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 235 if (irq) 236 bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 237 if (mspace) 238 bus_release_resource(dev, SYS_RES_MEMORY, 0, mspace); 239 240 return (-1); 241} 242 243static int 244pdq_eisa_shutdown(dev) 245 device_t dev; 246{ 247 pdq_softc_t *sc = device_get_softc(dev); 248 249 pdq_hwreset(sc->sc_pdq); 250 251 return (0); 252} 253 254static device_method_t pdq_eisa_methods[] = { 255 DEVMETHOD(device_probe, pdq_eisa_probe), 256 DEVMETHOD(device_attach, pdq_eisa_attach), 257 DEVMETHOD(device_shutdown, pdq_eisa_shutdown), 258 259 { 0, 0 } 260}; 261 262static driver_t pdq_eisa_driver = { 263 "fea", 264 pdq_eisa_methods, 265 sizeof(pdq_softc_t), 266}; 267 268static devclass_t pdq_devclass; 269 270DRIVER_MODULE(pdq, eisa, pdq_eisa_driver, pdq_devclass, 0, 0); 271