1 1.18 msaitoh /* $NetBSD: if_tra_mca.c,v 1.18 2016/07/11 11:31:51 msaitoh Exp $ */ 2 1.1 jdolecek 3 1.1 jdolecek /*- 4 1.1 jdolecek * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 1.1 jdolecek * All rights reserved. 6 1.1 jdolecek * 7 1.1 jdolecek * This code is derived from software contributed to The NetBSD Foundation 8 1.1 jdolecek * by Jaromir Dolecek. 9 1.1 jdolecek * 10 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 11 1.1 jdolecek * modification, are permitted provided that the following conditions 12 1.1 jdolecek * are met: 13 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 14 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 15 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 17 1.1 jdolecek * documentation and/or other materials provided with the distribution. 18 1.1 jdolecek * 19 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 jdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 jdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 jdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 jdolecek * POSSIBILITY OF SUCH DAMAGE. 30 1.1 jdolecek */ 31 1.1 jdolecek 32 1.1 jdolecek /* 33 1.2 jdolecek * Driver for Tiara LANCard/E II and friends adapted from if_ate_mca.c 34 1.2 jdolecek * by Dave J. Barnes 2004. 35 1.1 jdolecek */ 36 1.1 jdolecek 37 1.1 jdolecek #include <sys/cdefs.h> 38 1.18 msaitoh __KERNEL_RCSID(0, "$NetBSD: if_tra_mca.c,v 1.18 2016/07/11 11:31:51 msaitoh Exp $"); 39 1.1 jdolecek 40 1.1 jdolecek #include <sys/param.h> 41 1.1 jdolecek #include <sys/systm.h> 42 1.1 jdolecek #include <sys/device.h> 43 1.1 jdolecek #include <sys/socket.h> 44 1.1 jdolecek #include <sys/syslog.h> 45 1.1 jdolecek 46 1.1 jdolecek #include <net/if.h> 47 1.1 jdolecek #include <net/if_ether.h> 48 1.1 jdolecek #include <net/if_media.h> 49 1.1 jdolecek 50 1.8 ad #include <sys/bus.h> 51 1.8 ad #include <sys/intr.h> 52 1.1 jdolecek 53 1.1 jdolecek #include <dev/ic/mb86950reg.h> 54 1.1 jdolecek #include <dev/ic/mb86950var.h> 55 1.1 jdolecek 56 1.1 jdolecek #include <dev/mca/mcavar.h> 57 1.1 jdolecek #include <dev/mca/mcadevs.h> 58 1.1 jdolecek 59 1.14 cegger int tiara_mca_match(device_t, cfdata_t, void *); 60 1.14 cegger void tiara_mca_attach(device_t, device_t, void *); 61 1.1 jdolecek 62 1.1 jdolecek #define TIARA_NPORTS 0x20 /* 32 */ 63 1.1 jdolecek #define TIARA_PROM_ID 24 /* offset to mac addr stored in prom */ 64 1.1 jdolecek 65 1.1 jdolecek struct tiara_softc { 66 1.1 jdolecek struct mb86950_softc sc_mb86950; /* real "mb86950" softc */ 67 1.1 jdolecek 68 1.1 jdolecek /* MCA-specific goo. */ 69 1.1 jdolecek void *sc_ih; /* interrupt cookie */ 70 1.1 jdolecek }; 71 1.1 jdolecek 72 1.16 chs CFATTACH_DECL_NEW(tra_mca, sizeof(struct tiara_softc), 73 1.1 jdolecek tiara_mca_match, tiara_mca_attach, NULL, NULL); 74 1.1 jdolecek 75 1.1 jdolecek static const struct tiara_mca_product { 76 1.1 jdolecek u_int32_t tra_prodid; /* MCA product ID */ 77 1.1 jdolecek const char *tra_name; /* device name */ 78 1.1 jdolecek } tiara_mca_products[] = { 79 1.1 jdolecek { MCA_PRODUCT_TIARA, "Tiara LANCard/E2"}, 80 1.1 jdolecek { MCA_PRODUCT_TIARA_TP, "Tiara LANCard/E2 TP"}, 81 1.1 jdolecek { MCA_PRODUCT_SMC3016, "SMC 3016/MC"}, 82 1.5 christos { 0, NULL }, 83 1.1 jdolecek }; 84 1.1 jdolecek 85 1.11 dsl static const struct tiara_mca_product *tiara_mca_lookup(u_int32_t); 86 1.1 jdolecek 87 1.1 jdolecek static const struct tiara_mca_product * 88 1.12 dsl tiara_mca_lookup(u_int32_t id) 89 1.1 jdolecek { 90 1.1 jdolecek const struct tiara_mca_product *tra_p; 91 1.1 jdolecek 92 1.1 jdolecek for (tra_p = tiara_mca_products; tra_p->tra_name != NULL; tra_p++) 93 1.1 jdolecek if (id == tra_p->tra_prodid) 94 1.1 jdolecek return (tra_p); 95 1.1 jdolecek 96 1.1 jdolecek return (NULL); 97 1.1 jdolecek } 98 1.1 jdolecek 99 1.1 jdolecek int 100 1.16 chs tiara_mca_match(device_t parent, cfdata_t match, void *aux) 101 1.1 jdolecek { 102 1.1 jdolecek struct mca_attach_args *ma = (struct mca_attach_args *) aux; 103 1.1 jdolecek 104 1.1 jdolecek if (tiara_mca_lookup(ma->ma_id) != NULL) 105 1.1 jdolecek return (1); 106 1.1 jdolecek 107 1.1 jdolecek return (0); 108 1.1 jdolecek } 109 1.1 jdolecek 110 1.1 jdolecek /* see POS diagrams below for explanation */ 111 1.1 jdolecek static const int tiara_irq[] = { 112 1.1 jdolecek 3, 4, 7, 9 113 1.1 jdolecek }; 114 1.1 jdolecek static const int smc_iobase[] = { 115 1.1 jdolecek 0x300, 0x340, 0x360, 0x1980, 0x2000, 0x5680, 0x5900, 0x8080 116 1.1 jdolecek }; 117 1.1 jdolecek static const int smc_irq[] = { 118 1.1 jdolecek 9, 10, 11, 15, 3, 5, 7, 4 119 1.1 jdolecek }; 120 1.1 jdolecek 121 1.1 jdolecek void 122 1.14 cegger tiara_mca_attach(device_t parent, device_t self, void *aux) 123 1.1 jdolecek { 124 1.4 thorpej struct tiara_softc *isc = device_private(self); 125 1.1 jdolecek struct mb86950_softc *sc = &isc->sc_mb86950; 126 1.1 jdolecek struct mca_attach_args *ma = aux; 127 1.1 jdolecek bus_space_tag_t iot = ma->ma_iot; 128 1.1 jdolecek bus_space_handle_t ioh; 129 1.1 jdolecek u_int8_t myea[ETHER_ADDR_LEN]; 130 1.1 jdolecek int pos2; 131 1.1 jdolecek int iobase = 0, irq = 0; 132 1.1 jdolecek const struct tiara_mca_product *tra_p; 133 1.1 jdolecek 134 1.2 jdolecek pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2); 135 1.1 jdolecek 136 1.1 jdolecek tra_p = tiara_mca_lookup(ma->ma_id); 137 1.1 jdolecek 138 1.2 jdolecek switch (tra_p->tra_prodid) { 139 1.1 jdolecek 140 1.2 jdolecek case MCA_PRODUCT_TIARA: 141 1.2 jdolecek case MCA_PRODUCT_TIARA_TP: 142 1.1 jdolecek /* 143 1.1 jdolecek * POS register 2: (adf pos0) 144 1.1 jdolecek * 7 6 5 4 3 2 1 0 145 1.2 jdolecek * \_____/ \_/ \ \__ enable: 0=disabled, 1=enabled 146 1.1 jdolecek * \ \ \___ boot rom: 0=disabled, 1=enabled 147 1.1 jdolecek * \ \______ IRQ 00=3 01=4 10=7 11=9 148 1.1 jdolecek * \_________ Base I/O Port 149 1.2 jdolecek * 0000=0x1200 0001=0x1220 ... 1110=0x13c0 1111=0x13e0 150 1.1 jdolecek * 151 1.1 jdolecek * POS register 3: (adf pos1) not used 152 1.1 jdolecek * POS register 4: (adf pos2) not used 153 1.1 jdolecek * 154 1.1 jdolecek * POS register 5: (adf pos3) ignored 155 1.1 jdolecek * 156 1.1 jdolecek * 7 6 5 4 3 2 1 0 157 1.1 jdolecek * 1 1 0 X \____/ 158 1.1 jdolecek * \____EPROM Address 159 1.1 jdolecek */ 160 1.2 jdolecek iobase = 0x1200 + ((pos2 & 0xf0) << 1); 161 1.2 jdolecek irq = tiara_irq[((pos2 & 0x0c) >> 2)]; 162 1.1 jdolecek 163 1.1 jdolecek /* XXX SWAG for number pkts. */ 164 1.1 jdolecek /* My Tiara LANCard has 128K memory ?!? */ 165 1.1 jdolecek sc->txb_num_pkt = 4; 166 1.1 jdolecek sc->rxb_num_pkt = (65535 - 8192 - 4) / 64; 167 1.1 jdolecek /* XXX */ 168 1.1 jdolecek 169 1.2 jdolecek break; 170 1.1 jdolecek 171 1.1 jdolecek case MCA_PRODUCT_SMC3016: 172 1.1 jdolecek /* 173 1.1 jdolecek * POS register 2: (adf pos0) 174 1.1 jdolecek * 7 6 5 4 3 2 1 0 175 1.2 jdolecek * \_____/ \___/ \__ enable: 0=disabled, 1=enabled 176 1.1 jdolecek * \ \_____ I/O Address (see ioaddr table) 177 1.1 jdolecek * \__________ IRQ (see irq table) 178 1.1 jdolecek * 179 1.1 jdolecek * POS register 3: (adf pos1) ignored 180 1.2 jdolecek * 7 6 5 4 3 2 1 0 181 1.1 jdolecek * X X X X \____/ 182 1.1 jdolecek * \____EPROM Address (0000 = not used) 183 1.2 jdolecek */ 184 1.1 jdolecek iobase = smc_iobase[((pos2 & 0x0e) >> 1)]; 185 1.2 jdolecek if ((pos2 & 0x80) != 0) 186 1.2 jdolecek irq = smc_irq[((pos2 & 0x70) >> 4)]; 187 1.2 jdolecek else { 188 1.16 chs aprint_error_dev(self, "unsupported irq selected\n"); 189 1.2 jdolecek return; 190 1.2 jdolecek } 191 1.1 jdolecek 192 1.1 jdolecek /* XXX SWAG for number pkts. */ 193 1.1 jdolecek /* The SMC3016 has a 12K rx buffer and a 4k tx buffer */ 194 1.1 jdolecek sc->txb_num_pkt = 2; 195 1.1 jdolecek sc->rxb_num_pkt = (12288 - 4) / 64; 196 1.1 jdolecek /* XXX */ 197 1.1 jdolecek 198 1.2 jdolecek break; 199 1.2 jdolecek } 200 1.1 jdolecek 201 1.1 jdolecek 202 1.1 jdolecek #ifdef DIAGNOSTIC 203 1.1 jdolecek tra_p = tiara_mca_lookup(ma->ma_id); 204 1.1 jdolecek if (tra_p == NULL) { 205 1.9 cegger aprint_normal("\n"); 206 1.16 chs aprint_error_dev(self, "where did the card go?\n"); 207 1.1 jdolecek return; 208 1.1 jdolecek } 209 1.1 jdolecek #endif 210 1.1 jdolecek 211 1.18 msaitoh printf(" slot %d ports %#x-%#x irq %d: %s\n", ma->ma_slot + 1,iobase, 212 1.18 msaitoh iobase + TIARA_NPORTS, irq, tra_p->tra_name); 213 1.1 jdolecek 214 1.1 jdolecek /* Map i/o space. */ 215 1.1 jdolecek if (bus_space_map(iot, iobase, TIARA_NPORTS, 0, &ioh)) { 216 1.16 chs aprint_error_dev(self, "can't map i/o space\n"); 217 1.1 jdolecek return; 218 1.1 jdolecek } 219 1.1 jdolecek 220 1.16 chs sc->sc_dev = self; 221 1.1 jdolecek sc->sc_bst = iot; 222 1.1 jdolecek sc->sc_bsh = ioh; 223 1.1 jdolecek 224 1.1 jdolecek /* Get ethernet address from PROM */ 225 1.1 jdolecek bus_space_read_region_1(iot, ioh, TIARA_PROM_ID, myea, ETHER_ADDR_LEN); 226 1.1 jdolecek 227 1.1 jdolecek /* This interface is always enabled. */ 228 1.2 jdolecek /* XXX 229 1.1 jdolecek sc->sc_stat |= NIC_STAT_ENABLED; 230 1.2 jdolecek */ 231 1.2 jdolecek 232 1.1 jdolecek /* 233 1.1 jdolecek * Do generic MB86950 attach. 234 1.1 jdolecek */ 235 1.1 jdolecek mb86950_attach(sc, myea); 236 1.1 jdolecek 237 1.1 jdolecek 238 1.1 jdolecek mb86950_config(sc, NULL, 0, 0); 239 1.1 jdolecek 240 1.1 jdolecek /* Establish the interrupt handler. */ 241 1.1 jdolecek isc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_NET, 242 1.1 jdolecek mb86950_intr, sc); 243 1.1 jdolecek if (isc->sc_ih == NULL) { 244 1.18 msaitoh aprint_error_dev(self, 245 1.18 msaitoh "couldn't establish interrupt handler\n"); 246 1.1 jdolecek return; 247 1.1 jdolecek } 248 1.1 jdolecek } 249