1744Sgs150176 /* 2744Sgs150176 * CDDL HEADER START 3744Sgs150176 * 4744Sgs150176 * The contents of this file are subject to the terms of the 5*2311Sseb * Common Development and Distribution License (the "License"). 6*2311Sseb * You may not use this file except in compliance with the License. 7744Sgs150176 * 8744Sgs150176 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9744Sgs150176 * or http://www.opensolaris.org/os/licensing. 10744Sgs150176 * See the License for the specific language governing permissions 11744Sgs150176 * and limitations under the License. 12744Sgs150176 * 13744Sgs150176 * When distributing Covered Code, include this CDDL HEADER in each 14744Sgs150176 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15744Sgs150176 * If applicable, add the following below this CDDL HEADER, with the 16744Sgs150176 * fields enclosed by brackets "[]" replaced with your own identifying 17744Sgs150176 * information: Portions Copyright [yyyy] [name of copyright owner] 18744Sgs150176 * 19744Sgs150176 * CDDL HEADER END 20744Sgs150176 */ 21744Sgs150176 /* 22*2311Sseb * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23744Sgs150176 * Use is subject to license terms. 24744Sgs150176 */ 25744Sgs150176 26744Sgs150176 #pragma ident "%Z%%M% %I% %E% SMI" 27744Sgs150176 28744Sgs150176 #include "rge.h" 29744Sgs150176 30744Sgs150176 /* 31744Sgs150176 * This is the string displayed by modinfo, etc. 32744Sgs150176 * Make sure you keep the version ID up to date! 33744Sgs150176 */ 34744Sgs150176 static char rge_ident[] = "Realtek Gigabit Ethernet Driver v%I%"; 35744Sgs150176 36744Sgs150176 /* 37744Sgs150176 * Used for buffers allocated by ddi_dma_mem_alloc() 38744Sgs150176 */ 39744Sgs150176 static ddi_dma_attr_t dma_attr_buf = { 40744Sgs150176 DMA_ATTR_V0, /* dma_attr version */ 41744Sgs150176 (uint32_t)0, /* dma_attr_addr_lo */ 42744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_addr_hi */ 43744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_count_max */ 44744Sgs150176 (uint32_t)16, /* dma_attr_align */ 45744Sgs150176 0xFFFFFFFF, /* dma_attr_burstsizes */ 46744Sgs150176 1, /* dma_attr_minxfer */ 47744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_maxxfer */ 48744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_seg */ 49744Sgs150176 1, /* dma_attr_sgllen */ 50744Sgs150176 1, /* dma_attr_granular */ 51744Sgs150176 0, /* dma_attr_flags */ 52744Sgs150176 }; 53744Sgs150176 54744Sgs150176 /* 55744Sgs150176 * Used for BDs allocated by ddi_dma_mem_alloc() 56744Sgs150176 */ 57744Sgs150176 static ddi_dma_attr_t dma_attr_desc = { 58744Sgs150176 DMA_ATTR_V0, /* dma_attr version */ 59744Sgs150176 (uint32_t)0, /* dma_attr_addr_lo */ 60744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_addr_hi */ 61744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_count_max */ 62744Sgs150176 (uint32_t)256, /* dma_attr_align */ 63744Sgs150176 0xFFFFFFFF, /* dma_attr_burstsizes */ 64744Sgs150176 1, /* dma_attr_minxfer */ 65744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_maxxfer */ 66744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_seg */ 67744Sgs150176 1, /* dma_attr_sgllen */ 68744Sgs150176 1, /* dma_attr_granular */ 69744Sgs150176 0, /* dma_attr_flags */ 70744Sgs150176 }; 71744Sgs150176 72744Sgs150176 /* 73744Sgs150176 * PIO access attributes for registers 74744Sgs150176 */ 75744Sgs150176 static ddi_device_acc_attr_t rge_reg_accattr = { 76744Sgs150176 DDI_DEVICE_ATTR_V0, 77744Sgs150176 DDI_STRUCTURE_LE_ACC, 78744Sgs150176 DDI_STRICTORDER_ACC, 79744Sgs150176 DDI_DEFAULT_ACC 80744Sgs150176 }; 81744Sgs150176 82744Sgs150176 /* 83744Sgs150176 * DMA access attributes for descriptors 84744Sgs150176 */ 85744Sgs150176 static ddi_device_acc_attr_t rge_desc_accattr = { 86744Sgs150176 DDI_DEVICE_ATTR_V0, 87744Sgs150176 DDI_NEVERSWAP_ACC, 88744Sgs150176 DDI_STRICTORDER_ACC, 89744Sgs150176 DDI_DEFAULT_ACC 90744Sgs150176 }; 91744Sgs150176 92744Sgs150176 /* 93744Sgs150176 * DMA access attributes for data 94744Sgs150176 */ 95744Sgs150176 static ddi_device_acc_attr_t rge_buf_accattr = { 96744Sgs150176 DDI_DEVICE_ATTR_V0, 97744Sgs150176 DDI_NEVERSWAP_ACC, 98744Sgs150176 DDI_STRICTORDER_ACC, 99744Sgs150176 DDI_DEFAULT_ACC 100744Sgs150176 }; 101744Sgs150176 102744Sgs150176 /* 103744Sgs150176 * Property names 104744Sgs150176 */ 105744Sgs150176 static char debug_propname[] = "rge-debug-flags"; 106744Sgs150176 107*2311Sseb static int rge_m_start(void *); 108*2311Sseb static void rge_m_stop(void *); 109*2311Sseb static int rge_m_promisc(void *, boolean_t); 110*2311Sseb static int rge_m_multicst(void *, boolean_t, const uint8_t *); 111*2311Sseb static int rge_m_unicst(void *, const uint8_t *); 112*2311Sseb static void rge_m_resources(void *); 113*2311Sseb static void rge_m_ioctl(void *, queue_t *, mblk_t *); 114*2311Sseb static boolean_t rge_m_getcapab(void *, mac_capab_t, void *); 115*2311Sseb 116*2311Sseb #define RGE_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB) 117*2311Sseb 118*2311Sseb static mac_callbacks_t rge_m_callbacks = { 119*2311Sseb RGE_M_CALLBACK_FLAGS, 120*2311Sseb rge_m_stat, 121*2311Sseb rge_m_start, 122*2311Sseb rge_m_stop, 123*2311Sseb rge_m_promisc, 124*2311Sseb rge_m_multicst, 125*2311Sseb rge_m_unicst, 126*2311Sseb rge_m_tx, 127*2311Sseb rge_m_resources, 128*2311Sseb rge_m_ioctl, 129*2311Sseb rge_m_getcapab 130*2311Sseb }; 131744Sgs150176 132744Sgs150176 /* 133744Sgs150176 * Allocate an area of memory and a DMA handle for accessing it 134744Sgs150176 */ 135744Sgs150176 static int 136744Sgs150176 rge_alloc_dma_mem(rge_t *rgep, size_t memsize, ddi_dma_attr_t *dma_attr_p, 137744Sgs150176 ddi_device_acc_attr_t *acc_attr_p, uint_t dma_flags, dma_area_t *dma_p) 138744Sgs150176 { 139744Sgs150176 caddr_t vaddr; 140744Sgs150176 int err; 141744Sgs150176 142744Sgs150176 /* 143744Sgs150176 * Allocate handle 144744Sgs150176 */ 145744Sgs150176 err = ddi_dma_alloc_handle(rgep->devinfo, dma_attr_p, 146744Sgs150176 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl); 147744Sgs150176 if (err != DDI_SUCCESS) { 148744Sgs150176 dma_p->dma_hdl = NULL; 149744Sgs150176 return (DDI_FAILURE); 150744Sgs150176 } 151744Sgs150176 152744Sgs150176 /* 153744Sgs150176 * Allocate memory 154744Sgs150176 */ 155744Sgs150176 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p, 156744Sgs150176 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING), 157744Sgs150176 DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl); 158744Sgs150176 if (err != DDI_SUCCESS) { 159744Sgs150176 ddi_dma_free_handle(&dma_p->dma_hdl); 160744Sgs150176 dma_p->dma_hdl = NULL; 161744Sgs150176 dma_p->acc_hdl = NULL; 162744Sgs150176 return (DDI_FAILURE); 163744Sgs150176 } 164744Sgs150176 165744Sgs150176 /* 166744Sgs150176 * Bind the two together 167744Sgs150176 */ 168744Sgs150176 dma_p->mem_va = vaddr; 169744Sgs150176 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 170744Sgs150176 vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL, 171744Sgs150176 &dma_p->cookie, &dma_p->ncookies); 172744Sgs150176 if (err != DDI_DMA_MAPPED || dma_p->ncookies != 1) { 173744Sgs150176 ddi_dma_mem_free(&dma_p->acc_hdl); 174744Sgs150176 ddi_dma_free_handle(&dma_p->dma_hdl); 175744Sgs150176 dma_p->acc_hdl = NULL; 176744Sgs150176 dma_p->dma_hdl = NULL; 177744Sgs150176 return (DDI_FAILURE); 178744Sgs150176 } 179744Sgs150176 180744Sgs150176 dma_p->nslots = ~0U; 181744Sgs150176 dma_p->size = ~0U; 182744Sgs150176 dma_p->token = ~0U; 183744Sgs150176 dma_p->offset = 0; 184744Sgs150176 return (DDI_SUCCESS); 185744Sgs150176 } 186744Sgs150176 187744Sgs150176 /* 188744Sgs150176 * Free one allocated area of DMAable memory 189744Sgs150176 */ 190744Sgs150176 static void 191744Sgs150176 rge_free_dma_mem(dma_area_t *dma_p) 192744Sgs150176 { 193744Sgs150176 if (dma_p->dma_hdl != NULL) { 194744Sgs150176 if (dma_p->ncookies) { 195744Sgs150176 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 196744Sgs150176 dma_p->ncookies = 0; 197744Sgs150176 } 198744Sgs150176 ddi_dma_free_handle(&dma_p->dma_hdl); 199744Sgs150176 dma_p->dma_hdl = NULL; 200744Sgs150176 } 201744Sgs150176 202744Sgs150176 if (dma_p->acc_hdl != NULL) { 203744Sgs150176 ddi_dma_mem_free(&dma_p->acc_hdl); 204744Sgs150176 dma_p->acc_hdl = NULL; 205744Sgs150176 } 206744Sgs150176 } 207744Sgs150176 208744Sgs150176 /* 209744Sgs150176 * Utility routine to carve a slice off a chunk of allocated memory, 210744Sgs150176 * updating the chunk descriptor accordingly. The size of the slice 211744Sgs150176 * is given by the product of the <qty> and <size> parameters. 212744Sgs150176 */ 213744Sgs150176 static void 214744Sgs150176 rge_slice_chunk(dma_area_t *slice, dma_area_t *chunk, 215744Sgs150176 uint32_t qty, uint32_t size) 216744Sgs150176 { 217744Sgs150176 static uint32_t sequence = 0xbcd5704a; 218744Sgs150176 size_t totsize; 219744Sgs150176 220744Sgs150176 totsize = qty*size; 221744Sgs150176 ASSERT(size >= 0); 222744Sgs150176 ASSERT(totsize <= chunk->alength); 223744Sgs150176 224744Sgs150176 *slice = *chunk; 225744Sgs150176 slice->nslots = qty; 226744Sgs150176 slice->size = size; 227744Sgs150176 slice->alength = totsize; 228744Sgs150176 slice->token = ++sequence; 229744Sgs150176 230744Sgs150176 chunk->mem_va = (caddr_t)chunk->mem_va + totsize; 231744Sgs150176 chunk->alength -= totsize; 232744Sgs150176 chunk->offset += totsize; 233744Sgs150176 chunk->cookie.dmac_laddress += totsize; 234744Sgs150176 chunk->cookie.dmac_size -= totsize; 235744Sgs150176 } 236744Sgs150176 237744Sgs150176 238744Sgs150176 static int 239744Sgs150176 rge_alloc_bufs(rge_t *rgep) 240744Sgs150176 { 241744Sgs150176 size_t txdescsize; 242744Sgs150176 size_t rxdescsize; 243744Sgs150176 size_t txbuffsize; 244744Sgs150176 size_t rxbuffsize; 245744Sgs150176 size_t freebuffsize; 246744Sgs150176 int split; 247744Sgs150176 int err; 248744Sgs150176 249744Sgs150176 /* 250744Sgs150176 * Allocate memory & handle for packet statistics 251744Sgs150176 */ 252744Sgs150176 err = rge_alloc_dma_mem(rgep, 253744Sgs150176 RGE_STATS_DUMP_SIZE, 254744Sgs150176 &dma_attr_desc, 255744Sgs150176 &rge_desc_accattr, 256744Sgs150176 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 257744Sgs150176 &rgep->dma_area_stats); 258744Sgs150176 if (err != DDI_SUCCESS) 259744Sgs150176 return (DDI_FAILURE); 260744Sgs150176 rgep->hw_stats = DMA_VPTR(rgep->dma_area_stats); 261744Sgs150176 262744Sgs150176 /* 263744Sgs150176 * Allocate memory & handle for Tx descriptor ring 264744Sgs150176 */ 265744Sgs150176 txdescsize = RGE_SEND_SLOTS * sizeof (rge_bd_t); 266744Sgs150176 err = rge_alloc_dma_mem(rgep, 267744Sgs150176 txdescsize, 268744Sgs150176 &dma_attr_desc, 269744Sgs150176 &rge_desc_accattr, 270744Sgs150176 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 271744Sgs150176 &rgep->dma_area_txdesc); 272744Sgs150176 if (err != DDI_SUCCESS) 273744Sgs150176 return (DDI_FAILURE); 274744Sgs150176 275744Sgs150176 /* 276744Sgs150176 * Allocate memory & handle for Rx descriptor ring 277744Sgs150176 */ 278744Sgs150176 rxdescsize = RGE_RECV_SLOTS * sizeof (rge_bd_t); 279744Sgs150176 err = rge_alloc_dma_mem(rgep, 280744Sgs150176 rxdescsize, 281744Sgs150176 &dma_attr_desc, 282744Sgs150176 &rge_desc_accattr, 283744Sgs150176 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 284744Sgs150176 &rgep->dma_area_rxdesc); 285744Sgs150176 if (err != DDI_SUCCESS) 286744Sgs150176 return (DDI_FAILURE); 287744Sgs150176 288744Sgs150176 /* 289744Sgs150176 * Allocate memory & handle for Tx buffers 290744Sgs150176 */ 291744Sgs150176 txbuffsize = RGE_SEND_SLOTS * rgep->txbuf_size; 292744Sgs150176 ASSERT((txbuffsize % RGE_SPLIT) == 0); 293744Sgs150176 for (split = 0; split < RGE_SPLIT; ++split) { 294744Sgs150176 err = rge_alloc_dma_mem(rgep, 295744Sgs150176 txbuffsize/RGE_SPLIT, 296744Sgs150176 &dma_attr_buf, 297744Sgs150176 &rge_buf_accattr, 298744Sgs150176 DDI_DMA_WRITE | DDI_DMA_STREAMING, 299744Sgs150176 &rgep->dma_area_txbuf[split]); 300744Sgs150176 if (err != DDI_SUCCESS) 301744Sgs150176 return (DDI_FAILURE); 302744Sgs150176 } 303744Sgs150176 304744Sgs150176 /* 305744Sgs150176 * Allocate memory & handle for Rx buffers 306744Sgs150176 */ 307744Sgs150176 rxbuffsize = RGE_RECV_SLOTS * rgep->rxbuf_size; 308744Sgs150176 ASSERT((rxbuffsize % RGE_SPLIT) == 0); 309744Sgs150176 for (split = 0; split < RGE_SPLIT; ++split) { 310744Sgs150176 err = rge_alloc_dma_mem(rgep, 311744Sgs150176 rxbuffsize/RGE_SPLIT, 312744Sgs150176 &dma_attr_buf, 313744Sgs150176 &rge_buf_accattr, 314744Sgs150176 DDI_DMA_READ | DDI_DMA_STREAMING, 315744Sgs150176 &rgep->dma_area_rxbuf[split]); 316744Sgs150176 if (err != DDI_SUCCESS) 317744Sgs150176 return (DDI_FAILURE); 318744Sgs150176 } 319744Sgs150176 320744Sgs150176 /* 321744Sgs150176 * Allocate memory & handle for free Rx buffers 322744Sgs150176 */ 323744Sgs150176 freebuffsize = RGE_BUF_SLOTS * rgep->rxbuf_size; 324744Sgs150176 ASSERT((freebuffsize % RGE_SPLIT) == 0); 325744Sgs150176 for (split = 0; split < RGE_SPLIT; ++split) { 326744Sgs150176 err = rge_alloc_dma_mem(rgep, 327744Sgs150176 freebuffsize/RGE_SPLIT, 328744Sgs150176 &dma_attr_buf, 329744Sgs150176 &rge_buf_accattr, 330744Sgs150176 DDI_DMA_READ | DDI_DMA_STREAMING, 331744Sgs150176 &rgep->dma_area_freebuf[split]); 332744Sgs150176 if (err != DDI_SUCCESS) 333744Sgs150176 return (DDI_FAILURE); 334744Sgs150176 } 335744Sgs150176 336744Sgs150176 return (DDI_SUCCESS); 337744Sgs150176 } 338744Sgs150176 339744Sgs150176 /* 340744Sgs150176 * rge_free_bufs() -- free descriptors/buffers allocated for this 341744Sgs150176 * device instance. 342744Sgs150176 */ 343744Sgs150176 static void 344744Sgs150176 rge_free_bufs(rge_t *rgep) 345744Sgs150176 { 346744Sgs150176 int i; 347744Sgs150176 348744Sgs150176 rge_free_dma_mem(&rgep->dma_area_stats); 349744Sgs150176 rge_free_dma_mem(&rgep->dma_area_txdesc); 350744Sgs150176 rge_free_dma_mem(&rgep->dma_area_rxdesc); 351744Sgs150176 for (i = 0; i < RGE_SPLIT; i++) { 352744Sgs150176 rge_free_dma_mem(&rgep->dma_area_txbuf[i]); 353744Sgs150176 rge_free_dma_mem(&rgep->dma_area_rxbuf[i]); 354744Sgs150176 rge_free_dma_mem(&rgep->dma_area_freebuf[i]); 355744Sgs150176 } 356744Sgs150176 } 357744Sgs150176 358744Sgs150176 /* 359744Sgs150176 * ========== Transmit and receive ring reinitialisation ========== 360744Sgs150176 */ 361744Sgs150176 362744Sgs150176 /* 363744Sgs150176 * These <reinit> routines each reset the rx/tx rings to an initial 364744Sgs150176 * state, assuming that the corresponding <init> routine has already 365744Sgs150176 * been called exactly once. 366744Sgs150176 */ 367744Sgs150176 static void 368744Sgs150176 rge_reinit_send_ring(rge_t *rgep) 369744Sgs150176 { 370744Sgs150176 sw_sbd_t *ssbdp; 371744Sgs150176 rge_bd_t *bdp; 372744Sgs150176 uint32_t slot; 373744Sgs150176 374744Sgs150176 /* 375744Sgs150176 * re-init send ring 376744Sgs150176 */ 377744Sgs150176 DMA_ZERO(rgep->tx_desc); 378744Sgs150176 ssbdp = rgep->sw_sbds; 379744Sgs150176 bdp = rgep->tx_ring; 380744Sgs150176 for (slot = 0; slot < RGE_SEND_SLOTS; slot++) { 381744Sgs150176 bdp->host_buf_addr = 382744Sgs150176 RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress); 383744Sgs150176 bdp->host_buf_addr_hi = 384744Sgs150176 RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress >> 32); 385744Sgs150176 /* last BD in Tx ring */ 386744Sgs150176 if (slot == (RGE_SEND_SLOTS - 1)) 387744Sgs150176 bdp->flags_len = RGE_BSWAP_32(BD_FLAG_EOR); 388744Sgs150176 ssbdp++; 389744Sgs150176 bdp++; 390744Sgs150176 } 391744Sgs150176 DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV); 392744Sgs150176 rgep->tx_next = 0; 393744Sgs150176 rgep->tc_next = 0; 394744Sgs150176 rgep->tc_tail = 0; 395744Sgs150176 rgep->tx_flow = 0; 396744Sgs150176 rgep->tx_free = RGE_SEND_SLOTS; 397744Sgs150176 } 398744Sgs150176 399744Sgs150176 static void 400744Sgs150176 rge_reinit_recv_ring(rge_t *rgep) 401744Sgs150176 { 402744Sgs150176 rge_bd_t *bdp; 403744Sgs150176 sw_rbd_t *srbdp; 404744Sgs150176 dma_area_t *pbuf; 405744Sgs150176 uint32_t slot; 406744Sgs150176 407744Sgs150176 /* 408744Sgs150176 * re-init receive ring 409744Sgs150176 */ 410744Sgs150176 DMA_ZERO(rgep->rx_desc); 411744Sgs150176 srbdp = rgep->sw_rbds; 412744Sgs150176 bdp = rgep->rx_ring; 413744Sgs150176 for (slot = 0; slot < RGE_RECV_SLOTS; slot++) { 414744Sgs150176 pbuf = &srbdp->rx_buf->pbuf; 415744Sgs150176 bdp->host_buf_addr = 416744Sgs150176 RGE_BSWAP_32(pbuf->cookie.dmac_laddress + RGE_HEADROOM); 417744Sgs150176 bdp->host_buf_addr_hi = 418744Sgs150176 RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32); 419744Sgs150176 bdp->flags_len = RGE_BSWAP_32(BD_FLAG_HW_OWN | 420744Sgs150176 (rgep->rxbuf_size - RGE_HEADROOM)); 421744Sgs150176 /* last BD in Tx ring */ 422744Sgs150176 if (slot == (RGE_RECV_SLOTS - 1)) 423744Sgs150176 bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR); 424744Sgs150176 srbdp++; 425744Sgs150176 bdp++; 426744Sgs150176 } 427744Sgs150176 DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV); 428744Sgs150176 rgep->watchdog = 0; 429744Sgs150176 rgep->rx_next = 0; 430744Sgs150176 } 431744Sgs150176 432744Sgs150176 static void 433744Sgs150176 rge_reinit_buf_ring(rge_t *rgep) 434744Sgs150176 { 435744Sgs150176 /* 436744Sgs150176 * re-init free buffer ring 437744Sgs150176 */ 438744Sgs150176 rgep->rc_next = 0; 439744Sgs150176 rgep->rf_next = 0; 440744Sgs150176 if (rgep->rx_free != RGE_BUF_SLOTS) 441744Sgs150176 rgep->rx_bcopy = B_TRUE; 442744Sgs150176 } 443744Sgs150176 444744Sgs150176 static void 445744Sgs150176 rge_reinit_rings(rge_t *rgep) 446744Sgs150176 { 447744Sgs150176 rge_reinit_send_ring(rgep); 448744Sgs150176 rge_reinit_recv_ring(rgep); 449744Sgs150176 rge_reinit_buf_ring(rgep); 450744Sgs150176 } 451744Sgs150176 452744Sgs150176 static void 453744Sgs150176 rge_init_send_ring(rge_t *rgep) 454744Sgs150176 { 455744Sgs150176 uint32_t slot; 456744Sgs150176 uint32_t split; 457744Sgs150176 rge_bd_t *bdp; 458744Sgs150176 sw_sbd_t *ssbdp; 459744Sgs150176 dma_area_t buf_chunk; 460744Sgs150176 dma_area_t *pbuf; 461744Sgs150176 462744Sgs150176 /* 463744Sgs150176 * Allocate the array of s/w Tx Buffer Descriptors 464744Sgs150176 */ 465744Sgs150176 ssbdp = kmem_zalloc(RGE_SEND_SLOTS*sizeof (*ssbdp), KM_SLEEP); 466744Sgs150176 rgep->sw_sbds = ssbdp; 467744Sgs150176 468744Sgs150176 /* 469744Sgs150176 * Init send ring 470744Sgs150176 */ 471744Sgs150176 rgep->tx_next = 0; 472744Sgs150176 rgep->tc_next = 0; 473744Sgs150176 rgep->tc_tail = 0; 474744Sgs150176 rgep->tx_flow = 0; 475744Sgs150176 rgep->tx_free = RGE_SEND_SLOTS; 476744Sgs150176 rgep->tx_desc = rgep->dma_area_txdesc; 477744Sgs150176 DMA_ZERO(rgep->tx_desc); 478744Sgs150176 bdp = rgep->tx_desc.mem_va; 479744Sgs150176 rgep->tx_ring = bdp; 480744Sgs150176 for (split = 0; split < RGE_SPLIT; split++) { 481744Sgs150176 buf_chunk = rgep->dma_area_txbuf[split]; 482744Sgs150176 for (slot = 0; slot < RGE_SEND_SLOTS/RGE_SPLIT; slot++) { 483744Sgs150176 rge_slice_chunk(&ssbdp->desc, &rgep->dma_area_txdesc, 484744Sgs150176 1, sizeof (rge_bd_t)); 485744Sgs150176 pbuf = &ssbdp->pbuf; 486744Sgs150176 rge_slice_chunk(pbuf, &buf_chunk, 1, rgep->txbuf_size); 487744Sgs150176 bdp->host_buf_addr = 488744Sgs150176 RGE_BSWAP_32(pbuf->cookie.dmac_laddress); 489744Sgs150176 bdp->host_buf_addr_hi = 490744Sgs150176 RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32); 491744Sgs150176 /* last BD in Tx ring */ 492744Sgs150176 if (split == (RGE_SPLIT - 1) && 493744Sgs150176 slot == (RGE_SEND_SLOTS/RGE_SPLIT -1)) 494744Sgs150176 bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR); 495744Sgs150176 ssbdp++; 496744Sgs150176 bdp++; 497744Sgs150176 } 498744Sgs150176 } 499744Sgs150176 DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV); 500744Sgs150176 } 501744Sgs150176 502744Sgs150176 static int 503744Sgs150176 rge_init_recv_ring(rge_t *rgep) 504744Sgs150176 { 505744Sgs150176 uint32_t slot; 506744Sgs150176 uint32_t split; 507744Sgs150176 rge_bd_t *bdp; 508744Sgs150176 sw_rbd_t *srbdp; 509744Sgs150176 dma_buf_t *rx_buf; 510744Sgs150176 dma_area_t buf_chunk; 511744Sgs150176 dma_area_t *pbuf; 512744Sgs150176 513744Sgs150176 /* 514744Sgs150176 * Allocate the array of s/w Rx Buffer Descriptors 515744Sgs150176 */ 516744Sgs150176 srbdp = kmem_zalloc(RGE_RECV_SLOTS*sizeof (*srbdp), KM_SLEEP); 517744Sgs150176 rx_buf = kmem_zalloc(RGE_RECV_SLOTS*sizeof (*rx_buf), KM_SLEEP); 518744Sgs150176 rgep->sw_rbds = srbdp; 519744Sgs150176 rgep->sw_rbuf = rx_buf; 520744Sgs150176 521744Sgs150176 /* 522744Sgs150176 * Init receive ring 523744Sgs150176 */ 524744Sgs150176 rgep->rx_next = 0; 525744Sgs150176 rgep->rx_desc = rgep->dma_area_rxdesc; 526744Sgs150176 DMA_ZERO(rgep->rx_desc); 527744Sgs150176 bdp = rgep->rx_desc.mem_va; 528744Sgs150176 rgep->rx_ring = bdp; 529744Sgs150176 for (split = 0; split < RGE_SPLIT; split++) { 530744Sgs150176 buf_chunk = rgep->dma_area_rxbuf[split]; 531744Sgs150176 for (slot = 0; slot < RGE_RECV_SLOTS/RGE_SPLIT; slot++) { 532744Sgs150176 srbdp->rx_buf = rx_buf; 533744Sgs150176 pbuf = &rx_buf->pbuf; 534744Sgs150176 rge_slice_chunk(pbuf, &buf_chunk, 1, rgep->rxbuf_size); 535744Sgs150176 pbuf->alength -= RGE_HEADROOM; 536744Sgs150176 pbuf->offset += RGE_HEADROOM; 537744Sgs150176 rx_buf->rx_recycle.free_func = rge_rx_recycle; 538744Sgs150176 rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf; 539744Sgs150176 rx_buf->private = (caddr_t)rgep; 540744Sgs150176 rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf), 541744Sgs150176 rgep->rxbuf_size, 0, &rx_buf->rx_recycle); 542744Sgs150176 if (rx_buf->mp == NULL) { 543744Sgs150176 rge_problem(rgep, 544744Sgs150176 "rge_init_recv_ring: desballoc() failed"); 545744Sgs150176 return (DDI_FAILURE); 546744Sgs150176 } 547744Sgs150176 548744Sgs150176 bdp->host_buf_addr = RGE_BSWAP_32(RGE_HEADROOM + 549744Sgs150176 pbuf->cookie.dmac_laddress); 550744Sgs150176 bdp->host_buf_addr_hi = 551744Sgs150176 RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32); 552744Sgs150176 bdp->flags_len = RGE_BSWAP_32(BD_FLAG_HW_OWN | 553744Sgs150176 (rgep->rxbuf_size - RGE_HEADROOM)); 554744Sgs150176 /* last BD in Rx ring */ 555744Sgs150176 if (split == (RGE_SPLIT - 1) && 556744Sgs150176 slot == (RGE_RECV_SLOTS/RGE_SPLIT -1)) 557744Sgs150176 bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR); 558744Sgs150176 srbdp++; 559744Sgs150176 bdp++; 560744Sgs150176 rx_buf++; 561744Sgs150176 } 562744Sgs150176 } 563744Sgs150176 DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV); 564744Sgs150176 return (DDI_SUCCESS); 565744Sgs150176 } 566744Sgs150176 567744Sgs150176 static int 568744Sgs150176 rge_init_buf_ring(rge_t *rgep) 569744Sgs150176 { 570744Sgs150176 uint32_t slot; 571744Sgs150176 uint32_t split; 572744Sgs150176 sw_rbd_t *free_rbdp; 573744Sgs150176 dma_buf_t *rx_buf; 574744Sgs150176 dma_area_t buf_chunk; 575744Sgs150176 dma_area_t *pbuf; 576744Sgs150176 577744Sgs150176 /* 578744Sgs150176 * Allocate the array of s/w free Buffer Descriptors 579744Sgs150176 */ 580744Sgs150176 free_rbdp = kmem_zalloc(RGE_BUF_SLOTS*sizeof (*free_rbdp), KM_SLEEP); 581744Sgs150176 rx_buf = kmem_zalloc(RGE_BUF_SLOTS*sizeof (*rx_buf), KM_SLEEP); 582744Sgs150176 rgep->free_rbds = free_rbdp; 583744Sgs150176 rgep->sw_freebuf = rx_buf; 584744Sgs150176 585744Sgs150176 /* 586744Sgs150176 * Init free buffer ring 587744Sgs150176 */ 588744Sgs150176 rgep->rc_next = 0; 589744Sgs150176 rgep->rf_next = 0; 590744Sgs150176 rgep->rx_bcopy = B_FALSE; 591744Sgs150176 rgep->rx_free = RGE_BUF_SLOTS; 592744Sgs150176 for (split = 0; split < RGE_SPLIT; split++) { 593744Sgs150176 buf_chunk = rgep->dma_area_freebuf[split]; 594744Sgs150176 for (slot = 0; slot < RGE_BUF_SLOTS/RGE_SPLIT; slot++) { 595744Sgs150176 free_rbdp->rx_buf = rx_buf; 596744Sgs150176 pbuf = &rx_buf->pbuf; 597744Sgs150176 rge_slice_chunk(pbuf, &buf_chunk, 1, rgep->rxbuf_size); 598744Sgs150176 pbuf->alength -= RGE_HEADROOM; 599744Sgs150176 pbuf->offset += RGE_HEADROOM; 600744Sgs150176 rx_buf->rx_recycle.free_func = rge_rx_recycle; 601744Sgs150176 rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf; 602744Sgs150176 rx_buf->private = (caddr_t)rgep; 603744Sgs150176 rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf), 604744Sgs150176 rgep->rxbuf_size, 0, &rx_buf->rx_recycle); 605744Sgs150176 if (rx_buf->mp == NULL) { 606744Sgs150176 rge_problem(rgep, 607744Sgs150176 "rge_init_buf_ring: desballoc() failed"); 608744Sgs150176 return (DDI_FAILURE); 609744Sgs150176 } 610744Sgs150176 free_rbdp++; 611744Sgs150176 rx_buf++; 612744Sgs150176 } 613744Sgs150176 } 614744Sgs150176 return (DDI_SUCCESS); 615744Sgs150176 } 616744Sgs150176 617744Sgs150176 static int 618744Sgs150176 rge_init_rings(rge_t *rgep) 619744Sgs150176 { 620744Sgs150176 int err; 621744Sgs150176 622744Sgs150176 rge_init_send_ring(rgep); 623744Sgs150176 err = rge_init_recv_ring(rgep); 624744Sgs150176 err = rge_init_buf_ring(rgep); 625744Sgs150176 return (err); 626744Sgs150176 } 627744Sgs150176 628744Sgs150176 static void 629744Sgs150176 rge_fini_send_ring(rge_t *rgep) 630744Sgs150176 { 631744Sgs150176 kmem_free(rgep->sw_sbds, RGE_SEND_SLOTS * sizeof (sw_sbd_t)); 632744Sgs150176 } 633744Sgs150176 634744Sgs150176 static void 635744Sgs150176 rge_fini_recv_ring(rge_t *rgep) 636744Sgs150176 { 637744Sgs150176 dma_buf_t *rx_buf = rgep->sw_rbuf; 638744Sgs150176 uint32_t slot; 639744Sgs150176 640744Sgs150176 for (slot = 0; slot < RGE_RECV_SLOTS; slot++, rx_buf++) 641744Sgs150176 freemsg(rx_buf->mp); 642744Sgs150176 kmem_free(rgep->sw_rbuf, RGE_RECV_SLOTS * sizeof (dma_buf_t)); 643744Sgs150176 kmem_free(rgep->sw_rbds, RGE_RECV_SLOTS * sizeof (sw_rbd_t)); 644744Sgs150176 } 645744Sgs150176 646744Sgs150176 static void 647744Sgs150176 rge_fini_buf_ring(rge_t *rgep) 648744Sgs150176 { 649744Sgs150176 dma_buf_t *rx_buf = rgep->sw_freebuf; 650744Sgs150176 uint32_t slot; 651744Sgs150176 652744Sgs150176 for (slot = 0; slot < RGE_BUF_SLOTS; slot++, rx_buf++) 653744Sgs150176 freemsg(rx_buf->mp); 654744Sgs150176 kmem_free(rgep->sw_freebuf, RGE_BUF_SLOTS * sizeof (dma_buf_t)); 655744Sgs150176 kmem_free(rgep->free_rbds, RGE_BUF_SLOTS * sizeof (sw_rbd_t)); 656744Sgs150176 } 657744Sgs150176 658744Sgs150176 static void 659744Sgs150176 rge_fini_rings(rge_t *rgep) 660744Sgs150176 { 661744Sgs150176 rge_fini_send_ring(rgep); 662744Sgs150176 rge_fini_recv_ring(rgep); 663744Sgs150176 rge_fini_buf_ring(rgep); 664744Sgs150176 } 665744Sgs150176 666744Sgs150176 /* 667744Sgs150176 * ========== Internal state management entry points ========== 668744Sgs150176 */ 669744Sgs150176 670744Sgs150176 #undef RGE_DBG 671744Sgs150176 #define RGE_DBG RGE_DBG_NEMO /* debug flag for this code */ 672744Sgs150176 673744Sgs150176 /* 674744Sgs150176 * These routines provide all the functionality required by the 675744Sgs150176 * corresponding MAC layer entry points, but don't update the 676744Sgs150176 * MAC state so they can be called internally without disturbing 677744Sgs150176 * our record of what NEMO thinks we should be doing ... 678744Sgs150176 */ 679744Sgs150176 680744Sgs150176 /* 681744Sgs150176 * rge_reset() -- reset h/w & rings to initial state 682744Sgs150176 */ 683744Sgs150176 static void 684744Sgs150176 rge_reset(rge_t *rgep) 685744Sgs150176 { 686744Sgs150176 ASSERT(mutex_owned(rgep->genlock)); 687744Sgs150176 688744Sgs150176 /* 689744Sgs150176 * Grab all the other mutexes in the world (this should 690744Sgs150176 * ensure no other threads are manipulating driver state) 691744Sgs150176 */ 692744Sgs150176 mutex_enter(rgep->rx_lock); 693744Sgs150176 mutex_enter(rgep->rc_lock); 694744Sgs150176 rw_enter(rgep->errlock, RW_WRITER); 695744Sgs150176 696744Sgs150176 (void) rge_chip_reset(rgep); 697744Sgs150176 rge_reinit_rings(rgep); 698744Sgs150176 rge_chip_init(rgep); 699744Sgs150176 700744Sgs150176 /* 701744Sgs150176 * Free the world ... 702744Sgs150176 */ 703744Sgs150176 rw_exit(rgep->errlock); 704744Sgs150176 mutex_exit(rgep->rc_lock); 705744Sgs150176 mutex_exit(rgep->rx_lock); 706744Sgs150176 707744Sgs150176 RGE_DEBUG(("rge_reset($%p) done", (void *)rgep)); 708744Sgs150176 } 709744Sgs150176 710744Sgs150176 /* 711744Sgs150176 * rge_stop() -- stop processing, don't reset h/w or rings 712744Sgs150176 */ 713744Sgs150176 static void 714744Sgs150176 rge_stop(rge_t *rgep) 715744Sgs150176 { 716744Sgs150176 ASSERT(mutex_owned(rgep->genlock)); 717744Sgs150176 718744Sgs150176 rge_chip_stop(rgep, B_FALSE); 719744Sgs150176 720744Sgs150176 RGE_DEBUG(("rge_stop($%p) done", (void *)rgep)); 721744Sgs150176 } 722744Sgs150176 723744Sgs150176 /* 724744Sgs150176 * rge_start() -- start transmitting/receiving 725744Sgs150176 */ 726744Sgs150176 static void 727744Sgs150176 rge_start(rge_t *rgep) 728744Sgs150176 { 729744Sgs150176 ASSERT(mutex_owned(rgep->genlock)); 730744Sgs150176 731744Sgs150176 /* 732744Sgs150176 * Start chip processing, including enabling interrupts 733744Sgs150176 */ 734744Sgs150176 rge_chip_start(rgep); 735744Sgs150176 rgep->watchdog = 0; 736744Sgs150176 } 737744Sgs150176 738744Sgs150176 /* 739744Sgs150176 * rge_restart - restart transmitting/receiving after error or suspend 740744Sgs150176 */ 741744Sgs150176 void 742744Sgs150176 rge_restart(rge_t *rgep) 743744Sgs150176 { 744744Sgs150176 uint32_t i; 745744Sgs150176 746744Sgs150176 ASSERT(mutex_owned(rgep->genlock)); 747744Sgs150176 /* 748744Sgs150176 * Wait for posted buffer to be freed... 749744Sgs150176 */ 750744Sgs150176 if (!rgep->rx_bcopy) { 751744Sgs150176 for (i = 0; i < RXBUFF_FREE_LOOP; i++) { 752744Sgs150176 if (rgep->rx_free == RGE_BUF_SLOTS) 753744Sgs150176 break; 754744Sgs150176 drv_usecwait(1000); 755744Sgs150176 RGE_DEBUG(("rge_restart: waiting for rx buf free...")); 756744Sgs150176 } 757744Sgs150176 } 758744Sgs150176 rge_reset(rgep); 759744Sgs150176 rgep->stats.chip_reset++; 760744Sgs150176 if (rgep->rge_mac_state == RGE_MAC_STARTED) { 761744Sgs150176 rge_start(rgep); 762744Sgs150176 ddi_trigger_softintr(rgep->resched_id); 763744Sgs150176 } 764744Sgs150176 } 765744Sgs150176 766744Sgs150176 767744Sgs150176 /* 768744Sgs150176 * ========== Nemo-required management entry points ========== 769744Sgs150176 */ 770744Sgs150176 771744Sgs150176 #undef RGE_DBG 772744Sgs150176 #define RGE_DBG RGE_DBG_NEMO /* debug flag for this code */ 773744Sgs150176 774744Sgs150176 /* 775744Sgs150176 * rge_m_stop() -- stop transmitting/receiving 776744Sgs150176 */ 777744Sgs150176 static void 778744Sgs150176 rge_m_stop(void *arg) 779744Sgs150176 { 780744Sgs150176 rge_t *rgep = arg; /* private device info */ 781744Sgs150176 uint32_t i; 782744Sgs150176 783744Sgs150176 /* 784744Sgs150176 * Just stop processing, then record new MAC state 785744Sgs150176 */ 786744Sgs150176 mutex_enter(rgep->genlock); 787744Sgs150176 rge_stop(rgep); 788744Sgs150176 rgep->link_up_msg = rgep->link_down_msg = " (stopped)"; 789744Sgs150176 /* 790744Sgs150176 * Wait for posted buffer to be freed... 791744Sgs150176 */ 792744Sgs150176 if (!rgep->rx_bcopy) { 793744Sgs150176 for (i = 0; i < RXBUFF_FREE_LOOP; i++) { 794744Sgs150176 if (rgep->rx_free == RGE_BUF_SLOTS) 795744Sgs150176 break; 796744Sgs150176 drv_usecwait(1000); 797744Sgs150176 RGE_DEBUG(("rge_m_stop: waiting for rx buf free...")); 798744Sgs150176 } 799744Sgs150176 } 800744Sgs150176 rgep->rge_mac_state = RGE_MAC_STOPPED; 801744Sgs150176 RGE_DEBUG(("rge_m_stop($%p) done", arg)); 802744Sgs150176 mutex_exit(rgep->genlock); 803744Sgs150176 } 804744Sgs150176 805744Sgs150176 /* 806744Sgs150176 * rge_m_start() -- start transmitting/receiving 807744Sgs150176 */ 808744Sgs150176 static int 809744Sgs150176 rge_m_start(void *arg) 810744Sgs150176 { 811744Sgs150176 rge_t *rgep = arg; /* private device info */ 812744Sgs150176 813744Sgs150176 mutex_enter(rgep->genlock); 814744Sgs150176 815744Sgs150176 /* 816744Sgs150176 * Clear hw/sw statistics 817744Sgs150176 */ 818744Sgs150176 DMA_ZERO(rgep->dma_area_stats); 819744Sgs150176 bzero(&rgep->stats, sizeof (rge_stats_t)); 820744Sgs150176 821744Sgs150176 /* 822744Sgs150176 * Start processing and record new MAC state 823744Sgs150176 */ 824744Sgs150176 rge_reset(rgep); 825744Sgs150176 rgep->link_up_msg = rgep->link_down_msg = " (initialized)"; 826744Sgs150176 rge_start(rgep); 827744Sgs150176 rgep->rge_mac_state = RGE_MAC_STARTED; 828744Sgs150176 RGE_DEBUG(("rge_m_start($%p) done", arg)); 829744Sgs150176 830744Sgs150176 mutex_exit(rgep->genlock); 831744Sgs150176 832744Sgs150176 return (0); 833744Sgs150176 } 834744Sgs150176 835744Sgs150176 /* 836744Sgs150176 * rge_m_unicst_set() -- set the physical network address 837744Sgs150176 */ 838744Sgs150176 static int 839744Sgs150176 rge_m_unicst(void *arg, const uint8_t *macaddr) 840744Sgs150176 { 841744Sgs150176 rge_t *rgep = arg; /* private device info */ 842744Sgs150176 843744Sgs150176 /* 844744Sgs150176 * Remember the new current address in the driver state 845744Sgs150176 * Sync the chip's idea of the address too ... 846744Sgs150176 */ 847744Sgs150176 mutex_enter(rgep->genlock); 848744Sgs150176 bcopy(macaddr, rgep->netaddr, ETHERADDRL); 849744Sgs150176 rge_chip_sync(rgep, RGE_SET_MAC); 850744Sgs150176 mutex_exit(rgep->genlock); 851744Sgs150176 852744Sgs150176 return (0); 853744Sgs150176 } 854744Sgs150176 855744Sgs150176 /* 856744Sgs150176 * Compute the index of the required bit in the multicast hash map. 857744Sgs150176 * This must mirror the way the hardware actually does it! 858744Sgs150176 */ 859744Sgs150176 static uint32_t 860744Sgs150176 rge_hash_index(const uint8_t *mca) 861744Sgs150176 { 862744Sgs150176 uint32_t crc = (ulong_t)RGE_HASH_CRC; 863744Sgs150176 uint32_t const POLY = RGE_HASH_POLY; 864744Sgs150176 uint32_t msb; 865744Sgs150176 int bytes; 866744Sgs150176 uchar_t currentbyte; 867744Sgs150176 uint32_t index; 868744Sgs150176 int bit; 869744Sgs150176 870744Sgs150176 for (bytes = 0; bytes < ETHERADDRL; bytes++) { 871744Sgs150176 currentbyte = mca[bytes]; 872744Sgs150176 for (bit = 0; bit < 8; bit++) { 873744Sgs150176 msb = crc >> 31; 874744Sgs150176 crc <<= 1; 875744Sgs150176 if (msb ^ (currentbyte & 1)) { 876744Sgs150176 crc ^= POLY; 877744Sgs150176 crc |= 0x00000001; 878744Sgs150176 } 879744Sgs150176 currentbyte >>= 1; 880744Sgs150176 } 881744Sgs150176 } 882744Sgs150176 index = crc >> 26; 883744Sgs150176 884744Sgs150176 return (index); 885744Sgs150176 } 886744Sgs150176 887744Sgs150176 /* 888744Sgs150176 * rge_m_multicst_add() -- enable/disable a multicast address 889744Sgs150176 */ 890744Sgs150176 static int 891744Sgs150176 rge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 892744Sgs150176 { 893744Sgs150176 rge_t *rgep = arg; /* private device info */ 894744Sgs150176 struct ether_addr *addr; 895744Sgs150176 uint32_t index; 896744Sgs150176 uint32_t *hashp; 897744Sgs150176 898744Sgs150176 mutex_enter(rgep->genlock); 899744Sgs150176 hashp = rgep->mcast_hash; 900744Sgs150176 addr = (struct ether_addr *)mca; 901744Sgs150176 index = rge_hash_index(addr->ether_addr_octet); 902744Sgs150176 /* index value is between 0 and 63 */ 903744Sgs150176 904744Sgs150176 if (add) { 905744Sgs150176 if (rgep->mcast_refs[index]++) { 906744Sgs150176 mutex_exit(rgep->genlock); 907744Sgs150176 return (0); 908744Sgs150176 } 909744Sgs150176 hashp[index/32] |= 1<< (index % 32); 910744Sgs150176 } else { 911744Sgs150176 if (--rgep->mcast_refs[index]) { 912744Sgs150176 mutex_exit(rgep->genlock); 913744Sgs150176 return (0); 914744Sgs150176 } 915744Sgs150176 hashp[index/32] &= ~(1<< (index % 32)); 916744Sgs150176 } 917744Sgs150176 918744Sgs150176 /* 919744Sgs150176 * Set multicast register 920744Sgs150176 */ 921744Sgs150176 rge_chip_sync(rgep, RGE_SET_MUL); 922744Sgs150176 923744Sgs150176 mutex_exit(rgep->genlock); 924744Sgs150176 return (0); 925744Sgs150176 } 926744Sgs150176 927744Sgs150176 /* 928744Sgs150176 * rge_m_promisc() -- set or reset promiscuous mode on the board 929744Sgs150176 * 930744Sgs150176 * Program the hardware to enable/disable promiscuous and/or 931744Sgs150176 * receive-all-multicast modes. 932744Sgs150176 */ 933744Sgs150176 static int 934744Sgs150176 rge_m_promisc(void *arg, boolean_t on) 935744Sgs150176 { 936744Sgs150176 rge_t *rgep = arg; 937744Sgs150176 938744Sgs150176 /* 939744Sgs150176 * Store MAC layer specified mode and pass to chip layer to update h/w 940744Sgs150176 */ 941744Sgs150176 mutex_enter(rgep->genlock); 942744Sgs150176 943744Sgs150176 if (rgep->promisc == on) { 944744Sgs150176 mutex_exit(rgep->genlock); 945744Sgs150176 return (0); 946744Sgs150176 } 947744Sgs150176 rgep->promisc = on; 948744Sgs150176 rge_chip_sync(rgep, RGE_SET_PROMISC); 949744Sgs150176 RGE_DEBUG(("rge_m_promisc_set($%p) done", arg)); 950744Sgs150176 mutex_exit(rgep->genlock); 951744Sgs150176 return (0); 952744Sgs150176 } 953744Sgs150176 954744Sgs150176 /* 955744Sgs150176 * Loopback ioctl code 956744Sgs150176 */ 957744Sgs150176 958744Sgs150176 static lb_property_t loopmodes[] = { 959744Sgs150176 { normal, "normal", RGE_LOOP_NONE }, 960744Sgs150176 { internal, "PHY", RGE_LOOP_INTERNAL_PHY }, 961744Sgs150176 { internal, "MAC", RGE_LOOP_INTERNAL_MAC } 962744Sgs150176 }; 963744Sgs150176 964744Sgs150176 static enum ioc_reply 965744Sgs150176 rge_set_loop_mode(rge_t *rgep, uint32_t mode) 966744Sgs150176 { 967744Sgs150176 const char *msg; 968744Sgs150176 969744Sgs150176 /* 970744Sgs150176 * If the mode isn't being changed, there's nothing to do ... 971744Sgs150176 */ 972744Sgs150176 if (mode == rgep->param_loop_mode) 973744Sgs150176 return (IOC_ACK); 974744Sgs150176 975744Sgs150176 /* 976744Sgs150176 * Validate the requested mode and prepare a suitable message 977744Sgs150176 * to explain the link down/up cycle that the change will 978744Sgs150176 * probably induce ... 979744Sgs150176 */ 980744Sgs150176 switch (mode) { 981744Sgs150176 default: 982744Sgs150176 return (IOC_INVAL); 983744Sgs150176 984744Sgs150176 case RGE_LOOP_NONE: 985744Sgs150176 msg = " (loopback disabled)"; 986744Sgs150176 break; 987744Sgs150176 988744Sgs150176 case RGE_LOOP_INTERNAL_PHY: 989744Sgs150176 msg = " (PHY internal loopback selected)"; 990744Sgs150176 break; 991744Sgs150176 992744Sgs150176 case RGE_LOOP_INTERNAL_MAC: 993744Sgs150176 msg = " (MAC internal loopback selected)"; 994744Sgs150176 break; 995744Sgs150176 } 996744Sgs150176 997744Sgs150176 /* 998744Sgs150176 * All OK; tell the caller to reprogram 999744Sgs150176 * the PHY and/or MAC for the new mode ... 1000744Sgs150176 */ 1001744Sgs150176 rgep->link_down_msg = rgep->link_up_msg = msg; 1002744Sgs150176 rgep->param_loop_mode = mode; 1003744Sgs150176 return (IOC_RESTART_ACK); 1004744Sgs150176 } 1005744Sgs150176 1006744Sgs150176 static enum ioc_reply 1007744Sgs150176 rge_loop_ioctl(rge_t *rgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp) 1008744Sgs150176 { 1009744Sgs150176 lb_info_sz_t *lbsp; 1010744Sgs150176 lb_property_t *lbpp; 1011744Sgs150176 uint32_t *lbmp; 1012744Sgs150176 int cmd; 1013744Sgs150176 1014744Sgs150176 _NOTE(ARGUNUSED(wq)) 1015744Sgs150176 1016744Sgs150176 /* 1017744Sgs150176 * Validate format of ioctl 1018744Sgs150176 */ 1019744Sgs150176 if (mp->b_cont == NULL) 1020744Sgs150176 return (IOC_INVAL); 1021744Sgs150176 1022744Sgs150176 cmd = iocp->ioc_cmd; 1023744Sgs150176 switch (cmd) { 1024744Sgs150176 default: 1025744Sgs150176 /* NOTREACHED */ 1026744Sgs150176 rge_error(rgep, "rge_loop_ioctl: invalid cmd 0x%x", cmd); 1027744Sgs150176 return (IOC_INVAL); 1028744Sgs150176 1029744Sgs150176 case LB_GET_INFO_SIZE: 1030744Sgs150176 if (iocp->ioc_count != sizeof (lb_info_sz_t)) 1031744Sgs150176 return (IOC_INVAL); 1032744Sgs150176 lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr; 1033744Sgs150176 *lbsp = sizeof (loopmodes); 1034744Sgs150176 return (IOC_REPLY); 1035744Sgs150176 1036744Sgs150176 case LB_GET_INFO: 1037744Sgs150176 if (iocp->ioc_count != sizeof (loopmodes)) 1038744Sgs150176 return (IOC_INVAL); 1039744Sgs150176 lbpp = (lb_property_t *)mp->b_cont->b_rptr; 1040744Sgs150176 bcopy(loopmodes, lbpp, sizeof (loopmodes)); 1041744Sgs150176 return (IOC_REPLY); 1042744Sgs150176 1043744Sgs150176 case LB_GET_MODE: 1044744Sgs150176 if (iocp->ioc_count != sizeof (uint32_t)) 1045744Sgs150176 return (IOC_INVAL); 1046744Sgs150176 lbmp = (uint32_t *)mp->b_cont->b_rptr; 1047744Sgs150176 *lbmp = rgep->param_loop_mode; 1048744Sgs150176 return (IOC_REPLY); 1049744Sgs150176 1050744Sgs150176 case LB_SET_MODE: 1051744Sgs150176 if (iocp->ioc_count != sizeof (uint32_t)) 1052744Sgs150176 return (IOC_INVAL); 1053744Sgs150176 lbmp = (uint32_t *)mp->b_cont->b_rptr; 1054744Sgs150176 return (rge_set_loop_mode(rgep, *lbmp)); 1055744Sgs150176 } 1056744Sgs150176 } 1057744Sgs150176 1058744Sgs150176 /* 1059744Sgs150176 * Specific rge IOCTLs, the MAC layer handles the generic ones. 1060744Sgs150176 */ 1061744Sgs150176 static void 1062744Sgs150176 rge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 1063744Sgs150176 { 1064744Sgs150176 rge_t *rgep = arg; 1065744Sgs150176 struct iocblk *iocp; 1066744Sgs150176 enum ioc_reply status; 1067744Sgs150176 boolean_t need_privilege; 1068744Sgs150176 int err; 1069744Sgs150176 int cmd; 1070744Sgs150176 1071744Sgs150176 /* 1072744Sgs150176 * Validate the command before bothering with the mutex ... 1073744Sgs150176 */ 1074744Sgs150176 iocp = (struct iocblk *)mp->b_rptr; 1075744Sgs150176 iocp->ioc_error = 0; 1076744Sgs150176 need_privilege = B_TRUE; 1077744Sgs150176 cmd = iocp->ioc_cmd; 1078744Sgs150176 switch (cmd) { 1079744Sgs150176 default: 1080744Sgs150176 miocnak(wq, mp, 0, EINVAL); 1081744Sgs150176 return; 1082744Sgs150176 1083744Sgs150176 case RGE_MII_READ: 1084744Sgs150176 case RGE_MII_WRITE: 1085744Sgs150176 case RGE_DIAG: 1086744Sgs150176 case RGE_PEEK: 1087744Sgs150176 case RGE_POKE: 1088744Sgs150176 case RGE_PHY_RESET: 1089744Sgs150176 case RGE_SOFT_RESET: 1090744Sgs150176 case RGE_HARD_RESET: 1091744Sgs150176 break; 1092744Sgs150176 1093744Sgs150176 case LB_GET_INFO_SIZE: 1094744Sgs150176 case LB_GET_INFO: 1095744Sgs150176 case LB_GET_MODE: 1096744Sgs150176 need_privilege = B_FALSE; 1097744Sgs150176 /* FALLTHRU */ 1098744Sgs150176 case LB_SET_MODE: 1099744Sgs150176 break; 1100744Sgs150176 1101744Sgs150176 case ND_GET: 1102744Sgs150176 need_privilege = B_FALSE; 1103744Sgs150176 /* FALLTHRU */ 1104744Sgs150176 case ND_SET: 1105744Sgs150176 break; 1106744Sgs150176 } 1107744Sgs150176 1108744Sgs150176 if (need_privilege) { 1109744Sgs150176 /* 1110744Sgs150176 * Check for specific net_config privilege on Solaris 10+. 1111744Sgs150176 * Otherwise just check for root access ... 1112744Sgs150176 */ 1113744Sgs150176 if (secpolicy_net_config != NULL) 1114744Sgs150176 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 1115744Sgs150176 else 1116744Sgs150176 err = drv_priv(iocp->ioc_cr); 1117744Sgs150176 if (err != 0) { 1118744Sgs150176 miocnak(wq, mp, 0, err); 1119744Sgs150176 return; 1120744Sgs150176 } 1121744Sgs150176 } 1122744Sgs150176 1123744Sgs150176 mutex_enter(rgep->genlock); 1124744Sgs150176 1125744Sgs150176 switch (cmd) { 1126744Sgs150176 default: 1127744Sgs150176 _NOTE(NOTREACHED) 1128744Sgs150176 status = IOC_INVAL; 1129744Sgs150176 break; 1130744Sgs150176 1131744Sgs150176 case RGE_MII_READ: 1132744Sgs150176 case RGE_MII_WRITE: 1133744Sgs150176 case RGE_DIAG: 1134744Sgs150176 case RGE_PEEK: 1135744Sgs150176 case RGE_POKE: 1136744Sgs150176 case RGE_PHY_RESET: 1137744Sgs150176 case RGE_SOFT_RESET: 1138744Sgs150176 case RGE_HARD_RESET: 1139744Sgs150176 status = rge_chip_ioctl(rgep, wq, mp, iocp); 1140744Sgs150176 break; 1141744Sgs150176 1142744Sgs150176 case LB_GET_INFO_SIZE: 1143744Sgs150176 case LB_GET_INFO: 1144744Sgs150176 case LB_GET_MODE: 1145744Sgs150176 case LB_SET_MODE: 1146744Sgs150176 status = rge_loop_ioctl(rgep, wq, mp, iocp); 1147744Sgs150176 break; 1148744Sgs150176 1149744Sgs150176 case ND_GET: 1150744Sgs150176 case ND_SET: 1151744Sgs150176 status = rge_nd_ioctl(rgep, wq, mp, iocp); 1152744Sgs150176 break; 1153744Sgs150176 } 1154744Sgs150176 1155744Sgs150176 /* 1156744Sgs150176 * Do we need to reprogram the PHY and/or the MAC? 1157744Sgs150176 * Do it now, while we still have the mutex. 1158744Sgs150176 * 1159744Sgs150176 * Note: update the PHY first, 'cos it controls the 1160744Sgs150176 * speed/duplex parameters that the MAC code uses. 1161744Sgs150176 */ 1162744Sgs150176 switch (status) { 1163744Sgs150176 case IOC_RESTART_REPLY: 1164744Sgs150176 case IOC_RESTART_ACK: 1165744Sgs150176 rge_phy_update(rgep); 1166744Sgs150176 break; 1167744Sgs150176 } 1168744Sgs150176 1169744Sgs150176 mutex_exit(rgep->genlock); 1170744Sgs150176 1171744Sgs150176 /* 1172744Sgs150176 * Finally, decide how to reply 1173744Sgs150176 */ 1174744Sgs150176 switch (status) { 1175744Sgs150176 default: 1176744Sgs150176 case IOC_INVAL: 1177744Sgs150176 /* 1178744Sgs150176 * Error, reply with a NAK and EINVAL or the specified error 1179744Sgs150176 */ 1180744Sgs150176 miocnak(wq, mp, 0, iocp->ioc_error == 0 ? 1181744Sgs150176 EINVAL : iocp->ioc_error); 1182744Sgs150176 break; 1183744Sgs150176 1184744Sgs150176 case IOC_DONE: 1185744Sgs150176 /* 1186744Sgs150176 * OK, reply already sent 1187744Sgs150176 */ 1188744Sgs150176 break; 1189744Sgs150176 1190744Sgs150176 case IOC_RESTART_ACK: 1191744Sgs150176 case IOC_ACK: 1192744Sgs150176 /* 1193744Sgs150176 * OK, reply with an ACK 1194744Sgs150176 */ 1195744Sgs150176 miocack(wq, mp, 0, 0); 1196744Sgs150176 break; 1197744Sgs150176 1198744Sgs150176 case IOC_RESTART_REPLY: 1199744Sgs150176 case IOC_REPLY: 1200744Sgs150176 /* 1201744Sgs150176 * OK, send prepared reply as ACK or NAK 1202744Sgs150176 */ 1203744Sgs150176 mp->b_datap->db_type = iocp->ioc_error == 0 ? 1204744Sgs150176 M_IOCACK : M_IOCNAK; 1205744Sgs150176 qreply(wq, mp); 1206744Sgs150176 break; 1207744Sgs150176 } 1208744Sgs150176 } 1209744Sgs150176 1210744Sgs150176 static void 1211744Sgs150176 rge_m_resources(void *arg) 1212744Sgs150176 { 1213744Sgs150176 rge_t *rgep = arg; 1214744Sgs150176 mac_rx_fifo_t mrf; 1215744Sgs150176 1216744Sgs150176 mutex_enter(rgep->genlock); 1217744Sgs150176 1218744Sgs150176 /* 1219744Sgs150176 * Register Rx rings as resources and save mac 1220744Sgs150176 * resource id for future reference 1221744Sgs150176 */ 1222744Sgs150176 mrf.mrf_type = MAC_RX_FIFO; 1223744Sgs150176 mrf.mrf_blank = rge_chip_blank; 1224744Sgs150176 mrf.mrf_arg = (void *)rgep; 1225744Sgs150176 mrf.mrf_normal_blank_time = RGE_RX_INT_TIME; 1226744Sgs150176 mrf.mrf_normal_pkt_count = RGE_RX_INT_PKTS; 1227*2311Sseb rgep->handle = mac_resource_add(rgep->mh, (mac_resource_t *)&mrf); 1228744Sgs150176 1229744Sgs150176 mutex_exit(rgep->genlock); 1230744Sgs150176 } 1231744Sgs150176 1232*2311Sseb /* ARGSUSED */ 1233*2311Sseb static boolean_t 1234*2311Sseb rge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 1235*2311Sseb { 1236*2311Sseb switch (cap) { 1237*2311Sseb case MAC_CAPAB_HCKSUM: { 1238*2311Sseb uint32_t *hcksum_txflags = cap_data; 1239*2311Sseb *hcksum_txflags = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM; 1240*2311Sseb break; 1241*2311Sseb } 1242*2311Sseb case MAC_CAPAB_POLL: 1243*2311Sseb /* 1244*2311Sseb * There's nothing for us to fill in, simply returning 1245*2311Sseb * B_TRUE stating that we support polling is sufficient. 1246*2311Sseb */ 1247*2311Sseb break; 1248*2311Sseb default: 1249*2311Sseb return (B_FALSE); 1250*2311Sseb } 1251*2311Sseb return (B_TRUE); 1252*2311Sseb } 1253*2311Sseb 1254744Sgs150176 /* 1255744Sgs150176 * ========== Per-instance setup/teardown code ========== 1256744Sgs150176 */ 1257744Sgs150176 1258744Sgs150176 #undef RGE_DBG 1259744Sgs150176 #define RGE_DBG RGE_DBG_INIT /* debug flag for this code */ 1260744Sgs150176 1261744Sgs150176 static void 1262744Sgs150176 rge_unattach(rge_t *rgep) 1263744Sgs150176 { 1264744Sgs150176 /* 1265744Sgs150176 * Flag that no more activity may be initiated 1266744Sgs150176 */ 1267744Sgs150176 rgep->progress &= ~PROGRESS_READY; 1268744Sgs150176 rgep->rge_mac_state = RGE_MAC_UNATTACH; 1269744Sgs150176 1270744Sgs150176 /* 1271744Sgs150176 * Quiesce the PHY and MAC (leave it reset but still powered). 1272744Sgs150176 * Clean up and free all RGE data structures 1273744Sgs150176 */ 1274744Sgs150176 if (rgep->cyclic_id) { 1275744Sgs150176 mutex_enter(&cpu_lock); 1276744Sgs150176 cyclic_remove(rgep->cyclic_id); 1277744Sgs150176 mutex_exit(&cpu_lock); 1278744Sgs150176 } 1279744Sgs150176 1280744Sgs150176 if (rgep->progress & PROGRESS_KSTATS) 1281744Sgs150176 rge_fini_kstats(rgep); 1282744Sgs150176 1283744Sgs150176 if (rgep->progress & PROGRESS_PHY) 1284744Sgs150176 (void) rge_phy_reset(rgep); 1285744Sgs150176 1286744Sgs150176 if (rgep->progress & PROGRESS_INTR) { 1287744Sgs150176 mutex_enter(rgep->genlock); 1288744Sgs150176 (void) rge_chip_reset(rgep); 1289744Sgs150176 mutex_exit(rgep->genlock); 1290744Sgs150176 ddi_remove_intr(rgep->devinfo, 0, rgep->iblk); 1291744Sgs150176 rge_fini_rings(rgep); 1292744Sgs150176 mutex_destroy(rgep->rc_lock); 1293744Sgs150176 mutex_destroy(rgep->rx_lock); 1294744Sgs150176 mutex_destroy(rgep->tc_lock); 1295744Sgs150176 mutex_destroy(rgep->tx_lock); 1296744Sgs150176 rw_destroy(rgep->errlock); 1297744Sgs150176 mutex_destroy(rgep->genlock); 1298744Sgs150176 } 1299744Sgs150176 1300744Sgs150176 if (rgep->progress & PROGRESS_FACTOTUM) 1301744Sgs150176 ddi_remove_softintr(rgep->factotum_id); 1302744Sgs150176 1303744Sgs150176 if (rgep->progress & PROGRESS_RESCHED) 1304744Sgs150176 ddi_remove_softintr(rgep->resched_id); 1305744Sgs150176 1306744Sgs150176 rge_free_bufs(rgep); 1307744Sgs150176 1308744Sgs150176 if (rgep->progress & PROGRESS_NDD) 1309744Sgs150176 rge_nd_cleanup(rgep); 1310744Sgs150176 1311744Sgs150176 if (rgep->progress & PROGRESS_REGS) 1312744Sgs150176 ddi_regs_map_free(&rgep->io_handle); 1313744Sgs150176 1314744Sgs150176 if (rgep->progress & PROGRESS_CFG) 1315744Sgs150176 pci_config_teardown(&rgep->cfg_handle); 1316744Sgs150176 1317744Sgs150176 ddi_remove_minor_node(rgep->devinfo, NULL); 1318744Sgs150176 kmem_free(rgep, sizeof (*rgep)); 1319744Sgs150176 } 1320744Sgs150176 1321744Sgs150176 static int 1322744Sgs150176 rge_resume(dev_info_t *devinfo) 1323744Sgs150176 { 1324744Sgs150176 rge_t *rgep; /* Our private data */ 1325744Sgs150176 chip_id_t *cidp; 1326744Sgs150176 chip_id_t chipid; 1327744Sgs150176 1328744Sgs150176 rgep = ddi_get_driver_private(devinfo); 1329744Sgs150176 if (rgep == NULL) 1330744Sgs150176 return (DDI_FAILURE); 1331744Sgs150176 1332744Sgs150176 /* 1333744Sgs150176 * Refuse to resume if the data structures aren't consistent 1334744Sgs150176 */ 1335744Sgs150176 if (rgep->devinfo != devinfo) 1336744Sgs150176 return (DDI_FAILURE); 1337744Sgs150176 1338744Sgs150176 /* 1339744Sgs150176 * Read chip ID & set up config space command register(s) 1340744Sgs150176 * Refuse to resume if the chip has changed its identity! 1341744Sgs150176 */ 1342744Sgs150176 cidp = &rgep->chipid; 1343744Sgs150176 rge_chip_cfg_init(rgep, &chipid); 1344744Sgs150176 if (chipid.vendor != cidp->vendor) 1345744Sgs150176 return (DDI_FAILURE); 1346744Sgs150176 if (chipid.device != cidp->device) 1347744Sgs150176 return (DDI_FAILURE); 1348744Sgs150176 if (chipid.revision != cidp->revision) 1349744Sgs150176 return (DDI_FAILURE); 1350744Sgs150176 1351744Sgs150176 /* 1352744Sgs150176 * All OK, reinitialise h/w & kick off NEMO scheduling 1353744Sgs150176 */ 1354744Sgs150176 mutex_enter(rgep->genlock); 1355744Sgs150176 rge_restart(rgep); 1356744Sgs150176 mutex_exit(rgep->genlock); 1357744Sgs150176 return (DDI_SUCCESS); 1358744Sgs150176 } 1359744Sgs150176 1360744Sgs150176 1361744Sgs150176 /* 1362744Sgs150176 * attach(9E) -- Attach a device to the system 1363744Sgs150176 * 1364744Sgs150176 * Called once for each board successfully probed. 1365744Sgs150176 */ 1366744Sgs150176 static int 1367744Sgs150176 rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 1368744Sgs150176 { 1369744Sgs150176 rge_t *rgep; /* Our private data */ 1370*2311Sseb mac_register_t *macp; 1371744Sgs150176 chip_id_t *cidp; 1372744Sgs150176 cyc_handler_t cychand; 1373744Sgs150176 cyc_time_t cyctime; 1374744Sgs150176 caddr_t regs; 1375744Sgs150176 int instance; 1376744Sgs150176 int err; 1377744Sgs150176 1378744Sgs150176 /* 1379744Sgs150176 * we don't support high level interrupts in the driver 1380744Sgs150176 */ 1381744Sgs150176 if (ddi_intr_hilevel(devinfo, 0) != 0) { 1382744Sgs150176 cmn_err(CE_WARN, 1383744Sgs150176 "rge_attach -- unsupported high level interrupt"); 1384744Sgs150176 return (DDI_FAILURE); 1385744Sgs150176 } 1386744Sgs150176 1387744Sgs150176 instance = ddi_get_instance(devinfo); 1388744Sgs150176 RGE_GTRACE(("rge_attach($%p, %d) instance %d", 1389744Sgs150176 (void *)devinfo, cmd, instance)); 1390744Sgs150176 RGE_BRKPT(NULL, "rge_attach"); 1391744Sgs150176 1392744Sgs150176 switch (cmd) { 1393744Sgs150176 default: 1394744Sgs150176 return (DDI_FAILURE); 1395744Sgs150176 1396744Sgs150176 case DDI_RESUME: 1397744Sgs150176 return (rge_resume(devinfo)); 1398744Sgs150176 1399744Sgs150176 case DDI_ATTACH: 1400744Sgs150176 break; 1401744Sgs150176 } 1402744Sgs150176 1403744Sgs150176 rgep = kmem_zalloc(sizeof (*rgep), KM_SLEEP); 1404744Sgs150176 ddi_set_driver_private(devinfo, rgep); 1405744Sgs150176 rgep->devinfo = devinfo; 1406744Sgs150176 1407744Sgs150176 /* 1408744Sgs150176 * Initialize more fields in RGE private data 1409744Sgs150176 */ 1410744Sgs150176 rgep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 1411744Sgs150176 DDI_PROP_DONTPASS, debug_propname, rge_debug); 1412744Sgs150176 (void) snprintf(rgep->ifname, sizeof (rgep->ifname), "%s%d", 1413744Sgs150176 RGE_DRIVER_NAME, instance); 1414744Sgs150176 1415744Sgs150176 /* 1416744Sgs150176 * Map config space registers 1417744Sgs150176 * Read chip ID & set up config space command register(s) 1418744Sgs150176 * 1419744Sgs150176 * Note: this leaves the chip accessible by Memory Space 1420744Sgs150176 * accesses, but with interrupts and Bus Mastering off. 1421744Sgs150176 * This should ensure that nothing untoward will happen 1422744Sgs150176 * if it has been left active by the (net-)bootloader. 1423744Sgs150176 * We'll re-enable Bus Mastering once we've reset the chip, 1424744Sgs150176 * and allow interrupts only when everything else is set up. 1425744Sgs150176 */ 1426744Sgs150176 err = pci_config_setup(devinfo, &rgep->cfg_handle); 1427744Sgs150176 if (err != DDI_SUCCESS) { 1428744Sgs150176 rge_problem(rgep, "pci_config_setup() failed"); 1429744Sgs150176 goto attach_fail; 1430744Sgs150176 } 1431744Sgs150176 rgep->progress |= PROGRESS_CFG; 1432744Sgs150176 cidp = &rgep->chipid; 1433744Sgs150176 bzero(cidp, sizeof (*cidp)); 1434744Sgs150176 rge_chip_cfg_init(rgep, cidp); 1435744Sgs150176 1436744Sgs150176 /* 1437744Sgs150176 * Map operating registers 1438744Sgs150176 */ 1439744Sgs150176 err = ddi_regs_map_setup(devinfo, 1, ®s, 1440744Sgs150176 0, 0, &rge_reg_accattr, &rgep->io_handle); 1441744Sgs150176 if (err != DDI_SUCCESS) { 1442744Sgs150176 rge_problem(rgep, "ddi_regs_map_setup() failed"); 1443744Sgs150176 goto attach_fail; 1444744Sgs150176 } 1445744Sgs150176 rgep->io_regs = regs; 1446744Sgs150176 rgep->progress |= PROGRESS_REGS; 1447744Sgs150176 1448744Sgs150176 /* 1449744Sgs150176 * Register NDD-tweakable parameters 1450744Sgs150176 */ 1451744Sgs150176 if (rge_nd_init(rgep)) { 1452744Sgs150176 rge_problem(rgep, "rge_nd_init() failed"); 1453744Sgs150176 goto attach_fail; 1454744Sgs150176 } 1455744Sgs150176 rgep->progress |= PROGRESS_NDD; 1456744Sgs150176 1457744Sgs150176 /* 1458744Sgs150176 * Characterise the device, so we know its requirements. 1459744Sgs150176 * Then allocate the appropriate TX and RX descriptors & buffers. 1460744Sgs150176 */ 1461744Sgs150176 rge_chip_ident(rgep); 1462744Sgs150176 err = rge_alloc_bufs(rgep); 1463744Sgs150176 if (err != DDI_SUCCESS) { 1464744Sgs150176 rge_problem(rgep, "DMA buffer allocation failed"); 1465744Sgs150176 goto attach_fail; 1466744Sgs150176 } 1467744Sgs150176 1468744Sgs150176 /* 1469744Sgs150176 * Add the softint handlers: 1470744Sgs150176 * 1471744Sgs150176 * Both of these handlers are used to avoid restrictions on the 1472744Sgs150176 * context and/or mutexes required for some operations. In 1473744Sgs150176 * particular, the hardware interrupt handler and its subfunctions 1474744Sgs150176 * can detect a number of conditions that we don't want to handle 1475744Sgs150176 * in that context or with that set of mutexes held. So, these 1476744Sgs150176 * softints are triggered instead: 1477744Sgs150176 * 1478744Sgs150176 * the <resched> softint is triggered if if we have previously 1479744Sgs150176 * had to refuse to send a packet because of resource shortage 1480744Sgs150176 * (we've run out of transmit buffers), but the send completion 1481744Sgs150176 * interrupt handler has now detected that more buffers have 1482744Sgs150176 * become available. 1483744Sgs150176 * 1484744Sgs150176 * the <factotum> is triggered if the h/w interrupt handler 1485744Sgs150176 * sees the <link state changed> or <error> bits in the status 1486744Sgs150176 * block. It's also triggered periodically to poll the link 1487744Sgs150176 * state, just in case we aren't getting link status change 1488744Sgs150176 * interrupts ... 1489744Sgs150176 */ 1490744Sgs150176 err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, &rgep->resched_id, 1491744Sgs150176 NULL, NULL, rge_reschedule, (caddr_t)rgep); 1492744Sgs150176 if (err != DDI_SUCCESS) { 1493744Sgs150176 rge_problem(rgep, "ddi_add_softintr() failed"); 1494744Sgs150176 goto attach_fail; 1495744Sgs150176 } 1496744Sgs150176 rgep->progress |= PROGRESS_RESCHED; 1497744Sgs150176 err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, &rgep->factotum_id, 1498744Sgs150176 NULL, NULL, rge_chip_factotum, (caddr_t)rgep); 1499744Sgs150176 if (err != DDI_SUCCESS) { 1500744Sgs150176 rge_problem(rgep, "ddi_add_softintr() failed"); 1501744Sgs150176 goto attach_fail; 1502744Sgs150176 } 1503744Sgs150176 rgep->progress |= PROGRESS_FACTOTUM; 1504744Sgs150176 1505744Sgs150176 /* 1506744Sgs150176 * Add the h/w interrupt handler and initialise mutexes 1507744Sgs150176 */ 1508744Sgs150176 err = ddi_add_intr(devinfo, 0, &rgep->iblk, NULL, 1509744Sgs150176 rge_intr, (caddr_t)rgep); 1510744Sgs150176 if (err != DDI_SUCCESS) { 1511744Sgs150176 rge_problem(rgep, "ddi_add_intr() failed"); 1512744Sgs150176 goto attach_fail; 1513744Sgs150176 } 1514744Sgs150176 mutex_init(rgep->genlock, NULL, MUTEX_DRIVER, rgep->iblk); 1515744Sgs150176 rw_init(rgep->errlock, NULL, RW_DRIVER, rgep->iblk); 1516744Sgs150176 mutex_init(rgep->tx_lock, NULL, MUTEX_DRIVER, rgep->iblk); 1517744Sgs150176 mutex_init(rgep->tc_lock, NULL, MUTEX_DRIVER, rgep->iblk); 1518744Sgs150176 mutex_init(rgep->rx_lock, NULL, MUTEX_DRIVER, rgep->iblk); 1519744Sgs150176 mutex_init(rgep->rc_lock, NULL, MUTEX_DRIVER, rgep->iblk); 1520744Sgs150176 rgep->progress |= PROGRESS_INTR; 1521744Sgs150176 1522744Sgs150176 /* 1523744Sgs150176 * Initialize rings 1524744Sgs150176 */ 1525744Sgs150176 err = rge_init_rings(rgep); 1526744Sgs150176 if (err != DDI_SUCCESS) { 1527744Sgs150176 rge_problem(rgep, "rge_init_rings() failed"); 1528744Sgs150176 goto attach_fail; 1529744Sgs150176 } 1530744Sgs150176 1531744Sgs150176 /* 1532744Sgs150176 * Initialise link state variables 1533744Sgs150176 * Stop, reset & reinitialise the chip. 1534744Sgs150176 * Initialise the (internal) PHY. 1535744Sgs150176 */ 1536744Sgs150176 rgep->param_link_up = LINK_STATE_UNKNOWN; 1537744Sgs150176 rgep->link_up_msg = rgep->link_down_msg = " (initialised)"; 1538744Sgs150176 1539744Sgs150176 /* 1540744Sgs150176 * Reset chip & rings to initial state; also reset address 1541744Sgs150176 * filtering, promiscuity, loopback mode. 1542744Sgs150176 */ 1543744Sgs150176 mutex_enter(rgep->genlock); 1544744Sgs150176 (void) rge_chip_reset(rgep); 1545744Sgs150176 rge_chip_sync(rgep, RGE_GET_MAC); 1546744Sgs150176 bzero(rgep->mcast_hash, sizeof (rgep->mcast_hash)); 1547744Sgs150176 bzero(rgep->mcast_refs, sizeof (rgep->mcast_refs)); 1548744Sgs150176 rgep->promisc = B_FALSE; 1549744Sgs150176 rgep->param_loop_mode = RGE_LOOP_NONE; 1550744Sgs150176 mutex_exit(rgep->genlock); 1551744Sgs150176 rge_phy_init(rgep); 1552744Sgs150176 rgep->progress |= PROGRESS_PHY; 1553744Sgs150176 1554744Sgs150176 /* 1555744Sgs150176 * Create & initialise named kstats 1556744Sgs150176 */ 1557744Sgs150176 rge_init_kstats(rgep, instance); 1558744Sgs150176 rgep->progress |= PROGRESS_KSTATS; 1559744Sgs150176 1560*2311Sseb if ((macp = mac_alloc(MAC_VERSION)) == NULL) 1561*2311Sseb goto attach_fail; 1562*2311Sseb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1563*2311Sseb macp->m_driver = rgep; 1564744Sgs150176 macp->m_dip = devinfo; 1565*2311Sseb macp->m_src_addr = rgep->netaddr; 1566*2311Sseb macp->m_callbacks = &rge_m_callbacks; 1567*2311Sseb macp->m_min_sdu = 0; 1568*2311Sseb macp->m_max_sdu = rgep->param_default_mtu; 1569744Sgs150176 1570744Sgs150176 /* 1571744Sgs150176 * Finally, we're ready to register ourselves with the MAC layer 1572744Sgs150176 * interface; if this succeeds, we're all ready to start() 1573744Sgs150176 */ 1574*2311Sseb err = mac_register(macp, &rgep->mh); 1575*2311Sseb mac_free(macp); 1576*2311Sseb if (err != 0) 1577744Sgs150176 goto attach_fail; 1578744Sgs150176 1579744Sgs150176 cychand.cyh_func = rge_chip_cyclic; 1580744Sgs150176 cychand.cyh_arg = rgep; 1581744Sgs150176 cychand.cyh_level = CY_LOCK_LEVEL; 1582744Sgs150176 cyctime.cyt_when = 0; 1583744Sgs150176 cyctime.cyt_interval = RGE_CYCLIC_PERIOD; 1584744Sgs150176 mutex_enter(&cpu_lock); 1585744Sgs150176 rgep->cyclic_id = cyclic_add(&cychand, &cyctime); 1586744Sgs150176 mutex_exit(&cpu_lock); 1587744Sgs150176 1588744Sgs150176 rgep->progress |= PROGRESS_READY; 1589744Sgs150176 return (DDI_SUCCESS); 1590744Sgs150176 1591744Sgs150176 attach_fail: 1592744Sgs150176 rge_unattach(rgep); 1593744Sgs150176 return (DDI_FAILURE); 1594744Sgs150176 } 1595744Sgs150176 1596744Sgs150176 /* 1597744Sgs150176 * rge_suspend() -- suspend transmit/receive for powerdown 1598744Sgs150176 */ 1599744Sgs150176 static int 1600744Sgs150176 rge_suspend(rge_t *rgep) 1601744Sgs150176 { 1602744Sgs150176 /* 1603744Sgs150176 * Stop processing and idle (powerdown) the PHY ... 1604744Sgs150176 */ 1605744Sgs150176 mutex_enter(rgep->genlock); 1606744Sgs150176 rge_stop(rgep); 1607744Sgs150176 mutex_exit(rgep->genlock); 1608744Sgs150176 1609744Sgs150176 return (DDI_SUCCESS); 1610744Sgs150176 } 1611744Sgs150176 1612744Sgs150176 /* 1613744Sgs150176 * detach(9E) -- Detach a device from the system 1614744Sgs150176 */ 1615744Sgs150176 static int 1616744Sgs150176 rge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 1617744Sgs150176 { 1618744Sgs150176 rge_t *rgep; 1619744Sgs150176 1620744Sgs150176 RGE_GTRACE(("rge_detach($%p, %d)", (void *)devinfo, cmd)); 1621744Sgs150176 1622744Sgs150176 rgep = ddi_get_driver_private(devinfo); 1623744Sgs150176 1624744Sgs150176 switch (cmd) { 1625744Sgs150176 default: 1626744Sgs150176 return (DDI_FAILURE); 1627744Sgs150176 1628744Sgs150176 case DDI_SUSPEND: 1629744Sgs150176 return (rge_suspend(rgep)); 1630744Sgs150176 1631744Sgs150176 case DDI_DETACH: 1632744Sgs150176 break; 1633744Sgs150176 } 1634744Sgs150176 1635744Sgs150176 /* 1636744Sgs150176 * If there is any posted buffer, the driver should reject to be 1637744Sgs150176 * detached. Need notice upper layer to release them. 1638744Sgs150176 */ 1639744Sgs150176 if (rgep->rx_free != RGE_BUF_SLOTS) 1640744Sgs150176 return (DDI_FAILURE); 1641744Sgs150176 1642744Sgs150176 /* 1643744Sgs150176 * Unregister from the MAC layer subsystem. This can fail, in 1644744Sgs150176 * particular if there are DLPI style-2 streams still open - 1645744Sgs150176 * in which case we just return failure without shutting 1646744Sgs150176 * down chip operations. 1647744Sgs150176 */ 1648*2311Sseb if (mac_unregister(rgep->mh) != 0) 1649744Sgs150176 return (DDI_FAILURE); 1650744Sgs150176 1651744Sgs150176 /* 1652744Sgs150176 * All activity stopped, so we can clean up & exit 1653744Sgs150176 */ 1654744Sgs150176 rge_unattach(rgep); 1655744Sgs150176 return (DDI_SUCCESS); 1656744Sgs150176 } 1657744Sgs150176 1658744Sgs150176 1659744Sgs150176 /* 1660744Sgs150176 * ========== Module Loading Data & Entry Points ========== 1661744Sgs150176 */ 1662744Sgs150176 1663744Sgs150176 #undef RGE_DBG 1664744Sgs150176 #define RGE_DBG RGE_DBG_INIT /* debug flag for this code */ 1665744Sgs150176 DDI_DEFINE_STREAM_OPS(rge_dev_ops, nulldev, nulldev, rge_attach, rge_detach, 1666744Sgs150176 nodev, NULL, D_MP, NULL); 1667744Sgs150176 1668744Sgs150176 static struct modldrv rge_modldrv = { 1669744Sgs150176 &mod_driverops, /* Type of module. This one is a driver */ 1670744Sgs150176 rge_ident, /* short description */ 1671744Sgs150176 &rge_dev_ops /* driver specific ops */ 1672744Sgs150176 }; 1673744Sgs150176 1674744Sgs150176 static struct modlinkage modlinkage = { 1675744Sgs150176 MODREV_1, (void *)&rge_modldrv, NULL 1676744Sgs150176 }; 1677744Sgs150176 1678744Sgs150176 1679744Sgs150176 int 1680744Sgs150176 _info(struct modinfo *modinfop) 1681744Sgs150176 { 1682744Sgs150176 return (mod_info(&modlinkage, modinfop)); 1683744Sgs150176 } 1684744Sgs150176 1685744Sgs150176 int 1686744Sgs150176 _init(void) 1687744Sgs150176 { 1688744Sgs150176 int status; 1689744Sgs150176 1690744Sgs150176 mac_init_ops(&rge_dev_ops, "rge"); 1691744Sgs150176 status = mod_install(&modlinkage); 1692744Sgs150176 if (status == DDI_SUCCESS) 1693744Sgs150176 mutex_init(rge_log_mutex, NULL, MUTEX_DRIVER, NULL); 1694744Sgs150176 else 1695744Sgs150176 mac_fini_ops(&rge_dev_ops); 1696744Sgs150176 1697744Sgs150176 return (status); 1698744Sgs150176 } 1699744Sgs150176 1700744Sgs150176 int 1701744Sgs150176 _fini(void) 1702744Sgs150176 { 1703744Sgs150176 int status; 1704744Sgs150176 1705744Sgs150176 status = mod_remove(&modlinkage); 1706744Sgs150176 if (status == DDI_SUCCESS) { 1707744Sgs150176 mac_fini_ops(&rge_dev_ops); 1708744Sgs150176 mutex_destroy(rge_log_mutex); 1709744Sgs150176 } 1710744Sgs150176 return (status); 1711744Sgs150176 } 1712