1 1.15 martin /* $NetBSD: if_ne_mca.c,v 1.15 2008/04/28 20:23:53 martin Exp $ */ 2 1.1 jdolecek 3 1.1 jdolecek /*- 4 1.1 jdolecek * Copyright (c) 2001 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.1 jdolecek * Driver for Novell NE/2 Ethernet Adapter (and clones). 34 1.1 jdolecek * 35 1.1 jdolecek * According to Linux ne2 driver, Arco and Compex card should be also 36 1.1 jdolecek * supported by this driver. However, NetBSD driver was only tested 37 1.1 jdolecek * with the Novell adapter so far. 38 1.1 jdolecek */ 39 1.3 lukem 40 1.3 lukem #include <sys/cdefs.h> 41 1.15 martin __KERNEL_RCSID(0, "$NetBSD: if_ne_mca.c,v 1.15 2008/04/28 20:23:53 martin Exp $"); 42 1.1 jdolecek 43 1.1 jdolecek #include <sys/param.h> 44 1.1 jdolecek #include <sys/systm.h> 45 1.1 jdolecek #include <sys/mbuf.h> 46 1.1 jdolecek #include <sys/errno.h> 47 1.1 jdolecek #include <sys/device.h> 48 1.1 jdolecek #include <sys/protosw.h> 49 1.1 jdolecek #include <sys/socket.h> 50 1.1 jdolecek 51 1.1 jdolecek #include <net/if.h> 52 1.1 jdolecek #include <net/if_types.h> 53 1.1 jdolecek #include <net/if_media.h> 54 1.1 jdolecek #include <net/if_ether.h> 55 1.1 jdolecek 56 1.13 ad #include <sys/bus.h> 57 1.1 jdolecek 58 1.1 jdolecek #include <dev/ic/dp8390reg.h> 59 1.1 jdolecek #include <dev/ic/dp8390var.h> 60 1.1 jdolecek 61 1.1 jdolecek #include <dev/ic/ne2000reg.h> 62 1.1 jdolecek #include <dev/ic/ne2000var.h> 63 1.1 jdolecek 64 1.1 jdolecek #include <dev/ic/rtl80x9reg.h> 65 1.1 jdolecek #include <dev/ic/rtl80x9var.h> 66 1.1 jdolecek 67 1.1 jdolecek #include <dev/mca/mcadevs.h> 68 1.1 jdolecek #include <dev/mca/mcavar.h> 69 1.1 jdolecek 70 1.1 jdolecek #define NE2_NPORTS 0x30 71 1.1 jdolecek 72 1.1 jdolecek struct ne_mca_softc { 73 1.1 jdolecek struct ne2000_softc sc_ne2000; /* real "ne2000" softc */ 74 1.1 jdolecek 75 1.1 jdolecek /* MCA-specific goo */ 76 1.1 jdolecek void *sc_ih; /* interrupt handle */ 77 1.1 jdolecek }; 78 1.1 jdolecek 79 1.14 cube int ne_mca_match(device_t, cfdata_t , void *); 80 1.14 cube void ne_mca_attach(device_t, device_t, void *); 81 1.1 jdolecek 82 1.14 cube CFATTACH_DECL_NEW(ne_mca, sizeof(struct ne_mca_softc), 83 1.6 thorpej ne_mca_match, ne_mca_attach, NULL, NULL); 84 1.1 jdolecek 85 1.1 jdolecek static const struct ne_mca_products { 86 1.1 jdolecek u_int32_t ne_id; 87 1.1 jdolecek const char *ne_name; 88 1.1 jdolecek } ne_mca_products[] = { 89 1.1 jdolecek { MCA_PRODUCT_ARCOAE, "Arco Electronics AE/2 Ethernet Adapter" }, 90 1.1 jdolecek { MCA_PRODUCT_NE2, "Novell NE/2 Ethernet Adapter" }, 91 1.1 jdolecek { MCA_PRODUCT_CENET16, "Compex Inc. PS/2 ENET16-MC/P Microchannel Ad."}, 92 1.1 jdolecek { 0, NULL } 93 1.1 jdolecek }; 94 1.1 jdolecek 95 1.7 perry static const struct ne_mca_products *ne_mca_lookup(int id); 96 1.1 jdolecek 97 1.1 jdolecek static const struct ne_mca_products * 98 1.1 jdolecek ne_mca_lookup(int id) 99 1.1 jdolecek { 100 1.1 jdolecek const struct ne_mca_products *np; 101 1.1 jdolecek 102 1.8 perry for(np = ne_mca_products; np->ne_name; np++) 103 1.1 jdolecek if (id == np->ne_id) 104 1.1 jdolecek return (np); 105 1.1 jdolecek 106 1.1 jdolecek return (NULL); 107 1.1 jdolecek } 108 1.1 jdolecek 109 1.1 jdolecek int 110 1.14 cube ne_mca_match(device_t parent, cfdata_t cf, void *aux) 111 1.1 jdolecek { 112 1.1 jdolecek struct mca_attach_args *ma = aux; 113 1.1 jdolecek 114 1.1 jdolecek if (ne_mca_lookup(ma->ma_id)) 115 1.1 jdolecek return (1); 116 1.1 jdolecek 117 1.1 jdolecek return (0); 118 1.1 jdolecek } 119 1.1 jdolecek 120 1.1 jdolecek /* These values were taken from NE/2 ADF file */ 121 1.1 jdolecek static const int ne_mca_irq[] = { 122 1.1 jdolecek 3, 4, 5, 9 123 1.1 jdolecek }; 124 1.1 jdolecek static const int ne_mca_iobase[] = { 125 1.1 jdolecek 0, 0x1000, 0x2020, 0x8020, 0xa0a0, 0xb0b0, 0xc0c0, 0xc3d0 126 1.1 jdolecek }; 127 1.1 jdolecek 128 1.1 jdolecek void 129 1.14 cube ne_mca_attach(device_t parent, device_t self, void *aux) 130 1.1 jdolecek { 131 1.10 thorpej struct ne_mca_softc *psc = device_private(self); 132 1.1 jdolecek struct ne2000_softc *nsc = &psc->sc_ne2000; 133 1.1 jdolecek struct dp8390_softc *dsc = &nsc->sc_dp8390; 134 1.1 jdolecek struct mca_attach_args *ma = aux; 135 1.1 jdolecek bus_space_tag_t nict; 136 1.1 jdolecek bus_space_handle_t nich; 137 1.1 jdolecek bus_space_tag_t asict; 138 1.1 jdolecek bus_space_handle_t asich; 139 1.1 jdolecek int pos2, iobase, irq; 140 1.1 jdolecek const struct ne_mca_products *np; 141 1.1 jdolecek 142 1.14 cube dsc->sc_dev = self; 143 1.14 cube 144 1.1 jdolecek pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2); 145 1.1 jdolecek 146 1.1 jdolecek /* 147 1.1 jdolecek * POS register 2: (adf pos0) 148 1.8 perry * 149 1.1 jdolecek * 7 6 5 4 3 2 1 0 150 1.1 jdolecek * \_/ | \___/ \__ enable: 0=adapter disabled, 1=adapter enabled 151 1.1 jdolecek * | | \____ I/O, Mem: 001=0x1000-0x102f 010=0x2020-0x204f 152 1.1 jdolecek * | | 011=0x8020-0x804f 100=0xa0a0-0xa0cf 153 1.1 jdolecek * | | 101=0xb0b0-0xb0df 110=0xc0c0-0xc0ef 154 1.1 jdolecek * \ \ 111=0xc3d0-0xc3ff 155 1.1 jdolecek * \ \________ Boot Rom: 1=disabled 0=enabled 156 1.1 jdolecek * \__________ Interrupt level: 00=3 01=4 10=5 11=9 157 1.1 jdolecek */ 158 1.1 jdolecek 159 1.1 jdolecek np = ne_mca_lookup(ma->ma_id); 160 1.1 jdolecek 161 1.1 jdolecek iobase = ne_mca_iobase[(pos2 & 0x0e) >> 1]; 162 1.1 jdolecek irq = ne_mca_irq[(pos2 & 0x60) >> 5]; 163 1.8 perry 164 1.14 cube aprint_normal(" slot %d irq %d: %s\n", ma->ma_slot + 1, irq, 165 1.14 cube np->ne_name); 166 1.2 jdolecek 167 1.1 jdolecek nict = ma->ma_iot; 168 1.1 jdolecek 169 1.1 jdolecek /* Map the device. */ 170 1.1 jdolecek if (bus_space_map(nict, iobase, NE2_NPORTS, 0, &nich)) { 171 1.14 cube aprint_error_dev(self, "can't map i/o space\n"); 172 1.1 jdolecek return; 173 1.1 jdolecek } 174 1.1 jdolecek 175 1.1 jdolecek asict = nict; 176 1.1 jdolecek if (bus_space_subregion(nict, nich, NE2000_ASIC_OFFSET, 177 1.1 jdolecek NE2000_ASIC_NPORTS, &asich)) { 178 1.14 cube aprint_error_dev(self, "can't subregion i/o space\n"); 179 1.1 jdolecek return; 180 1.1 jdolecek } 181 1.1 jdolecek 182 1.1 jdolecek dsc->sc_regt = nict; 183 1.1 jdolecek dsc->sc_regh = nich; 184 1.1 jdolecek 185 1.1 jdolecek nsc->sc_asict = asict; 186 1.1 jdolecek nsc->sc_asich = asich; 187 1.1 jdolecek 188 1.1 jdolecek /* This interface is always enabled. */ 189 1.1 jdolecek dsc->sc_enabled = 1; 190 1.1 jdolecek 191 1.1 jdolecek dsc->sc_mediachange = NULL; 192 1.1 jdolecek dsc->sc_mediastatus = NULL; 193 1.1 jdolecek dsc->sc_media_init = NULL; 194 1.1 jdolecek dsc->init_card = NULL; 195 1.1 jdolecek 196 1.1 jdolecek /* 197 1.1 jdolecek * This is necessary for NE/2. Hopefully the other clones also work 198 1.1 jdolecek * this way. 199 1.1 jdolecek */ 200 1.1 jdolecek nsc->sc_type = NE2000_TYPE_AX88190; 201 1.1 jdolecek 202 1.1 jdolecek /* 203 1.1 jdolecek * Do generic NE2000 attach. This will read the station address 204 1.1 jdolecek * from the EEPROM. 205 1.1 jdolecek */ 206 1.1 jdolecek if (ne2000_attach(nsc, NULL)) 207 1.1 jdolecek return; 208 1.1 jdolecek 209 1.1 jdolecek /* establish interrupt handler */ 210 1.1 jdolecek psc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_NET, dp8390_intr, 211 1.1 jdolecek dsc); 212 1.1 jdolecek if (psc->sc_ih == NULL) { 213 1.14 cube aprint_error_dev(self, 214 1.14 cube "couldn't establish interrupt handler\n"); 215 1.1 jdolecek return; 216 1.1 jdolecek } 217 1.1 jdolecek } 218