1/*- 2 * Copyright (c) 2005, M. Warner Losh 3 * All rights reserved. 4 * Copyright (c) 1995, David Greenman 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD$"); 32 33#include "opt_ed.h" 34 35#ifdef ED_3C503 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/sockio.h> 40#include <sys/mbuf.h> 41#include <sys/kernel.h> 42#include <sys/socket.h> 43#include <sys/syslog.h> 44 45#include <sys/bus.h> 46 47#include <machine/bus.h> 48#include <sys/rman.h> 49#include <machine/resource.h> 50 51#include <net/ethernet.h> 52#include <net/if.h> 53#include <net/if_var.h> /* XXX: ed_3c503_mediachg() */ 54#include <net/if_arp.h> 55#include <net/if_dl.h> 56#include <net/if_mib.h> 57#include <net/if_media.h> 58 59#include <net/bpf.h> 60 61#include <dev/ed/if_edreg.h> 62#include <dev/ed/if_edvar.h> 63 64static void ed_3c503_mediachg(struct ed_softc *sc); 65 66/* 67 * Probe and vendor-specific initialization routine for 3Com 3c503 boards 68 */ 69int 70ed_probe_3Com(device_t dev, int port_rid, int flags) 71{ 72 struct ed_softc *sc = device_get_softc(dev); 73 int error; 74 int i; 75 u_int memsize; 76 u_char isa16bit; 77 rman_res_t conf_maddr, conf_msize, irq, junk, pmem; 78 79 error = ed_alloc_port(dev, 0, ED_3COM_IO_PORTS); 80 if (error) 81 return (error); 82 83 sc->asic_offset = ED_3COM_ASIC_OFFSET; 84 sc->nic_offset = ED_3COM_NIC_OFFSET; 85 86 /* 87 * Verify that the kernel configured I/O address matches the board 88 * configured address 89 */ 90 switch (ed_asic_inb(sc, ED_3COM_BCFR)) { 91 case ED_3COM_BCFR_300: 92 if (rman_get_start(sc->port_res) != 0x300) 93 return (ENXIO); 94 break; 95 case ED_3COM_BCFR_310: 96 if (rman_get_start(sc->port_res) != 0x310) 97 return (ENXIO); 98 break; 99 case ED_3COM_BCFR_330: 100 if (rman_get_start(sc->port_res) != 0x330) 101 return (ENXIO); 102 break; 103 case ED_3COM_BCFR_350: 104 if (rman_get_start(sc->port_res) != 0x350) 105 return (ENXIO); 106 break; 107 case ED_3COM_BCFR_250: 108 if (rman_get_start(sc->port_res) != 0x250) 109 return (ENXIO); 110 break; 111 case ED_3COM_BCFR_280: 112 if (rman_get_start(sc->port_res) != 0x280) 113 return (ENXIO); 114 break; 115 case ED_3COM_BCFR_2A0: 116 if (rman_get_start(sc->port_res) != 0x2a0) 117 return (ENXIO); 118 break; 119 case ED_3COM_BCFR_2E0: 120 if (rman_get_start(sc->port_res) != 0x2e0) 121 return (ENXIO); 122 break; 123 default: 124 return (ENXIO); 125 } 126 127 error = bus_get_resource(dev, SYS_RES_MEMORY, 0, 128 &conf_maddr, &conf_msize); 129 if (error) 130 return (error); 131 132 /* 133 * Verify that the kernel shared memory address matches the board 134 * configured address. 135 */ 136 switch (ed_asic_inb(sc, ED_3COM_PCFR)) { 137 case ED_3COM_PCFR_DC000: 138 if (conf_maddr != 0xdc000) 139 return (ENXIO); 140 break; 141 case ED_3COM_PCFR_D8000: 142 if (conf_maddr != 0xd8000) 143 return (ENXIO); 144 break; 145 case ED_3COM_PCFR_CC000: 146 if (conf_maddr != 0xcc000) 147 return (ENXIO); 148 break; 149 case ED_3COM_PCFR_C8000: 150 if (conf_maddr != 0xc8000) 151 return (ENXIO); 152 break; 153 default: 154 return (ENXIO); 155 } 156 157 158 /* 159 * Reset NIC and ASIC. Enable on-board transceiver throughout reset 160 * sequence because it'll lock up if the cable isn't connected if we 161 * don't. 162 */ 163 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL); 164 165 /* 166 * Wait for a while, then un-reset it 167 */ 168 DELAY(50); 169 170 /* 171 * The 3Com ASIC defaults to rather strange settings for the CR after 172 * a reset - it's important to set it again after the following outb 173 * (this is done when we map the PROM below). 174 */ 175 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL); 176 177 /* 178 * Wait a bit for the NIC to recover from the reset 179 */ 180 DELAY(5000); 181 182 sc->vendor = ED_VENDOR_3COM; 183 sc->type_str = "3c503"; 184 sc->mem_shared = 1; 185 sc->cr_proto = ED_CR_RD2; 186 187 /* 188 * Hmmm...a 16bit 3Com board has 16k of memory, but only an 8k window 189 * to it. 190 */ 191 memsize = 8192; 192 193 /* 194 * Get station address from on-board ROM 195 */ 196 197 /* 198 * First, map ethernet address PROM over the top of where the NIC 199 * registers normally appear. 200 */ 201 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL); 202 203 for (i = 0; i < ETHER_ADDR_LEN; ++i) 204 sc->enaddr[i] = ed_nic_inb(sc, i); 205 206 /* 207 * Unmap PROM - select NIC registers. The proper setting of the 208 * tranceiver is set in ed_init so that the attach code is given a 209 * chance to set the default based on a compile-time config option 210 */ 211 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL); 212 213 /* 214 * Determine if this is an 8bit or 16bit board 215 */ 216 217 /* 218 * select page 0 registers 219 */ 220 ed_nic_barrier(sc, ED_P0_CR, 1, 221 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 222 ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_0 | ED_CR_RD2 | ED_CR_STP); 223 ed_nic_barrier(sc, ED_P0_CR, 1, 224 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 225 226 /* 227 * Attempt to clear WTS bit. If it doesn't clear, then this is a 16bit 228 * board. 229 */ 230 ed_nic_outb(sc, ED_P0_DCR, 0); 231 232 /* 233 * select page 2 registers 234 */ 235 ed_nic_barrier(sc, ED_P0_CR, 1, 236 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 237 ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_2 | ED_CR_RD2 | ED_CR_STP); 238 ed_nic_barrier(sc, ED_P0_CR, 1, 239 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 240 241 /* 242 * The 3c503 forces the WTS bit to a one if this is a 16bit board 243 */ 244 if (ed_nic_inb(sc, ED_P2_DCR) & ED_DCR_WTS) 245 isa16bit = 1; 246 else 247 isa16bit = 0; 248 249 /* 250 * select page 0 registers 251 */ 252 ed_nic_outb(sc, ED_P2_CR, ED_CR_RD2 | ED_CR_STP); 253 254 error = ed_alloc_memory(dev, 0, memsize); 255 if (error) 256 return (error); 257 258 pmem = rman_get_start(sc->mem_res); 259 error = ed_isa_mem_ok(dev, pmem, memsize); 260 if (error) 261 return (error); 262 263 sc->mem_start = 0; 264 sc->mem_size = memsize; 265 sc->mem_end = sc->mem_start + memsize; 266 267 /* 268 * We have an entire 8k window to put the transmit buffers on the 269 * 16bit boards. But since the 16bit 3c503's shared memory is only 270 * fast enough to overlap the loading of one full-size packet, trying 271 * to load more than 2 buffers can actually leave the transmitter idle 272 * during the load. So 2 seems the best value. (Although a mix of 273 * variable-sized packets might change this assumption. Nonetheless, 274 * we optimize for linear transfers of same-size packets.) 275 */ 276 if (isa16bit) { 277 if (flags & ED_FLAGS_NO_MULTI_BUFFERING) 278 sc->txb_cnt = 1; 279 else 280 sc->txb_cnt = 2; 281 282 sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_16BIT; 283 sc->rec_page_start = ED_3COM_RX_PAGE_OFFSET_16BIT; 284 sc->rec_page_stop = memsize / ED_PAGE_SIZE + 285 ED_3COM_RX_PAGE_OFFSET_16BIT; 286 sc->mem_ring = sc->mem_start; 287 } else { 288 sc->txb_cnt = 1; 289 sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_8BIT; 290 sc->rec_page_start = ED_TXBUF_SIZE + ED_3COM_TX_PAGE_OFFSET_8BIT; 291 sc->rec_page_stop = memsize / ED_PAGE_SIZE + 292 ED_3COM_TX_PAGE_OFFSET_8BIT; 293 sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE); 294 } 295 296 sc->isa16bit = isa16bit; 297 298 /* 299 * Initialize GA page start/stop registers. Probably only needed if 300 * doing DMA, but what the hell. 301 */ 302 ed_asic_outb(sc, ED_3COM_PSTR, sc->rec_page_start); 303 ed_asic_outb(sc, ED_3COM_PSPR, sc->rec_page_stop); 304 305 /* 306 * Set IRQ. 3c503 only allows a choice of irq 2-5. 307 */ 308 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk); 309 if (error) 310 return (error); 311 312 switch (irq) { 313 case 2: 314 case 9: 315 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2); 316 break; 317 case 3: 318 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3); 319 break; 320 case 4: 321 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4); 322 break; 323 case 5: 324 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5); 325 break; 326 default: 327 device_printf(dev, "Invalid irq configuration (%jd) must be 3-5,9 for 3c503\n", 328 irq); 329 return (ENXIO); 330 } 331 332 /* 333 * Initialize GA configuration register. Set bank and enable shared 334 * mem. 335 */ 336 ed_asic_outb(sc, ED_3COM_GACFR, ED_3COM_GACFR_RSEL | 337 ED_3COM_GACFR_MBS0); 338 339 /* 340 * Initialize "Vector Pointer" registers. These gawd-awful things are 341 * compared to 20 bits of the address on ISA, and if they match, the 342 * shared memory is disabled. We set them to 0xffff0...allegedly the 343 * reset vector. 344 */ 345 ed_asic_outb(sc, ED_3COM_VPTR2, 0xff); 346 ed_asic_outb(sc, ED_3COM_VPTR1, 0xff); 347 ed_asic_outb(sc, ED_3COM_VPTR0, 0x00); 348 349 error = ed_clear_memory(dev); 350 if (error == 0) { 351 sc->sc_mediachg = ed_3c503_mediachg; 352 sc->sc_write_mbufs = ed_shmem_write_mbufs; 353 } 354 return (error); 355} 356 357static void 358ed_3c503_mediachg(struct ed_softc *sc) 359{ 360 struct ifnet *ifp = sc->ifp; 361 362 /* 363 * If this is a 3Com board, the tranceiver must be software enabled 364 * (there is no settable hardware default). 365 */ 366 if (ifp->if_flags & IFF_LINK2) 367 ed_asic_outb(sc, ED_3COM_CR, 0); 368 else 369 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL); 370} 371 372#endif /* ED_3C503 */ 373