1744Sgs150176 /* 2744Sgs150176 * CDDL HEADER START 3744Sgs150176 * 4744Sgs150176 * The contents of this file are subject to the terms of the 52311Sseb * Common Development and Distribution License (the "License"). 62311Sseb * 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 /* 2210814SKHF04453@nifty.ne.jp * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23744Sgs150176 * Use is subject to license terms. 24744Sgs150176 */ 25744Sgs150176 26744Sgs150176 #include "rge.h" 27744Sgs150176 28744Sgs150176 /* 29744Sgs150176 * This is the string displayed by modinfo, etc. 30744Sgs150176 * Make sure you keep the version ID up to date! 31744Sgs150176 */ 327656SSherry.Moore@Sun.COM static char rge_ident[] = "Realtek 1Gb Ethernet"; 33744Sgs150176 34744Sgs150176 /* 35744Sgs150176 * Used for buffers allocated by ddi_dma_mem_alloc() 36744Sgs150176 */ 37744Sgs150176 static ddi_dma_attr_t dma_attr_buf = { 38744Sgs150176 DMA_ATTR_V0, /* dma_attr version */ 39744Sgs150176 (uint32_t)0, /* dma_attr_addr_lo */ 40744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_addr_hi */ 41744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_count_max */ 42744Sgs150176 (uint32_t)16, /* dma_attr_align */ 43744Sgs150176 0xFFFFFFFF, /* dma_attr_burstsizes */ 44744Sgs150176 1, /* dma_attr_minxfer */ 45744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_maxxfer */ 46744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_seg */ 47744Sgs150176 1, /* dma_attr_sgllen */ 48744Sgs150176 1, /* dma_attr_granular */ 49744Sgs150176 0, /* dma_attr_flags */ 50744Sgs150176 }; 51744Sgs150176 52744Sgs150176 /* 53744Sgs150176 * Used for BDs allocated by ddi_dma_mem_alloc() 54744Sgs150176 */ 55744Sgs150176 static ddi_dma_attr_t dma_attr_desc = { 56744Sgs150176 DMA_ATTR_V0, /* dma_attr version */ 57744Sgs150176 (uint32_t)0, /* dma_attr_addr_lo */ 58744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_addr_hi */ 59744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_count_max */ 60744Sgs150176 (uint32_t)256, /* dma_attr_align */ 61744Sgs150176 0xFFFFFFFF, /* dma_attr_burstsizes */ 62744Sgs150176 1, /* dma_attr_minxfer */ 63744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_maxxfer */ 64744Sgs150176 (uint32_t)0xFFFFFFFF, /* dma_attr_seg */ 65744Sgs150176 1, /* dma_attr_sgllen */ 66744Sgs150176 1, /* dma_attr_granular */ 67744Sgs150176 0, /* dma_attr_flags */ 68744Sgs150176 }; 69744Sgs150176 70744Sgs150176 /* 71744Sgs150176 * PIO access attributes for registers 72744Sgs150176 */ 73744Sgs150176 static ddi_device_acc_attr_t rge_reg_accattr = { 74744Sgs150176 DDI_DEVICE_ATTR_V0, 75744Sgs150176 DDI_STRUCTURE_LE_ACC, 76744Sgs150176 DDI_STRICTORDER_ACC, 77744Sgs150176 DDI_DEFAULT_ACC 78744Sgs150176 }; 79744Sgs150176 80744Sgs150176 /* 81744Sgs150176 * DMA access attributes for descriptors 82744Sgs150176 */ 83744Sgs150176 static ddi_device_acc_attr_t rge_desc_accattr = { 84744Sgs150176 DDI_DEVICE_ATTR_V0, 85744Sgs150176 DDI_NEVERSWAP_ACC, 86744Sgs150176 DDI_STRICTORDER_ACC, 87744Sgs150176 DDI_DEFAULT_ACC 88744Sgs150176 }; 89744Sgs150176 90744Sgs150176 /* 91744Sgs150176 * DMA access attributes for data 92744Sgs150176 */ 93744Sgs150176 static ddi_device_acc_attr_t rge_buf_accattr = { 94744Sgs150176 DDI_DEVICE_ATTR_V0, 95744Sgs150176 DDI_NEVERSWAP_ACC, 96744Sgs150176 DDI_STRICTORDER_ACC, 97744Sgs150176 DDI_DEFAULT_ACC 98744Sgs150176 }; 99744Sgs150176 100744Sgs150176 /* 101744Sgs150176 * Property names 102744Sgs150176 */ 1032544Sgs150176 static char debug_propname[] = "rge_debug_flags"; 1042544Sgs150176 static char mtu_propname[] = "default_mtu"; 1052544Sgs150176 static char msi_propname[] = "msi_enable"; 106744Sgs150176 1072311Sseb static int rge_m_start(void *); 1082311Sseb static void rge_m_stop(void *); 1092311Sseb static int rge_m_promisc(void *, boolean_t); 1102311Sseb static int rge_m_multicst(void *, boolean_t, const uint8_t *); 1112311Sseb static int rge_m_unicst(void *, const uint8_t *); 1122311Sseb static void rge_m_ioctl(void *, queue_t *, mblk_t *); 1132311Sseb static boolean_t rge_m_getcapab(void *, mac_capab_t, void *); 1142311Sseb 1158275SEric Cheng #define RGE_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB) 1162311Sseb 1172311Sseb static mac_callbacks_t rge_m_callbacks = { 1182311Sseb RGE_M_CALLBACK_FLAGS, 1192311Sseb rge_m_stat, 1202311Sseb rge_m_start, 1212311Sseb rge_m_stop, 1222311Sseb rge_m_promisc, 1232311Sseb rge_m_multicst, 1242311Sseb rge_m_unicst, 1252311Sseb rge_m_tx, 1262311Sseb rge_m_ioctl, 1272311Sseb rge_m_getcapab 1282311Sseb }; 129744Sgs150176 130744Sgs150176 /* 131744Sgs150176 * Allocate an area of memory and a DMA handle for accessing it 132744Sgs150176 */ 133744Sgs150176 static int 134744Sgs150176 rge_alloc_dma_mem(rge_t *rgep, size_t memsize, ddi_dma_attr_t *dma_attr_p, 135744Sgs150176 ddi_device_acc_attr_t *acc_attr_p, uint_t dma_flags, dma_area_t *dma_p) 136744Sgs150176 { 137744Sgs150176 caddr_t vaddr; 138744Sgs150176 int err; 139744Sgs150176 140744Sgs150176 /* 141744Sgs150176 * Allocate handle 142744Sgs150176 */ 143744Sgs150176 err = ddi_dma_alloc_handle(rgep->devinfo, dma_attr_p, 1445107Seota DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl); 145744Sgs150176 if (err != DDI_SUCCESS) { 146744Sgs150176 dma_p->dma_hdl = NULL; 147744Sgs150176 return (DDI_FAILURE); 148744Sgs150176 } 149744Sgs150176 150744Sgs150176 /* 151744Sgs150176 * Allocate memory 152744Sgs150176 */ 153744Sgs150176 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p, 154744Sgs150176 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING), 155744Sgs150176 DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl); 156744Sgs150176 if (err != DDI_SUCCESS) { 157744Sgs150176 ddi_dma_free_handle(&dma_p->dma_hdl); 158744Sgs150176 dma_p->dma_hdl = NULL; 159744Sgs150176 dma_p->acc_hdl = NULL; 160744Sgs150176 return (DDI_FAILURE); 161744Sgs150176 } 162744Sgs150176 163744Sgs150176 /* 164744Sgs150176 * Bind the two together 165744Sgs150176 */ 166744Sgs150176 dma_p->mem_va = vaddr; 167744Sgs150176 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 168744Sgs150176 vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL, 169744Sgs150176 &dma_p->cookie, &dma_p->ncookies); 170744Sgs150176 if (err != DDI_DMA_MAPPED || dma_p->ncookies != 1) { 171744Sgs150176 ddi_dma_mem_free(&dma_p->acc_hdl); 172744Sgs150176 ddi_dma_free_handle(&dma_p->dma_hdl); 173744Sgs150176 dma_p->acc_hdl = NULL; 174744Sgs150176 dma_p->dma_hdl = NULL; 175744Sgs150176 return (DDI_FAILURE); 176744Sgs150176 } 177744Sgs150176 178744Sgs150176 dma_p->nslots = ~0U; 179744Sgs150176 dma_p->size = ~0U; 180744Sgs150176 dma_p->token = ~0U; 181744Sgs150176 dma_p->offset = 0; 182744Sgs150176 return (DDI_SUCCESS); 183744Sgs150176 } 184744Sgs150176 185744Sgs150176 /* 186744Sgs150176 * Free one allocated area of DMAable memory 187744Sgs150176 */ 188744Sgs150176 static void 189744Sgs150176 rge_free_dma_mem(dma_area_t *dma_p) 190744Sgs150176 { 191744Sgs150176 if (dma_p->dma_hdl != NULL) { 192744Sgs150176 if (dma_p->ncookies) { 193744Sgs150176 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 194744Sgs150176 dma_p->ncookies = 0; 195744Sgs150176 } 196744Sgs150176 ddi_dma_free_handle(&dma_p->dma_hdl); 197744Sgs150176 dma_p->dma_hdl = NULL; 198744Sgs150176 } 199744Sgs150176 200744Sgs150176 if (dma_p->acc_hdl != NULL) { 201744Sgs150176 ddi_dma_mem_free(&dma_p->acc_hdl); 202744Sgs150176 dma_p->acc_hdl = NULL; 203744Sgs150176 } 204744Sgs150176 } 205744Sgs150176 206744Sgs150176 /* 207744Sgs150176 * Utility routine to carve a slice off a chunk of allocated memory, 208744Sgs150176 * updating the chunk descriptor accordingly. The size of the slice 209744Sgs150176 * is given by the product of the <qty> and <size> parameters. 210744Sgs150176 */ 211744Sgs150176 static void 212744Sgs150176 rge_slice_chunk(dma_area_t *slice, dma_area_t *chunk, 213744Sgs150176 uint32_t qty, uint32_t size) 214744Sgs150176 { 215744Sgs150176 static uint32_t sequence = 0xbcd5704a; 216744Sgs150176 size_t totsize; 217744Sgs150176 218744Sgs150176 totsize = qty*size; 219744Sgs150176 ASSERT(totsize <= chunk->alength); 220744Sgs150176 221744Sgs150176 *slice = *chunk; 222744Sgs150176 slice->nslots = qty; 223744Sgs150176 slice->size = size; 224744Sgs150176 slice->alength = totsize; 225744Sgs150176 slice->token = ++sequence; 226744Sgs150176 227744Sgs150176 chunk->mem_va = (caddr_t)chunk->mem_va + totsize; 228744Sgs150176 chunk->alength -= totsize; 229744Sgs150176 chunk->offset += totsize; 230744Sgs150176 chunk->cookie.dmac_laddress += totsize; 231744Sgs150176 chunk->cookie.dmac_size -= totsize; 232744Sgs150176 } 233744Sgs150176 234744Sgs150176 static int 235744Sgs150176 rge_alloc_bufs(rge_t *rgep) 236744Sgs150176 { 237744Sgs150176 size_t txdescsize; 238744Sgs150176 size_t rxdescsize; 239744Sgs150176 int err; 240744Sgs150176 241744Sgs150176 /* 242744Sgs150176 * Allocate memory & handle for packet statistics 243744Sgs150176 */ 244744Sgs150176 err = rge_alloc_dma_mem(rgep, 245744Sgs150176 RGE_STATS_DUMP_SIZE, 246744Sgs150176 &dma_attr_desc, 247744Sgs150176 &rge_desc_accattr, 248744Sgs150176 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 249744Sgs150176 &rgep->dma_area_stats); 250744Sgs150176 if (err != DDI_SUCCESS) 251744Sgs150176 return (DDI_FAILURE); 252744Sgs150176 rgep->hw_stats = DMA_VPTR(rgep->dma_area_stats); 253744Sgs150176 254744Sgs150176 /* 255744Sgs150176 * Allocate memory & handle for Tx descriptor ring 256744Sgs150176 */ 257744Sgs150176 txdescsize = RGE_SEND_SLOTS * sizeof (rge_bd_t); 258744Sgs150176 err = rge_alloc_dma_mem(rgep, 259744Sgs150176 txdescsize, 260744Sgs150176 &dma_attr_desc, 261744Sgs150176 &rge_desc_accattr, 262744Sgs150176 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 263744Sgs150176 &rgep->dma_area_txdesc); 264744Sgs150176 if (err != DDI_SUCCESS) 265744Sgs150176 return (DDI_FAILURE); 266744Sgs150176 267744Sgs150176 /* 268744Sgs150176 * Allocate memory & handle for Rx descriptor ring 269744Sgs150176 */ 270744Sgs150176 rxdescsize = RGE_RECV_SLOTS * sizeof (rge_bd_t); 271744Sgs150176 err = rge_alloc_dma_mem(rgep, 272744Sgs150176 rxdescsize, 273744Sgs150176 &dma_attr_desc, 274744Sgs150176 &rge_desc_accattr, 275744Sgs150176 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 276744Sgs150176 &rgep->dma_area_rxdesc); 277744Sgs150176 if (err != DDI_SUCCESS) 278744Sgs150176 return (DDI_FAILURE); 279744Sgs150176 280744Sgs150176 return (DDI_SUCCESS); 281744Sgs150176 } 282744Sgs150176 283744Sgs150176 /* 284744Sgs150176 * rge_free_bufs() -- free descriptors/buffers allocated for this 285744Sgs150176 * device instance. 286744Sgs150176 */ 287744Sgs150176 static void 288744Sgs150176 rge_free_bufs(rge_t *rgep) 289744Sgs150176 { 290744Sgs150176 rge_free_dma_mem(&rgep->dma_area_stats); 291744Sgs150176 rge_free_dma_mem(&rgep->dma_area_txdesc); 292744Sgs150176 rge_free_dma_mem(&rgep->dma_area_rxdesc); 293744Sgs150176 } 294744Sgs150176 295744Sgs150176 /* 296744Sgs150176 * ========== Transmit and receive ring reinitialisation ========== 297744Sgs150176 */ 298744Sgs150176 299744Sgs150176 /* 300744Sgs150176 * These <reinit> routines each reset the rx/tx rings to an initial 301744Sgs150176 * state, assuming that the corresponding <init> routine has already 302744Sgs150176 * been called exactly once. 303744Sgs150176 */ 304744Sgs150176 static void 305744Sgs150176 rge_reinit_send_ring(rge_t *rgep) 306744Sgs150176 { 307744Sgs150176 sw_sbd_t *ssbdp; 308744Sgs150176 rge_bd_t *bdp; 309744Sgs150176 uint32_t slot; 310744Sgs150176 311744Sgs150176 /* 312744Sgs150176 * re-init send ring 313744Sgs150176 */ 314744Sgs150176 DMA_ZERO(rgep->tx_desc); 315744Sgs150176 ssbdp = rgep->sw_sbds; 316744Sgs150176 bdp = rgep->tx_ring; 317744Sgs150176 for (slot = 0; slot < RGE_SEND_SLOTS; slot++) { 318744Sgs150176 bdp->host_buf_addr = 319744Sgs150176 RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress); 320744Sgs150176 bdp->host_buf_addr_hi = 321744Sgs150176 RGE_BSWAP_32(ssbdp->pbuf.cookie.dmac_laddress >> 32); 322744Sgs150176 /* last BD in Tx ring */ 323744Sgs150176 if (slot == (RGE_SEND_SLOTS - 1)) 324744Sgs150176 bdp->flags_len = RGE_BSWAP_32(BD_FLAG_EOR); 325744Sgs150176 ssbdp++; 326744Sgs150176 bdp++; 327744Sgs150176 } 328744Sgs150176 DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV); 329744Sgs150176 rgep->tx_next = 0; 330744Sgs150176 rgep->tc_next = 0; 331744Sgs150176 rgep->tc_tail = 0; 332744Sgs150176 rgep->tx_flow = 0; 333744Sgs150176 rgep->tx_free = RGE_SEND_SLOTS; 334744Sgs150176 } 335744Sgs150176 336744Sgs150176 static void 337744Sgs150176 rge_reinit_recv_ring(rge_t *rgep) 338744Sgs150176 { 339744Sgs150176 rge_bd_t *bdp; 340744Sgs150176 sw_rbd_t *srbdp; 341744Sgs150176 dma_area_t *pbuf; 342744Sgs150176 uint32_t slot; 343744Sgs150176 344744Sgs150176 /* 345744Sgs150176 * re-init receive ring 346744Sgs150176 */ 347744Sgs150176 DMA_ZERO(rgep->rx_desc); 348744Sgs150176 srbdp = rgep->sw_rbds; 349744Sgs150176 bdp = rgep->rx_ring; 350744Sgs150176 for (slot = 0; slot < RGE_RECV_SLOTS; slot++) { 351744Sgs150176 pbuf = &srbdp->rx_buf->pbuf; 352744Sgs150176 bdp->host_buf_addr = 3532544Sgs150176 RGE_BSWAP_32(pbuf->cookie.dmac_laddress + rgep->head_room); 354744Sgs150176 bdp->host_buf_addr_hi = 355744Sgs150176 RGE_BSWAP_32(pbuf->cookie.dmac_laddress >> 32); 356744Sgs150176 bdp->flags_len = RGE_BSWAP_32(BD_FLAG_HW_OWN | 3572544Sgs150176 (rgep->rxbuf_size - rgep->head_room)); 358744Sgs150176 /* last BD in Tx ring */ 359744Sgs150176 if (slot == (RGE_RECV_SLOTS - 1)) 360744Sgs150176 bdp->flags_len |= RGE_BSWAP_32(BD_FLAG_EOR); 361744Sgs150176 srbdp++; 362744Sgs150176 bdp++; 363744Sgs150176 } 364744Sgs150176 DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV); 365744Sgs150176 rgep->watchdog = 0; 366744Sgs150176 rgep->rx_next = 0; 367744Sgs150176 } 368744Sgs150176 369744Sgs150176 static void 370744Sgs150176 rge_reinit_buf_ring(rge_t *rgep) 371744Sgs150176 { 3722544Sgs150176 3732544Sgs150176 if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) 3742544Sgs150176 return; 3752544Sgs150176 376744Sgs150176 /* 3772544Sgs150176 * If all the up-sending buffers haven't been returned to driver, 3782544Sgs150176 * use bcopy() only in rx process. 379744Sgs150176 */ 380744Sgs150176 if (rgep->rx_free != RGE_BUF_SLOTS) 381744Sgs150176 rgep->rx_bcopy = B_TRUE; 382744Sgs150176 } 383744Sgs150176 384744Sgs150176 static void 385744Sgs150176 rge_reinit_rings(rge_t *rgep) 386744Sgs150176 { 387744Sgs150176 rge_reinit_send_ring(rgep); 388744Sgs150176 rge_reinit_recv_ring(rgep); 389744Sgs150176 rge_reinit_buf_ring(rgep); 390744Sgs150176 } 391744Sgs150176 392744Sgs150176 static void 3932544Sgs150176 rge_fini_send_ring(rge_t *rgep) 3942544Sgs150176 { 3952544Sgs150176 sw_sbd_t *ssbdp; 3962544Sgs150176 uint32_t slot; 3972544Sgs150176 3982544Sgs150176 ssbdp = rgep->sw_sbds; 3992544Sgs150176 for (slot = 0; slot < RGE_SEND_SLOTS; ++slot) { 4002544Sgs150176 rge_free_dma_mem(&ssbdp->pbuf); 4012544Sgs150176 ssbdp++; 4022544Sgs150176 } 4032544Sgs150176 4042544Sgs150176 kmem_free(rgep->sw_sbds, RGE_SEND_SLOTS * sizeof (sw_sbd_t)); 4052544Sgs150176 rgep->sw_sbds = NULL; 4062544Sgs150176 } 4072544Sgs150176 4082544Sgs150176 static void 4092544Sgs150176 rge_fini_recv_ring(rge_t *rgep) 4102544Sgs150176 { 4112544Sgs150176 sw_rbd_t *srbdp; 4122544Sgs150176 uint32_t slot; 4132544Sgs150176 4142544Sgs150176 srbdp = rgep->sw_rbds; 4152544Sgs150176 for (slot = 0; slot < RGE_RECV_SLOTS; ++srbdp, ++slot) { 4162544Sgs150176 if (srbdp->rx_buf) { 4172544Sgs150176 if (srbdp->rx_buf->mp != NULL) { 4182544Sgs150176 freemsg(srbdp->rx_buf->mp); 4192544Sgs150176 srbdp->rx_buf->mp = NULL; 4202544Sgs150176 } 4212544Sgs150176 rge_free_dma_mem(&srbdp->rx_buf->pbuf); 4222544Sgs150176 kmem_free(srbdp->rx_buf, sizeof (dma_buf_t)); 4232544Sgs150176 srbdp->rx_buf = NULL; 4242544Sgs150176 } 4252544Sgs150176 } 4262544Sgs150176 4272544Sgs150176 kmem_free(rgep->sw_rbds, RGE_RECV_SLOTS * sizeof (sw_rbd_t)); 4282544Sgs150176 rgep->sw_rbds = NULL; 4292544Sgs150176 } 4302544Sgs150176 4312544Sgs150176 static void 4322544Sgs150176 rge_fini_buf_ring(rge_t *rgep) 4332544Sgs150176 { 4342544Sgs150176 sw_rbd_t *srbdp; 4352544Sgs150176 uint32_t slot; 4362544Sgs150176 4372544Sgs150176 if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) 4382544Sgs150176 return; 4392544Sgs150176 4402544Sgs150176 ASSERT(rgep->rx_free == RGE_BUF_SLOTS); 4412544Sgs150176 4422544Sgs150176 srbdp = rgep->free_srbds; 4432544Sgs150176 for (slot = 0; slot < RGE_BUF_SLOTS; ++srbdp, ++slot) { 4442544Sgs150176 if (srbdp->rx_buf != NULL) { 4452544Sgs150176 if (srbdp->rx_buf->mp != NULL) { 4462544Sgs150176 freemsg(srbdp->rx_buf->mp); 4472544Sgs150176 srbdp->rx_buf->mp = NULL; 4482544Sgs150176 } 4492544Sgs150176 rge_free_dma_mem(&srbdp->rx_buf->pbuf); 4502544Sgs150176 kmem_free(srbdp->rx_buf, sizeof (dma_buf_t)); 4512544Sgs150176 srbdp->rx_buf = NULL; 4522544Sgs150176 } 4532544Sgs150176 } 4542544Sgs150176 4552544Sgs150176 kmem_free(rgep->free_srbds, RGE_BUF_SLOTS * sizeof (sw_rbd_t)); 4562544Sgs150176 rgep->free_srbds = NULL; 4572544Sgs150176 } 4582544Sgs150176 4592544Sgs150176 static void 4602544Sgs150176 rge_fini_rings(rge_t *rgep) 4612544Sgs150176 { 4622544Sgs150176 rge_fini_send_ring(rgep); 4632544Sgs150176 rge_fini_recv_ring(rgep); 4642544Sgs150176 rge_fini_buf_ring(rgep); 4652544Sgs150176 } 4662544Sgs150176 4672544Sgs150176 static int 468744Sgs150176 rge_init_send_ring(rge_t *rgep) 469744Sgs150176 { 470744Sgs150176 uint32_t slot; 471744Sgs150176 sw_sbd_t *ssbdp; 472744Sgs150176 dma_area_t *pbuf; 4732544Sgs150176 dma_area_t desc; 4742544Sgs150176 int err; 475744Sgs150176 476744Sgs150176 /* 477744Sgs150176 * Allocate the array of s/w Tx Buffer Descriptors 478744Sgs150176 */ 479744Sgs150176 ssbdp = kmem_zalloc(RGE_SEND_SLOTS*sizeof (*ssbdp), KM_SLEEP); 480744Sgs150176 rgep->sw_sbds = ssbdp; 481744Sgs150176 482744Sgs150176 /* 483744Sgs150176 * Init send ring 484744Sgs150176 */ 485744Sgs150176 rgep->tx_desc = rgep->dma_area_txdesc; 486744Sgs150176 DMA_ZERO(rgep->tx_desc); 4872544Sgs150176 rgep->tx_ring = rgep->tx_desc.mem_va; 4882544Sgs150176 4892544Sgs150176 desc = rgep->tx_desc; 4902544Sgs150176 for (slot = 0; slot < RGE_SEND_SLOTS; slot++) { 4912544Sgs150176 rge_slice_chunk(&ssbdp->desc, &desc, 1, sizeof (rge_bd_t)); 4922544Sgs150176 4932544Sgs150176 /* 4942544Sgs150176 * Allocate memory & handle for Tx buffers 4952544Sgs150176 */ 4962544Sgs150176 pbuf = &ssbdp->pbuf; 4972544Sgs150176 err = rge_alloc_dma_mem(rgep, rgep->txbuf_size, 4982544Sgs150176 &dma_attr_buf, &rge_buf_accattr, 4992544Sgs150176 DDI_DMA_WRITE | DDI_DMA_STREAMING, pbuf); 5002544Sgs150176 if (err != DDI_SUCCESS) { 5012544Sgs150176 rge_error(rgep, 5022544Sgs150176 "rge_init_send_ring: alloc tx buffer failed"); 5032544Sgs150176 rge_fini_send_ring(rgep); 5042544Sgs150176 return (DDI_FAILURE); 505744Sgs150176 } 5062544Sgs150176 ssbdp++; 507744Sgs150176 } 5082544Sgs150176 ASSERT(desc.alength == 0); 5092544Sgs150176 510744Sgs150176 DMA_SYNC(rgep->tx_desc, DDI_DMA_SYNC_FORDEV); 5112544Sgs150176 return (DDI_SUCCESS); 512744Sgs150176 } 513744Sgs150176 514744Sgs150176 static int 515744Sgs150176 rge_init_recv_ring(rge_t *rgep) 516744Sgs150176 { 517744Sgs150176 uint32_t slot; 518744Sgs150176 sw_rbd_t *srbdp; 519744Sgs150176 dma_buf_t *rx_buf; 520744Sgs150176 dma_area_t *pbuf; 5212544Sgs150176 int err; 522744Sgs150176 523744Sgs150176 /* 524744Sgs150176 * Allocate the array of s/w Rx Buffer Descriptors 525744Sgs150176 */ 526744Sgs150176 srbdp = kmem_zalloc(RGE_RECV_SLOTS*sizeof (*srbdp), KM_SLEEP); 527744Sgs150176 rgep->sw_rbds = srbdp; 528744Sgs150176 529744Sgs150176 /* 530744Sgs150176 * Init receive ring 531744Sgs150176 */ 532744Sgs150176 rgep->rx_next = 0; 533744Sgs150176 rgep->rx_desc = rgep->dma_area_rxdesc; 534744Sgs150176 DMA_ZERO(rgep->rx_desc); 5352544Sgs150176 rgep->rx_ring = rgep->rx_desc.mem_va; 5362544Sgs150176 5372544Sgs150176 for (slot = 0; slot < RGE_RECV_SLOTS; slot++) { 5382544Sgs150176 srbdp->rx_buf = rx_buf = 5392544Sgs150176 kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP); 5402544Sgs150176 5412544Sgs150176 /* 5422544Sgs150176 * Allocate memory & handle for Rx buffers 5432544Sgs150176 */ 5442544Sgs150176 pbuf = &rx_buf->pbuf; 5452544Sgs150176 err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size, 5462544Sgs150176 &dma_attr_buf, &rge_buf_accattr, 5472544Sgs150176 DDI_DMA_READ | DDI_DMA_STREAMING, pbuf); 5482544Sgs150176 if (err != DDI_SUCCESS) { 5492544Sgs150176 rge_fini_recv_ring(rgep); 5502544Sgs150176 rge_error(rgep, 5512544Sgs150176 "rge_init_recv_ring: alloc rx buffer failed"); 5522544Sgs150176 return (DDI_FAILURE); 5532544Sgs150176 } 5542544Sgs150176 5552544Sgs150176 pbuf->alength -= rgep->head_room; 5562544Sgs150176 pbuf->offset += rgep->head_room; 5572544Sgs150176 if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY)) { 558744Sgs150176 rx_buf->rx_recycle.free_func = rge_rx_recycle; 559744Sgs150176 rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf; 560744Sgs150176 rx_buf->private = (caddr_t)rgep; 561744Sgs150176 rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf), 562744Sgs150176 rgep->rxbuf_size, 0, &rx_buf->rx_recycle); 563744Sgs150176 if (rx_buf->mp == NULL) { 5642544Sgs150176 rge_fini_recv_ring(rgep); 565744Sgs150176 rge_problem(rgep, 566744Sgs150176 "rge_init_recv_ring: desballoc() failed"); 567744Sgs150176 return (DDI_FAILURE); 568744Sgs150176 } 569744Sgs150176 } 5702544Sgs150176 srbdp++; 571744Sgs150176 } 572744Sgs150176 DMA_SYNC(rgep->rx_desc, DDI_DMA_SYNC_FORDEV); 573744Sgs150176 return (DDI_SUCCESS); 574744Sgs150176 } 575744Sgs150176 576744Sgs150176 static int 577744Sgs150176 rge_init_buf_ring(rge_t *rgep) 578744Sgs150176 { 579744Sgs150176 uint32_t slot; 5802544Sgs150176 sw_rbd_t *free_srbdp; 581744Sgs150176 dma_buf_t *rx_buf; 582744Sgs150176 dma_area_t *pbuf; 5832544Sgs150176 int err; 5842544Sgs150176 5852544Sgs150176 if (rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) { 5862544Sgs150176 rgep->rx_bcopy = B_TRUE; 5872544Sgs150176 return (DDI_SUCCESS); 5882544Sgs150176 } 589744Sgs150176 590744Sgs150176 /* 591744Sgs150176 * Allocate the array of s/w free Buffer Descriptors 592744Sgs150176 */ 5932544Sgs150176 free_srbdp = kmem_zalloc(RGE_BUF_SLOTS*sizeof (*free_srbdp), KM_SLEEP); 5942544Sgs150176 rgep->free_srbds = free_srbdp; 595744Sgs150176 596744Sgs150176 /* 597744Sgs150176 * Init free buffer ring 598744Sgs150176 */ 599744Sgs150176 rgep->rc_next = 0; 600744Sgs150176 rgep->rf_next = 0; 601744Sgs150176 rgep->rx_bcopy = B_FALSE; 602744Sgs150176 rgep->rx_free = RGE_BUF_SLOTS; 6032544Sgs150176 for (slot = 0; slot < RGE_BUF_SLOTS; slot++) { 6042544Sgs150176 free_srbdp->rx_buf = rx_buf = 6052544Sgs150176 kmem_zalloc(sizeof (dma_buf_t), KM_SLEEP); 6062544Sgs150176 6072544Sgs150176 /* 6082544Sgs150176 * Allocate memory & handle for free Rx buffers 6092544Sgs150176 */ 6102544Sgs150176 pbuf = &rx_buf->pbuf; 6112544Sgs150176 err = rge_alloc_dma_mem(rgep, rgep->rxbuf_size, 6122544Sgs150176 &dma_attr_buf, &rge_buf_accattr, 6132544Sgs150176 DDI_DMA_READ | DDI_DMA_STREAMING, pbuf); 6142544Sgs150176 if (err != DDI_SUCCESS) { 6152544Sgs150176 rge_fini_buf_ring(rgep); 6162544Sgs150176 rge_error(rgep, 6172544Sgs150176 "rge_init_buf_ring: alloc rx free buffer failed"); 6182544Sgs150176 return (DDI_FAILURE); 619744Sgs150176 } 6202544Sgs150176 pbuf->alength -= rgep->head_room; 6212544Sgs150176 pbuf->offset += rgep->head_room; 6222544Sgs150176 rx_buf->rx_recycle.free_func = rge_rx_recycle; 6232544Sgs150176 rx_buf->rx_recycle.free_arg = (caddr_t)rx_buf; 6242544Sgs150176 rx_buf->private = (caddr_t)rgep; 6252544Sgs150176 rx_buf->mp = desballoc(DMA_VPTR(rx_buf->pbuf), 6262544Sgs150176 rgep->rxbuf_size, 0, &rx_buf->rx_recycle); 6272544Sgs150176 if (rx_buf->mp == NULL) { 6282544Sgs150176 rge_fini_buf_ring(rgep); 6292544Sgs150176 rge_problem(rgep, 6302544Sgs150176 "rge_init_buf_ring: desballoc() failed"); 6312544Sgs150176 return (DDI_FAILURE); 6322544Sgs150176 } 6332544Sgs150176 free_srbdp++; 634744Sgs150176 } 635744Sgs150176 return (DDI_SUCCESS); 636744Sgs150176 } 637744Sgs150176 638744Sgs150176 static int 639744Sgs150176 rge_init_rings(rge_t *rgep) 640744Sgs150176 { 641744Sgs150176 int err; 642744Sgs150176 6432544Sgs150176 err = rge_init_send_ring(rgep); 6442544Sgs150176 if (err != DDI_SUCCESS) 6452544Sgs150176 return (DDI_FAILURE); 646744Sgs150176 6472544Sgs150176 err = rge_init_recv_ring(rgep); 6482544Sgs150176 if (err != DDI_SUCCESS) { 6492544Sgs150176 rge_fini_send_ring(rgep); 6502544Sgs150176 return (DDI_FAILURE); 6512544Sgs150176 } 652744Sgs150176 6532544Sgs150176 err = rge_init_buf_ring(rgep); 6542544Sgs150176 if (err != DDI_SUCCESS) { 6552544Sgs150176 rge_fini_send_ring(rgep); 6562544Sgs150176 rge_fini_recv_ring(rgep); 6572544Sgs150176 return (DDI_FAILURE); 6582544Sgs150176 } 659744Sgs150176 6602544Sgs150176 return (DDI_SUCCESS); 661744Sgs150176 } 662744Sgs150176 663744Sgs150176 /* 664744Sgs150176 * ========== Internal state management entry points ========== 665744Sgs150176 */ 666744Sgs150176 667744Sgs150176 #undef RGE_DBG 668744Sgs150176 #define RGE_DBG RGE_DBG_NEMO /* debug flag for this code */ 669744Sgs150176 670744Sgs150176 /* 671744Sgs150176 * These routines provide all the functionality required by the 672744Sgs150176 * corresponding MAC layer entry points, but don't update the 673744Sgs150176 * MAC state so they can be called internally without disturbing 674744Sgs150176 * our record of what NEMO thinks we should be doing ... 675744Sgs150176 */ 676744Sgs150176 677744Sgs150176 /* 678744Sgs150176 * rge_reset() -- reset h/w & rings to initial state 679744Sgs150176 */ 680744Sgs150176 static void 681744Sgs150176 rge_reset(rge_t *rgep) 682744Sgs150176 { 683744Sgs150176 ASSERT(mutex_owned(rgep->genlock)); 684744Sgs150176 685744Sgs150176 /* 686744Sgs150176 * Grab all the other mutexes in the world (this should 687744Sgs150176 * ensure no other threads are manipulating driver state) 688744Sgs150176 */ 689744Sgs150176 mutex_enter(rgep->rx_lock); 690744Sgs150176 mutex_enter(rgep->rc_lock); 691744Sgs150176 rw_enter(rgep->errlock, RW_WRITER); 692744Sgs150176 693744Sgs150176 (void) rge_chip_reset(rgep); 694744Sgs150176 rge_reinit_rings(rgep); 695744Sgs150176 rge_chip_init(rgep); 696744Sgs150176 697744Sgs150176 /* 698744Sgs150176 * Free the world ... 699744Sgs150176 */ 700744Sgs150176 rw_exit(rgep->errlock); 701744Sgs150176 mutex_exit(rgep->rc_lock); 702744Sgs150176 mutex_exit(rgep->rx_lock); 703744Sgs150176 7046410Smx205022 rgep->stats.rpackets = 0; 7056410Smx205022 rgep->stats.rbytes = 0; 7066410Smx205022 rgep->stats.opackets = 0; 7076410Smx205022 rgep->stats.obytes = 0; 7086410Smx205022 rgep->stats.tx_pre_ismax = B_FALSE; 7096410Smx205022 rgep->stats.tx_cur_ismax = B_FALSE; 7106410Smx205022 711744Sgs150176 RGE_DEBUG(("rge_reset($%p) done", (void *)rgep)); 712744Sgs150176 } 713744Sgs150176 714744Sgs150176 /* 715744Sgs150176 * rge_stop() -- stop processing, don't reset h/w or rings 716744Sgs150176 */ 717744Sgs150176 static void 718744Sgs150176 rge_stop(rge_t *rgep) 719744Sgs150176 { 720744Sgs150176 ASSERT(mutex_owned(rgep->genlock)); 721744Sgs150176 722744Sgs150176 rge_chip_stop(rgep, B_FALSE); 723744Sgs150176 724744Sgs150176 RGE_DEBUG(("rge_stop($%p) done", (void *)rgep)); 725744Sgs150176 } 726744Sgs150176 727744Sgs150176 /* 728744Sgs150176 * rge_start() -- start transmitting/receiving 729744Sgs150176 */ 730744Sgs150176 static void 731744Sgs150176 rge_start(rge_t *rgep) 732744Sgs150176 { 733744Sgs150176 ASSERT(mutex_owned(rgep->genlock)); 734744Sgs150176 735744Sgs150176 /* 736744Sgs150176 * Start chip processing, including enabling interrupts 737744Sgs150176 */ 738744Sgs150176 rge_chip_start(rgep); 739744Sgs150176 rgep->watchdog = 0; 740744Sgs150176 } 741744Sgs150176 742744Sgs150176 /* 743744Sgs150176 * rge_restart - restart transmitting/receiving after error or suspend 744744Sgs150176 */ 745744Sgs150176 void 746744Sgs150176 rge_restart(rge_t *rgep) 747744Sgs150176 { 748744Sgs150176 uint32_t i; 749744Sgs150176 750744Sgs150176 ASSERT(mutex_owned(rgep->genlock)); 751744Sgs150176 /* 752744Sgs150176 * Wait for posted buffer to be freed... 753744Sgs150176 */ 754744Sgs150176 if (!rgep->rx_bcopy) { 755744Sgs150176 for (i = 0; i < RXBUFF_FREE_LOOP; i++) { 756744Sgs150176 if (rgep->rx_free == RGE_BUF_SLOTS) 757744Sgs150176 break; 758744Sgs150176 drv_usecwait(1000); 759744Sgs150176 RGE_DEBUG(("rge_restart: waiting for rx buf free...")); 760744Sgs150176 } 761744Sgs150176 } 762744Sgs150176 rge_reset(rgep); 763744Sgs150176 rgep->stats.chip_reset++; 764744Sgs150176 if (rgep->rge_mac_state == RGE_MAC_STARTED) { 765744Sgs150176 rge_start(rgep); 7662544Sgs150176 rgep->resched_needed = B_TRUE; 7672544Sgs150176 (void) ddi_intr_trigger_softint(rgep->resched_hdl, NULL); 768744Sgs150176 } 769744Sgs150176 } 770744Sgs150176 771744Sgs150176 772744Sgs150176 /* 773744Sgs150176 * ========== Nemo-required management entry points ========== 774744Sgs150176 */ 775744Sgs150176 776744Sgs150176 #undef RGE_DBG 777744Sgs150176 #define RGE_DBG RGE_DBG_NEMO /* debug flag for this code */ 778744Sgs150176 779744Sgs150176 /* 780744Sgs150176 * rge_m_stop() -- stop transmitting/receiving 781744Sgs150176 */ 782744Sgs150176 static void 783744Sgs150176 rge_m_stop(void *arg) 784744Sgs150176 { 785744Sgs150176 rge_t *rgep = arg; /* private device info */ 786744Sgs150176 uint32_t i; 787744Sgs150176 788744Sgs150176 /* 789744Sgs150176 * Just stop processing, then record new MAC state 790744Sgs150176 */ 791744Sgs150176 mutex_enter(rgep->genlock); 7926764Smx205022 if (rgep->suspended) { 7936764Smx205022 ASSERT(rgep->rge_mac_state == RGE_MAC_STOPPED); 7946764Smx205022 mutex_exit(rgep->genlock); 7956764Smx205022 return; 7966764Smx205022 } 797744Sgs150176 rge_stop(rgep); 798744Sgs150176 /* 799744Sgs150176 * Wait for posted buffer to be freed... 800744Sgs150176 */ 801744Sgs150176 if (!rgep->rx_bcopy) { 802744Sgs150176 for (i = 0; i < RXBUFF_FREE_LOOP; i++) { 803744Sgs150176 if (rgep->rx_free == RGE_BUF_SLOTS) 804744Sgs150176 break; 805744Sgs150176 drv_usecwait(1000); 806744Sgs150176 RGE_DEBUG(("rge_m_stop: waiting for rx buf free...")); 807744Sgs150176 } 808744Sgs150176 } 809744Sgs150176 rgep->rge_mac_state = RGE_MAC_STOPPED; 810744Sgs150176 RGE_DEBUG(("rge_m_stop($%p) done", arg)); 811744Sgs150176 mutex_exit(rgep->genlock); 812744Sgs150176 } 813744Sgs150176 814744Sgs150176 /* 815744Sgs150176 * rge_m_start() -- start transmitting/receiving 816744Sgs150176 */ 817744Sgs150176 static int 818744Sgs150176 rge_m_start(void *arg) 819744Sgs150176 { 820744Sgs150176 rge_t *rgep = arg; /* private device info */ 821744Sgs150176 822744Sgs150176 mutex_enter(rgep->genlock); 8236764Smx205022 if (rgep->suspended) { 8246764Smx205022 mutex_exit(rgep->genlock); 8256764Smx205022 return (DDI_FAILURE); 8266764Smx205022 } 827744Sgs150176 /* 828744Sgs150176 * Clear hw/sw statistics 829744Sgs150176 */ 830744Sgs150176 DMA_ZERO(rgep->dma_area_stats); 831744Sgs150176 bzero(&rgep->stats, sizeof (rge_stats_t)); 832744Sgs150176 833744Sgs150176 /* 834744Sgs150176 * Start processing and record new MAC state 835744Sgs150176 */ 836744Sgs150176 rge_reset(rgep); 837744Sgs150176 rge_start(rgep); 838744Sgs150176 rgep->rge_mac_state = RGE_MAC_STARTED; 839744Sgs150176 RGE_DEBUG(("rge_m_start($%p) done", arg)); 840744Sgs150176 841744Sgs150176 mutex_exit(rgep->genlock); 842744Sgs150176 843744Sgs150176 return (0); 844744Sgs150176 } 845744Sgs150176 846744Sgs150176 /* 847744Sgs150176 * rge_m_unicst_set() -- set the physical network address 848744Sgs150176 */ 849744Sgs150176 static int 850744Sgs150176 rge_m_unicst(void *arg, const uint8_t *macaddr) 851744Sgs150176 { 852744Sgs150176 rge_t *rgep = arg; /* private device info */ 853744Sgs150176 854744Sgs150176 /* 855744Sgs150176 * Remember the new current address in the driver state 856744Sgs150176 * Sync the chip's idea of the address too ... 857744Sgs150176 */ 858744Sgs150176 mutex_enter(rgep->genlock); 859744Sgs150176 bcopy(macaddr, rgep->netaddr, ETHERADDRL); 8606764Smx205022 8616764Smx205022 if (rgep->suspended) { 8626764Smx205022 mutex_exit(rgep->genlock); 8636764Smx205022 return (DDI_SUCCESS); 8646764Smx205022 } 8656764Smx205022 866744Sgs150176 rge_chip_sync(rgep, RGE_SET_MAC); 867744Sgs150176 mutex_exit(rgep->genlock); 868744Sgs150176 869744Sgs150176 return (0); 870744Sgs150176 } 871744Sgs150176 872744Sgs150176 /* 873744Sgs150176 * Compute the index of the required bit in the multicast hash map. 874744Sgs150176 * This must mirror the way the hardware actually does it! 875744Sgs150176 */ 876744Sgs150176 static uint32_t 877744Sgs150176 rge_hash_index(const uint8_t *mca) 878744Sgs150176 { 8792544Sgs150176 uint32_t crc = (uint32_t)RGE_HASH_CRC; 880744Sgs150176 uint32_t const POLY = RGE_HASH_POLY; 881744Sgs150176 uint32_t msb; 882744Sgs150176 int bytes; 883744Sgs150176 uchar_t currentbyte; 884744Sgs150176 uint32_t index; 885744Sgs150176 int bit; 886744Sgs150176 887744Sgs150176 for (bytes = 0; bytes < ETHERADDRL; bytes++) { 888744Sgs150176 currentbyte = mca[bytes]; 889744Sgs150176 for (bit = 0; bit < 8; bit++) { 890744Sgs150176 msb = crc >> 31; 891744Sgs150176 crc <<= 1; 8922544Sgs150176 if (msb ^ (currentbyte & 1)) 893744Sgs150176 crc ^= POLY; 894744Sgs150176 currentbyte >>= 1; 895744Sgs150176 } 896744Sgs150176 } 897744Sgs150176 index = crc >> 26; 8982544Sgs150176 /* the index value is between 0 and 63(0x3f) */ 899744Sgs150176 900744Sgs150176 return (index); 901744Sgs150176 } 902744Sgs150176 903744Sgs150176 /* 904744Sgs150176 * rge_m_multicst_add() -- enable/disable a multicast address 905744Sgs150176 */ 906744Sgs150176 static int 907744Sgs150176 rge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 908744Sgs150176 { 909744Sgs150176 rge_t *rgep = arg; /* private device info */ 910744Sgs150176 struct ether_addr *addr; 911744Sgs150176 uint32_t index; 9122544Sgs150176 uint32_t reg; 9132544Sgs150176 uint8_t *hashp; 914744Sgs150176 915744Sgs150176 mutex_enter(rgep->genlock); 916744Sgs150176 hashp = rgep->mcast_hash; 917744Sgs150176 addr = (struct ether_addr *)mca; 9182544Sgs150176 /* 9192544Sgs150176 * Calculate the Multicast address hash index value 9202544Sgs150176 * Normally, the position of MAR0-MAR7 is 9212544Sgs150176 * MAR0: offset 0x08, ..., MAR7: offset 0x0F. 9222544Sgs150176 * 9232544Sgs150176 * For pcie chipset, the position of MAR0-MAR7 is 9242544Sgs150176 * different from others: 9252544Sgs150176 * MAR0: offset 0x0F, ..., MAR7: offset 0x08. 9262544Sgs150176 */ 927744Sgs150176 index = rge_hash_index(addr->ether_addr_octet); 9282544Sgs150176 if (rgep->chipid.is_pcie) 9292544Sgs150176 reg = (~(index / RGE_MCAST_NUM)) & 0x7; 9302544Sgs150176 else 9312544Sgs150176 reg = index / RGE_MCAST_NUM; 932744Sgs150176 933744Sgs150176 if (add) { 934744Sgs150176 if (rgep->mcast_refs[index]++) { 935744Sgs150176 mutex_exit(rgep->genlock); 936744Sgs150176 return (0); 937744Sgs150176 } 9382544Sgs150176 hashp[reg] |= 1 << (index % RGE_MCAST_NUM); 939744Sgs150176 } else { 940744Sgs150176 if (--rgep->mcast_refs[index]) { 941744Sgs150176 mutex_exit(rgep->genlock); 942744Sgs150176 return (0); 943744Sgs150176 } 9442544Sgs150176 hashp[reg] &= ~ (1 << (index % RGE_MCAST_NUM)); 945744Sgs150176 } 946744Sgs150176 9476764Smx205022 if (rgep->suspended) { 9486764Smx205022 mutex_exit(rgep->genlock); 9496764Smx205022 return (DDI_SUCCESS); 9506764Smx205022 } 9516764Smx205022 952744Sgs150176 /* 953744Sgs150176 * Set multicast register 954744Sgs150176 */ 955744Sgs150176 rge_chip_sync(rgep, RGE_SET_MUL); 956744Sgs150176 957744Sgs150176 mutex_exit(rgep->genlock); 958744Sgs150176 return (0); 959744Sgs150176 } 960744Sgs150176 961744Sgs150176 /* 962744Sgs150176 * rge_m_promisc() -- set or reset promiscuous mode on the board 963744Sgs150176 * 964744Sgs150176 * Program the hardware to enable/disable promiscuous and/or 965744Sgs150176 * receive-all-multicast modes. 966744Sgs150176 */ 967744Sgs150176 static int 968744Sgs150176 rge_m_promisc(void *arg, boolean_t on) 969744Sgs150176 { 970744Sgs150176 rge_t *rgep = arg; 971744Sgs150176 972744Sgs150176 /* 973744Sgs150176 * Store MAC layer specified mode and pass to chip layer to update h/w 974744Sgs150176 */ 975744Sgs150176 mutex_enter(rgep->genlock); 976744Sgs150176 977744Sgs150176 if (rgep->promisc == on) { 978744Sgs150176 mutex_exit(rgep->genlock); 979744Sgs150176 return (0); 980744Sgs150176 } 981744Sgs150176 rgep->promisc = on; 9826764Smx205022 9836764Smx205022 if (rgep->suspended) { 9846764Smx205022 mutex_exit(rgep->genlock); 9856764Smx205022 return (DDI_SUCCESS); 9866764Smx205022 } 9876764Smx205022 988744Sgs150176 rge_chip_sync(rgep, RGE_SET_PROMISC); 989744Sgs150176 RGE_DEBUG(("rge_m_promisc_set($%p) done", arg)); 990744Sgs150176 mutex_exit(rgep->genlock); 991744Sgs150176 return (0); 992744Sgs150176 } 993744Sgs150176 994744Sgs150176 /* 995744Sgs150176 * Loopback ioctl code 996744Sgs150176 */ 997744Sgs150176 998744Sgs150176 static lb_property_t loopmodes[] = { 999744Sgs150176 { normal, "normal", RGE_LOOP_NONE }, 1000744Sgs150176 { internal, "PHY", RGE_LOOP_INTERNAL_PHY }, 1001744Sgs150176 { internal, "MAC", RGE_LOOP_INTERNAL_MAC } 1002744Sgs150176 }; 1003744Sgs150176 1004744Sgs150176 static enum ioc_reply 1005744Sgs150176 rge_set_loop_mode(rge_t *rgep, uint32_t mode) 1006744Sgs150176 { 1007744Sgs150176 /* 1008744Sgs150176 * If the mode isn't being changed, there's nothing to do ... 1009744Sgs150176 */ 1010744Sgs150176 if (mode == rgep->param_loop_mode) 1011744Sgs150176 return (IOC_ACK); 1012744Sgs150176 1013744Sgs150176 /* 1014744Sgs150176 * Validate the requested mode and prepare a suitable message 1015744Sgs150176 * to explain the link down/up cycle that the change will 1016744Sgs150176 * probably induce ... 1017744Sgs150176 */ 1018744Sgs150176 switch (mode) { 1019744Sgs150176 default: 1020744Sgs150176 return (IOC_INVAL); 1021744Sgs150176 1022744Sgs150176 case RGE_LOOP_NONE: 1023744Sgs150176 case RGE_LOOP_INTERNAL_PHY: 1024744Sgs150176 case RGE_LOOP_INTERNAL_MAC: 1025744Sgs150176 break; 1026744Sgs150176 } 1027744Sgs150176 1028744Sgs150176 /* 1029744Sgs150176 * All OK; tell the caller to reprogram 1030744Sgs150176 * the PHY and/or MAC for the new mode ... 1031744Sgs150176 */ 1032744Sgs150176 rgep->param_loop_mode = mode; 1033744Sgs150176 return (IOC_RESTART_ACK); 1034744Sgs150176 } 1035744Sgs150176 1036744Sgs150176 static enum ioc_reply 1037744Sgs150176 rge_loop_ioctl(rge_t *rgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp) 1038744Sgs150176 { 1039744Sgs150176 lb_info_sz_t *lbsp; 1040744Sgs150176 lb_property_t *lbpp; 1041744Sgs150176 uint32_t *lbmp; 1042744Sgs150176 int cmd; 1043744Sgs150176 1044744Sgs150176 _NOTE(ARGUNUSED(wq)) 1045744Sgs150176 1046744Sgs150176 /* 1047744Sgs150176 * Validate format of ioctl 1048744Sgs150176 */ 1049744Sgs150176 if (mp->b_cont == NULL) 1050744Sgs150176 return (IOC_INVAL); 1051744Sgs150176 1052744Sgs150176 cmd = iocp->ioc_cmd; 1053744Sgs150176 switch (cmd) { 1054744Sgs150176 default: 1055744Sgs150176 /* NOTREACHED */ 1056744Sgs150176 rge_error(rgep, "rge_loop_ioctl: invalid cmd 0x%x", cmd); 1057744Sgs150176 return (IOC_INVAL); 1058744Sgs150176 1059744Sgs150176 case LB_GET_INFO_SIZE: 1060744Sgs150176 if (iocp->ioc_count != sizeof (lb_info_sz_t)) 1061744Sgs150176 return (IOC_INVAL); 1062744Sgs150176 lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr; 1063744Sgs150176 *lbsp = sizeof (loopmodes); 1064744Sgs150176 return (IOC_REPLY); 1065744Sgs150176 1066744Sgs150176 case LB_GET_INFO: 1067744Sgs150176 if (iocp->ioc_count != sizeof (loopmodes)) 1068744Sgs150176 return (IOC_INVAL); 1069744Sgs150176 lbpp = (lb_property_t *)mp->b_cont->b_rptr; 1070744Sgs150176 bcopy(loopmodes, lbpp, sizeof (loopmodes)); 1071744Sgs150176 return (IOC_REPLY); 1072744Sgs150176 1073744Sgs150176 case LB_GET_MODE: 1074744Sgs150176 if (iocp->ioc_count != sizeof (uint32_t)) 1075744Sgs150176 return (IOC_INVAL); 1076744Sgs150176 lbmp = (uint32_t *)mp->b_cont->b_rptr; 1077744Sgs150176 *lbmp = rgep->param_loop_mode; 1078744Sgs150176 return (IOC_REPLY); 1079744Sgs150176 1080744Sgs150176 case LB_SET_MODE: 1081744Sgs150176 if (iocp->ioc_count != sizeof (uint32_t)) 1082744Sgs150176 return (IOC_INVAL); 1083744Sgs150176 lbmp = (uint32_t *)mp->b_cont->b_rptr; 1084744Sgs150176 return (rge_set_loop_mode(rgep, *lbmp)); 1085744Sgs150176 } 1086744Sgs150176 } 1087744Sgs150176 1088744Sgs150176 /* 1089744Sgs150176 * Specific rge IOCTLs, the MAC layer handles the generic ones. 1090744Sgs150176 */ 1091744Sgs150176 static void 1092744Sgs150176 rge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 1093744Sgs150176 { 1094744Sgs150176 rge_t *rgep = arg; 1095744Sgs150176 struct iocblk *iocp; 1096744Sgs150176 enum ioc_reply status; 1097744Sgs150176 boolean_t need_privilege; 1098744Sgs150176 int err; 1099744Sgs150176 int cmd; 1100744Sgs150176 1101744Sgs150176 /* 11026764Smx205022 * If suspended, we might actually be able to do some of 11036764Smx205022 * these ioctls, but it is harder to make sure they occur 11046764Smx205022 * without actually putting the hardware in an undesireable 11056764Smx205022 * state. So just NAK it. 11066764Smx205022 */ 11076764Smx205022 mutex_enter(rgep->genlock); 11086764Smx205022 if (rgep->suspended) { 11096764Smx205022 miocnak(wq, mp, 0, EINVAL); 11106764Smx205022 mutex_exit(rgep->genlock); 11116764Smx205022 return; 11126764Smx205022 } 11136764Smx205022 mutex_exit(rgep->genlock); 11146764Smx205022 11156764Smx205022 /* 1116744Sgs150176 * Validate the command before bothering with the mutex ... 1117744Sgs150176 */ 1118744Sgs150176 iocp = (struct iocblk *)mp->b_rptr; 1119744Sgs150176 iocp->ioc_error = 0; 1120744Sgs150176 need_privilege = B_TRUE; 1121744Sgs150176 cmd = iocp->ioc_cmd; 1122744Sgs150176 switch (cmd) { 1123744Sgs150176 default: 1124744Sgs150176 miocnak(wq, mp, 0, EINVAL); 1125744Sgs150176 return; 1126744Sgs150176 1127744Sgs150176 case RGE_MII_READ: 1128744Sgs150176 case RGE_MII_WRITE: 1129744Sgs150176 case RGE_DIAG: 1130744Sgs150176 case RGE_PEEK: 1131744Sgs150176 case RGE_POKE: 1132744Sgs150176 case RGE_PHY_RESET: 1133744Sgs150176 case RGE_SOFT_RESET: 1134744Sgs150176 case RGE_HARD_RESET: 1135744Sgs150176 break; 1136744Sgs150176 1137744Sgs150176 case LB_GET_INFO_SIZE: 1138744Sgs150176 case LB_GET_INFO: 1139744Sgs150176 case LB_GET_MODE: 1140744Sgs150176 need_privilege = B_FALSE; 1141744Sgs150176 /* FALLTHRU */ 1142744Sgs150176 case LB_SET_MODE: 1143744Sgs150176 break; 1144744Sgs150176 1145744Sgs150176 case ND_GET: 1146744Sgs150176 need_privilege = B_FALSE; 1147744Sgs150176 /* FALLTHRU */ 1148744Sgs150176 case ND_SET: 1149744Sgs150176 break; 1150744Sgs150176 } 1151744Sgs150176 1152744Sgs150176 if (need_privilege) { 1153744Sgs150176 /* 11542544Sgs150176 * Check for specific net_config privilege 1155744Sgs150176 */ 11562544Sgs150176 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 1157744Sgs150176 if (err != 0) { 1158744Sgs150176 miocnak(wq, mp, 0, err); 1159744Sgs150176 return; 1160744Sgs150176 } 1161744Sgs150176 } 1162744Sgs150176 1163744Sgs150176 mutex_enter(rgep->genlock); 1164744Sgs150176 1165744Sgs150176 switch (cmd) { 1166744Sgs150176 default: 1167744Sgs150176 _NOTE(NOTREACHED) 1168744Sgs150176 status = IOC_INVAL; 1169744Sgs150176 break; 1170744Sgs150176 1171744Sgs150176 case RGE_MII_READ: 1172744Sgs150176 case RGE_MII_WRITE: 1173744Sgs150176 case RGE_DIAG: 1174744Sgs150176 case RGE_PEEK: 1175744Sgs150176 case RGE_POKE: 1176744Sgs150176 case RGE_PHY_RESET: 1177744Sgs150176 case RGE_SOFT_RESET: 1178744Sgs150176 case RGE_HARD_RESET: 1179744Sgs150176 status = rge_chip_ioctl(rgep, wq, mp, iocp); 1180744Sgs150176 break; 1181744Sgs150176 1182744Sgs150176 case LB_GET_INFO_SIZE: 1183744Sgs150176 case LB_GET_INFO: 1184744Sgs150176 case LB_GET_MODE: 1185744Sgs150176 case LB_SET_MODE: 1186744Sgs150176 status = rge_loop_ioctl(rgep, wq, mp, iocp); 1187744Sgs150176 break; 1188744Sgs150176 1189744Sgs150176 case ND_GET: 1190744Sgs150176 case ND_SET: 1191744Sgs150176 status = rge_nd_ioctl(rgep, wq, mp, iocp); 1192744Sgs150176 break; 1193744Sgs150176 } 1194744Sgs150176 1195744Sgs150176 /* 1196744Sgs150176 * Do we need to reprogram the PHY and/or the MAC? 1197744Sgs150176 * Do it now, while we still have the mutex. 1198744Sgs150176 * 1199744Sgs150176 * Note: update the PHY first, 'cos it controls the 1200744Sgs150176 * speed/duplex parameters that the MAC code uses. 1201744Sgs150176 */ 1202744Sgs150176 switch (status) { 1203744Sgs150176 case IOC_RESTART_REPLY: 1204744Sgs150176 case IOC_RESTART_ACK: 1205744Sgs150176 rge_phy_update(rgep); 1206744Sgs150176 break; 1207744Sgs150176 } 1208744Sgs150176 1209744Sgs150176 mutex_exit(rgep->genlock); 1210744Sgs150176 1211744Sgs150176 /* 1212744Sgs150176 * Finally, decide how to reply 1213744Sgs150176 */ 1214744Sgs150176 switch (status) { 1215744Sgs150176 default: 1216744Sgs150176 case IOC_INVAL: 1217744Sgs150176 /* 1218744Sgs150176 * Error, reply with a NAK and EINVAL or the specified error 1219744Sgs150176 */ 1220744Sgs150176 miocnak(wq, mp, 0, iocp->ioc_error == 0 ? 12215107Seota EINVAL : iocp->ioc_error); 1222744Sgs150176 break; 1223744Sgs150176 1224744Sgs150176 case IOC_DONE: 1225744Sgs150176 /* 1226744Sgs150176 * OK, reply already sent 1227744Sgs150176 */ 1228744Sgs150176 break; 1229744Sgs150176 1230744Sgs150176 case IOC_RESTART_ACK: 1231744Sgs150176 case IOC_ACK: 1232744Sgs150176 /* 1233744Sgs150176 * OK, reply with an ACK 1234744Sgs150176 */ 1235744Sgs150176 miocack(wq, mp, 0, 0); 1236744Sgs150176 break; 1237744Sgs150176 1238744Sgs150176 case IOC_RESTART_REPLY: 1239744Sgs150176 case IOC_REPLY: 1240744Sgs150176 /* 1241744Sgs150176 * OK, send prepared reply as ACK or NAK 1242744Sgs150176 */ 1243744Sgs150176 mp->b_datap->db_type = iocp->ioc_error == 0 ? 12445107Seota M_IOCACK : M_IOCNAK; 1245744Sgs150176 qreply(wq, mp); 1246744Sgs150176 break; 1247744Sgs150176 } 1248744Sgs150176 } 1249744Sgs150176 12502311Sseb /* ARGSUSED */ 12512311Sseb static boolean_t 12522311Sseb rge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 12532311Sseb { 12547516SYong.Tan@Sun.COM rge_t *rgep = arg; 12557516SYong.Tan@Sun.COM 12562311Sseb switch (cap) { 12572311Sseb case MAC_CAPAB_HCKSUM: { 12582311Sseb uint32_t *hcksum_txflags = cap_data; 12597516SYong.Tan@Sun.COM switch (rgep->chipid.mac_ver) { 12607516SYong.Tan@Sun.COM case MAC_VER_8169: 12617516SYong.Tan@Sun.COM case MAC_VER_8169S_D: 12627516SYong.Tan@Sun.COM case MAC_VER_8169S_E: 12637516SYong.Tan@Sun.COM case MAC_VER_8169SB: 12647516SYong.Tan@Sun.COM case MAC_VER_8169SC: 12657516SYong.Tan@Sun.COM case MAC_VER_8168: 12667516SYong.Tan@Sun.COM case MAC_VER_8168B_B: 12677516SYong.Tan@Sun.COM case MAC_VER_8168B_C: 12687516SYong.Tan@Sun.COM case MAC_VER_8101E: 12697516SYong.Tan@Sun.COM *hcksum_txflags = HCKSUM_INET_FULL_V4 | 12707516SYong.Tan@Sun.COM HCKSUM_IPHDRCKSUM; 12717516SYong.Tan@Sun.COM break; 127210814SKHF04453@nifty.ne.jp case MAC_VER_8168C: 12737516SYong.Tan@Sun.COM case MAC_VER_8101E_B: 12747516SYong.Tan@Sun.COM case MAC_VER_8101E_C: 12757516SYong.Tan@Sun.COM default: 12767516SYong.Tan@Sun.COM *hcksum_txflags = 0; 12777516SYong.Tan@Sun.COM break; 12787516SYong.Tan@Sun.COM } 12792311Sseb break; 12802311Sseb } 12812311Sseb default: 12822311Sseb return (B_FALSE); 12832311Sseb } 12842311Sseb return (B_TRUE); 12852311Sseb } 12862311Sseb 1287744Sgs150176 /* 12882544Sgs150176 * ============ Init MSI/Fixed Interrupt routines ============== 12892544Sgs150176 */ 12902544Sgs150176 12912544Sgs150176 /* 12922544Sgs150176 * rge_add_intrs: 12932544Sgs150176 * 12942544Sgs150176 * Register FIXED or MSI interrupts. 12952544Sgs150176 */ 12962544Sgs150176 static int 12972544Sgs150176 rge_add_intrs(rge_t *rgep, int intr_type) 12982544Sgs150176 { 12992544Sgs150176 dev_info_t *dip = rgep->devinfo; 13002544Sgs150176 int avail; 13012544Sgs150176 int actual; 13022544Sgs150176 int intr_size; 13032544Sgs150176 int count; 13042544Sgs150176 int i, j; 13052544Sgs150176 int ret; 13062544Sgs150176 13072544Sgs150176 /* Get number of interrupts */ 13082544Sgs150176 ret = ddi_intr_get_nintrs(dip, intr_type, &count); 13092544Sgs150176 if ((ret != DDI_SUCCESS) || (count == 0)) { 13102544Sgs150176 rge_error(rgep, "ddi_intr_get_nintrs() failure, ret: %d, " 13112544Sgs150176 "count: %d", ret, count); 13122544Sgs150176 return (DDI_FAILURE); 13132544Sgs150176 } 13142544Sgs150176 13152544Sgs150176 /* Get number of available interrupts */ 13162544Sgs150176 ret = ddi_intr_get_navail(dip, intr_type, &avail); 13172544Sgs150176 if ((ret != DDI_SUCCESS) || (avail == 0)) { 13182544Sgs150176 rge_error(rgep, "ddi_intr_get_navail() failure, " 13192544Sgs150176 "ret: %d, avail: %d\n", ret, avail); 13202544Sgs150176 return (DDI_FAILURE); 13212544Sgs150176 } 13222544Sgs150176 13232544Sgs150176 /* Allocate an array of interrupt handles */ 13242544Sgs150176 intr_size = count * sizeof (ddi_intr_handle_t); 13252544Sgs150176 rgep->htable = kmem_alloc(intr_size, KM_SLEEP); 13262544Sgs150176 rgep->intr_rqst = count; 13272544Sgs150176 13282544Sgs150176 /* Call ddi_intr_alloc() */ 13292544Sgs150176 ret = ddi_intr_alloc(dip, rgep->htable, intr_type, 0, 13302544Sgs150176 count, &actual, DDI_INTR_ALLOC_NORMAL); 13312544Sgs150176 if (ret != DDI_SUCCESS || actual == 0) { 13322544Sgs150176 rge_error(rgep, "ddi_intr_alloc() failed %d\n", ret); 13332544Sgs150176 kmem_free(rgep->htable, intr_size); 13342544Sgs150176 return (DDI_FAILURE); 13352544Sgs150176 } 13362544Sgs150176 if (actual < count) { 13372544Sgs150176 rge_log(rgep, "ddi_intr_alloc() Requested: %d, Received: %d\n", 13382544Sgs150176 count, actual); 13392544Sgs150176 } 13402544Sgs150176 rgep->intr_cnt = actual; 13412544Sgs150176 13422544Sgs150176 /* 13432544Sgs150176 * Get priority for first msi, assume remaining are all the same 13442544Sgs150176 */ 13452544Sgs150176 if ((ret = ddi_intr_get_pri(rgep->htable[0], &rgep->intr_pri)) != 13462544Sgs150176 DDI_SUCCESS) { 13472544Sgs150176 rge_error(rgep, "ddi_intr_get_pri() failed %d\n", ret); 13482544Sgs150176 /* Free already allocated intr */ 13492544Sgs150176 for (i = 0; i < actual; i++) { 13502544Sgs150176 (void) ddi_intr_free(rgep->htable[i]); 13512544Sgs150176 } 13522544Sgs150176 kmem_free(rgep->htable, intr_size); 13532544Sgs150176 return (DDI_FAILURE); 13542544Sgs150176 } 13552544Sgs150176 13562544Sgs150176 /* Test for high level mutex */ 13572544Sgs150176 if (rgep->intr_pri >= ddi_intr_get_hilevel_pri()) { 13582544Sgs150176 rge_error(rgep, "rge_add_intrs:" 13592544Sgs150176 "Hi level interrupt not supported"); 13602544Sgs150176 for (i = 0; i < actual; i++) 13612544Sgs150176 (void) ddi_intr_free(rgep->htable[i]); 13622544Sgs150176 kmem_free(rgep->htable, intr_size); 13632544Sgs150176 return (DDI_FAILURE); 13642544Sgs150176 } 13652544Sgs150176 13662544Sgs150176 /* Call ddi_intr_add_handler() */ 13672544Sgs150176 for (i = 0; i < actual; i++) { 13682544Sgs150176 if ((ret = ddi_intr_add_handler(rgep->htable[i], rge_intr, 13692544Sgs150176 (caddr_t)rgep, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) { 13702544Sgs150176 rge_error(rgep, "ddi_intr_add_handler() " 13712544Sgs150176 "failed %d\n", ret); 13722544Sgs150176 /* Remove already added intr */ 13732544Sgs150176 for (j = 0; j < i; j++) 13742544Sgs150176 (void) ddi_intr_remove_handler(rgep->htable[j]); 13752544Sgs150176 /* Free already allocated intr */ 13762544Sgs150176 for (i = 0; i < actual; i++) { 13772544Sgs150176 (void) ddi_intr_free(rgep->htable[i]); 13782544Sgs150176 } 13792544Sgs150176 kmem_free(rgep->htable, intr_size); 13802544Sgs150176 return (DDI_FAILURE); 13812544Sgs150176 } 13822544Sgs150176 } 13832544Sgs150176 13842544Sgs150176 if ((ret = ddi_intr_get_cap(rgep->htable[0], &rgep->intr_cap)) 13852544Sgs150176 != DDI_SUCCESS) { 13862544Sgs150176 rge_error(rgep, "ddi_intr_get_cap() failed %d\n", ret); 13872544Sgs150176 for (i = 0; i < actual; i++) { 13882544Sgs150176 (void) ddi_intr_remove_handler(rgep->htable[i]); 13892544Sgs150176 (void) ddi_intr_free(rgep->htable[i]); 13902544Sgs150176 } 13912544Sgs150176 kmem_free(rgep->htable, intr_size); 13922544Sgs150176 return (DDI_FAILURE); 13932544Sgs150176 } 13942544Sgs150176 13952544Sgs150176 return (DDI_SUCCESS); 13962544Sgs150176 } 13972544Sgs150176 13982544Sgs150176 /* 13992544Sgs150176 * rge_rem_intrs: 14002544Sgs150176 * 14012544Sgs150176 * Unregister FIXED or MSI interrupts 14022544Sgs150176 */ 14032544Sgs150176 static void 14042544Sgs150176 rge_rem_intrs(rge_t *rgep) 14052544Sgs150176 { 14062544Sgs150176 int i; 14072544Sgs150176 14082544Sgs150176 /* Disable all interrupts */ 14092544Sgs150176 if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) { 14102544Sgs150176 /* Call ddi_intr_block_disable() */ 14112544Sgs150176 (void) ddi_intr_block_disable(rgep->htable, rgep->intr_cnt); 14122544Sgs150176 } else { 14132544Sgs150176 for (i = 0; i < rgep->intr_cnt; i++) { 14142544Sgs150176 (void) ddi_intr_disable(rgep->htable[i]); 14152544Sgs150176 } 14162544Sgs150176 } 14172544Sgs150176 14182544Sgs150176 /* Call ddi_intr_remove_handler() */ 14192544Sgs150176 for (i = 0; i < rgep->intr_cnt; i++) { 14202544Sgs150176 (void) ddi_intr_remove_handler(rgep->htable[i]); 14212544Sgs150176 (void) ddi_intr_free(rgep->htable[i]); 14222544Sgs150176 } 14232544Sgs150176 14242544Sgs150176 kmem_free(rgep->htable, rgep->intr_rqst * sizeof (ddi_intr_handle_t)); 14252544Sgs150176 } 14262544Sgs150176 14272544Sgs150176 /* 1428744Sgs150176 * ========== Per-instance setup/teardown code ========== 1429744Sgs150176 */ 1430744Sgs150176 1431744Sgs150176 #undef RGE_DBG 1432744Sgs150176 #define RGE_DBG RGE_DBG_INIT /* debug flag for this code */ 1433744Sgs150176 1434744Sgs150176 static void 1435744Sgs150176 rge_unattach(rge_t *rgep) 1436744Sgs150176 { 1437744Sgs150176 /* 1438744Sgs150176 * Flag that no more activity may be initiated 1439744Sgs150176 */ 1440744Sgs150176 rgep->progress &= ~PROGRESS_READY; 1441744Sgs150176 rgep->rge_mac_state = RGE_MAC_UNATTACH; 1442744Sgs150176 1443744Sgs150176 /* 1444744Sgs150176 * Quiesce the PHY and MAC (leave it reset but still powered). 1445744Sgs150176 * Clean up and free all RGE data structures 1446744Sgs150176 */ 14475107Seota if (rgep->periodic_id != NULL) { 14485107Seota ddi_periodic_delete(rgep->periodic_id); 14495107Seota rgep->periodic_id = NULL; 1450744Sgs150176 } 1451744Sgs150176 1452744Sgs150176 if (rgep->progress & PROGRESS_KSTATS) 1453744Sgs150176 rge_fini_kstats(rgep); 1454744Sgs150176 1455744Sgs150176 if (rgep->progress & PROGRESS_PHY) 1456744Sgs150176 (void) rge_phy_reset(rgep); 1457744Sgs150176 14582544Sgs150176 if (rgep->progress & PROGRESS_INIT) { 1459744Sgs150176 mutex_enter(rgep->genlock); 1460744Sgs150176 (void) rge_chip_reset(rgep); 1461744Sgs150176 mutex_exit(rgep->genlock); 1462744Sgs150176 rge_fini_rings(rgep); 14632544Sgs150176 } 14642544Sgs150176 14652544Sgs150176 if (rgep->progress & PROGRESS_INTR) { 14662544Sgs150176 rge_rem_intrs(rgep); 1467744Sgs150176 mutex_destroy(rgep->rc_lock); 1468744Sgs150176 mutex_destroy(rgep->rx_lock); 1469744Sgs150176 mutex_destroy(rgep->tc_lock); 1470744Sgs150176 mutex_destroy(rgep->tx_lock); 1471744Sgs150176 rw_destroy(rgep->errlock); 1472744Sgs150176 mutex_destroy(rgep->genlock); 1473744Sgs150176 } 1474744Sgs150176 1475744Sgs150176 if (rgep->progress & PROGRESS_FACTOTUM) 14762544Sgs150176 (void) ddi_intr_remove_softint(rgep->factotum_hdl); 1477744Sgs150176 1478744Sgs150176 if (rgep->progress & PROGRESS_RESCHED) 14792544Sgs150176 (void) ddi_intr_remove_softint(rgep->resched_hdl); 1480744Sgs150176 1481744Sgs150176 if (rgep->progress & PROGRESS_NDD) 1482744Sgs150176 rge_nd_cleanup(rgep); 1483744Sgs150176 14845735Smx205022 rge_free_bufs(rgep); 14855735Smx205022 1486744Sgs150176 if (rgep->progress & PROGRESS_REGS) 1487744Sgs150176 ddi_regs_map_free(&rgep->io_handle); 1488744Sgs150176 1489744Sgs150176 if (rgep->progress & PROGRESS_CFG) 1490744Sgs150176 pci_config_teardown(&rgep->cfg_handle); 1491744Sgs150176 1492744Sgs150176 ddi_remove_minor_node(rgep->devinfo, NULL); 1493744Sgs150176 kmem_free(rgep, sizeof (*rgep)); 1494744Sgs150176 } 1495744Sgs150176 1496744Sgs150176 static int 1497744Sgs150176 rge_resume(dev_info_t *devinfo) 1498744Sgs150176 { 1499744Sgs150176 rge_t *rgep; /* Our private data */ 1500744Sgs150176 chip_id_t *cidp; 1501744Sgs150176 chip_id_t chipid; 1502744Sgs150176 1503744Sgs150176 rgep = ddi_get_driver_private(devinfo); 15046764Smx205022 15056764Smx205022 /* 15066764Smx205022 * If there are state inconsistancies, this is bad. Returning 15076764Smx205022 * DDI_FAILURE here will eventually cause the machine to panic, 15086764Smx205022 * so it is best done here so that there is a possibility of 15096764Smx205022 * debugging the problem. 15106764Smx205022 */ 1511744Sgs150176 if (rgep == NULL) 15126764Smx205022 cmn_err(CE_PANIC, 15136764Smx205022 "rge: ngep returned from ddi_get_driver_private was NULL"); 1514744Sgs150176 1515744Sgs150176 /* 1516744Sgs150176 * Refuse to resume if the data structures aren't consistent 1517744Sgs150176 */ 1518744Sgs150176 if (rgep->devinfo != devinfo) 15196764Smx205022 cmn_err(CE_PANIC, 15206764Smx205022 "rge: passed devinfo not the same as saved devinfo"); 1521744Sgs150176 1522744Sgs150176 /* 1523744Sgs150176 * Read chip ID & set up config space command register(s) 1524744Sgs150176 * Refuse to resume if the chip has changed its identity! 1525744Sgs150176 */ 1526744Sgs150176 cidp = &rgep->chipid; 1527744Sgs150176 rge_chip_cfg_init(rgep, &chipid); 1528744Sgs150176 if (chipid.vendor != cidp->vendor) 1529744Sgs150176 return (DDI_FAILURE); 1530744Sgs150176 if (chipid.device != cidp->device) 1531744Sgs150176 return (DDI_FAILURE); 1532744Sgs150176 if (chipid.revision != cidp->revision) 1533744Sgs150176 return (DDI_FAILURE); 1534744Sgs150176 15356764Smx205022 mutex_enter(rgep->genlock); 15366764Smx205022 15376764Smx205022 /* 15386764Smx205022 * Only in one case, this conditional branch can be executed: the port 15396764Smx205022 * hasn't been plumbed. 15406764Smx205022 */ 15416764Smx205022 if (rgep->suspended == B_FALSE) { 15426764Smx205022 mutex_exit(rgep->genlock); 15436764Smx205022 return (DDI_SUCCESS); 15446764Smx205022 } 15456764Smx205022 rgep->rge_mac_state = RGE_MAC_STARTED; 1546744Sgs150176 /* 1547744Sgs150176 * All OK, reinitialise h/w & kick off NEMO scheduling 1548744Sgs150176 */ 1549744Sgs150176 rge_restart(rgep); 15506764Smx205022 rgep->suspended = B_FALSE; 15516764Smx205022 1552744Sgs150176 mutex_exit(rgep->genlock); 15536764Smx205022 1554744Sgs150176 return (DDI_SUCCESS); 1555744Sgs150176 } 1556744Sgs150176 1557744Sgs150176 1558744Sgs150176 /* 1559744Sgs150176 * attach(9E) -- Attach a device to the system 1560744Sgs150176 * 1561744Sgs150176 * Called once for each board successfully probed. 1562744Sgs150176 */ 1563744Sgs150176 static int 1564744Sgs150176 rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 1565744Sgs150176 { 1566744Sgs150176 rge_t *rgep; /* Our private data */ 15672311Sseb mac_register_t *macp; 1568744Sgs150176 chip_id_t *cidp; 15692544Sgs150176 int intr_types; 1570744Sgs150176 caddr_t regs; 1571744Sgs150176 int instance; 15722544Sgs150176 int i; 1573744Sgs150176 int err; 1574744Sgs150176 1575744Sgs150176 /* 1576744Sgs150176 * we don't support high level interrupts in the driver 1577744Sgs150176 */ 1578744Sgs150176 if (ddi_intr_hilevel(devinfo, 0) != 0) { 1579744Sgs150176 cmn_err(CE_WARN, 1580744Sgs150176 "rge_attach -- unsupported high level interrupt"); 1581744Sgs150176 return (DDI_FAILURE); 1582744Sgs150176 } 1583744Sgs150176 1584744Sgs150176 instance = ddi_get_instance(devinfo); 1585744Sgs150176 RGE_GTRACE(("rge_attach($%p, %d) instance %d", 15865107Seota (void *)devinfo, cmd, instance)); 1587744Sgs150176 RGE_BRKPT(NULL, "rge_attach"); 1588744Sgs150176 1589744Sgs150176 switch (cmd) { 1590744Sgs150176 default: 1591744Sgs150176 return (DDI_FAILURE); 1592744Sgs150176 1593744Sgs150176 case DDI_RESUME: 1594744Sgs150176 return (rge_resume(devinfo)); 1595744Sgs150176 1596744Sgs150176 case DDI_ATTACH: 1597744Sgs150176 break; 1598744Sgs150176 } 1599744Sgs150176 1600744Sgs150176 rgep = kmem_zalloc(sizeof (*rgep), KM_SLEEP); 1601744Sgs150176 ddi_set_driver_private(devinfo, rgep); 1602744Sgs150176 rgep->devinfo = devinfo; 1603744Sgs150176 1604744Sgs150176 /* 1605744Sgs150176 * Initialize more fields in RGE private data 1606744Sgs150176 */ 16072544Sgs150176 rgep->rge_mac_state = RGE_MAC_ATTACH; 1608744Sgs150176 rgep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 16095107Seota DDI_PROP_DONTPASS, debug_propname, rge_debug); 16102544Sgs150176 rgep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 16115107Seota DDI_PROP_DONTPASS, mtu_propname, ETHERMTU); 16122544Sgs150176 rgep->msi_enable = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 16135107Seota DDI_PROP_DONTPASS, msi_propname, B_TRUE); 1614744Sgs150176 (void) snprintf(rgep->ifname, sizeof (rgep->ifname), "%s%d", 16155107Seota RGE_DRIVER_NAME, instance); 1616744Sgs150176 1617744Sgs150176 /* 1618744Sgs150176 * Map config space registers 1619744Sgs150176 * Read chip ID & set up config space command register(s) 1620744Sgs150176 * 1621744Sgs150176 * Note: this leaves the chip accessible by Memory Space 1622744Sgs150176 * accesses, but with interrupts and Bus Mastering off. 1623744Sgs150176 * This should ensure that nothing untoward will happen 1624744Sgs150176 * if it has been left active by the (net-)bootloader. 1625744Sgs150176 * We'll re-enable Bus Mastering once we've reset the chip, 1626744Sgs150176 * and allow interrupts only when everything else is set up. 1627744Sgs150176 */ 1628744Sgs150176 err = pci_config_setup(devinfo, &rgep->cfg_handle); 1629744Sgs150176 if (err != DDI_SUCCESS) { 1630744Sgs150176 rge_problem(rgep, "pci_config_setup() failed"); 1631744Sgs150176 goto attach_fail; 1632744Sgs150176 } 1633744Sgs150176 rgep->progress |= PROGRESS_CFG; 1634744Sgs150176 cidp = &rgep->chipid; 1635744Sgs150176 bzero(cidp, sizeof (*cidp)); 1636744Sgs150176 rge_chip_cfg_init(rgep, cidp); 1637744Sgs150176 1638744Sgs150176 /* 1639744Sgs150176 * Map operating registers 1640744Sgs150176 */ 1641*11365SZhen.W@Sun.COM err = ddi_regs_map_setup(devinfo, 2, ®s, 1642744Sgs150176 0, 0, &rge_reg_accattr, &rgep->io_handle); 1643744Sgs150176 if (err != DDI_SUCCESS) { 1644744Sgs150176 rge_problem(rgep, "ddi_regs_map_setup() failed"); 1645744Sgs150176 goto attach_fail; 1646744Sgs150176 } 1647744Sgs150176 rgep->io_regs = regs; 1648744Sgs150176 rgep->progress |= PROGRESS_REGS; 1649744Sgs150176 1650744Sgs150176 /* 1651744Sgs150176 * Characterise the device, so we know its requirements. 1652744Sgs150176 * Then allocate the appropriate TX and RX descriptors & buffers. 1653744Sgs150176 */ 1654744Sgs150176 rge_chip_ident(rgep); 1655744Sgs150176 err = rge_alloc_bufs(rgep); 1656744Sgs150176 if (err != DDI_SUCCESS) { 1657744Sgs150176 rge_problem(rgep, "DMA buffer allocation failed"); 1658744Sgs150176 goto attach_fail; 1659744Sgs150176 } 1660744Sgs150176 1661744Sgs150176 /* 16625735Smx205022 * Register NDD-tweakable parameters 16635735Smx205022 */ 16645735Smx205022 if (rge_nd_init(rgep)) { 16655735Smx205022 rge_problem(rgep, "rge_nd_init() failed"); 16665735Smx205022 goto attach_fail; 16675735Smx205022 } 16685735Smx205022 rgep->progress |= PROGRESS_NDD; 16695735Smx205022 16705735Smx205022 /* 1671744Sgs150176 * Add the softint handlers: 1672744Sgs150176 * 1673744Sgs150176 * Both of these handlers are used to avoid restrictions on the 1674744Sgs150176 * context and/or mutexes required for some operations. In 1675744Sgs150176 * particular, the hardware interrupt handler and its subfunctions 1676744Sgs150176 * can detect a number of conditions that we don't want to handle 1677744Sgs150176 * in that context or with that set of mutexes held. So, these 1678744Sgs150176 * softints are triggered instead: 1679744Sgs150176 * 1680744Sgs150176 * the <resched> softint is triggered if if we have previously 1681744Sgs150176 * had to refuse to send a packet because of resource shortage 1682744Sgs150176 * (we've run out of transmit buffers), but the send completion 1683744Sgs150176 * interrupt handler has now detected that more buffers have 1684744Sgs150176 * become available. 1685744Sgs150176 * 1686744Sgs150176 * the <factotum> is triggered if the h/w interrupt handler 1687744Sgs150176 * sees the <link state changed> or <error> bits in the status 1688744Sgs150176 * block. It's also triggered periodically to poll the link 1689744Sgs150176 * state, just in case we aren't getting link status change 1690744Sgs150176 * interrupts ... 1691744Sgs150176 */ 16922544Sgs150176 err = ddi_intr_add_softint(devinfo, &rgep->resched_hdl, 16935107Seota DDI_INTR_SOFTPRI_MIN, rge_reschedule, (caddr_t)rgep); 1694744Sgs150176 if (err != DDI_SUCCESS) { 16952544Sgs150176 rge_problem(rgep, "ddi_intr_add_softint() failed"); 1696744Sgs150176 goto attach_fail; 1697744Sgs150176 } 1698744Sgs150176 rgep->progress |= PROGRESS_RESCHED; 16992544Sgs150176 err = ddi_intr_add_softint(devinfo, &rgep->factotum_hdl, 17005107Seota DDI_INTR_SOFTPRI_MIN, rge_chip_factotum, (caddr_t)rgep); 1701744Sgs150176 if (err != DDI_SUCCESS) { 17022544Sgs150176 rge_problem(rgep, "ddi_intr_add_softint() failed"); 1703744Sgs150176 goto attach_fail; 1704744Sgs150176 } 1705744Sgs150176 rgep->progress |= PROGRESS_FACTOTUM; 1706744Sgs150176 1707744Sgs150176 /* 17082544Sgs150176 * Get supported interrupt types 1709744Sgs150176 */ 17102544Sgs150176 if (ddi_intr_get_supported_types(devinfo, &intr_types) 17112544Sgs150176 != DDI_SUCCESS) { 17122544Sgs150176 rge_error(rgep, "ddi_intr_get_supported_types failed\n"); 1713744Sgs150176 goto attach_fail; 1714744Sgs150176 } 17152544Sgs150176 17162544Sgs150176 /* 17172544Sgs150176 * Add the h/w interrupt handler and initialise mutexes 17186764Smx205022 * RTL8101E is observed to have MSI invalidation issue after S/R. 17196764Smx205022 * So the FIXED interrupt is used instead. 17202544Sgs150176 */ 17216764Smx205022 if (rgep->chipid.mac_ver == MAC_VER_8101E) 17226764Smx205022 rgep->msi_enable = B_FALSE; 17232544Sgs150176 if ((intr_types & DDI_INTR_TYPE_MSI) && rgep->msi_enable) { 17242544Sgs150176 if (rge_add_intrs(rgep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) { 17252544Sgs150176 rge_error(rgep, "MSI registration failed, " 17262544Sgs150176 "trying FIXED interrupt type\n"); 17272544Sgs150176 } else { 17282544Sgs150176 rge_log(rgep, "Using MSI interrupt type\n"); 17292544Sgs150176 rgep->intr_type = DDI_INTR_TYPE_MSI; 17302544Sgs150176 rgep->progress |= PROGRESS_INTR; 17312544Sgs150176 } 17322544Sgs150176 } 17332544Sgs150176 if (!(rgep->progress & PROGRESS_INTR) && 17342544Sgs150176 (intr_types & DDI_INTR_TYPE_FIXED)) { 17352544Sgs150176 if (rge_add_intrs(rgep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) { 17362544Sgs150176 rge_error(rgep, "FIXED interrupt " 17372544Sgs150176 "registration failed\n"); 17382544Sgs150176 goto attach_fail; 17392544Sgs150176 } 17402544Sgs150176 rge_log(rgep, "Using FIXED interrupt type\n"); 17412544Sgs150176 rgep->intr_type = DDI_INTR_TYPE_FIXED; 17422544Sgs150176 rgep->progress |= PROGRESS_INTR; 17432544Sgs150176 } 17442544Sgs150176 if (!(rgep->progress & PROGRESS_INTR)) { 17452544Sgs150176 rge_error(rgep, "No interrupts registered\n"); 17462544Sgs150176 goto attach_fail; 17472544Sgs150176 } 17482544Sgs150176 mutex_init(rgep->genlock, NULL, MUTEX_DRIVER, 17492544Sgs150176 DDI_INTR_PRI(rgep->intr_pri)); 17502544Sgs150176 rw_init(rgep->errlock, NULL, RW_DRIVER, 17512544Sgs150176 DDI_INTR_PRI(rgep->intr_pri)); 17522544Sgs150176 mutex_init(rgep->tx_lock, NULL, MUTEX_DRIVER, 17532544Sgs150176 DDI_INTR_PRI(rgep->intr_pri)); 17542544Sgs150176 mutex_init(rgep->tc_lock, NULL, MUTEX_DRIVER, 17552544Sgs150176 DDI_INTR_PRI(rgep->intr_pri)); 17562544Sgs150176 mutex_init(rgep->rx_lock, NULL, MUTEX_DRIVER, 17572544Sgs150176 DDI_INTR_PRI(rgep->intr_pri)); 17582544Sgs150176 mutex_init(rgep->rc_lock, NULL, MUTEX_DRIVER, 17592544Sgs150176 DDI_INTR_PRI(rgep->intr_pri)); 1760744Sgs150176 1761744Sgs150176 /* 1762744Sgs150176 * Initialize rings 1763744Sgs150176 */ 1764744Sgs150176 err = rge_init_rings(rgep); 1765744Sgs150176 if (err != DDI_SUCCESS) { 1766744Sgs150176 rge_problem(rgep, "rge_init_rings() failed"); 1767744Sgs150176 goto attach_fail; 1768744Sgs150176 } 17692544Sgs150176 rgep->progress |= PROGRESS_INIT; 17702544Sgs150176 17712544Sgs150176 /* 17722544Sgs150176 * Now that mutex locks are initialized, enable interrupts. 17732544Sgs150176 */ 17742544Sgs150176 if (rgep->intr_cap & DDI_INTR_FLAG_BLOCK) { 17752544Sgs150176 /* Call ddi_intr_block_enable() for MSI interrupts */ 17762544Sgs150176 (void) ddi_intr_block_enable(rgep->htable, rgep->intr_cnt); 17772544Sgs150176 } else { 17782544Sgs150176 /* Call ddi_intr_enable for MSI or FIXED interrupts */ 17792544Sgs150176 for (i = 0; i < rgep->intr_cnt; i++) { 17802544Sgs150176 (void) ddi_intr_enable(rgep->htable[i]); 17812544Sgs150176 } 17822544Sgs150176 } 1783744Sgs150176 1784744Sgs150176 /* 1785744Sgs150176 * Initialise link state variables 1786744Sgs150176 * Stop, reset & reinitialise the chip. 1787744Sgs150176 * Initialise the (internal) PHY. 1788744Sgs150176 */ 1789744Sgs150176 rgep->param_link_up = LINK_STATE_UNKNOWN; 1790744Sgs150176 1791744Sgs150176 /* 1792744Sgs150176 * Reset chip & rings to initial state; also reset address 1793744Sgs150176 * filtering, promiscuity, loopback mode. 1794744Sgs150176 */ 1795744Sgs150176 mutex_enter(rgep->genlock); 1796744Sgs150176 (void) rge_chip_reset(rgep); 1797744Sgs150176 rge_chip_sync(rgep, RGE_GET_MAC); 1798744Sgs150176 bzero(rgep->mcast_hash, sizeof (rgep->mcast_hash)); 1799744Sgs150176 bzero(rgep->mcast_refs, sizeof (rgep->mcast_refs)); 1800744Sgs150176 rgep->promisc = B_FALSE; 1801744Sgs150176 rgep->param_loop_mode = RGE_LOOP_NONE; 1802744Sgs150176 mutex_exit(rgep->genlock); 1803744Sgs150176 rge_phy_init(rgep); 1804744Sgs150176 rgep->progress |= PROGRESS_PHY; 1805744Sgs150176 1806744Sgs150176 /* 1807744Sgs150176 * Create & initialise named kstats 1808744Sgs150176 */ 1809744Sgs150176 rge_init_kstats(rgep, instance); 1810744Sgs150176 rgep->progress |= PROGRESS_KSTATS; 1811744Sgs150176 18122311Sseb if ((macp = mac_alloc(MAC_VERSION)) == NULL) 18132311Sseb goto attach_fail; 18142311Sseb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 18152311Sseb macp->m_driver = rgep; 1816744Sgs150176 macp->m_dip = devinfo; 18172311Sseb macp->m_src_addr = rgep->netaddr; 18182311Sseb macp->m_callbacks = &rge_m_callbacks; 18192311Sseb macp->m_min_sdu = 0; 18202544Sgs150176 macp->m_max_sdu = rgep->default_mtu; 18215895Syz147064 macp->m_margin = VLAN_TAGSZ; 1822744Sgs150176 1823744Sgs150176 /* 1824744Sgs150176 * Finally, we're ready to register ourselves with the MAC layer 1825744Sgs150176 * interface; if this succeeds, we're all ready to start() 1826744Sgs150176 */ 18272311Sseb err = mac_register(macp, &rgep->mh); 18282311Sseb mac_free(macp); 18292311Sseb if (err != 0) 1830744Sgs150176 goto attach_fail; 1831744Sgs150176 18325107Seota /* 18335107Seota * Register a periodical handler. 18345107Seota * reg_chip_cyclic() is invoked in kernel context. 18355107Seota */ 18365107Seota rgep->periodic_id = ddi_periodic_add(rge_chip_cyclic, rgep, 18375107Seota RGE_CYCLIC_PERIOD, DDI_IPL_0); 1838744Sgs150176 1839744Sgs150176 rgep->progress |= PROGRESS_READY; 1840744Sgs150176 return (DDI_SUCCESS); 1841744Sgs150176 1842744Sgs150176 attach_fail: 1843744Sgs150176 rge_unattach(rgep); 1844744Sgs150176 return (DDI_FAILURE); 1845744Sgs150176 } 1846744Sgs150176 1847744Sgs150176 /* 1848744Sgs150176 * rge_suspend() -- suspend transmit/receive for powerdown 1849744Sgs150176 */ 1850744Sgs150176 static int 1851744Sgs150176 rge_suspend(rge_t *rgep) 1852744Sgs150176 { 1853744Sgs150176 /* 1854744Sgs150176 * Stop processing and idle (powerdown) the PHY ... 1855744Sgs150176 */ 1856744Sgs150176 mutex_enter(rgep->genlock); 18577825SMin.Xu@Sun.COM rw_enter(rgep->errlock, RW_WRITER); 18586764Smx205022 18596764Smx205022 if (rgep->rge_mac_state != RGE_MAC_STARTED) { 18607825SMin.Xu@Sun.COM rw_exit(rgep->errlock); 18616764Smx205022 mutex_exit(rgep->genlock); 18626764Smx205022 return (DDI_SUCCESS); 18636764Smx205022 } 18646764Smx205022 18656764Smx205022 rgep->suspended = B_TRUE; 1866744Sgs150176 rge_stop(rgep); 18676764Smx205022 rgep->rge_mac_state = RGE_MAC_STOPPED; 18686764Smx205022 18696764Smx205022 rw_exit(rgep->errlock); 1870744Sgs150176 mutex_exit(rgep->genlock); 1871744Sgs150176 1872744Sgs150176 return (DDI_SUCCESS); 1873744Sgs150176 } 1874744Sgs150176 1875744Sgs150176 /* 18767656SSherry.Moore@Sun.COM * quiesce(9E) entry point. 18777656SSherry.Moore@Sun.COM * 18787656SSherry.Moore@Sun.COM * This function is called when the system is single-threaded at high 18797656SSherry.Moore@Sun.COM * PIL with preemption disabled. Therefore, this function must not be 18807656SSherry.Moore@Sun.COM * blocked. 18817656SSherry.Moore@Sun.COM * 18827656SSherry.Moore@Sun.COM * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 18837656SSherry.Moore@Sun.COM * DDI_FAILURE indicates an error condition and should almost never happen. 18847656SSherry.Moore@Sun.COM */ 18857656SSherry.Moore@Sun.COM static int 18867656SSherry.Moore@Sun.COM rge_quiesce(dev_info_t *devinfo) 18877656SSherry.Moore@Sun.COM { 18887656SSherry.Moore@Sun.COM rge_t *rgep = ddi_get_driver_private(devinfo); 18897656SSherry.Moore@Sun.COM 18907656SSherry.Moore@Sun.COM if (rgep == NULL) 18917656SSherry.Moore@Sun.COM return (DDI_FAILURE); 18927656SSherry.Moore@Sun.COM 18937656SSherry.Moore@Sun.COM /* 18947656SSherry.Moore@Sun.COM * Turn off debugging 18957656SSherry.Moore@Sun.COM */ 18967656SSherry.Moore@Sun.COM rge_debug = 0; 18977656SSherry.Moore@Sun.COM rgep->debug = 0; 18987656SSherry.Moore@Sun.COM 18997656SSherry.Moore@Sun.COM /* Stop the chip */ 19007656SSherry.Moore@Sun.COM rge_chip_stop(rgep, B_FALSE); 19017656SSherry.Moore@Sun.COM 19027656SSherry.Moore@Sun.COM return (DDI_SUCCESS); 19037656SSherry.Moore@Sun.COM } 19047656SSherry.Moore@Sun.COM 19057656SSherry.Moore@Sun.COM /* 1906744Sgs150176 * detach(9E) -- Detach a device from the system 1907744Sgs150176 */ 1908744Sgs150176 static int 1909744Sgs150176 rge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 1910744Sgs150176 { 1911744Sgs150176 rge_t *rgep; 1912744Sgs150176 1913744Sgs150176 RGE_GTRACE(("rge_detach($%p, %d)", (void *)devinfo, cmd)); 1914744Sgs150176 1915744Sgs150176 rgep = ddi_get_driver_private(devinfo); 1916744Sgs150176 1917744Sgs150176 switch (cmd) { 1918744Sgs150176 default: 1919744Sgs150176 return (DDI_FAILURE); 1920744Sgs150176 1921744Sgs150176 case DDI_SUSPEND: 1922744Sgs150176 return (rge_suspend(rgep)); 1923744Sgs150176 1924744Sgs150176 case DDI_DETACH: 1925744Sgs150176 break; 1926744Sgs150176 } 1927744Sgs150176 1928744Sgs150176 /* 1929744Sgs150176 * If there is any posted buffer, the driver should reject to be 1930744Sgs150176 * detached. Need notice upper layer to release them. 1931744Sgs150176 */ 19322544Sgs150176 if (!(rgep->chip_flags & CHIP_FLAG_FORCE_BCOPY) && 19332544Sgs150176 rgep->rx_free != RGE_BUF_SLOTS) 1934744Sgs150176 return (DDI_FAILURE); 1935744Sgs150176 1936744Sgs150176 /* 1937744Sgs150176 * Unregister from the MAC layer subsystem. This can fail, in 1938744Sgs150176 * particular if there are DLPI style-2 streams still open - 1939744Sgs150176 * in which case we just return failure without shutting 1940744Sgs150176 * down chip operations. 1941744Sgs150176 */ 19422311Sseb if (mac_unregister(rgep->mh) != 0) 1943744Sgs150176 return (DDI_FAILURE); 1944744Sgs150176 1945744Sgs150176 /* 1946744Sgs150176 * All activity stopped, so we can clean up & exit 1947744Sgs150176 */ 1948744Sgs150176 rge_unattach(rgep); 1949744Sgs150176 return (DDI_SUCCESS); 1950744Sgs150176 } 1951744Sgs150176 1952744Sgs150176 1953744Sgs150176 /* 1954744Sgs150176 * ========== Module Loading Data & Entry Points ========== 1955744Sgs150176 */ 1956744Sgs150176 1957744Sgs150176 #undef RGE_DBG 1958744Sgs150176 #define RGE_DBG RGE_DBG_INIT /* debug flag for this code */ 1959744Sgs150176 DDI_DEFINE_STREAM_OPS(rge_dev_ops, nulldev, nulldev, rge_attach, rge_detach, 19607656SSherry.Moore@Sun.COM nodev, NULL, D_MP, NULL, rge_quiesce); 1961744Sgs150176 1962744Sgs150176 static struct modldrv rge_modldrv = { 1963744Sgs150176 &mod_driverops, /* Type of module. This one is a driver */ 1964744Sgs150176 rge_ident, /* short description */ 1965744Sgs150176 &rge_dev_ops /* driver specific ops */ 1966744Sgs150176 }; 1967744Sgs150176 1968744Sgs150176 static struct modlinkage modlinkage = { 1969744Sgs150176 MODREV_1, (void *)&rge_modldrv, NULL 1970744Sgs150176 }; 1971744Sgs150176 1972744Sgs150176 1973744Sgs150176 int 1974744Sgs150176 _info(struct modinfo *modinfop) 1975744Sgs150176 { 1976744Sgs150176 return (mod_info(&modlinkage, modinfop)); 1977744Sgs150176 } 1978744Sgs150176 1979744Sgs150176 int 1980744Sgs150176 _init(void) 1981744Sgs150176 { 1982744Sgs150176 int status; 1983744Sgs150176 1984744Sgs150176 mac_init_ops(&rge_dev_ops, "rge"); 1985744Sgs150176 status = mod_install(&modlinkage); 1986744Sgs150176 if (status == DDI_SUCCESS) 1987744Sgs150176 mutex_init(rge_log_mutex, NULL, MUTEX_DRIVER, NULL); 1988744Sgs150176 else 1989744Sgs150176 mac_fini_ops(&rge_dev_ops); 1990744Sgs150176 1991744Sgs150176 return (status); 1992744Sgs150176 } 1993744Sgs150176 1994744Sgs150176 int 1995744Sgs150176 _fini(void) 1996744Sgs150176 { 1997744Sgs150176 int status; 1998744Sgs150176 1999744Sgs150176 status = mod_remove(&modlinkage); 2000744Sgs150176 if (status == DDI_SUCCESS) { 2001744Sgs150176 mac_fini_ops(&rge_dev_ops); 2002744Sgs150176 mutex_destroy(rge_log_mutex); 2003744Sgs150176 } 2004744Sgs150176 return (status); 2005744Sgs150176 } 2006