1/* $NetBSD: if_tr_isa.c,v 1.22 2009/05/12 08:44:19 cegger Exp $ */ 2 3/* XXXJRT changes isa_attach_args too early!! */ 4 5/* 6 * Copyright (c) 1999 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Onno van der Linden. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#include <sys/cdefs.h> 35__KERNEL_RCSID(0, "$NetBSD: if_tr_isa.c,v 1.22 2009/05/12 08:44:19 cegger Exp $"); 36 37#undef TRISADEBUG 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/socket.h> 42#include <sys/device.h> 43 44#include <net/if.h> 45#include <net/if_ether.h> 46#include <net/if_media.h> 47 48#include <sys/cpu.h> 49#include <sys/bus.h> 50#include <sys/intr.h> 51 52#include <dev/isa/isavar.h> 53 54#include <dev/ic/tropicreg.h> 55#include <dev/ic/tropicvar.h> 56 57 58int tr_isa_probe(device_t, cfdata_t, void *); 59int trtcm_isa_probe(device_t, cfdata_t, void *); 60int tribm_isa_probe(device_t, cfdata_t, void *); 61void tr_isa_attach(device_t, device_t, void *); 62int tr_isa_map_io(struct isa_attach_args *, bus_space_handle_t *, 63 bus_space_handle_t *); 64void tr_isa_unmap_io(struct isa_attach_args *, bus_space_handle_t, 65 bus_space_handle_t); 66int trtcm_isa_mediachange(struct tr_softc *); 67void trtcm_isa_mediastatus(struct tr_softc *, struct ifmediareq *); 68#ifdef TRISADEBUG 69void tr_isa_dumpaip(bus_space_tag_t, bus_space_handle_t); 70#endif 71 72/* 73 * List of manufacturer specific probe routines. Order is important. 74 */ 75int (*tr_isa_probe_list[])(device_t, cfdata_t, void *) = { 76 trtcm_isa_probe, 77 tribm_isa_probe, 78 0 79 }; 80 81CFATTACH_DECL(tr_isa, sizeof(struct tr_softc), 82 tr_isa_probe, tr_isa_attach, NULL, NULL); 83 84int 85tr_isa_map_io(struct isa_attach_args *ia, bus_space_handle_t *pioh, bus_space_handle_t *mmioh) 86{ 87 bus_size_t mmio; 88 u_int8_t s; 89 90 if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 91 ia->ia_io[0].ir_size, 0, pioh)) { 92 printf("tr_isa_map_io: can't map PIO ports\n"); 93 return 1; 94 } 95 96 /* Read adapter switches and calculate addresses of MMIO. */ 97 s = bus_space_read_1(ia->ia_iot, *pioh, TR_SWITCH); 98 99 if ((s & 0xfc) < ((TR_MMIO_MINADDR - TR_MMIO_OFFSET) >> 11) || 100 (s & 0xfc) > ((TR_MMIO_MAXADDR - TR_MMIO_OFFSET) >> 11)) { 101 bus_space_unmap(ia->ia_iot, *pioh, ia->ia_io[0].ir_size); 102 return 1; 103 } 104 105 mmio = ((s & 0xfc) << 11) + TR_MMIO_OFFSET; 106 if (bus_space_map(ia->ia_memt, mmio, TR_MMIO_SIZE, 0, mmioh)) { 107 printf("tr_isa_map_io: can't map MMIO region 0x%05lx/%d\n", 108 (u_long)mmio, TR_MMIO_SIZE); 109 bus_space_unmap(ia->ia_iot, *pioh, ia->ia_io[0].ir_size); 110 return 1; 111 } 112 return 0; 113} 114 115void 116tr_isa_unmap_io(struct isa_attach_args *ia, bus_space_handle_t pioh, bus_space_handle_t mmioh) 117{ 118 bus_space_unmap(ia->ia_memt, mmioh, TR_MMIO_SIZE); 119 bus_space_unmap(ia->ia_iot, pioh, ia->ia_io[0].ir_size); 120} 121 122static u_char tr_isa_id[] = { 123 5, 0, 4, 9, 4, 3, 4, 15, 3, 6, 3, 1, 3, 1, 3, 0, 3, 9, 3, 9, 3, 0, 2, 0 124}; 125 126/* 127 * XXX handle multiple IBM TR cards (sram mapping !!) 128 */ 129 130int 131tr_isa_probe(device_t parent, cfdata_t match, void *aux) 132{ 133 struct isa_attach_args *ia = aux; 134 int i; 135 bus_size_t tr_id; 136 bus_space_handle_t sramh, pioh, mmioh; 137 int probecode; 138 int matched = 0; 139 140 if (ia->ia_nio < 1) 141 return (0); 142 if (ia->ia_niomem < 1) 143 return (0); 144 if (ia->ia_nirq < 1) 145 return (0); 146 147 if (ISA_DIRECT_CONFIG(ia)) 148 return (0); 149 150 for (i = 0; tr_isa_probe_list[i] != 0; i++) { 151 probecode = tr_isa_probe_list[i](parent, match, aux); 152 if (probecode < 0) 153 return 0; /* Fail instantly. */ 154 if (probecode > 0) 155 break; /* We have a match. */ 156 } 157 if (tr_isa_probe_list[i] == 0) 158 return 0; /* Nothing matched. */ 159 if (tr_isa_map_io(ia, &pioh, &mmioh)) 160 return 0; 161 tr_id = TR_ID_OFFSET; 162 matched = 1; 163 for (i = 0; i < sizeof(tr_isa_id); i++) { 164 if (bus_space_read_1(ia->ia_memt, mmioh, tr_id) != 165 tr_isa_id[i]) 166 matched = 0; 167 tr_id += 2; 168 } 169#ifdef TRISADEBUG 170 tr_isa_dumpaip(ia->ia_memt, mmioh); 171#endif 172 tr_isa_unmap_io(ia, pioh, mmioh); 173 if (!matched) { 174 return 0; 175 } 176 if (bus_space_map(ia->ia_memt, ia->ia_iomem[0].ir_addr, 177 ia->ia_iomem[0].ir_size, 0, &sramh)) { 178 printf("tr_isa_probe: can't map shared ram\n"); 179 return 0; 180 } 181 bus_space_unmap(ia->ia_memt, sramh, ia->ia_iomem[0].ir_size); 182 183 ia->ia_nio = 1; 184 ia->ia_niomem = 1; 185 ia->ia_nirq = 1; 186 187 ia->ia_ndrq = 0; 188 189 return 1; 190} 191 192int trtcm_setspeed(struct tr_softc *, int); 193 194void 195tr_isa_attach(device_t parent, device_t self, void *aux) 196{ 197 struct tr_softc *sc = (void *) self; 198 struct isa_attach_args *ia = aux; 199 200 printf("\n"); 201 202 sc->sc_piot = ia->ia_iot; 203 sc->sc_memt = ia->ia_memt; 204 if (tr_isa_map_io(ia, &sc->sc_pioh, &sc->sc_mmioh)) { 205 printf("tr_isa_attach: IO space vanished\n"); 206 return; 207 } 208 if (bus_space_map(sc->sc_memt, ia->ia_iomem[0].ir_addr, 209 ia->ia_iomem[0].ir_size, 0, &sc->sc_sramh)) { 210 printf("tr_isa_attach: shared ram space vanished\n"); 211 return; 212 } 213 /* set ACA offset */ 214 sc->sc_aca = TR_ACA_OFFSET; 215 sc->sc_memwinsz = ia->ia_iomem[0].ir_size; 216 sc->sc_maddr = ia->ia_iomem[0].ir_addr; 217 /* 218 * Determine total RAM on adapter and decide how much to use. 219 * XXX Since we don't use RAM paging, use sc_memwinsz for now. 220 */ 221 sc->sc_memsize = sc->sc_memwinsz; 222 sc->sc_memreserved = 0; 223 224 if (tr_reset(sc) != 0) 225 return; 226 227 if (ia->ia_aux != NULL) { 228 sc->sc_mediastatus = trtcm_isa_mediastatus; 229 sc->sc_mediachange = trtcm_isa_mediachange; 230 } 231 else { 232 sc->sc_mediastatus = NULL; 233 sc->sc_mediachange = NULL; 234 } 235 236 if (tr_attach(sc) != 0) 237 return; 238 239/* 240 * XXX 3Com 619 can use LEVEL intr 241 */ 242 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 243 IST_EDGE, IPL_NET, tr_intr, sc); 244} 245 246#ifdef TRISADEBUG 247/* 248 * Dump the adapters AIP 249 */ 250void 251tr_isa_dumpaip(bus_space_tag_t memt, bus_space_handle_t mmioh) 252{ 253 unsigned int off, val; 254 printf("AIP contents:"); 255 for (off=0; off < 256; off++) { 256 val = bus_space_read_1(memt, mmioh, TR_MAC_OFFSET + off); 257 if ((off % 16) == 0) 258 printf("\n"); 259 printf("%02x ", val); 260 } 261 printf("\n"); 262} 263#endif 264