1141586Simp/*- 2141586Simp * Copyright (c) 2005, M. Warner Losh 3141586Simp * All rights reserved. 4141586Simp * Copyright (c) 1995, David Greenman 5141586Simp * All rights reserved. 6141586Simp * 7141586Simp * Redistribution and use in source and binary forms, with or without 8141586Simp * modification, are permitted provided that the following conditions 9141586Simp * are met: 10141586Simp * 1. Redistributions of source code must retain the above copyright 11141586Simp * notice unmodified, this list of conditions, and the following 12141586Simp * disclaimer. 13141586Simp * 2. Redistributions in binary form must reproduce the above copyright 14141586Simp * notice, this list of conditions and the following disclaimer in the 15141586Simp * documentation and/or other materials provided with the distribution. 16141586Simp * 17141586Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18141586Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19141586Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20141586Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21141586Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22141586Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23141586Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24141586Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25141586Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26141586Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27141586Simp * SUCH DAMAGE. 28141586Simp */ 29141586Simp 30141586Simp#include <sys/cdefs.h> 31141586Simp__FBSDID("$FreeBSD$"); 32141586Simp 33141586Simp#include "opt_ed.h" 34141586Simp 35141586Simp#ifdef ED_3C503 36141586Simp 37141586Simp#include <sys/param.h> 38141586Simp#include <sys/systm.h> 39141586Simp#include <sys/sockio.h> 40141586Simp#include <sys/mbuf.h> 41141586Simp#include <sys/kernel.h> 42141586Simp#include <sys/socket.h> 43141586Simp#include <sys/syslog.h> 44141586Simp 45141586Simp#include <sys/bus.h> 46141586Simp 47141586Simp#include <machine/bus.h> 48141586Simp#include <sys/rman.h> 49141586Simp#include <machine/resource.h> 50141586Simp 51141586Simp#include <net/ethernet.h> 52141586Simp#include <net/if.h> 53257176Sglebius#include <net/if_var.h> /* XXX: ed_3c503_mediachg() */ 54141586Simp#include <net/if_arp.h> 55141586Simp#include <net/if_dl.h> 56141586Simp#include <net/if_mib.h> 57141586Simp#include <net/if_media.h> 58141586Simp 59141586Simp#include <net/bpf.h> 60141586Simp 61141586Simp#include <dev/ed/if_edreg.h> 62141586Simp#include <dev/ed/if_edvar.h> 63141586Simp 64154895Simpstatic void ed_3c503_mediachg(struct ed_softc *sc); 65154895Simp 66141586Simp/* 67141586Simp * Probe and vendor-specific initialization routine for 3Com 3c503 boards 68141586Simp */ 69141586Simpint 70141586Simped_probe_3Com(device_t dev, int port_rid, int flags) 71141586Simp{ 72141586Simp struct ed_softc *sc = device_get_softc(dev); 73141586Simp int error; 74141586Simp int i; 75141586Simp u_int memsize; 76141586Simp u_char isa16bit; 77294883Sjhibbits rman_res_t conf_maddr, conf_msize, irq, junk, pmem; 78141586Simp 79141586Simp error = ed_alloc_port(dev, 0, ED_3COM_IO_PORTS); 80141586Simp if (error) 81141586Simp return (error); 82141586Simp 83141586Simp sc->asic_offset = ED_3COM_ASIC_OFFSET; 84141586Simp sc->nic_offset = ED_3COM_NIC_OFFSET; 85141586Simp 86141586Simp /* 87141586Simp * Verify that the kernel configured I/O address matches the board 88141586Simp * configured address 89141586Simp */ 90141586Simp switch (ed_asic_inb(sc, ED_3COM_BCFR)) { 91141586Simp case ED_3COM_BCFR_300: 92141586Simp if (rman_get_start(sc->port_res) != 0x300) 93141586Simp return (ENXIO); 94141586Simp break; 95141586Simp case ED_3COM_BCFR_310: 96141586Simp if (rman_get_start(sc->port_res) != 0x310) 97141586Simp return (ENXIO); 98141586Simp break; 99141586Simp case ED_3COM_BCFR_330: 100141586Simp if (rman_get_start(sc->port_res) != 0x330) 101141586Simp return (ENXIO); 102141586Simp break; 103141586Simp case ED_3COM_BCFR_350: 104141586Simp if (rman_get_start(sc->port_res) != 0x350) 105141586Simp return (ENXIO); 106141586Simp break; 107141586Simp case ED_3COM_BCFR_250: 108141586Simp if (rman_get_start(sc->port_res) != 0x250) 109141586Simp return (ENXIO); 110141586Simp break; 111141586Simp case ED_3COM_BCFR_280: 112141586Simp if (rman_get_start(sc->port_res) != 0x280) 113141586Simp return (ENXIO); 114141586Simp break; 115141586Simp case ED_3COM_BCFR_2A0: 116141586Simp if (rman_get_start(sc->port_res) != 0x2a0) 117141586Simp return (ENXIO); 118141586Simp break; 119141586Simp case ED_3COM_BCFR_2E0: 120141586Simp if (rman_get_start(sc->port_res) != 0x2e0) 121141586Simp return (ENXIO); 122141586Simp break; 123141586Simp default: 124141586Simp return (ENXIO); 125141586Simp } 126141586Simp 127141586Simp error = bus_get_resource(dev, SYS_RES_MEMORY, 0, 128141586Simp &conf_maddr, &conf_msize); 129141586Simp if (error) 130141586Simp return (error); 131141586Simp 132141586Simp /* 133141586Simp * Verify that the kernel shared memory address matches the board 134141586Simp * configured address. 135141586Simp */ 136141586Simp switch (ed_asic_inb(sc, ED_3COM_PCFR)) { 137141586Simp case ED_3COM_PCFR_DC000: 138141586Simp if (conf_maddr != 0xdc000) 139141586Simp return (ENXIO); 140141586Simp break; 141141586Simp case ED_3COM_PCFR_D8000: 142141586Simp if (conf_maddr != 0xd8000) 143141586Simp return (ENXIO); 144141586Simp break; 145141586Simp case ED_3COM_PCFR_CC000: 146141586Simp if (conf_maddr != 0xcc000) 147141586Simp return (ENXIO); 148141586Simp break; 149141586Simp case ED_3COM_PCFR_C8000: 150141586Simp if (conf_maddr != 0xc8000) 151141586Simp return (ENXIO); 152141586Simp break; 153141586Simp default: 154141586Simp return (ENXIO); 155141586Simp } 156141586Simp 157141586Simp 158141586Simp /* 159141586Simp * Reset NIC and ASIC. Enable on-board transceiver throughout reset 160141586Simp * sequence because it'll lock up if the cable isn't connected if we 161141586Simp * don't. 162141586Simp */ 163141586Simp ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL); 164141586Simp 165141586Simp /* 166141586Simp * Wait for a while, then un-reset it 167141586Simp */ 168141586Simp DELAY(50); 169141586Simp 170141586Simp /* 171141586Simp * The 3Com ASIC defaults to rather strange settings for the CR after 172141586Simp * a reset - it's important to set it again after the following outb 173141586Simp * (this is done when we map the PROM below). 174141586Simp */ 175141586Simp ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL); 176141586Simp 177141586Simp /* 178141586Simp * Wait a bit for the NIC to recover from the reset 179141586Simp */ 180141586Simp DELAY(5000); 181141586Simp 182141586Simp sc->vendor = ED_VENDOR_3COM; 183141586Simp sc->type_str = "3c503"; 184141586Simp sc->mem_shared = 1; 185141586Simp sc->cr_proto = ED_CR_RD2; 186141586Simp 187141586Simp /* 188141586Simp * Hmmm...a 16bit 3Com board has 16k of memory, but only an 8k window 189141586Simp * to it. 190141586Simp */ 191141586Simp memsize = 8192; 192141586Simp 193141586Simp /* 194141586Simp * Get station address from on-board ROM 195141586Simp */ 196141586Simp 197141586Simp /* 198141586Simp * First, map ethernet address PROM over the top of where the NIC 199141586Simp * registers normally appear. 200141586Simp */ 201141586Simp ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL); 202141586Simp 203141586Simp for (i = 0; i < ETHER_ADDR_LEN; ++i) 204147256Sbrooks sc->enaddr[i] = ed_nic_inb(sc, i); 205141586Simp 206141586Simp /* 207141586Simp * Unmap PROM - select NIC registers. The proper setting of the 208141586Simp * tranceiver is set in ed_init so that the attach code is given a 209141586Simp * chance to set the default based on a compile-time config option 210141586Simp */ 211141586Simp ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL); 212141586Simp 213141586Simp /* 214141586Simp * Determine if this is an 8bit or 16bit board 215141586Simp */ 216141586Simp 217141586Simp /* 218141586Simp * select page 0 registers 219141586Simp */ 220260050Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 221260050Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 222260050Smarius ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_0 | ED_CR_RD2 | ED_CR_STP); 223260050Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 224260050Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 225141586Simp 226141586Simp /* 227141586Simp * Attempt to clear WTS bit. If it doesn't clear, then this is a 16bit 228141586Simp * board. 229141586Simp */ 230141586Simp ed_nic_outb(sc, ED_P0_DCR, 0); 231141586Simp 232141586Simp /* 233141586Simp * select page 2 registers 234141586Simp */ 235260050Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 236260050Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 237141586Simp ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_2 | ED_CR_RD2 | ED_CR_STP); 238260050Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 239260050Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 240141586Simp 241141586Simp /* 242141586Simp * The 3c503 forces the WTS bit to a one if this is a 16bit board 243141586Simp */ 244141586Simp if (ed_nic_inb(sc, ED_P2_DCR) & ED_DCR_WTS) 245141586Simp isa16bit = 1; 246141586Simp else 247141586Simp isa16bit = 0; 248141586Simp 249141586Simp /* 250141586Simp * select page 0 registers 251141586Simp */ 252141586Simp ed_nic_outb(sc, ED_P2_CR, ED_CR_RD2 | ED_CR_STP); 253141586Simp 254141586Simp error = ed_alloc_memory(dev, 0, memsize); 255141586Simp if (error) 256141586Simp return (error); 257141586Simp 258141586Simp pmem = rman_get_start(sc->mem_res); 259141586Simp error = ed_isa_mem_ok(dev, pmem, memsize); 260141586Simp if (error) 261141586Simp return (error); 262141586Simp 263149558Simp sc->mem_start = 0; 264141586Simp sc->mem_size = memsize; 265141586Simp sc->mem_end = sc->mem_start + memsize; 266141586Simp 267141586Simp /* 268141586Simp * We have an entire 8k window to put the transmit buffers on the 269141586Simp * 16bit boards. But since the 16bit 3c503's shared memory is only 270141586Simp * fast enough to overlap the loading of one full-size packet, trying 271141586Simp * to load more than 2 buffers can actually leave the transmitter idle 272141586Simp * during the load. So 2 seems the best value. (Although a mix of 273141586Simp * variable-sized packets might change this assumption. Nonetheless, 274141586Simp * we optimize for linear transfers of same-size packets.) 275141586Simp */ 276141586Simp if (isa16bit) { 277141586Simp if (flags & ED_FLAGS_NO_MULTI_BUFFERING) 278141586Simp sc->txb_cnt = 1; 279141586Simp else 280141586Simp sc->txb_cnt = 2; 281141586Simp 282141586Simp sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_16BIT; 283141586Simp sc->rec_page_start = ED_3COM_RX_PAGE_OFFSET_16BIT; 284141586Simp sc->rec_page_stop = memsize / ED_PAGE_SIZE + 285141586Simp ED_3COM_RX_PAGE_OFFSET_16BIT; 286141586Simp sc->mem_ring = sc->mem_start; 287141586Simp } else { 288141586Simp sc->txb_cnt = 1; 289141586Simp sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_8BIT; 290141586Simp sc->rec_page_start = ED_TXBUF_SIZE + ED_3COM_TX_PAGE_OFFSET_8BIT; 291141586Simp sc->rec_page_stop = memsize / ED_PAGE_SIZE + 292141586Simp ED_3COM_TX_PAGE_OFFSET_8BIT; 293141586Simp sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE); 294141586Simp } 295141586Simp 296141586Simp sc->isa16bit = isa16bit; 297141586Simp 298141586Simp /* 299141586Simp * Initialize GA page start/stop registers. Probably only needed if 300141586Simp * doing DMA, but what the hell. 301141586Simp */ 302141586Simp ed_asic_outb(sc, ED_3COM_PSTR, sc->rec_page_start); 303141586Simp ed_asic_outb(sc, ED_3COM_PSPR, sc->rec_page_stop); 304141586Simp 305141586Simp /* 306141586Simp * Set IRQ. 3c503 only allows a choice of irq 2-5. 307141586Simp */ 308141586Simp error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk); 309141586Simp if (error) 310141586Simp return (error); 311141586Simp 312141586Simp switch (irq) { 313141586Simp case 2: 314141586Simp case 9: 315141586Simp ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2); 316141586Simp break; 317141586Simp case 3: 318141586Simp ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3); 319141586Simp break; 320141586Simp case 4: 321141586Simp ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4); 322141586Simp break; 323141586Simp case 5: 324141586Simp ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5); 325141586Simp break; 326141586Simp default: 327297000Sjhibbits device_printf(dev, "Invalid irq configuration (%jd) must be 3-5,9 for 3c503\n", 328141586Simp irq); 329141586Simp return (ENXIO); 330141586Simp } 331141586Simp 332141586Simp /* 333141586Simp * Initialize GA configuration register. Set bank and enable shared 334141586Simp * mem. 335141586Simp */ 336141586Simp ed_asic_outb(sc, ED_3COM_GACFR, ED_3COM_GACFR_RSEL | 337154924Simp ED_3COM_GACFR_MBS0); 338141586Simp 339141586Simp /* 340141586Simp * Initialize "Vector Pointer" registers. These gawd-awful things are 341141586Simp * compared to 20 bits of the address on ISA, and if they match, the 342141586Simp * shared memory is disabled. We set them to 0xffff0...allegedly the 343141586Simp * reset vector. 344141586Simp */ 345141586Simp ed_asic_outb(sc, ED_3COM_VPTR2, 0xff); 346141586Simp ed_asic_outb(sc, ED_3COM_VPTR1, 0xff); 347141586Simp ed_asic_outb(sc, ED_3COM_VPTR0, 0x00); 348141586Simp 349154895Simp error = ed_clear_memory(dev); 350154924Simp if (error == 0) { 351154895Simp sc->sc_mediachg = ed_3c503_mediachg; 352154924Simp sc->sc_write_mbufs = ed_shmem_write_mbufs; 353154924Simp } 354154895Simp return (error); 355141586Simp} 356141586Simp 357154895Simpstatic void 358154895Simped_3c503_mediachg(struct ed_softc *sc) 359154895Simp{ 360154895Simp struct ifnet *ifp = sc->ifp; 361154895Simp 362154895Simp /* 363154895Simp * If this is a 3Com board, the tranceiver must be software enabled 364154895Simp * (there is no settable hardware default). 365154895Simp */ 366154895Simp if (ifp->if_flags & IFF_LINK2) 367154895Simp ed_asic_outb(sc, ED_3COM_CR, 0); 368154895Simp else 369154895Simp ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL); 370154895Simp} 371154895Simp 372141586Simp#endif /* ED_3C503 */ 373