if_txp.c revision 189004
168349Sobrien/* $OpenBSD: if_txp.c,v 1.48 2001/06/27 06:34:50 kjc Exp $ */ 268349Sobrien 368349Sobrien/*- 468349Sobrien * Copyright (c) 2001 568349Sobrien * Jason L. Wright <jason@thought.net>, Theo de Raadt, and 668349Sobrien * Aaron Campbell <aaron@monkey.org>. All rights reserved. 768349Sobrien * 868349Sobrien * Redistribution and use in source and binary forms, with or without 968349Sobrien * modification, are permitted provided that the following conditions 1068349Sobrien * are met: 1168349Sobrien * 1. Redistributions of source code must retain the above copyright 1268349Sobrien * notice, this list of conditions and the following disclaimer. 1368349Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1468349Sobrien * notice, this list of conditions and the following disclaimer in the 1568349Sobrien * documentation and/or other materials provided with the distribution. 1668349Sobrien * 3. All advertising materials mentioning features or use of this software 1768349Sobrien * must display the following acknowledgement: 1868349Sobrien * This product includes software developed by Jason L. Wright, 1968349Sobrien * Theo de Raadt and Aaron Campbell. 2068349Sobrien * 4. Neither the name of the author nor the names of any co-contributors 2168349Sobrien * may be used to endorse or promote products derived from this software 2268349Sobrien * without specific prior written permission. 2368349Sobrien * 2468349Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 2568349Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2668349Sobrien * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2768349Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 2868349Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2968349Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3068349Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3168349Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3268349Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3368349Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3468349Sobrien * THE POSSIBILITY OF SUCH DAMAGE. 3568349Sobrien */ 3668349Sobrien 3768349Sobrien#include <sys/cdefs.h> 3868349Sobrien__FBSDID("$FreeBSD: head/sys/dev/txp/if_txp.c 189004 2009-02-24 18:09:31Z rdivacky $"); 3968349Sobrien 4068349Sobrien/* 4168349Sobrien * Driver for 3c990 (Typhoon) Ethernet ASIC 4268349Sobrien */ 4368349Sobrien#include <sys/param.h> 4468349Sobrien#include <sys/systm.h> 4568349Sobrien#include <sys/sockio.h> 4668349Sobrien#include <sys/mbuf.h> 4768349Sobrien#include <sys/malloc.h> 4868349Sobrien#include <sys/kernel.h> 4968349Sobrien#include <sys/module.h> 5068349Sobrien#include <sys/socket.h> 5168349Sobrien 5268349Sobrien#include <net/if.h> 5368349Sobrien#include <net/if_arp.h> 5468349Sobrien#include <net/ethernet.h> 5568349Sobrien#include <net/if_dl.h> 5668349Sobrien#include <net/if_types.h> 5768349Sobrien#include <net/if_vlan_var.h> 5868349Sobrien 5968349Sobrien#include <netinet/in.h> 6068349Sobrien#include <netinet/in_systm.h> 6168349Sobrien#include <netinet/in_var.h> 6268349Sobrien#include <netinet/ip.h> 6368349Sobrien#include <netinet/if_ether.h> 6468349Sobrien#include <machine/in_cksum.h> 6568349Sobrien 6668349Sobrien#include <net/if_media.h> 6768349Sobrien 6868349Sobrien#include <net/bpf.h> 6968349Sobrien 7068349Sobrien#include <vm/vm.h> /* for vtophys */ 7168349Sobrien#include <vm/pmap.h> /* for vtophys */ 7268349Sobrien#include <machine/bus.h> 7368349Sobrien#include <machine/resource.h> 7468349Sobrien#include <sys/bus.h> 7568349Sobrien#include <sys/rman.h> 7668349Sobrien 7768349Sobrien#include <dev/mii/mii.h> 7868349Sobrien#include <dev/mii/miivar.h> 7968349Sobrien#include <dev/pci/pcireg.h> 8068349Sobrien#include <dev/pci/pcivar.h> 8168349Sobrien 8268349Sobrien#define TXP_USEIOSPACE 8368349Sobrien#define __STRICT_ALIGNMENT 8468349Sobrien 8568349Sobrien#include <dev/txp/if_txpreg.h> 8668349Sobrien#include <dev/txp/3c990img.h> 8768349Sobrien 8868349Sobrien#ifndef lint 8968349Sobrienstatic const char rcsid[] = 9068349Sobrien "$FreeBSD: head/sys/dev/txp/if_txp.c 189004 2009-02-24 18:09:31Z rdivacky $"; 9168349Sobrien#endif 9268349Sobrien 9368349Sobrien/* 9468349Sobrien * Various supported device vendors/types and their names. 9568349Sobrien */ 9668349Sobrienstatic struct txp_type txp_devs[] = { 9768349Sobrien { TXP_VENDORID_3COM, TXP_DEVICEID_3CR990_TX_95, 9868349Sobrien "3Com 3cR990-TX-95 Etherlink with 3XP Processor" }, 9968349Sobrien { TXP_VENDORID_3COM, TXP_DEVICEID_3CR990_TX_97, 10068349Sobrien "3Com 3cR990-TX-97 Etherlink with 3XP Processor" }, 10168349Sobrien { TXP_VENDORID_3COM, TXP_DEVICEID_3CR990B_TXM, 10268349Sobrien "3Com 3cR990B-TXM Etherlink with 3XP Processor" }, 10368349Sobrien { TXP_VENDORID_3COM, TXP_DEVICEID_3CR990_SRV_95, 10468349Sobrien "3Com 3cR990-SRV-95 Etherlink Server with 3XP Processor" }, 10568349Sobrien { TXP_VENDORID_3COM, TXP_DEVICEID_3CR990_SRV_97, 10668349Sobrien "3Com 3cR990-SRV-97 Etherlink Server with 3XP Processor" }, 10768349Sobrien { TXP_VENDORID_3COM, TXP_DEVICEID_3CR990B_SRV, 10868349Sobrien "3Com 3cR990B-SRV Etherlink Server with 3XP Processor" }, 10968349Sobrien { 0, 0, NULL } 11068349Sobrien}; 11168349Sobrien 11268349Sobrienstatic int txp_probe(device_t); 11368349Sobrienstatic int txp_attach(device_t); 11468349Sobrienstatic int txp_detach(device_t); 11568349Sobrienstatic void txp_intr(void *); 11668349Sobrienstatic void txp_tick(void *); 11768349Sobrienstatic int txp_shutdown(device_t); 11868349Sobrienstatic int txp_ioctl(struct ifnet *, u_long, caddr_t); 11968349Sobrienstatic void txp_start(struct ifnet *); 12068349Sobrienstatic void txp_start_locked(struct ifnet *); 12168349Sobrienstatic void txp_stop(struct txp_softc *); 12268349Sobrienstatic void txp_init(void *); 12368349Sobrienstatic void txp_init_locked(struct txp_softc *); 12468349Sobrienstatic void txp_watchdog(struct ifnet *); 12568349Sobrien 12668349Sobrienstatic void txp_release_resources(struct txp_softc *); 12768349Sobrienstatic int txp_chip_init(struct txp_softc *); 12868349Sobrienstatic int txp_reset_adapter(struct txp_softc *); 12968349Sobrienstatic int txp_download_fw(struct txp_softc *); 13068349Sobrienstatic int txp_download_fw_wait(struct txp_softc *); 13168349Sobrienstatic int txp_download_fw_section(struct txp_softc *, 13268349Sobrien struct txp_fw_section_header *, int); 13368349Sobrienstatic int txp_alloc_rings(struct txp_softc *); 13468349Sobrienstatic int txp_rxring_fill(struct txp_softc *); 13568349Sobrienstatic void txp_rxring_empty(struct txp_softc *); 13668349Sobrienstatic void txp_set_filter(struct txp_softc *); 13768349Sobrien 13868349Sobrienstatic int txp_cmd_desc_numfree(struct txp_softc *); 13968349Sobrienstatic int txp_command(struct txp_softc *, u_int16_t, u_int16_t, u_int32_t, 14068349Sobrien u_int32_t, u_int16_t *, u_int32_t *, u_int32_t *, int); 14168349Sobrienstatic int txp_command2(struct txp_softc *, u_int16_t, u_int16_t, 14268349Sobrien u_int32_t, u_int32_t, struct txp_ext_desc *, u_int8_t, 14368349Sobrien struct txp_rsp_desc **, int); 14468349Sobrienstatic int txp_response(struct txp_softc *, u_int32_t, u_int16_t, u_int16_t, 14568349Sobrien struct txp_rsp_desc **); 14668349Sobrienstatic void txp_rsp_fixup(struct txp_softc *, struct txp_rsp_desc *, 14768349Sobrien struct txp_rsp_desc *); 14868349Sobrienstatic void txp_capabilities(struct txp_softc *); 14968349Sobrien 15068349Sobrienstatic void txp_ifmedia_sts(struct ifnet *, struct ifmediareq *); 15168349Sobrienstatic int txp_ifmedia_upd(struct ifnet *); 15268349Sobrien#ifdef TXP_DEBUG 15368349Sobrienstatic void txp_show_descriptor(void *); 15468349Sobrien#endif 15568349Sobrienstatic void txp_tx_reclaim(struct txp_softc *, struct txp_tx_ring *); 15668349Sobrienstatic void txp_rxbuf_reclaim(struct txp_softc *); 15768349Sobrienstatic void txp_rx_reclaim(struct txp_softc *, struct txp_rx_ring *); 15868349Sobrien 15968349Sobrien#ifdef TXP_USEIOSPACE 16068349Sobrien#define TXP_RES SYS_RES_IOPORT 16168349Sobrien#define TXP_RID TXP_PCI_LOIO 16268349Sobrien#else 16368349Sobrien#define TXP_RES SYS_RES_MEMORY 16468349Sobrien#define TXP_RID TXP_PCI_LOMEM 16568349Sobrien#endif 16668349Sobrien 16768349Sobrienstatic device_method_t txp_methods[] = { 16868349Sobrien /* Device interface */ 16968349Sobrien DEVMETHOD(device_probe, txp_probe), 17068349Sobrien DEVMETHOD(device_attach, txp_attach), 17168349Sobrien DEVMETHOD(device_detach, txp_detach), 17268349Sobrien DEVMETHOD(device_shutdown, txp_shutdown), 17368349Sobrien { 0, 0 } 17468349Sobrien}; 17568349Sobrien 17668349Sobrienstatic driver_t txp_driver = { 17768349Sobrien "txp", 17868349Sobrien txp_methods, 17968349Sobrien sizeof(struct txp_softc) 18068349Sobrien}; 18168349Sobrien 18268349Sobrienstatic devclass_t txp_devclass; 18368349Sobrien 18468349SobrienDRIVER_MODULE(txp, pci, txp_driver, txp_devclass, 0, 0); 18568349SobrienMODULE_DEPEND(txp, pci, 1, 1, 1); 18668349SobrienMODULE_DEPEND(txp, ether, 1, 1, 1); 18768349Sobrien 18868349Sobrienstatic int 18968349Sobrientxp_probe(dev) 19068349Sobrien device_t dev; 19168349Sobrien{ 19268349Sobrien struct txp_type *t; 19368349Sobrien 19468349Sobrien t = txp_devs; 19568349Sobrien 19668349Sobrien while(t->txp_name != NULL) { 19768349Sobrien if ((pci_get_vendor(dev) == t->txp_vid) && 19868349Sobrien (pci_get_device(dev) == t->txp_did)) { 19968349Sobrien device_set_desc(dev, t->txp_name); 20068349Sobrien return(BUS_PROBE_DEFAULT); 20168349Sobrien } 20268349Sobrien t++; 20368349Sobrien } 20468349Sobrien 20568349Sobrien return(ENXIO); 20668349Sobrien} 20768349Sobrien 20868349Sobrienstatic int 20968349Sobrientxp_attach(dev) 21068349Sobrien device_t dev; 21168349Sobrien{ 21268349Sobrien struct txp_softc *sc; 21368349Sobrien struct ifnet *ifp; 21468349Sobrien u_int16_t p1; 21568349Sobrien u_int32_t p2; 21668349Sobrien int error = 0, rid; 21768349Sobrien u_char eaddr[6]; 21868349Sobrien 21968349Sobrien sc = device_get_softc(dev); 22068349Sobrien sc->sc_dev = dev; 22168349Sobrien sc->sc_cold = 1; 22268349Sobrien 22368349Sobrien mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 22468349Sobrien MTX_DEF); 225 callout_init_mtx(&sc->sc_tick, &sc->sc_mtx, 0); 226 227 /* 228 * Map control/status registers. 229 */ 230 pci_enable_busmaster(dev); 231 232 rid = TXP_RID; 233 sc->sc_res = bus_alloc_resource_any(dev, TXP_RES, &rid, 234 RF_ACTIVE); 235 236 if (sc->sc_res == NULL) { 237 device_printf(dev, "couldn't map ports/memory\n"); 238 error = ENXIO; 239 goto fail; 240 } 241 242 sc->sc_bt = rman_get_bustag(sc->sc_res); 243 sc->sc_bh = rman_get_bushandle(sc->sc_res); 244 245 /* Allocate interrupt */ 246 rid = 0; 247 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 248 RF_SHAREABLE | RF_ACTIVE); 249 250 if (sc->sc_irq == NULL) { 251 device_printf(dev, "couldn't map interrupt\n"); 252 error = ENXIO; 253 goto fail; 254 } 255 256 if (txp_chip_init(sc)) { 257 error = ENXIO; 258 goto fail; 259 } 260 261 sc->sc_fwbuf = contigmalloc(32768, M_DEVBUF, 262 M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0); 263 if (sc->sc_fwbuf == NULL) { 264 device_printf(dev, "no memory for firmware\n"); 265 error = ENXIO; 266 goto fail; 267 } 268 error = txp_download_fw(sc); 269 contigfree(sc->sc_fwbuf, 32768, M_DEVBUF); 270 sc->sc_fwbuf = NULL; 271 272 if (error) 273 goto fail; 274 275 sc->sc_ldata = contigmalloc(sizeof(struct txp_ldata), M_DEVBUF, 276 M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0); 277 if (sc->sc_ldata == NULL) { 278 device_printf(dev, "no memory for descriptor ring\n"); 279 error = ENXIO; 280 goto fail; 281 } 282 bzero(sc->sc_ldata, sizeof(struct txp_ldata)); 283 284 if (txp_alloc_rings(sc)) { 285 error = ENXIO; 286 goto fail; 287 } 288 289 if (txp_command(sc, TXP_CMD_MAX_PKT_SIZE_WRITE, TXP_MAX_PKTLEN, 0, 0, 290 NULL, NULL, NULL, 1)) { 291 error = ENXIO; 292 goto fail; 293 } 294 295 if (txp_command(sc, TXP_CMD_STATION_ADDRESS_READ, 0, 0, 0, 296 &p1, &p2, NULL, 1)) { 297 error = ENXIO; 298 goto fail; 299 } 300 301 eaddr[0] = ((u_int8_t *)&p1)[1]; 302 eaddr[1] = ((u_int8_t *)&p1)[0]; 303 eaddr[2] = ((u_int8_t *)&p2)[3]; 304 eaddr[3] = ((u_int8_t *)&p2)[2]; 305 eaddr[4] = ((u_int8_t *)&p2)[1]; 306 eaddr[5] = ((u_int8_t *)&p2)[0]; 307 308 sc->sc_cold = 0; 309 310 ifmedia_init(&sc->sc_ifmedia, 0, txp_ifmedia_upd, txp_ifmedia_sts); 311 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); 312 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL); 313 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); 314 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); 315 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX|IFM_HDX, 0, NULL); 316 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); 317 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); 318 319 sc->sc_xcvr = TXP_XCVR_AUTO; 320 txp_command(sc, TXP_CMD_XCVR_SELECT, TXP_XCVR_AUTO, 0, 0, 321 NULL, NULL, NULL, 0); 322 ifmedia_set(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO); 323 324 ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 325 if (ifp == NULL) { 326 device_printf(dev, "can not if_alloc()\n"); 327 error = ENOSPC; 328 goto fail; 329 } 330 ifp->if_softc = sc; 331 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 332 ifp->if_mtu = ETHERMTU; 333 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 334 ifp->if_ioctl = txp_ioctl; 335 ifp->if_start = txp_start; 336 ifp->if_watchdog = txp_watchdog; 337 ifp->if_init = txp_init; 338 ifp->if_baudrate = 100000000; 339 ifp->if_snd.ifq_maxlen = TX_ENTRIES; 340 ifp->if_hwassist = 0; 341 txp_capabilities(sc); 342 343 /* 344 * Attach us everywhere 345 */ 346 ether_ifattach(ifp, eaddr); 347 348 error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_NET | INTR_MPSAFE, 349 NULL, txp_intr, sc, &sc->sc_intrhand); 350 351 if (error) { 352 ether_ifdetach(ifp); 353 device_printf(dev, "couldn't set up irq\n"); 354 goto fail; 355 } 356 357 return(0); 358 359fail: 360 txp_release_resources(sc); 361 mtx_destroy(&sc->sc_mtx); 362 return(error); 363} 364 365static int 366txp_detach(dev) 367 device_t dev; 368{ 369 struct txp_softc *sc; 370 struct ifnet *ifp; 371 int i; 372 373 sc = device_get_softc(dev); 374 ifp = sc->sc_ifp; 375 376 TXP_LOCK(sc); 377 txp_stop(sc); 378 TXP_UNLOCK(sc); 379 txp_shutdown(dev); 380 callout_drain(&sc->sc_tick); 381 382 ifmedia_removeall(&sc->sc_ifmedia); 383 ether_ifdetach(ifp); 384 385 for (i = 0; i < RXBUF_ENTRIES; i++) 386 free(sc->sc_rxbufs[i].rb_sd, M_DEVBUF); 387 388 txp_release_resources(sc); 389 390 mtx_destroy(&sc->sc_mtx); 391 return(0); 392} 393 394static void 395txp_release_resources(sc) 396 struct txp_softc *sc; 397{ 398 device_t dev; 399 400 dev = sc->sc_dev; 401 402 if (sc->sc_intrhand != NULL) 403 bus_teardown_intr(dev, sc->sc_irq, sc->sc_intrhand); 404 405 if (sc->sc_irq != NULL) 406 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq); 407 408 if (sc->sc_res != NULL) 409 bus_release_resource(dev, TXP_RES, TXP_RID, sc->sc_res); 410 411 if (sc->sc_ldata != NULL) 412 contigfree(sc->sc_ldata, sizeof(struct txp_ldata), M_DEVBUF); 413 414 if (sc->sc_ifp) 415 if_free(sc->sc_ifp); 416 417 return; 418} 419 420static int 421txp_chip_init(sc) 422 struct txp_softc *sc; 423{ 424 /* disable interrupts */ 425 WRITE_REG(sc, TXP_IER, 0); 426 WRITE_REG(sc, TXP_IMR, 427 TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT | 428 TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 | 429 TXP_INT_LATCH); 430 431 /* ack all interrupts */ 432 WRITE_REG(sc, TXP_ISR, TXP_INT_RESERVED | TXP_INT_LATCH | 433 TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 | 434 TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT | 435 TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 | 436 TXP_INT_A2H_3 | TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0); 437 438 if (txp_reset_adapter(sc)) 439 return (-1); 440 441 /* disable interrupts */ 442 WRITE_REG(sc, TXP_IER, 0); 443 WRITE_REG(sc, TXP_IMR, 444 TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT | 445 TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 | 446 TXP_INT_LATCH); 447 448 /* ack all interrupts */ 449 WRITE_REG(sc, TXP_ISR, TXP_INT_RESERVED | TXP_INT_LATCH | 450 TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 | 451 TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT | 452 TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 | 453 TXP_INT_A2H_3 | TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0); 454 455 return (0); 456} 457 458static int 459txp_reset_adapter(sc) 460 struct txp_softc *sc; 461{ 462 u_int32_t r; 463 int i; 464 465 r = 0; 466 WRITE_REG(sc, TXP_SRR, TXP_SRR_ALL); 467 DELAY(1000); 468 WRITE_REG(sc, TXP_SRR, 0); 469 470 /* Should wait max 6 seconds */ 471 for (i = 0; i < 6000; i++) { 472 r = READ_REG(sc, TXP_A2H_0); 473 if (r == STAT_WAITING_FOR_HOST_REQUEST) 474 break; 475 DELAY(1000); 476 } 477 478 if (r != STAT_WAITING_FOR_HOST_REQUEST) { 479 device_printf(sc->sc_dev, "reset hung\n"); 480 return (-1); 481 } 482 483 return (0); 484} 485 486static int 487txp_download_fw(sc) 488 struct txp_softc *sc; 489{ 490 struct txp_fw_file_header *fileheader; 491 struct txp_fw_section_header *secthead; 492 int sect; 493 u_int32_t r, i, ier, imr; 494 495 r = 0; 496 ier = READ_REG(sc, TXP_IER); 497 WRITE_REG(sc, TXP_IER, ier | TXP_INT_A2H_0); 498 499 imr = READ_REG(sc, TXP_IMR); 500 WRITE_REG(sc, TXP_IMR, imr | TXP_INT_A2H_0); 501 502 for (i = 0; i < 10000; i++) { 503 r = READ_REG(sc, TXP_A2H_0); 504 if (r == STAT_WAITING_FOR_HOST_REQUEST) 505 break; 506 DELAY(50); 507 } 508 if (r != STAT_WAITING_FOR_HOST_REQUEST) { 509 device_printf(sc->sc_dev, "not waiting for host request\n"); 510 return (-1); 511 } 512 513 /* Ack the status */ 514 WRITE_REG(sc, TXP_ISR, TXP_INT_A2H_0); 515 516 fileheader = (struct txp_fw_file_header *)tc990image; 517 if (bcmp("TYPHOON", fileheader->magicid, sizeof(fileheader->magicid))) { 518 device_printf(sc->sc_dev, "fw invalid magic\n"); 519 return (-1); 520 } 521 522 /* Tell boot firmware to get ready for image */ 523 WRITE_REG(sc, TXP_H2A_1, fileheader->addr); 524 WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_RUNTIME_IMAGE); 525 526 if (txp_download_fw_wait(sc)) { 527 device_printf(sc->sc_dev, "fw wait failed, initial\n"); 528 return (-1); 529 } 530 531 secthead = (struct txp_fw_section_header *)(((u_int8_t *)tc990image) + 532 sizeof(struct txp_fw_file_header)); 533 534 for (sect = 0; sect < fileheader->nsections; sect++) { 535 if (txp_download_fw_section(sc, secthead, sect)) 536 return (-1); 537 secthead = (struct txp_fw_section_header *) 538 (((u_int8_t *)secthead) + secthead->nbytes + 539 sizeof(*secthead)); 540 } 541 542 WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_DOWNLOAD_COMPLETE); 543 544 for (i = 0; i < 10000; i++) { 545 r = READ_REG(sc, TXP_A2H_0); 546 if (r == STAT_WAITING_FOR_BOOT) 547 break; 548 DELAY(50); 549 } 550 if (r != STAT_WAITING_FOR_BOOT) { 551 device_printf(sc->sc_dev, "not waiting for boot\n"); 552 return (-1); 553 } 554 555 WRITE_REG(sc, TXP_IER, ier); 556 WRITE_REG(sc, TXP_IMR, imr); 557 558 return (0); 559} 560 561static int 562txp_download_fw_wait(sc) 563 struct txp_softc *sc; 564{ 565 u_int32_t i, r; 566 567 r = 0; 568 for (i = 0; i < 10000; i++) { 569 r = READ_REG(sc, TXP_ISR); 570 if (r & TXP_INT_A2H_0) 571 break; 572 DELAY(50); 573 } 574 575 if (!(r & TXP_INT_A2H_0)) { 576 device_printf(sc->sc_dev, "fw wait failed comm0\n"); 577 return (-1); 578 } 579 580 WRITE_REG(sc, TXP_ISR, TXP_INT_A2H_0); 581 582 r = READ_REG(sc, TXP_A2H_0); 583 if (r != STAT_WAITING_FOR_SEGMENT) { 584 device_printf(sc->sc_dev, "fw not waiting for segment\n"); 585 return (-1); 586 } 587 return (0); 588} 589 590static int 591txp_download_fw_section(sc, sect, sectnum) 592 struct txp_softc *sc; 593 struct txp_fw_section_header *sect; 594 int sectnum; 595{ 596 vm_offset_t dma; 597 int rseg, err = 0; 598 struct mbuf m; 599 u_int16_t csum; 600 601 /* Skip zero length sections */ 602 if (sect->nbytes == 0) 603 return (0); 604 605 /* Make sure we aren't past the end of the image */ 606 rseg = ((u_int8_t *)sect) - ((u_int8_t *)tc990image); 607 if (rseg >= sizeof(tc990image)) { 608 device_printf(sc->sc_dev, "fw invalid section address, " 609 "section %d\n", sectnum); 610 return (-1); 611 } 612 613 /* Make sure this section doesn't go past the end */ 614 rseg += sect->nbytes; 615 if (rseg >= sizeof(tc990image)) { 616 device_printf(sc->sc_dev, "fw truncated section %d\n", 617 sectnum); 618 return (-1); 619 } 620 621 bcopy(((u_int8_t *)sect) + sizeof(*sect), sc->sc_fwbuf, sect->nbytes); 622 dma = vtophys(sc->sc_fwbuf); 623 624 /* 625 * dummy up mbuf and verify section checksum 626 */ 627 m.m_type = MT_DATA; 628 m.m_next = m.m_nextpkt = NULL; 629 m.m_len = sect->nbytes; 630 m.m_data = sc->sc_fwbuf; 631 m.m_flags = 0; 632 csum = in_cksum(&m, sect->nbytes); 633 if (csum != sect->cksum) { 634 device_printf(sc->sc_dev, "fw section %d, bad " 635 "cksum (expected 0x%x got 0x%x)\n", 636 sectnum, sect->cksum, csum); 637 err = -1; 638 goto bail; 639 } 640 641 WRITE_REG(sc, TXP_H2A_1, sect->nbytes); 642 WRITE_REG(sc, TXP_H2A_2, sect->cksum); 643 WRITE_REG(sc, TXP_H2A_3, sect->addr); 644 WRITE_REG(sc, TXP_H2A_4, 0); 645 WRITE_REG(sc, TXP_H2A_5, dma & 0xffffffff); 646 WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_SEGMENT_AVAILABLE); 647 648 if (txp_download_fw_wait(sc)) { 649 device_printf(sc->sc_dev, "fw wait failed, " 650 "section %d\n", sectnum); 651 err = -1; 652 } 653 654bail: 655 return (err); 656} 657 658static void 659txp_intr(vsc) 660 void *vsc; 661{ 662 struct txp_softc *sc = vsc; 663 struct txp_hostvar *hv = sc->sc_hostvar; 664 u_int32_t isr; 665 666 /* mask all interrupts */ 667 TXP_LOCK(sc); 668 WRITE_REG(sc, TXP_IMR, TXP_INT_RESERVED | TXP_INT_SELF | 669 TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 | 670 TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0 | 671 TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 | 672 TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT | TXP_INT_LATCH); 673 674 isr = READ_REG(sc, TXP_ISR); 675 while (isr) { 676 WRITE_REG(sc, TXP_ISR, isr); 677 678 if ((*sc->sc_rxhir.r_roff) != (*sc->sc_rxhir.r_woff)) 679 txp_rx_reclaim(sc, &sc->sc_rxhir); 680 if ((*sc->sc_rxlor.r_roff) != (*sc->sc_rxlor.r_woff)) 681 txp_rx_reclaim(sc, &sc->sc_rxlor); 682 683 if (hv->hv_rx_buf_write_idx == hv->hv_rx_buf_read_idx) 684 txp_rxbuf_reclaim(sc); 685 686 if (sc->sc_txhir.r_cnt && (sc->sc_txhir.r_cons != 687 TXP_OFFSET2IDX(*(sc->sc_txhir.r_off)))) 688 txp_tx_reclaim(sc, &sc->sc_txhir); 689 690 if (sc->sc_txlor.r_cnt && (sc->sc_txlor.r_cons != 691 TXP_OFFSET2IDX(*(sc->sc_txlor.r_off)))) 692 txp_tx_reclaim(sc, &sc->sc_txlor); 693 694 isr = READ_REG(sc, TXP_ISR); 695 } 696 697 /* unmask all interrupts */ 698 WRITE_REG(sc, TXP_IMR, TXP_INT_A2H_3); 699 700 txp_start_locked(sc->sc_ifp); 701 TXP_UNLOCK(sc); 702 703 return; 704} 705 706static void 707txp_rx_reclaim(sc, r) 708 struct txp_softc *sc; 709 struct txp_rx_ring *r; 710{ 711 struct ifnet *ifp = sc->sc_ifp; 712 struct txp_rx_desc *rxd; 713 struct mbuf *m; 714 struct txp_swdesc *sd = NULL; 715 u_int32_t roff, woff; 716 717 TXP_LOCK_ASSERT(sc); 718 roff = *r->r_roff; 719 woff = *r->r_woff; 720 rxd = r->r_desc + (roff / sizeof(struct txp_rx_desc)); 721 722 while (roff != woff) { 723 724 if (rxd->rx_flags & RX_FLAGS_ERROR) { 725 device_printf(sc->sc_dev, "error 0x%x\n", 726 rxd->rx_stat); 727 ifp->if_ierrors++; 728 goto next; 729 } 730 731 /* retrieve stashed pointer */ 732 sd = rxd->rx_sd; 733 734 m = sd->sd_mbuf; 735 sd->sd_mbuf = NULL; 736 737 m->m_pkthdr.len = m->m_len = rxd->rx_len; 738 739#ifdef __STRICT_ALIGNMENT 740 { 741 /* 742 * XXX Nice chip, except it won't accept "off by 2" 743 * buffers, so we're force to copy. Supposedly 744 * this will be fixed in a newer firmware rev 745 * and this will be temporary. 746 */ 747 struct mbuf *mnew; 748 749 mnew = m_devget(mtod(m, caddr_t), rxd->rx_len, 750 ETHER_ALIGN, ifp, NULL); 751 m_freem(m); 752 if (mnew == NULL) { 753 ifp->if_ierrors++; 754 goto next; 755 } 756 m = mnew; 757 } 758#endif 759 760 if (rxd->rx_stat & RX_STAT_IPCKSUMBAD) 761 m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 762 else if (rxd->rx_stat & RX_STAT_IPCKSUMGOOD) 763 m->m_pkthdr.csum_flags |= 764 CSUM_IP_CHECKED|CSUM_IP_VALID; 765 766 if ((rxd->rx_stat & RX_STAT_TCPCKSUMGOOD) || 767 (rxd->rx_stat & RX_STAT_UDPCKSUMGOOD)) { 768 m->m_pkthdr.csum_flags |= 769 CSUM_DATA_VALID|CSUM_PSEUDO_HDR; 770 m->m_pkthdr.csum_data = 0xffff; 771 } 772 773 if (rxd->rx_stat & RX_STAT_VLAN) { 774 m->m_pkthdr.ether_vtag = htons(rxd->rx_vlan >> 16); 775 m->m_flags |= M_VLANTAG; 776 } 777 778 TXP_UNLOCK(sc); 779 (*ifp->if_input)(ifp, m); 780 TXP_LOCK(sc); 781 782next: 783 784 roff += sizeof(struct txp_rx_desc); 785 if (roff == (RX_ENTRIES * sizeof(struct txp_rx_desc))) { 786 roff = 0; 787 rxd = r->r_desc; 788 } else 789 rxd++; 790 woff = *r->r_woff; 791 } 792 793 *r->r_roff = woff; 794 795 return; 796} 797 798static void 799txp_rxbuf_reclaim(sc) 800 struct txp_softc *sc; 801{ 802 struct ifnet *ifp = sc->sc_ifp; 803 struct txp_hostvar *hv = sc->sc_hostvar; 804 struct txp_rxbuf_desc *rbd; 805 struct txp_swdesc *sd; 806 u_int32_t i; 807 808 TXP_LOCK_ASSERT(sc); 809 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 810 return; 811 812 i = sc->sc_rxbufprod; 813 rbd = sc->sc_rxbufs + i; 814 815 while (1) { 816 sd = rbd->rb_sd; 817 if (sd->sd_mbuf != NULL) 818 break; 819 820 sd->sd_mbuf = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 821 if (sd->sd_mbuf == NULL) 822 return; 823 sd->sd_mbuf->m_pkthdr.rcvif = ifp; 824 sd->sd_mbuf->m_pkthdr.len = sd->sd_mbuf->m_len = MCLBYTES; 825 826 rbd->rb_paddrlo = vtophys(mtod(sd->sd_mbuf, vm_offset_t)) 827 & 0xffffffff; 828 rbd->rb_paddrhi = 0; 829 830 hv->hv_rx_buf_write_idx = TXP_IDX2OFFSET(i); 831 832 if (++i == RXBUF_ENTRIES) { 833 i = 0; 834 rbd = sc->sc_rxbufs; 835 } else 836 rbd++; 837 } 838 839 sc->sc_rxbufprod = i; 840 841 return; 842} 843 844/* 845 * Reclaim mbufs and entries from a transmit ring. 846 */ 847static void 848txp_tx_reclaim(sc, r) 849 struct txp_softc *sc; 850 struct txp_tx_ring *r; 851{ 852 struct ifnet *ifp = sc->sc_ifp; 853 u_int32_t idx = TXP_OFFSET2IDX(*(r->r_off)); 854 u_int32_t cons = r->r_cons, cnt = r->r_cnt; 855 struct txp_tx_desc *txd = r->r_desc + cons; 856 struct txp_swdesc *sd = sc->sc_txd + cons; 857 struct mbuf *m; 858 859 TXP_LOCK_ASSERT(sc); 860 while (cons != idx) { 861 if (cnt == 0) 862 break; 863 864 if ((txd->tx_flags & TX_FLAGS_TYPE_M) == 865 TX_FLAGS_TYPE_DATA) { 866 m = sd->sd_mbuf; 867 if (m != NULL) { 868 m_freem(m); 869 txd->tx_addrlo = 0; 870 txd->tx_addrhi = 0; 871 ifp->if_opackets++; 872 } 873 } 874 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 875 876 if (++cons == TX_ENTRIES) { 877 txd = r->r_desc; 878 cons = 0; 879 sd = sc->sc_txd; 880 } else { 881 txd++; 882 sd++; 883 } 884 885 cnt--; 886 } 887 888 r->r_cons = cons; 889 r->r_cnt = cnt; 890 if (cnt == 0) 891 ifp->if_timer = 0; 892} 893 894static int 895txp_shutdown(dev) 896 device_t dev; 897{ 898 struct txp_softc *sc; 899 900 sc = device_get_softc(dev); 901 902 TXP_LOCK(sc); 903 904 /* mask all interrupts */ 905 WRITE_REG(sc, TXP_IMR, 906 TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT | 907 TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 | 908 TXP_INT_LATCH); 909 910 txp_command(sc, TXP_CMD_TX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 0); 911 txp_command(sc, TXP_CMD_RX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 0); 912 txp_command(sc, TXP_CMD_HALT, 0, 0, 0, NULL, NULL, NULL, 0); 913 TXP_UNLOCK(sc); 914 915 return(0); 916} 917 918static int 919txp_alloc_rings(sc) 920 struct txp_softc *sc; 921{ 922 struct txp_boot_record *boot; 923 struct txp_ldata *ld; 924 u_int32_t r; 925 int i; 926 927 r = 0; 928 ld = sc->sc_ldata; 929 boot = &ld->txp_boot; 930 931 /* boot record */ 932 sc->sc_boot = boot; 933 934 /* host variables */ 935 bzero(&ld->txp_hostvar, sizeof(struct txp_hostvar)); 936 boot->br_hostvar_lo = vtophys(&ld->txp_hostvar); 937 boot->br_hostvar_hi = 0; 938 sc->sc_hostvar = (struct txp_hostvar *)&ld->txp_hostvar; 939 940 /* hi priority tx ring */ 941 boot->br_txhipri_lo = vtophys(&ld->txp_txhiring);; 942 boot->br_txhipri_hi = 0; 943 boot->br_txhipri_siz = TX_ENTRIES * sizeof(struct txp_tx_desc); 944 sc->sc_txhir.r_reg = TXP_H2A_1; 945 sc->sc_txhir.r_desc = (struct txp_tx_desc *)&ld->txp_txhiring; 946 sc->sc_txhir.r_cons = sc->sc_txhir.r_prod = sc->sc_txhir.r_cnt = 0; 947 sc->sc_txhir.r_off = &sc->sc_hostvar->hv_tx_hi_desc_read_idx; 948 949 /* lo priority tx ring */ 950 boot->br_txlopri_lo = vtophys(&ld->txp_txloring); 951 boot->br_txlopri_hi = 0; 952 boot->br_txlopri_siz = TX_ENTRIES * sizeof(struct txp_tx_desc); 953 sc->sc_txlor.r_reg = TXP_H2A_3; 954 sc->sc_txlor.r_desc = (struct txp_tx_desc *)&ld->txp_txloring; 955 sc->sc_txlor.r_cons = sc->sc_txlor.r_prod = sc->sc_txlor.r_cnt = 0; 956 sc->sc_txlor.r_off = &sc->sc_hostvar->hv_tx_lo_desc_read_idx; 957 958 /* high priority rx ring */ 959 boot->br_rxhipri_lo = vtophys(&ld->txp_rxhiring); 960 boot->br_rxhipri_hi = 0; 961 boot->br_rxhipri_siz = RX_ENTRIES * sizeof(struct txp_rx_desc); 962 sc->sc_rxhir.r_desc = (struct txp_rx_desc *)&ld->txp_rxhiring; 963 sc->sc_rxhir.r_roff = &sc->sc_hostvar->hv_rx_hi_read_idx; 964 sc->sc_rxhir.r_woff = &sc->sc_hostvar->hv_rx_hi_write_idx; 965 966 /* low priority rx ring */ 967 boot->br_rxlopri_lo = vtophys(&ld->txp_rxloring); 968 boot->br_rxlopri_hi = 0; 969 boot->br_rxlopri_siz = RX_ENTRIES * sizeof(struct txp_rx_desc); 970 sc->sc_rxlor.r_desc = (struct txp_rx_desc *)&ld->txp_rxloring; 971 sc->sc_rxlor.r_roff = &sc->sc_hostvar->hv_rx_lo_read_idx; 972 sc->sc_rxlor.r_woff = &sc->sc_hostvar->hv_rx_lo_write_idx; 973 974 /* command ring */ 975 bzero(&ld->txp_cmdring, sizeof(struct txp_cmd_desc) * CMD_ENTRIES); 976 boot->br_cmd_lo = vtophys(&ld->txp_cmdring); 977 boot->br_cmd_hi = 0; 978 boot->br_cmd_siz = CMD_ENTRIES * sizeof(struct txp_cmd_desc); 979 sc->sc_cmdring.base = (struct txp_cmd_desc *)&ld->txp_cmdring; 980 sc->sc_cmdring.size = CMD_ENTRIES * sizeof(struct txp_cmd_desc); 981 sc->sc_cmdring.lastwrite = 0; 982 983 /* response ring */ 984 bzero(&ld->txp_rspring, sizeof(struct txp_rsp_desc) * RSP_ENTRIES); 985 boot->br_resp_lo = vtophys(&ld->txp_rspring); 986 boot->br_resp_hi = 0; 987 boot->br_resp_siz = CMD_ENTRIES * sizeof(struct txp_rsp_desc); 988 sc->sc_rspring.base = (struct txp_rsp_desc *)&ld->txp_rspring; 989 sc->sc_rspring.size = RSP_ENTRIES * sizeof(struct txp_rsp_desc); 990 sc->sc_rspring.lastwrite = 0; 991 992 /* receive buffer ring */ 993 boot->br_rxbuf_lo = vtophys(&ld->txp_rxbufs); 994 boot->br_rxbuf_hi = 0; 995 boot->br_rxbuf_siz = RXBUF_ENTRIES * sizeof(struct txp_rxbuf_desc); 996 sc->sc_rxbufs = (struct txp_rxbuf_desc *)&ld->txp_rxbufs; 997 998 for (i = 0; i < RXBUF_ENTRIES; i++) { 999 struct txp_swdesc *sd; 1000 if (sc->sc_rxbufs[i].rb_sd != NULL) 1001 continue; 1002 sc->sc_rxbufs[i].rb_sd = malloc(sizeof(struct txp_swdesc), 1003 M_DEVBUF, M_NOWAIT); 1004 if (sc->sc_rxbufs[i].rb_sd == NULL) 1005 return(ENOBUFS); 1006 sd = sc->sc_rxbufs[i].rb_sd; 1007 sd->sd_mbuf = NULL; 1008 } 1009 sc->sc_rxbufprod = 0; 1010 1011 /* zero dma */ 1012 bzero(&ld->txp_zero, sizeof(u_int32_t)); 1013 boot->br_zero_lo = vtophys(&ld->txp_zero); 1014 boot->br_zero_hi = 0; 1015 1016 /* See if it's waiting for boot, and try to boot it */ 1017 for (i = 0; i < 10000; i++) { 1018 r = READ_REG(sc, TXP_A2H_0); 1019 if (r == STAT_WAITING_FOR_BOOT) 1020 break; 1021 DELAY(50); 1022 } 1023 1024 if (r != STAT_WAITING_FOR_BOOT) { 1025 device_printf(sc->sc_dev, "not waiting for boot\n"); 1026 return(ENXIO); 1027 } 1028 1029 WRITE_REG(sc, TXP_H2A_2, 0); 1030 WRITE_REG(sc, TXP_H2A_1, vtophys(sc->sc_boot)); 1031 WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_REGISTER_BOOT_RECORD); 1032 1033 /* See if it booted */ 1034 for (i = 0; i < 10000; i++) { 1035 r = READ_REG(sc, TXP_A2H_0); 1036 if (r == STAT_RUNNING) 1037 break; 1038 DELAY(50); 1039 } 1040 if (r != STAT_RUNNING) { 1041 device_printf(sc->sc_dev, "fw not running\n"); 1042 return(ENXIO); 1043 } 1044 1045 /* Clear TX and CMD ring write registers */ 1046 WRITE_REG(sc, TXP_H2A_1, TXP_BOOTCMD_NULL); 1047 WRITE_REG(sc, TXP_H2A_2, TXP_BOOTCMD_NULL); 1048 WRITE_REG(sc, TXP_H2A_3, TXP_BOOTCMD_NULL); 1049 WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_NULL); 1050 1051 return (0); 1052} 1053 1054static int 1055txp_ioctl(ifp, command, data) 1056 struct ifnet *ifp; 1057 u_long command; 1058 caddr_t data; 1059{ 1060 struct txp_softc *sc = ifp->if_softc; 1061 struct ifreq *ifr = (struct ifreq *)data; 1062 int error = 0; 1063 1064 switch(command) { 1065 case SIOCSIFFLAGS: 1066 TXP_LOCK(sc); 1067 if (ifp->if_flags & IFF_UP) { 1068 txp_init_locked(sc); 1069 } else { 1070 if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1071 txp_stop(sc); 1072 } 1073 TXP_UNLOCK(sc); 1074 break; 1075 case SIOCADDMULTI: 1076 case SIOCDELMULTI: 1077 /* 1078 * Multicast list has changed; set the hardware 1079 * filter accordingly. 1080 */ 1081 TXP_LOCK(sc); 1082 txp_set_filter(sc); 1083 TXP_UNLOCK(sc); 1084 error = 0; 1085 break; 1086 case SIOCGIFMEDIA: 1087 case SIOCSIFMEDIA: 1088 error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, command); 1089 break; 1090 default: 1091 error = ether_ioctl(ifp, command, data); 1092 break; 1093 } 1094 1095 return(error); 1096} 1097 1098static int 1099txp_rxring_fill(sc) 1100 struct txp_softc *sc; 1101{ 1102 int i; 1103 struct ifnet *ifp; 1104 struct txp_swdesc *sd; 1105 1106 TXP_LOCK_ASSERT(sc); 1107 ifp = sc->sc_ifp; 1108 1109 for (i = 0; i < RXBUF_ENTRIES; i++) { 1110 sd = sc->sc_rxbufs[i].rb_sd; 1111 sd->sd_mbuf = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 1112 if (sd->sd_mbuf == NULL) 1113 return(ENOBUFS); 1114 1115 sd->sd_mbuf->m_pkthdr.len = sd->sd_mbuf->m_len = MCLBYTES; 1116 sd->sd_mbuf->m_pkthdr.rcvif = ifp; 1117 1118 sc->sc_rxbufs[i].rb_paddrlo = 1119 vtophys(mtod(sd->sd_mbuf, vm_offset_t)); 1120 sc->sc_rxbufs[i].rb_paddrhi = 0; 1121 } 1122 1123 sc->sc_hostvar->hv_rx_buf_write_idx = (RXBUF_ENTRIES - 1) * 1124 sizeof(struct txp_rxbuf_desc); 1125 1126 return(0); 1127} 1128 1129static void 1130txp_rxring_empty(sc) 1131 struct txp_softc *sc; 1132{ 1133 int i; 1134 struct txp_swdesc *sd; 1135 1136 TXP_LOCK_ASSERT(sc); 1137 if (sc->sc_rxbufs == NULL) 1138 return; 1139 1140 for (i = 0; i < RXBUF_ENTRIES; i++) { 1141 if (&sc->sc_rxbufs[i] == NULL) 1142 continue; 1143 sd = sc->sc_rxbufs[i].rb_sd; 1144 if (sd == NULL) 1145 continue; 1146 if (sd->sd_mbuf != NULL) { 1147 m_freem(sd->sd_mbuf); 1148 sd->sd_mbuf = NULL; 1149 } 1150 } 1151 1152 return; 1153} 1154 1155static void 1156txp_init(xsc) 1157 void *xsc; 1158{ 1159 struct txp_softc *sc; 1160 1161 sc = xsc; 1162 TXP_LOCK(sc); 1163 txp_init_locked(sc); 1164 TXP_UNLOCK(sc); 1165} 1166 1167static void 1168txp_init_locked(sc) 1169 struct txp_softc *sc; 1170{ 1171 struct ifnet *ifp; 1172 u_int16_t p1; 1173 u_int32_t p2; 1174 1175 TXP_LOCK_ASSERT(sc); 1176 ifp = sc->sc_ifp; 1177 1178 if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1179 return; 1180 1181 txp_stop(sc); 1182 1183 txp_command(sc, TXP_CMD_MAX_PKT_SIZE_WRITE, TXP_MAX_PKTLEN, 0, 0, 1184 NULL, NULL, NULL, 1); 1185 1186 /* Set station address. */ 1187 ((u_int8_t *)&p1)[1] = IF_LLADDR(sc->sc_ifp)[0]; 1188 ((u_int8_t *)&p1)[0] = IF_LLADDR(sc->sc_ifp)[1]; 1189 ((u_int8_t *)&p2)[3] = IF_LLADDR(sc->sc_ifp)[2]; 1190 ((u_int8_t *)&p2)[2] = IF_LLADDR(sc->sc_ifp)[3]; 1191 ((u_int8_t *)&p2)[1] = IF_LLADDR(sc->sc_ifp)[4]; 1192 ((u_int8_t *)&p2)[0] = IF_LLADDR(sc->sc_ifp)[5]; 1193 txp_command(sc, TXP_CMD_STATION_ADDRESS_WRITE, p1, p2, 0, 1194 NULL, NULL, NULL, 1); 1195 1196 txp_set_filter(sc); 1197 1198 txp_rxring_fill(sc); 1199 1200 txp_command(sc, TXP_CMD_TX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1); 1201 txp_command(sc, TXP_CMD_RX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1); 1202 1203 WRITE_REG(sc, TXP_IER, TXP_INT_RESERVED | TXP_INT_SELF | 1204 TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 | 1205 TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0 | 1206 TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 | 1207 TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT | TXP_INT_LATCH); 1208 WRITE_REG(sc, TXP_IMR, TXP_INT_A2H_3); 1209 1210 ifp->if_drv_flags |= IFF_DRV_RUNNING; 1211 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1212 ifp->if_timer = 0; 1213 1214 callout_reset(&sc->sc_tick, hz, txp_tick, sc); 1215} 1216 1217static void 1218txp_tick(vsc) 1219 void *vsc; 1220{ 1221 struct txp_softc *sc = vsc; 1222 struct ifnet *ifp = sc->sc_ifp; 1223 struct txp_rsp_desc *rsp = NULL; 1224 struct txp_ext_desc *ext; 1225 1226 TXP_LOCK_ASSERT(sc); 1227 txp_rxbuf_reclaim(sc); 1228 1229 if (txp_command2(sc, TXP_CMD_READ_STATISTICS, 0, 0, 0, NULL, 0, 1230 &rsp, 1)) 1231 goto out; 1232 if (rsp->rsp_numdesc != 6) 1233 goto out; 1234 if (txp_command(sc, TXP_CMD_CLEAR_STATISTICS, 0, 0, 0, 1235 NULL, NULL, NULL, 1)) 1236 goto out; 1237 ext = (struct txp_ext_desc *)(rsp + 1); 1238 1239 ifp->if_ierrors += ext[3].ext_2 + ext[3].ext_3 + ext[3].ext_4 + 1240 ext[4].ext_1 + ext[4].ext_4; 1241 ifp->if_oerrors += ext[0].ext_1 + ext[1].ext_1 + ext[1].ext_4 + 1242 ext[2].ext_1; 1243 ifp->if_collisions += ext[0].ext_2 + ext[0].ext_3 + ext[1].ext_2 + 1244 ext[1].ext_3; 1245 ifp->if_opackets += rsp->rsp_par2; 1246 ifp->if_ipackets += ext[2].ext_3; 1247 1248out: 1249 if (rsp != NULL) 1250 free(rsp, M_DEVBUF); 1251 1252 callout_reset(&sc->sc_tick, hz, txp_tick, sc); 1253 1254 return; 1255} 1256 1257static void 1258txp_start(ifp) 1259 struct ifnet *ifp; 1260{ 1261 struct txp_softc *sc; 1262 1263 sc = ifp->if_softc; 1264 TXP_LOCK(sc); 1265 txp_start_locked(ifp); 1266 TXP_UNLOCK(sc); 1267} 1268 1269static void 1270txp_start_locked(ifp) 1271 struct ifnet *ifp; 1272{ 1273 struct txp_softc *sc = ifp->if_softc; 1274 struct txp_tx_ring *r = &sc->sc_txhir; 1275 struct txp_tx_desc *txd; 1276 struct txp_frag_desc *fxd; 1277 struct mbuf *m, *m0; 1278 struct txp_swdesc *sd; 1279 u_int32_t firstprod, firstcnt, prod, cnt; 1280 1281 TXP_LOCK_ASSERT(sc); 1282 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1283 IFF_DRV_RUNNING) 1284 return; 1285 1286 prod = r->r_prod; 1287 cnt = r->r_cnt; 1288 1289 while (1) { 1290 IF_DEQUEUE(&ifp->if_snd, m); 1291 if (m == NULL) 1292 break; 1293 1294 firstprod = prod; 1295 firstcnt = cnt; 1296 1297 sd = sc->sc_txd + prod; 1298 sd->sd_mbuf = m; 1299 1300 if ((TX_ENTRIES - cnt) < 4) 1301 goto oactive; 1302 1303 txd = r->r_desc + prod; 1304 1305 txd->tx_flags = TX_FLAGS_TYPE_DATA; 1306 txd->tx_numdesc = 0; 1307 txd->tx_addrlo = 0; 1308 txd->tx_addrhi = 0; 1309 txd->tx_totlen = 0; 1310 txd->tx_pflags = 0; 1311 1312 if (++prod == TX_ENTRIES) 1313 prod = 0; 1314 1315 if (++cnt >= (TX_ENTRIES - 4)) 1316 goto oactive; 1317 1318 if (m->m_flags & M_VLANTAG) { 1319 txd->tx_pflags = TX_PFLAGS_VLAN | 1320 (htons(m->m_pkthdr.ether_vtag) << TX_PFLAGS_VLANTAG_S); 1321 } 1322 1323 if (m->m_pkthdr.csum_flags & CSUM_IP) 1324 txd->tx_pflags |= TX_PFLAGS_IPCKSUM; 1325 1326#if 0 1327 if (m->m_pkthdr.csum_flags & CSUM_TCP) 1328 txd->tx_pflags |= TX_PFLAGS_TCPCKSUM; 1329 if (m->m_pkthdr.csum_flags & CSUM_UDP) 1330 txd->tx_pflags |= TX_PFLAGS_UDPCKSUM; 1331#endif 1332 1333 fxd = (struct txp_frag_desc *)(r->r_desc + prod); 1334 for (m0 = m; m0 != NULL; m0 = m0->m_next) { 1335 if (m0->m_len == 0) 1336 continue; 1337 if (++cnt >= (TX_ENTRIES - 4)) 1338 goto oactive; 1339 1340 txd->tx_numdesc++; 1341 1342 fxd->frag_flags = FRAG_FLAGS_TYPE_FRAG; 1343 fxd->frag_rsvd1 = 0; 1344 fxd->frag_len = m0->m_len; 1345 fxd->frag_addrlo = vtophys(mtod(m0, vm_offset_t)); 1346 fxd->frag_addrhi = 0; 1347 fxd->frag_rsvd2 = 0; 1348 1349 if (++prod == TX_ENTRIES) { 1350 fxd = (struct txp_frag_desc *)r->r_desc; 1351 prod = 0; 1352 } else 1353 fxd++; 1354 1355 } 1356 1357 ifp->if_timer = 5; 1358 1359 ETHER_BPF_MTAP(ifp, m); 1360 WRITE_REG(sc, r->r_reg, TXP_IDX2OFFSET(prod)); 1361 } 1362 1363 r->r_prod = prod; 1364 r->r_cnt = cnt; 1365 return; 1366 1367oactive: 1368 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1369 r->r_prod = firstprod; 1370 r->r_cnt = firstcnt; 1371 IF_PREPEND(&ifp->if_snd, m); 1372 return; 1373} 1374 1375/* 1376 * Handle simple commands sent to the typhoon 1377 */ 1378static int 1379txp_command(struct txp_softc *sc, u_int16_t id, u_int16_t in1, u_int32_t in2, 1380 u_int32_t in3, u_int16_t *out1, u_int32_t *out2, u_int32_t *out3, int wait) 1381{ 1382 struct txp_rsp_desc *rsp = NULL; 1383 1384 if (txp_command2(sc, id, in1, in2, in3, NULL, 0, &rsp, wait)) 1385 return (-1); 1386 1387 if (!wait) 1388 return (0); 1389 1390 if (out1 != NULL) 1391 *out1 = rsp->rsp_par1; 1392 if (out2 != NULL) 1393 *out2 = rsp->rsp_par2; 1394 if (out3 != NULL) 1395 *out3 = rsp->rsp_par3; 1396 free(rsp, M_DEVBUF); 1397 return (0); 1398} 1399 1400static int 1401txp_command2(struct txp_softc *sc, u_int16_t id, u_int16_t in1, u_int32_t in2, 1402 u_int32_t in3, struct txp_ext_desc *in_extp, u_int8_t in_extn, 1403 struct txp_rsp_desc **rspp, int wait) 1404{ 1405 struct txp_hostvar *hv = sc->sc_hostvar; 1406 struct txp_cmd_desc *cmd; 1407 struct txp_ext_desc *ext; 1408 u_int32_t idx, i; 1409 u_int16_t seq; 1410 1411 if (txp_cmd_desc_numfree(sc) < (in_extn + 1)) { 1412 device_printf(sc->sc_dev, "no free cmd descriptors\n"); 1413 return (-1); 1414 } 1415 1416 idx = sc->sc_cmdring.lastwrite; 1417 cmd = (struct txp_cmd_desc *)(((u_int8_t *)sc->sc_cmdring.base) + idx); 1418 bzero(cmd, sizeof(*cmd)); 1419 1420 cmd->cmd_numdesc = in_extn; 1421 cmd->cmd_seq = seq = sc->sc_seq++; 1422 cmd->cmd_id = id; 1423 cmd->cmd_par1 = in1; 1424 cmd->cmd_par2 = in2; 1425 cmd->cmd_par3 = in3; 1426 cmd->cmd_flags = CMD_FLAGS_TYPE_CMD | 1427 (wait ? CMD_FLAGS_RESP : 0) | CMD_FLAGS_VALID; 1428 1429 idx += sizeof(struct txp_cmd_desc); 1430 if (idx == sc->sc_cmdring.size) 1431 idx = 0; 1432 1433 for (i = 0; i < in_extn; i++) { 1434 ext = (struct txp_ext_desc *)(((u_int8_t *)sc->sc_cmdring.base) + idx); 1435 bcopy(in_extp, ext, sizeof(struct txp_ext_desc)); 1436 in_extp++; 1437 idx += sizeof(struct txp_cmd_desc); 1438 if (idx == sc->sc_cmdring.size) 1439 idx = 0; 1440 } 1441 1442 sc->sc_cmdring.lastwrite = idx; 1443 1444 WRITE_REG(sc, TXP_H2A_2, sc->sc_cmdring.lastwrite); 1445 1446 if (!wait) 1447 return (0); 1448 1449 for (i = 0; i < 10000; i++) { 1450 idx = hv->hv_resp_read_idx; 1451 if (idx != hv->hv_resp_write_idx) { 1452 *rspp = NULL; 1453 if (txp_response(sc, idx, id, seq, rspp)) 1454 return (-1); 1455 if (*rspp != NULL) 1456 break; 1457 } 1458 DELAY(50); 1459 } 1460 if (i == 1000 || (*rspp) == NULL) { 1461 device_printf(sc->sc_dev, "0x%x command failed\n", id); 1462 return (-1); 1463 } 1464 1465 return (0); 1466} 1467 1468static int 1469txp_response(struct txp_softc *sc, u_int32_t ridx, u_int16_t id, u_int16_t seq, 1470 struct txp_rsp_desc **rspp) 1471{ 1472 struct txp_hostvar *hv = sc->sc_hostvar; 1473 struct txp_rsp_desc *rsp; 1474 1475 while (ridx != hv->hv_resp_write_idx) { 1476 rsp = (struct txp_rsp_desc *)(((u_int8_t *)sc->sc_rspring.base) + ridx); 1477 1478 if (id == rsp->rsp_id && rsp->rsp_seq == seq) { 1479 *rspp = (struct txp_rsp_desc *)malloc( 1480 sizeof(struct txp_rsp_desc) * (rsp->rsp_numdesc + 1), 1481 M_DEVBUF, M_NOWAIT); 1482 if ((*rspp) == NULL) 1483 return (-1); 1484 txp_rsp_fixup(sc, rsp, *rspp); 1485 return (0); 1486 } 1487 1488 if (rsp->rsp_flags & RSP_FLAGS_ERROR) { 1489 device_printf(sc->sc_dev, "response error!\n"); 1490 txp_rsp_fixup(sc, rsp, NULL); 1491 ridx = hv->hv_resp_read_idx; 1492 continue; 1493 } 1494 1495 switch (rsp->rsp_id) { 1496 case TXP_CMD_CYCLE_STATISTICS: 1497 case TXP_CMD_MEDIA_STATUS_READ: 1498 break; 1499 case TXP_CMD_HELLO_RESPONSE: 1500 device_printf(sc->sc_dev, "hello\n"); 1501 break; 1502 default: 1503 device_printf(sc->sc_dev, "unknown id(0x%x)\n", 1504 rsp->rsp_id); 1505 } 1506 1507 txp_rsp_fixup(sc, rsp, NULL); 1508 ridx = hv->hv_resp_read_idx; 1509 hv->hv_resp_read_idx = ridx; 1510 } 1511 1512 return (0); 1513} 1514 1515static void 1516txp_rsp_fixup(sc, rsp, dst) 1517 struct txp_softc *sc; 1518 struct txp_rsp_desc *rsp, *dst; 1519{ 1520 struct txp_rsp_desc *src = rsp; 1521 struct txp_hostvar *hv = sc->sc_hostvar; 1522 u_int32_t i, ridx; 1523 1524 ridx = hv->hv_resp_read_idx; 1525 1526 for (i = 0; i < rsp->rsp_numdesc + 1; i++) { 1527 if (dst != NULL) 1528 bcopy(src, dst++, sizeof(struct txp_rsp_desc)); 1529 ridx += sizeof(struct txp_rsp_desc); 1530 if (ridx == sc->sc_rspring.size) { 1531 src = sc->sc_rspring.base; 1532 ridx = 0; 1533 } else 1534 src++; 1535 sc->sc_rspring.lastwrite = hv->hv_resp_read_idx = ridx; 1536 } 1537 1538 hv->hv_resp_read_idx = ridx; 1539} 1540 1541static int 1542txp_cmd_desc_numfree(sc) 1543 struct txp_softc *sc; 1544{ 1545 struct txp_hostvar *hv = sc->sc_hostvar; 1546 struct txp_boot_record *br = sc->sc_boot; 1547 u_int32_t widx, ridx, nfree; 1548 1549 widx = sc->sc_cmdring.lastwrite; 1550 ridx = hv->hv_cmd_read_idx; 1551 1552 if (widx == ridx) { 1553 /* Ring is completely free */ 1554 nfree = br->br_cmd_siz - sizeof(struct txp_cmd_desc); 1555 } else { 1556 if (widx > ridx) 1557 nfree = br->br_cmd_siz - 1558 (widx - ridx + sizeof(struct txp_cmd_desc)); 1559 else 1560 nfree = ridx - widx - sizeof(struct txp_cmd_desc); 1561 } 1562 1563 return (nfree / sizeof(struct txp_cmd_desc)); 1564} 1565 1566static void 1567txp_stop(sc) 1568 struct txp_softc *sc; 1569{ 1570 struct ifnet *ifp; 1571 1572 TXP_LOCK_ASSERT(sc); 1573 ifp = sc->sc_ifp; 1574 1575 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1576 1577 callout_stop(&sc->sc_tick); 1578 1579 txp_command(sc, TXP_CMD_TX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 1); 1580 txp_command(sc, TXP_CMD_RX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 1); 1581 1582 txp_rxring_empty(sc); 1583 1584 return; 1585} 1586 1587static void 1588txp_watchdog(ifp) 1589 struct ifnet *ifp; 1590{ 1591 return; 1592} 1593 1594static int 1595txp_ifmedia_upd(ifp) 1596 struct ifnet *ifp; 1597{ 1598 struct txp_softc *sc = ifp->if_softc; 1599 struct ifmedia *ifm = &sc->sc_ifmedia; 1600 u_int16_t new_xcvr; 1601 1602 TXP_LOCK(sc); 1603 if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) { 1604 TXP_UNLOCK(sc); 1605 return (EINVAL); 1606 } 1607 1608 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) { 1609 if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1610 new_xcvr = TXP_XCVR_10_FDX; 1611 else 1612 new_xcvr = TXP_XCVR_10_HDX; 1613 } else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) { 1614 if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) 1615 new_xcvr = TXP_XCVR_100_FDX; 1616 else 1617 new_xcvr = TXP_XCVR_100_HDX; 1618 } else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) { 1619 new_xcvr = TXP_XCVR_AUTO; 1620 } else { 1621 TXP_UNLOCK(sc); 1622 return (EINVAL); 1623 } 1624 1625 /* nothing to do */ 1626 if (sc->sc_xcvr == new_xcvr) { 1627 TXP_UNLOCK(sc); 1628 return (0); 1629 } 1630 1631 txp_command(sc, TXP_CMD_XCVR_SELECT, new_xcvr, 0, 0, 1632 NULL, NULL, NULL, 0); 1633 sc->sc_xcvr = new_xcvr; 1634 TXP_UNLOCK(sc); 1635 1636 return (0); 1637} 1638 1639static void 1640txp_ifmedia_sts(ifp, ifmr) 1641 struct ifnet *ifp; 1642 struct ifmediareq *ifmr; 1643{ 1644 struct txp_softc *sc = ifp->if_softc; 1645 struct ifmedia *ifm = &sc->sc_ifmedia; 1646 u_int16_t bmsr, bmcr, anar, anlpar; 1647 1648 ifmr->ifm_status = IFM_AVALID; 1649 ifmr->ifm_active = IFM_ETHER; 1650 1651 TXP_LOCK(sc); 1652 if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_BMSR, 0, 1653 &bmsr, NULL, NULL, 1)) 1654 goto bail; 1655 if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_BMSR, 0, 1656 &bmsr, NULL, NULL, 1)) 1657 goto bail; 1658 1659 if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_BMCR, 0, 1660 &bmcr, NULL, NULL, 1)) 1661 goto bail; 1662 1663 if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_ANLPAR, 0, 1664 &anlpar, NULL, NULL, 1)) 1665 goto bail; 1666 1667 if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_ANAR, 0, 1668 &anar, NULL, NULL, 1)) 1669 goto bail; 1670 TXP_UNLOCK(sc); 1671 1672 if (bmsr & BMSR_LINK) 1673 ifmr->ifm_status |= IFM_ACTIVE; 1674 1675 if (bmcr & BMCR_ISO) { 1676 ifmr->ifm_active |= IFM_NONE; 1677 ifmr->ifm_status = 0; 1678 return; 1679 } 1680 1681 if (bmcr & BMCR_LOOP) 1682 ifmr->ifm_active |= IFM_LOOP; 1683 1684 if (bmcr & BMCR_AUTOEN) { 1685 if ((bmsr & BMSR_ACOMP) == 0) { 1686 ifmr->ifm_active |= IFM_NONE; 1687 return; 1688 } 1689 1690 anlpar &= anar; 1691 if (anlpar & ANLPAR_TX_FD) 1692 ifmr->ifm_active |= IFM_100_TX|IFM_FDX; 1693 else if (anlpar & ANLPAR_T4) 1694 ifmr->ifm_active |= IFM_100_T4; 1695 else if (anlpar & ANLPAR_TX) 1696 ifmr->ifm_active |= IFM_100_TX; 1697 else if (anlpar & ANLPAR_10_FD) 1698 ifmr->ifm_active |= IFM_10_T|IFM_FDX; 1699 else if (anlpar & ANLPAR_10) 1700 ifmr->ifm_active |= IFM_10_T; 1701 else 1702 ifmr->ifm_active |= IFM_NONE; 1703 } else 1704 ifmr->ifm_active = ifm->ifm_cur->ifm_media; 1705 return; 1706 1707bail: 1708 TXP_UNLOCK(sc); 1709 ifmr->ifm_active |= IFM_NONE; 1710 ifmr->ifm_status &= ~IFM_AVALID; 1711} 1712 1713#ifdef TXP_DEBUG 1714static void 1715txp_show_descriptor(d) 1716 void *d; 1717{ 1718 struct txp_cmd_desc *cmd = d; 1719 struct txp_rsp_desc *rsp = d; 1720 struct txp_tx_desc *txd = d; 1721 struct txp_frag_desc *frgd = d; 1722 1723 switch (cmd->cmd_flags & CMD_FLAGS_TYPE_M) { 1724 case CMD_FLAGS_TYPE_CMD: 1725 /* command descriptor */ 1726 printf("[cmd flags 0x%x num %d id %d seq %d par1 0x%x par2 0x%x par3 0x%x]\n", 1727 cmd->cmd_flags, cmd->cmd_numdesc, cmd->cmd_id, cmd->cmd_seq, 1728 cmd->cmd_par1, cmd->cmd_par2, cmd->cmd_par3); 1729 break; 1730 case CMD_FLAGS_TYPE_RESP: 1731 /* response descriptor */ 1732 printf("[rsp flags 0x%x num %d id %d seq %d par1 0x%x par2 0x%x par3 0x%x]\n", 1733 rsp->rsp_flags, rsp->rsp_numdesc, rsp->rsp_id, rsp->rsp_seq, 1734 rsp->rsp_par1, rsp->rsp_par2, rsp->rsp_par3); 1735 break; 1736 case CMD_FLAGS_TYPE_DATA: 1737 /* data header (assuming tx for now) */ 1738 printf("[data flags 0x%x num %d totlen %d addr 0x%x/0x%x pflags 0x%x]", 1739 txd->tx_flags, txd->tx_numdesc, txd->tx_totlen, 1740 txd->tx_addrlo, txd->tx_addrhi, txd->tx_pflags); 1741 break; 1742 case CMD_FLAGS_TYPE_FRAG: 1743 /* fragment descriptor */ 1744 printf("[frag flags 0x%x rsvd1 0x%x len %d addr 0x%x/0x%x rsvd2 0x%x]", 1745 frgd->frag_flags, frgd->frag_rsvd1, frgd->frag_len, 1746 frgd->frag_addrlo, frgd->frag_addrhi, frgd->frag_rsvd2); 1747 break; 1748 default: 1749 printf("[unknown(%x) flags 0x%x num %d id %d seq %d par1 0x%x par2 0x%x par3 0x%x]\n", 1750 cmd->cmd_flags & CMD_FLAGS_TYPE_M, 1751 cmd->cmd_flags, cmd->cmd_numdesc, cmd->cmd_id, cmd->cmd_seq, 1752 cmd->cmd_par1, cmd->cmd_par2, cmd->cmd_par3); 1753 break; 1754 } 1755} 1756#endif 1757 1758static void 1759txp_set_filter(sc) 1760 struct txp_softc *sc; 1761{ 1762 struct ifnet *ifp = sc->sc_ifp; 1763 u_int32_t crc, carry, hashbit, hash[2]; 1764 u_int16_t filter; 1765 u_int8_t octet; 1766 int i, j, mcnt = 0; 1767 struct ifmultiaddr *ifma; 1768 char *enm; 1769 1770 if (ifp->if_flags & IFF_PROMISC) { 1771 filter = TXP_RXFILT_PROMISC; 1772 goto setit; 1773 } 1774 1775 filter = TXP_RXFILT_DIRECT; 1776 1777 if (ifp->if_flags & IFF_BROADCAST) 1778 filter |= TXP_RXFILT_BROADCAST; 1779 1780 if (ifp->if_flags & IFF_ALLMULTI) 1781 filter |= TXP_RXFILT_ALLMULTI; 1782 else { 1783 hash[0] = hash[1] = 0; 1784 1785 IF_ADDR_LOCK(ifp); 1786 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1787 if (ifma->ifma_addr->sa_family != AF_LINK) 1788 continue; 1789 1790 enm = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); 1791 mcnt++; 1792 crc = 0xffffffff; 1793 1794 for (i = 0; i < ETHER_ADDR_LEN; i++) { 1795 octet = enm[i]; 1796 for (j = 0; j < 8; j++) { 1797 carry = ((crc & 0x80000000) ? 1 : 0) ^ 1798 (octet & 1); 1799 crc <<= 1; 1800 octet >>= 1; 1801 if (carry) 1802 crc = (crc ^ TXP_POLYNOMIAL) | 1803 carry; 1804 } 1805 } 1806 hashbit = (u_int16_t)(crc & (64 - 1)); 1807 hash[hashbit / 32] |= (1 << hashbit % 32); 1808 } 1809 IF_ADDR_UNLOCK(ifp); 1810 1811 if (mcnt > 0) { 1812 filter |= TXP_RXFILT_HASHMULTI; 1813 txp_command(sc, TXP_CMD_MCAST_HASH_MASK_WRITE, 1814 2, hash[0], hash[1], NULL, NULL, NULL, 0); 1815 } 1816 } 1817 1818setit: 1819 1820 txp_command(sc, TXP_CMD_RX_FILTER_WRITE, filter, 0, 0, 1821 NULL, NULL, NULL, 1); 1822 1823 return; 1824} 1825 1826static void 1827txp_capabilities(sc) 1828 struct txp_softc *sc; 1829{ 1830 struct ifnet *ifp = sc->sc_ifp; 1831 struct txp_rsp_desc *rsp = NULL; 1832 struct txp_ext_desc *ext; 1833 1834 if (txp_command2(sc, TXP_CMD_OFFLOAD_READ, 0, 0, 0, NULL, 0, &rsp, 1)) 1835 goto out; 1836 1837 if (rsp->rsp_numdesc != 1) 1838 goto out; 1839 ext = (struct txp_ext_desc *)(rsp + 1); 1840 1841 sc->sc_tx_capability = ext->ext_1 & OFFLOAD_MASK; 1842 sc->sc_rx_capability = ext->ext_2 & OFFLOAD_MASK; 1843 ifp->if_capabilities = 0; 1844 1845 if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_VLAN) { 1846 sc->sc_tx_capability |= OFFLOAD_VLAN; 1847 sc->sc_rx_capability |= OFFLOAD_VLAN; 1848 ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 1849 } 1850 1851#if 0 1852 /* not ready yet */ 1853 if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_IPSEC) { 1854 sc->sc_tx_capability |= OFFLOAD_IPSEC; 1855 sc->sc_rx_capability |= OFFLOAD_IPSEC; 1856 ifp->if_capabilities |= IFCAP_IPSEC; 1857 } 1858#endif 1859 1860 if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_IPCKSUM) { 1861 sc->sc_tx_capability |= OFFLOAD_IPCKSUM; 1862 sc->sc_rx_capability |= OFFLOAD_IPCKSUM; 1863 ifp->if_capabilities |= IFCAP_HWCSUM; 1864 ifp->if_hwassist |= CSUM_IP; 1865 } 1866 1867 if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_TCPCKSUM) { 1868#if 0 1869 sc->sc_tx_capability |= OFFLOAD_TCPCKSUM; 1870#endif 1871 sc->sc_rx_capability |= OFFLOAD_TCPCKSUM; 1872 ifp->if_capabilities |= IFCAP_HWCSUM; 1873 } 1874 1875 if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_UDPCKSUM) { 1876#if 0 1877 sc->sc_tx_capability |= OFFLOAD_UDPCKSUM; 1878#endif 1879 sc->sc_rx_capability |= OFFLOAD_UDPCKSUM; 1880 ifp->if_capabilities |= IFCAP_HWCSUM; 1881 } 1882 ifp->if_capenable = ifp->if_capabilities; 1883 1884 if (txp_command(sc, TXP_CMD_OFFLOAD_WRITE, 0, 1885 sc->sc_tx_capability, sc->sc_rx_capability, NULL, NULL, NULL, 1)) 1886 goto out; 1887 1888out: 1889 if (rsp != NULL) 1890 free(rsp, M_DEVBUF); 1891 1892 return; 1893} 1894