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 31#include <sys/cdefs.h>
|
32__FBSDID("$FreeBSD: head/sys/dev/ed/if_ed_novell.c 141681 2005-02-11 06:02:27Z imp $");
|
32__FBSDID("$FreeBSD: head/sys/dev/ed/if_ed_novell.c 141932 2005-02-14 23:00:41Z imp $"); |
33 34#include "opt_ed.h" 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/sockio.h> 39#include <sys/mbuf.h> 40#include <sys/kernel.h> 41#include <sys/socket.h> 42#include <sys/syslog.h> 43 44#include <sys/bus.h> 45 46#include <machine/bus.h> 47#include <sys/rman.h> 48#include <machine/resource.h> 49 50#include <net/ethernet.h> 51#include <net/if.h> 52#include <net/if_arp.h> 53#include <net/if_dl.h> 54#include <net/if_mib.h> 55#include <net/if_media.h> 56 57#include <net/bpf.h> 58 59#include <dev/ed/if_edreg.h> 60#include <dev/ed/if_edvar.h> 61 62static int ed_probe_gwether(device_t); 63 64/* 65 * Probe and vendor-specific initialization routine for NE1000/2000 boards 66 */
|
67int
|
67static int |
68ed_probe_Novell_generic(device_t dev, int flags) 69{ 70 struct ed_softc *sc = device_get_softc(dev);
|
71 u_int memsize, n;
|
71 u_int memsize; |
72 int error;
|
73 u_char romdata[16], tmp;
|
73 u_char tmp; |
74 static char test_pattern[32] = "THIS is A memory TEST pattern"; 75 char test_buffer[32]; 76 77 /* Reset the board */ 78 if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) { 79 ed_asic_outb(sc, ED_NOVELL_RESET, 0); 80 DELAY(200); 81 } 82 tmp = ed_asic_inb(sc, ED_NOVELL_RESET); 83 84 /* 85 * I don't know if this is necessary; probably cruft leftover from 86 * Clarkson packet driver code. Doesn't do a thing on the boards I've 87 * tested. -DG [note that an outb(0x84, 0) seems to work here, and is 88 * non-invasive...but some boards don't seem to reset and I don't have 89 * complete documentation on what the 'right' thing to do is...so we 90 * do the invasive thing for now. Yuck.] 91 */ 92 ed_asic_outb(sc, ED_NOVELL_RESET, tmp); 93 DELAY(5000); 94 95 /* 96 * This is needed because some NE clones apparently don't reset the 97 * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX 98 * - this makes the probe invasive! ...Done against my better 99 * judgement. -DLG 100 */ 101 ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 102 DELAY(5000); 103 104 /* Make sure that we really have an 8390 based board */ 105 if (!ed_probe_generic8390(sc)) 106 return (ENXIO); 107 108 sc->vendor = ED_VENDOR_NOVELL; 109 sc->mem_shared = 0; 110 sc->cr_proto = ED_CR_RD2; 111 112 /* 113 * Test the ability to read and write to the NIC memory. This has the 114 * side affect of determining if this is an NE1000 or an NE2000. 115 */ 116 117 /* 118 * This prevents packets from being stored in the NIC memory when the 119 * readmem routine turns on the start bit in the CR. 120 */ 121 ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON); 122 123 /* Temporarily initialize DCR for byte operations */ 124 ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS); 125 126 ed_nic_outb(sc, ED_P0_PSTART, 8192 / ED_PAGE_SIZE); 127 ed_nic_outb(sc, ED_P0_PSTOP, 16384 / ED_PAGE_SIZE); 128 129 sc->isa16bit = 0; 130 131 /* 132 * Write a test pattern in byte mode. If this fails, then there 133 * probably isn't any memory at 8k - which likely means that the board 134 * is an NE2000. 135 */ 136 ed_pio_writemem(sc, test_pattern, 8192, sizeof(test_pattern)); 137 ed_pio_readmem(sc, 8192, test_buffer, sizeof(test_pattern)); 138 139 if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) { 140 sc->type = ED_TYPE_NE1000; 141 sc->type_str = "NE1000"; 142 } else { 143 144 /* Not an NE1000 - try NE2000 */ 145 ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS); 146 ed_nic_outb(sc, ED_P0_PSTART, 16384 / ED_PAGE_SIZE); 147 ed_nic_outb(sc, ED_P0_PSTOP, 32768 / ED_PAGE_SIZE); 148 149 sc->isa16bit = 1; 150 151 /* 152 * Write a test pattern in word mode. If this also fails, then 153 * we don't know what this board is. 154 */ 155 ed_pio_writemem(sc, test_pattern, 16384, sizeof(test_pattern)); 156 ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern)); 157 if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) { 158 sc->type = ED_TYPE_NE2000; 159 sc->type_str = "NE2000"; 160 } else { 161 return (ENXIO); 162 } 163 } 164 sc->chip_type = ED_CHIP_TYPE_DP8390; 165 166 /* 8k of memory plus an additional 8k if 16bit */ 167 memsize = 8192 + sc->isa16bit * 8192; 168 sc->mem_size = memsize; 169 170 /* NIC memory doesn't start at zero on an NE board */ 171 /* The start address is tied to the bus width */ 172 sc->mem_start = (char *) 8192 + sc->isa16bit * 8192; 173 sc->mem_end = sc->mem_start + memsize; 174 sc->tx_page_start = memsize / ED_PAGE_SIZE; 175 176 if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) { 177 error = ed_probe_gwether(dev); 178 if (error) 179 return (error); 180 } 181 182 /* 183 * Use one xmit buffer if < 16k, two buffers otherwise (if not told 184 * otherwise). 185 */ 186 if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) 187 sc->txb_cnt = 1; 188 else 189 sc->txb_cnt = 2; 190 191 sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE; 192 sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE; 193 194 sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
|
195
196 ed_pio_readmem(sc, 0, romdata, 16);
197 for (n = 0; n < ETHER_ADDR_LEN; n++)
198 sc->arpcom.ac_enaddr[n] = romdata[n * (sc->isa16bit + 1)];
199
200 if ((ED_FLAGS_GETTYPE(flags) == ED_FLAGS_GWETHER) &&
201 (sc->arpcom.ac_enaddr[2] == 0x86)) {
202 sc->type_str = "Gateway AT";
203 }
204
|
195 /* clear any pending interrupts that might have occurred above */ 196 ed_nic_outb(sc, ED_P0_ISR, 0xff); 197 198 return (0); 199} 200 201int 202ed_probe_Novell(device_t dev, int port_rid, int flags) 203{ 204 struct ed_softc *sc = device_get_softc(dev); 205 int error; 206 207 error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS); 208 if (error) 209 return (error); 210 211 sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 212 sc->nic_offset = ED_NOVELL_NIC_OFFSET; 213 214 return ed_probe_Novell_generic(dev, flags); 215} 216 217static int 218ed_probe_gwether(device_t dev) 219{ 220 int x, i, msize = 0; 221 long mstart = 0; 222 char pbuf0[ED_PAGE_SIZE], pbuf[ED_PAGE_SIZE], tbuf[ED_PAGE_SIZE]; 223 struct ed_softc *sc = device_get_softc(dev); 224 225 for (i = 0; i < ED_PAGE_SIZE; i++) 226 pbuf0[i] = 0; 227 228 /* Clear all the memory. */ 229 for (x = 1; x < 256; x++) 230 ed_pio_writemem(sc, pbuf0, x * 256, ED_PAGE_SIZE); 231 232 /* Search for the start of RAM. */ 233 for (x = 1; x < 256; x++) { 234 ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE); 235 if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) { 236 for (i = 0; i < ED_PAGE_SIZE; i++) 237 pbuf[i] = 255 - x; 238 ed_pio_writemem(sc, pbuf, x * 256, ED_PAGE_SIZE); 239 ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE); 240 if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0) { 241 mstart = x * ED_PAGE_SIZE; 242 msize = ED_PAGE_SIZE; 243 break; 244 } 245 } 246 } 247 if (mstart == 0) { 248 device_printf(dev, "Cannot find start of RAM.\n"); 249 return (ENXIO); 250 } 251 252 /* Probe the size of RAM. */ 253 for (x = (mstart / ED_PAGE_SIZE) + 1; x < 256; x++) { 254 ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE); 255 if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) { 256 for (i = 0; i < ED_PAGE_SIZE; i++) 257 pbuf[i] = 255 - x; 258 ed_pio_writemem(sc, pbuf, x * 256, ED_PAGE_SIZE); 259 ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE); 260 if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0) 261 msize += ED_PAGE_SIZE; 262 else { 263 break; 264 } 265 } else { 266 break; 267 } 268 } 269 270 if (msize == 0) { 271 device_printf(dev, 272 "Cannot find any RAM, start : %ld, x = %d.\n", mstart, x); 273 return (ENXIO); 274 } 275 device_printf(dev, "RAM start at %ld, size : %d.\n", mstart, msize); 276 277 sc->mem_size = msize; 278 sc->mem_start = (caddr_t)(uintptr_t) mstart; 279 sc->mem_end = (caddr_t)(uintptr_t) (msize + mstart); 280 sc->tx_page_start = mstart / ED_PAGE_SIZE; 281 return 0; 282}
|
283 284void 285ed_Novell_read_mac(struct ed_softc *sc) 286{ 287 int n; 288 uint8_t romdata[16]; 289 290 /* 291 * Pull the MAC address out of the roms that are on the isa 292 * version of these cards. 293 */ 294 ed_pio_readmem(sc, 0, romdata, 16); 295 for (n = 0; n < ETHER_ADDR_LEN; n++) 296 sc->arpcom.ac_enaddr[n] = romdata[n * (sc->isa16bit + 1)]; 297} |
|