1*eef4f27bSRobert Mustacchi /*
2*eef4f27bSRobert Mustacchi * Copyright 2014-2017 Cavium, Inc.
3*eef4f27bSRobert Mustacchi * The contents of this file are subject to the terms of the Common Development
4*eef4f27bSRobert Mustacchi * and Distribution License, v.1, (the "License").
5*eef4f27bSRobert Mustacchi *
6*eef4f27bSRobert Mustacchi * You may not use this file except in compliance with the License.
7*eef4f27bSRobert Mustacchi *
8*eef4f27bSRobert Mustacchi * You can obtain a copy of the License at available
9*eef4f27bSRobert Mustacchi * at http://opensource.org/licenses/CDDL-1.0
10*eef4f27bSRobert Mustacchi *
11*eef4f27bSRobert Mustacchi * See the License for the specific language governing permissions and
12*eef4f27bSRobert Mustacchi * limitations under the License.
13*eef4f27bSRobert Mustacchi */
14*eef4f27bSRobert Mustacchi
15*eef4f27bSRobert Mustacchi /*
16*eef4f27bSRobert Mustacchi * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
17*eef4f27bSRobert Mustacchi * Copyright (c) 2019, Joyent, Inc.
18*eef4f27bSRobert Mustacchi */
19*eef4f27bSRobert Mustacchi
20*eef4f27bSRobert Mustacchi #include "bnx.h"
21*eef4f27bSRobert Mustacchi #include "bnxgld.h"
22*eef4f27bSRobert Mustacchi #include "bnxhwi.h"
23*eef4f27bSRobert Mustacchi #include "bnxint.h"
24*eef4f27bSRobert Mustacchi #include "bnxtmr.h"
25*eef4f27bSRobert Mustacchi #include "bnxcfg.h"
26*eef4f27bSRobert Mustacchi
27*eef4f27bSRobert Mustacchi #define BNX_PRODUCT_BANNER "QLogic 570x/571x Gigabit Ethernet Driver "\
28*eef4f27bSRobert Mustacchi BRCMVERSION
29*eef4f27bSRobert Mustacchi
30*eef4f27bSRobert Mustacchi #define BNX_PRODUCT_INFO "QLogic 570x/571x GbE "\
31*eef4f27bSRobert Mustacchi BRCMVERSION
32*eef4f27bSRobert Mustacchi
33*eef4f27bSRobert Mustacchi ddi_device_acc_attr_t bnxAccessAttribBAR = {
34*eef4f27bSRobert Mustacchi DDI_DEVICE_ATTR_V0, /* devacc_attr_version */
35*eef4f27bSRobert Mustacchi DDI_STRUCTURE_LE_ACC, /* devacc_attr_endian_flags */
36*eef4f27bSRobert Mustacchi DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */
37*eef4f27bSRobert Mustacchi DDI_DEFAULT_ACC /* devacc_attr_access */
38*eef4f27bSRobert Mustacchi };
39*eef4f27bSRobert Mustacchi
40*eef4f27bSRobert Mustacchi ddi_device_acc_attr_t bnxAccessAttribBUF = {
41*eef4f27bSRobert Mustacchi DDI_DEVICE_ATTR_V0, /* devacc_attr_version */
42*eef4f27bSRobert Mustacchi DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */
43*eef4f27bSRobert Mustacchi DDI_STRICTORDER_ACC, /* devacc_attr_dataorder */
44*eef4f27bSRobert Mustacchi DDI_DEFAULT_ACC /* devacc_attr_access */
45*eef4f27bSRobert Mustacchi };
46*eef4f27bSRobert Mustacchi
47*eef4f27bSRobert Mustacchi
48*eef4f27bSRobert Mustacchi /*
49*eef4f27bSRobert Mustacchi * Name: bnx_free_system_resources
50*eef4f27bSRobert Mustacchi *
51*eef4f27bSRobert Mustacchi * Input: ptr to device structure
52*eef4f27bSRobert Mustacchi *
53*eef4f27bSRobert Mustacchi * Return: void
54*eef4f27bSRobert Mustacchi *
55*eef4f27bSRobert Mustacchi * Description:
56*eef4f27bSRobert Mustacchi * This function is called from detach() entry point to free most
57*eef4f27bSRobert Mustacchi * resources held by this device instance.
58*eef4f27bSRobert Mustacchi */
59*eef4f27bSRobert Mustacchi static int
bnx_free_system_resources(um_device_t * const umdevice)60*eef4f27bSRobert Mustacchi bnx_free_system_resources(um_device_t * const umdevice)
61*eef4f27bSRobert Mustacchi {
62*eef4f27bSRobert Mustacchi if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_MINOR_NODE) {
63*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag &= ~DRV_RESOURCE_MINOR_NODE;
64*eef4f27bSRobert Mustacchi #ifdef _USE_FRIENDLY_NAME
65*eef4f27bSRobert Mustacchi ddi_remove_minor_node(umdevice->os_param.dip,
66*eef4f27bSRobert Mustacchi (char *)ddi_driver_name(umdevice->os_param.dip));
67*eef4f27bSRobert Mustacchi #else
68*eef4f27bSRobert Mustacchi ddi_remove_minor_node(umdevice->os_param.dip,
69*eef4f27bSRobert Mustacchi ddi_get_name(umdevice->os_param.dip));
70*eef4f27bSRobert Mustacchi #endif
71*eef4f27bSRobert Mustacchi }
72*eef4f27bSRobert Mustacchi
73*eef4f27bSRobert Mustacchi if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_TIMER) {
74*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag &=
75*eef4f27bSRobert Mustacchi ~DRV_RESOURCE_TIMER;
76*eef4f27bSRobert Mustacchi bnx_timer_fini(umdevice);
77*eef4f27bSRobert Mustacchi }
78*eef4f27bSRobert Mustacchi
79*eef4f27bSRobert Mustacchi if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_GLD_REGISTER) {
80*eef4f27bSRobert Mustacchi if (bnx_gld_fini(umdevice)) {
81*eef4f27bSRobert Mustacchi /*
82*eef4f27bSRobert Mustacchi * FIXME -- If bnx_gld_fini() fails, we need to
83*eef4f27bSRobert Mustacchi * reactivate resources.
84*eef4f27bSRobert Mustacchi */
85*eef4f27bSRobert Mustacchi return (-1);
86*eef4f27bSRobert Mustacchi }
87*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag &=
88*eef4f27bSRobert Mustacchi ~DRV_RESOURCE_GLD_REGISTER;
89*eef4f27bSRobert Mustacchi }
90*eef4f27bSRobert Mustacchi
91*eef4f27bSRobert Mustacchi if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_KSTAT) {
92*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag &= ~DRV_RESOURCE_KSTAT;
93*eef4f27bSRobert Mustacchi bnx_kstat_fini(umdevice);
94*eef4f27bSRobert Mustacchi }
95*eef4f27bSRobert Mustacchi
96*eef4f27bSRobert Mustacchi if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_HDWR_REGISTER) {
97*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag &=
98*eef4f27bSRobert Mustacchi ~DRV_RESOURCE_HDWR_REGISTER;
99*eef4f27bSRobert Mustacchi bnx_hdwr_fini(umdevice);
100*eef4f27bSRobert Mustacchi }
101*eef4f27bSRobert Mustacchi
102*eef4f27bSRobert Mustacchi if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_MUTEX) {
103*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag &= ~DRV_RESOURCE_MUTEX;
104*eef4f27bSRobert Mustacchi mutex_destroy(&umdevice->os_param.ind_mutex);
105*eef4f27bSRobert Mustacchi mutex_destroy(&umdevice->os_param.phy_mutex);
106*eef4f27bSRobert Mustacchi mutex_destroy(&umdevice->os_param.rcv_mutex);
107*eef4f27bSRobert Mustacchi }
108*eef4f27bSRobert Mustacchi
109*eef4f27bSRobert Mustacchi if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_INTR_1) {
110*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag &= ~DRV_RESOURCE_INTR_1;
111*eef4f27bSRobert Mustacchi bnxIntrFini(umdevice);
112*eef4f27bSRobert Mustacchi }
113*eef4f27bSRobert Mustacchi
114*eef4f27bSRobert Mustacchi if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_MAP_REGS) {
115*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag &= ~DRV_RESOURCE_MAP_REGS;
116*eef4f27bSRobert Mustacchi ddi_regs_map_free(&umdevice->os_param.reg_acc_handle);
117*eef4f27bSRobert Mustacchi umdevice->lm_dev.vars.dmaRegAccHandle = NULL;
118*eef4f27bSRobert Mustacchi umdevice->os_param.reg_acc_handle = NULL;
119*eef4f27bSRobert Mustacchi }
120*eef4f27bSRobert Mustacchi
121*eef4f27bSRobert Mustacchi if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_PCICFG_MAPPED) {
122*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag &=
123*eef4f27bSRobert Mustacchi ~DRV_RESOURCE_PCICFG_MAPPED;
124*eef4f27bSRobert Mustacchi pci_config_teardown(&umdevice->os_param.pci_cfg_handle);
125*eef4f27bSRobert Mustacchi }
126*eef4f27bSRobert Mustacchi
127*eef4f27bSRobert Mustacchi return (0);
128*eef4f27bSRobert Mustacchi }
129*eef4f27bSRobert Mustacchi
130*eef4f27bSRobert Mustacchi
131*eef4f27bSRobert Mustacchi
132*eef4f27bSRobert Mustacchi /*
133*eef4f27bSRobert Mustacchi * Name: bnx_attach_attach
134*eef4f27bSRobert Mustacchi *
135*eef4f27bSRobert Mustacchi * Input: ptr to dev_info_t
136*eef4f27bSRobert Mustacchi *
137*eef4f27bSRobert Mustacchi * Return: DDI_SUCCESS or DDI_FAILURE.
138*eef4f27bSRobert Mustacchi *
139*eef4f27bSRobert Mustacchi * Description: This is the main code involving all important driver data struct
140*eef4f27bSRobert Mustacchi * and device initialization stuff. This function allocates driver
141*eef4f27bSRobert Mustacchi * soft state for this instance of the driver, sets access up
142*eef4f27bSRobert Mustacchi * attributes for the device, maps BAR register space, initializes
143*eef4f27bSRobert Mustacchi * the hardware, determines interrupt pin, registers interrupt
144*eef4f27bSRobert Mustacchi * service routine with the OS and initializes receive/transmit
145*eef4f27bSRobert Mustacchi * mutex. After successful completion of above mentioned tasks,
146*eef4f27bSRobert Mustacchi * the driver registers with the GLD and creates minor node in
147*eef4f27bSRobert Mustacchi * the file system tree for this device.
148*eef4f27bSRobert Mustacchi */
149*eef4f27bSRobert Mustacchi static int
bnx_attach_attach(um_device_t * umdevice)150*eef4f27bSRobert Mustacchi bnx_attach_attach(um_device_t *umdevice)
151*eef4f27bSRobert Mustacchi {
152*eef4f27bSRobert Mustacchi int rc;
153*eef4f27bSRobert Mustacchi int instance;
154*eef4f27bSRobert Mustacchi unsigned int val;
155*eef4f27bSRobert Mustacchi int chip_id;
156*eef4f27bSRobert Mustacchi int device_id;
157*eef4f27bSRobert Mustacchi int subdevice_id;
158*eef4f27bSRobert Mustacchi off_t regSize;
159*eef4f27bSRobert Mustacchi
160*eef4f27bSRobert Mustacchi dev_info_t *dip;
161*eef4f27bSRobert Mustacchi
162*eef4f27bSRobert Mustacchi dip = umdevice->os_param.dip;
163*eef4f27bSRobert Mustacchi
164*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag = 0;
165*eef4f27bSRobert Mustacchi
166*eef4f27bSRobert Mustacchi rc = pci_config_setup(umdevice->os_param.dip,
167*eef4f27bSRobert Mustacchi &umdevice->os_param.pci_cfg_handle);
168*eef4f27bSRobert Mustacchi if (rc != DDI_SUCCESS) {
169*eef4f27bSRobert Mustacchi cmn_err(CE_WARN,
170*eef4f27bSRobert Mustacchi "%s: Failed to setup PCI configuration space accesses.\n",
171*eef4f27bSRobert Mustacchi umdevice->dev_name);
172*eef4f27bSRobert Mustacchi goto error;
173*eef4f27bSRobert Mustacchi }
174*eef4f27bSRobert Mustacchi
175*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag |= DRV_RESOURCE_PCICFG_MAPPED;
176*eef4f27bSRobert Mustacchi
177*eef4f27bSRobert Mustacchi rc = ddi_dev_regsize(dip, 1, ®Size);
178*eef4f27bSRobert Mustacchi if (rc != DDI_SUCCESS) {
179*eef4f27bSRobert Mustacchi cmn_err(CE_WARN, "%s: failed to determine register set size.",
180*eef4f27bSRobert Mustacchi umdevice->dev_name);
181*eef4f27bSRobert Mustacchi }
182*eef4f27bSRobert Mustacchi
183*eef4f27bSRobert Mustacchi /*
184*eef4f27bSRobert Mustacchi * Setup device memory mapping so that LM driver can start accessing it.
185*eef4f27bSRobert Mustacchi */
186*eef4f27bSRobert Mustacchi rc = ddi_regs_map_setup(dip,
187*eef4f27bSRobert Mustacchi 1, /* BAR */
188*eef4f27bSRobert Mustacchi &umdevice->os_param.regs_addr,
189*eef4f27bSRobert Mustacchi 0, /* OFFSET */
190*eef4f27bSRobert Mustacchi regSize,
191*eef4f27bSRobert Mustacchi &bnxAccessAttribBAR,
192*eef4f27bSRobert Mustacchi &umdevice->os_param.reg_acc_handle);
193*eef4f27bSRobert Mustacchi if (rc != DDI_SUCCESS) {
194*eef4f27bSRobert Mustacchi cmn_err(CE_WARN,
195*eef4f27bSRobert Mustacchi "%s: Failed to memory map device.\n",
196*eef4f27bSRobert Mustacchi umdevice->dev_name);
197*eef4f27bSRobert Mustacchi goto error;
198*eef4f27bSRobert Mustacchi }
199*eef4f27bSRobert Mustacchi
200*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag |= DRV_RESOURCE_MAP_REGS;
201*eef4f27bSRobert Mustacchi
202*eef4f27bSRobert Mustacchi bnx_cfg_msix(umdevice);
203*eef4f27bSRobert Mustacchi
204*eef4f27bSRobert Mustacchi if (bnxIntrInit(umdevice) != 0) {
205*eef4f27bSRobert Mustacchi goto error;
206*eef4f27bSRobert Mustacchi }
207*eef4f27bSRobert Mustacchi
208*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag |= DRV_RESOURCE_INTR_1;
209*eef4f27bSRobert Mustacchi
210*eef4f27bSRobert Mustacchi mutex_init(&umdevice->os_param.rcv_mutex, NULL,
211*eef4f27bSRobert Mustacchi MUTEX_DRIVER, DDI_INTR_PRI(umdevice->intrPriority));
212*eef4f27bSRobert Mustacchi mutex_init(&umdevice->os_param.phy_mutex, NULL,
213*eef4f27bSRobert Mustacchi MUTEX_DRIVER, DDI_INTR_PRI(umdevice->intrPriority));
214*eef4f27bSRobert Mustacchi mutex_init(&umdevice->os_param.ind_mutex, NULL,
215*eef4f27bSRobert Mustacchi MUTEX_DRIVER, DDI_INTR_PRI(umdevice->intrPriority));
216*eef4f27bSRobert Mustacchi
217*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag |= DRV_RESOURCE_MUTEX;
218*eef4f27bSRobert Mustacchi
219*eef4f27bSRobert Mustacchi /*
220*eef4f27bSRobert Mustacchi * Call lower module's initialization routines to initialize
221*eef4f27bSRobert Mustacchi * hardware and related components within BNX.
222*eef4f27bSRobert Mustacchi */
223*eef4f27bSRobert Mustacchi if (bnx_hdwr_init(umdevice)) {
224*eef4f27bSRobert Mustacchi goto error;
225*eef4f27bSRobert Mustacchi }
226*eef4f27bSRobert Mustacchi
227*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag |= DRV_RESOURCE_HDWR_REGISTER;
228*eef4f27bSRobert Mustacchi
229*eef4f27bSRobert Mustacchi if (!bnx_kstat_init(umdevice)) {
230*eef4f27bSRobert Mustacchi goto error;
231*eef4f27bSRobert Mustacchi }
232*eef4f27bSRobert Mustacchi
233*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag |= DRV_RESOURCE_KSTAT;
234*eef4f27bSRobert Mustacchi
235*eef4f27bSRobert Mustacchi if (bnx_gld_init(umdevice)) {
236*eef4f27bSRobert Mustacchi goto error;
237*eef4f27bSRobert Mustacchi }
238*eef4f27bSRobert Mustacchi
239*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag |= DRV_RESOURCE_GLD_REGISTER;
240*eef4f27bSRobert Mustacchi
241*eef4f27bSRobert Mustacchi bnx_timer_init(umdevice);
242*eef4f27bSRobert Mustacchi
243*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag |= DRV_RESOURCE_TIMER;
244*eef4f27bSRobert Mustacchi
245*eef4f27bSRobert Mustacchi instance = ddi_get_instance(umdevice->os_param.dip);
246*eef4f27bSRobert Mustacchi
247*eef4f27bSRobert Mustacchi /* Create a minor node entry in /devices . */
248*eef4f27bSRobert Mustacchi #ifdef _USE_FRIENDLY_NAME
249*eef4f27bSRobert Mustacchi rc = ddi_create_minor_node(dip, (char *)ddi_driver_name(dip),
250*eef4f27bSRobert Mustacchi S_IFCHR, instance, DDI_PSEUDO, 0);
251*eef4f27bSRobert Mustacchi #else
252*eef4f27bSRobert Mustacchi rc = ddi_create_minor_node(dip, ddi_get_name(dip),
253*eef4f27bSRobert Mustacchi S_IFCHR, instance, DDI_PSEUDO, 0);
254*eef4f27bSRobert Mustacchi #endif
255*eef4f27bSRobert Mustacchi if (rc == DDI_FAILURE) {
256*eef4f27bSRobert Mustacchi cmn_err(CE_WARN, "%s: Failed to create device minor node.\n",
257*eef4f27bSRobert Mustacchi umdevice->dev_name);
258*eef4f27bSRobert Mustacchi goto error;
259*eef4f27bSRobert Mustacchi }
260*eef4f27bSRobert Mustacchi
261*eef4f27bSRobert Mustacchi umdevice->os_param.active_resc_flag |= DRV_RESOURCE_MINOR_NODE;
262*eef4f27bSRobert Mustacchi
263*eef4f27bSRobert Mustacchi ddi_report_dev(dip);
264*eef4f27bSRobert Mustacchi
265*eef4f27bSRobert Mustacchi device_id = pci_config_get16(umdevice->os_param.pci_cfg_handle,
266*eef4f27bSRobert Mustacchi 0x2);
267*eef4f27bSRobert Mustacchi subdevice_id = pci_config_get16(umdevice->os_param.pci_cfg_handle,
268*eef4f27bSRobert Mustacchi 0x2e);
269*eef4f27bSRobert Mustacchi
270*eef4f27bSRobert Mustacchi /* Dip into PCI config space to determine if we have 5716's */
271*eef4f27bSRobert Mustacchi if ((device_id == 0x163b) && (subdevice_id == 0x163b)) {
272*eef4f27bSRobert Mustacchi chip_id = 0x5716;
273*eef4f27bSRobert Mustacchi } else {
274*eef4f27bSRobert Mustacchi chip_id = CHIP_NUM(&umdevice->lm_dev) >> 16;
275*eef4f27bSRobert Mustacchi }
276*eef4f27bSRobert Mustacchi
277*eef4f27bSRobert Mustacchi (void) snprintf(umdevice->version, sizeof (umdevice->version), "%s",
278*eef4f27bSRobert Mustacchi BRCMVERSION);
279*eef4f27bSRobert Mustacchi
280*eef4f27bSRobert Mustacchi /* Get firmware version. */
281*eef4f27bSRobert Mustacchi REG_RD_IND(&umdevice->lm_dev,
282*eef4f27bSRobert Mustacchi umdevice->lm_dev.hw_info.shmem_base +
283*eef4f27bSRobert Mustacchi OFFSETOF(shmem_region_t, dev_info.bc_rev), &val);
284*eef4f27bSRobert Mustacchi umdevice->dev_var.fw_ver = (val & 0xFFFF0000) | ((val & 0xFF00) >> 8);
285*eef4f27bSRobert Mustacchi
286*eef4f27bSRobert Mustacchi (void) snprintf(umdevice->versionFW, sizeof (umdevice->versionFW),
287*eef4f27bSRobert Mustacchi "0x%x", umdevice->dev_var.fw_ver);
288*eef4f27bSRobert Mustacchi
289*eef4f27bSRobert Mustacchi (void) snprintf(umdevice->chipName, sizeof (umdevice->chipName),
290*eef4f27bSRobert Mustacchi "BCM%x", chip_id);
291*eef4f27bSRobert Mustacchi
292*eef4f27bSRobert Mustacchi (void) snprintf(umdevice->intrAlloc, sizeof (umdevice->intrAlloc),
293*eef4f27bSRobert Mustacchi "1 %s", (umdevice->intrType == DDI_INTR_TYPE_MSIX) ? "MSIX" :
294*eef4f27bSRobert Mustacchi (umdevice->intrType == DDI_INTR_TYPE_MSI) ? "MSI" :
295*eef4f27bSRobert Mustacchi "Fixed");
296*eef4f27bSRobert Mustacchi
297*eef4f27bSRobert Mustacchi cmn_err(CE_NOTE,
298*eef4f27bSRobert Mustacchi "!%s: (%s) BCM%x device with F/W Ver%x is initialized (%s)",
299*eef4f27bSRobert Mustacchi umdevice->dev_name, umdevice->version,
300*eef4f27bSRobert Mustacchi chip_id, umdevice->dev_var.fw_ver,
301*eef4f27bSRobert Mustacchi umdevice->intrAlloc);
302*eef4f27bSRobert Mustacchi
303*eef4f27bSRobert Mustacchi return (0);
304*eef4f27bSRobert Mustacchi
305*eef4f27bSRobert Mustacchi error:
306*eef4f27bSRobert Mustacchi (void) bnx_free_system_resources(umdevice);
307*eef4f27bSRobert Mustacchi
308*eef4f27bSRobert Mustacchi return (-1);
309*eef4f27bSRobert Mustacchi }
310*eef4f27bSRobert Mustacchi
311*eef4f27bSRobert Mustacchi /*
312*eef4f27bSRobert Mustacchi * Name: bnx_attach
313*eef4f27bSRobert Mustacchi *
314*eef4f27bSRobert Mustacchi * Input: ptr to dev_info_t, command code for the task to be executed
315*eef4f27bSRobert Mustacchi *
316*eef4f27bSRobert Mustacchi * Return: DDI_SUCCESS or DDI_FAILURE.
317*eef4f27bSRobert Mustacchi *
318*eef4f27bSRobert Mustacchi * Description: OS determined module attach entry point.
319*eef4f27bSRobert Mustacchi */
320*eef4f27bSRobert Mustacchi static int
bnx_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)321*eef4f27bSRobert Mustacchi bnx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
322*eef4f27bSRobert Mustacchi {
323*eef4f27bSRobert Mustacchi um_device_t *umdevice;
324*eef4f27bSRobert Mustacchi int ret_val = DDI_SUCCESS;
325*eef4f27bSRobert Mustacchi
326*eef4f27bSRobert Mustacchi switch (cmd) {
327*eef4f27bSRobert Mustacchi case DDI_ATTACH:
328*eef4f27bSRobert Mustacchi umdevice = kmem_zalloc(sizeof (um_device_t),
329*eef4f27bSRobert Mustacchi KM_NOSLEEP);
330*eef4f27bSRobert Mustacchi if (umdevice == NULL) {
331*eef4f27bSRobert Mustacchi cmn_err(CE_WARN, "%s: Failed to allocate "
332*eef4f27bSRobert Mustacchi "device memory.\n", __func__);
333*eef4f27bSRobert Mustacchi ret_val = DDI_FAILURE;
334*eef4f27bSRobert Mustacchi break;
335*eef4f27bSRobert Mustacchi }
336*eef4f27bSRobert Mustacchi
337*eef4f27bSRobert Mustacchi /* Save dev_info_t info in the driver struture. */
338*eef4f27bSRobert Mustacchi umdevice->os_param.dip = dip;
339*eef4f27bSRobert Mustacchi
340*eef4f27bSRobert Mustacchi /*
341*eef4f27bSRobert Mustacchi * Obtain a human-readable name to prepend all our
342*eef4f27bSRobert Mustacchi * messages with.
343*eef4f27bSRobert Mustacchi */
344*eef4f27bSRobert Mustacchi umdevice->instance = ddi_get_instance(dip);
345*eef4f27bSRobert Mustacchi (void) snprintf(umdevice->dev_name,
346*eef4f27bSRobert Mustacchi sizeof (umdevice->dev_name), "%s%d", "bnx",
347*eef4f27bSRobert Mustacchi umdevice->instance);
348*eef4f27bSRobert Mustacchi
349*eef4f27bSRobert Mustacchi /*
350*eef4f27bSRobert Mustacchi * Set driver private pointer to per device structure
351*eef4f27bSRobert Mustacchi * ptr.
352*eef4f27bSRobert Mustacchi */
353*eef4f27bSRobert Mustacchi ddi_set_driver_private(dip, (caddr_t)umdevice);
354*eef4f27bSRobert Mustacchi
355*eef4f27bSRobert Mustacchi umdevice->magic = BNX_MAGIC;
356*eef4f27bSRobert Mustacchi
357*eef4f27bSRobert Mustacchi if (bnx_attach_attach(umdevice)) {
358*eef4f27bSRobert Mustacchi ddi_set_driver_private(dip, (caddr_t)NULL);
359*eef4f27bSRobert Mustacchi kmem_free(umdevice, sizeof (um_device_t));
360*eef4f27bSRobert Mustacchi ret_val = DDI_FAILURE;
361*eef4f27bSRobert Mustacchi }
362*eef4f27bSRobert Mustacchi break;
363*eef4f27bSRobert Mustacchi
364*eef4f27bSRobert Mustacchi case DDI_RESUME:
365*eef4f27bSRobert Mustacchi /* Retrieve our device structure. */
366*eef4f27bSRobert Mustacchi umdevice = ddi_get_driver_private(dip);
367*eef4f27bSRobert Mustacchi if (umdevice == NULL) {
368*eef4f27bSRobert Mustacchi ret_val = DDI_FAILURE;
369*eef4f27bSRobert Mustacchi break;
370*eef4f27bSRobert Mustacchi }
371*eef4f27bSRobert Mustacchi break;
372*eef4f27bSRobert Mustacchi
373*eef4f27bSRobert Mustacchi default:
374*eef4f27bSRobert Mustacchi ret_val = DDI_FAILURE;
375*eef4f27bSRobert Mustacchi break;
376*eef4f27bSRobert Mustacchi }
377*eef4f27bSRobert Mustacchi
378*eef4f27bSRobert Mustacchi return (ret_val);
379*eef4f27bSRobert Mustacchi }
380*eef4f27bSRobert Mustacchi
381*eef4f27bSRobert Mustacchi /*
382*eef4f27bSRobert Mustacchi * Name: bnx_detach
383*eef4f27bSRobert Mustacchi *
384*eef4f27bSRobert Mustacchi * Input: ptr to dev_info_t, command code for the task to be executed
385*eef4f27bSRobert Mustacchi *
386*eef4f27bSRobert Mustacchi * Return: DDI_SUCCESS or DDI_FAILURE.
387*eef4f27bSRobert Mustacchi *
388*eef4f27bSRobert Mustacchi * Description: OS determined module detach entry point.
389*eef4f27bSRobert Mustacchi */
390*eef4f27bSRobert Mustacchi static int
bnx_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)391*eef4f27bSRobert Mustacchi bnx_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
392*eef4f27bSRobert Mustacchi {
393*eef4f27bSRobert Mustacchi um_device_t *umdevice;
394*eef4f27bSRobert Mustacchi int ret_val = DDI_SUCCESS;
395*eef4f27bSRobert Mustacchi
396*eef4f27bSRobert Mustacchi switch (cmd) {
397*eef4f27bSRobert Mustacchi case DDI_DETACH:
398*eef4f27bSRobert Mustacchi umdevice = ddi_get_driver_private(dip);
399*eef4f27bSRobert Mustacchi if (umdevice == NULL) {
400*eef4f27bSRobert Mustacchi /* Must have failed attach. */
401*eef4f27bSRobert Mustacchi ret_val = DDI_SUCCESS;
402*eef4f27bSRobert Mustacchi break;
403*eef4f27bSRobert Mustacchi }
404*eef4f27bSRobert Mustacchi
405*eef4f27bSRobert Mustacchi /* Sanity check. */
406*eef4f27bSRobert Mustacchi if (umdevice == NULL) {
407*eef4f27bSRobert Mustacchi cmn_err(CE_WARN,
408*eef4f27bSRobert Mustacchi "%s: Sanity check failed(1).", __func__);
409*eef4f27bSRobert Mustacchi ret_val = DDI_SUCCESS;
410*eef4f27bSRobert Mustacchi break;
411*eef4f27bSRobert Mustacchi }
412*eef4f27bSRobert Mustacchi
413*eef4f27bSRobert Mustacchi /* Sanity check. */
414*eef4f27bSRobert Mustacchi if (umdevice->os_param.dip != dip) {
415*eef4f27bSRobert Mustacchi cmn_err(CE_WARN,
416*eef4f27bSRobert Mustacchi "%s: Sanity check failed(2).", __func__);
417*eef4f27bSRobert Mustacchi ret_val = DDI_SUCCESS;
418*eef4f27bSRobert Mustacchi break;
419*eef4f27bSRobert Mustacchi }
420*eef4f27bSRobert Mustacchi
421*eef4f27bSRobert Mustacchi /* Another sanity check. */
422*eef4f27bSRobert Mustacchi if (umdevice->intr_enabled != B_FALSE) {
423*eef4f27bSRobert Mustacchi cmn_err(CE_WARN, "%s: Detaching a device "
424*eef4f27bSRobert Mustacchi "that is currently running!!!\n",
425*eef4f27bSRobert Mustacchi umdevice->dev_name);
426*eef4f27bSRobert Mustacchi ret_val = DDI_FAILURE;
427*eef4f27bSRobert Mustacchi break;
428*eef4f27bSRobert Mustacchi }
429*eef4f27bSRobert Mustacchi
430*eef4f27bSRobert Mustacchi if (bnx_free_system_resources(umdevice)) {
431*eef4f27bSRobert Mustacchi ret_val = DDI_FAILURE;
432*eef4f27bSRobert Mustacchi break;
433*eef4f27bSRobert Mustacchi }
434*eef4f27bSRobert Mustacchi
435*eef4f27bSRobert Mustacchi ddi_set_driver_private(dip, (caddr_t)NULL);
436*eef4f27bSRobert Mustacchi kmem_free(umdevice, sizeof (um_device_t));
437*eef4f27bSRobert Mustacchi break;
438*eef4f27bSRobert Mustacchi
439*eef4f27bSRobert Mustacchi case DDI_SUSPEND:
440*eef4f27bSRobert Mustacchi /* Retrieve our device structure. */
441*eef4f27bSRobert Mustacchi umdevice = ddi_get_driver_private(dip);
442*eef4f27bSRobert Mustacchi if (umdevice == NULL) {
443*eef4f27bSRobert Mustacchi ret_val = DDI_FAILURE;
444*eef4f27bSRobert Mustacchi break;
445*eef4f27bSRobert Mustacchi }
446*eef4f27bSRobert Mustacchi break;
447*eef4f27bSRobert Mustacchi
448*eef4f27bSRobert Mustacchi default:
449*eef4f27bSRobert Mustacchi ret_val = DDI_FAILURE;
450*eef4f27bSRobert Mustacchi break;
451*eef4f27bSRobert Mustacchi }
452*eef4f27bSRobert Mustacchi
453*eef4f27bSRobert Mustacchi return (ret_val);
454*eef4f27bSRobert Mustacchi }
455*eef4f27bSRobert Mustacchi
456*eef4f27bSRobert Mustacchi /*
457*eef4f27bSRobert Mustacchi * Name: bnx_quiesce
458*eef4f27bSRobert Mustacchi *
459*eef4f27bSRobert Mustacchi * Input: ptr to dev_info_t
460*eef4f27bSRobert Mustacchi *
461*eef4f27bSRobert Mustacchi * Return: DDI_SUCCESS or DDI_FAILURE.
462*eef4f27bSRobert Mustacchi *
463*eef4f27bSRobert Mustacchi * Description: quiesce(9E) entry point.
464*eef4f27bSRobert Mustacchi * This function will make sure no more interrupts and DMA of
465*eef4f27bSRobert Mustacchi * the hardware. It is called when the system is single-threaded
466*eef4f27bSRobert Mustacchi * at high PIL with preemption disabled. Thus this function should
467*eef4f27bSRobert Mustacchi * not be blocked.
468*eef4f27bSRobert Mustacchi */
469*eef4f27bSRobert Mustacchi static int
bnx_quiesce(dev_info_t * dip)470*eef4f27bSRobert Mustacchi bnx_quiesce(dev_info_t *dip)
471*eef4f27bSRobert Mustacchi {
472*eef4f27bSRobert Mustacchi um_device_t *umdevice;
473*eef4f27bSRobert Mustacchi
474*eef4f27bSRobert Mustacchi umdevice = ddi_get_driver_private(dip);
475*eef4f27bSRobert Mustacchi
476*eef4f27bSRobert Mustacchi /* Sanity check. */
477*eef4f27bSRobert Mustacchi if (umdevice == NULL || umdevice->os_param.dip != dip) {
478*eef4f27bSRobert Mustacchi cmn_err(CE_WARN, "%s: Sanity check failed.", __func__);
479*eef4f27bSRobert Mustacchi return (DDI_FAILURE);
480*eef4f27bSRobert Mustacchi }
481*eef4f27bSRobert Mustacchi
482*eef4f27bSRobert Mustacchi /* Stop the device from generating any interrupts. */
483*eef4f27bSRobert Mustacchi lm_disable_int(&(umdevice->lm_dev));
484*eef4f27bSRobert Mustacchi
485*eef4f27bSRobert Mustacchi /* Set RX mask to stop receiving any further packets */
486*eef4f27bSRobert Mustacchi (void) lm_set_rx_mask(&(umdevice->lm_dev), RX_FILTER_USER_IDX0,
487*eef4f27bSRobert Mustacchi LM_RX_MASK_ACCEPT_NONE);
488*eef4f27bSRobert Mustacchi
489*eef4f27bSRobert Mustacchi return (DDI_SUCCESS);
490*eef4f27bSRobert Mustacchi }
491*eef4f27bSRobert Mustacchi
492*eef4f27bSRobert Mustacchi DDI_DEFINE_STREAM_OPS(bnx_dev_ops, nulldev, nulldev, bnx_attach, bnx_detach, \
493*eef4f27bSRobert Mustacchi nodev, NULL, (D_MP | D_64BIT), NULL, bnx_quiesce);
494*eef4f27bSRobert Mustacchi
495*eef4f27bSRobert Mustacchi static struct modldrv bnx_modldrv = {
496*eef4f27bSRobert Mustacchi &mod_driverops, /* drv_modops */
497*eef4f27bSRobert Mustacchi BNX_PRODUCT_INFO, /* drv_linkinfo */
498*eef4f27bSRobert Mustacchi &bnx_dev_ops /* drv_dev_ops */
499*eef4f27bSRobert Mustacchi };
500*eef4f27bSRobert Mustacchi
501*eef4f27bSRobert Mustacchi static struct modlinkage bnx_modlinkage = {
502*eef4f27bSRobert Mustacchi MODREV_1, /* ml_rev */
503*eef4f27bSRobert Mustacchi &bnx_modldrv, /* ml_linkage */
504*eef4f27bSRobert Mustacchi NULL /* NULL termination */
505*eef4f27bSRobert Mustacchi };
506*eef4f27bSRobert Mustacchi
507*eef4f27bSRobert Mustacchi /*
508*eef4f27bSRobert Mustacchi * Name: _init
509*eef4f27bSRobert Mustacchi *
510*eef4f27bSRobert Mustacchi * Input: None
511*eef4f27bSRobert Mustacchi *
512*eef4f27bSRobert Mustacchi * Return: SUCCESS or FAILURE.
513*eef4f27bSRobert Mustacchi *
514*eef4f27bSRobert Mustacchi * Description: OS determined driver module load entry point.
515*eef4f27bSRobert Mustacchi */
516*eef4f27bSRobert Mustacchi int
_init(void)517*eef4f27bSRobert Mustacchi _init(void)
518*eef4f27bSRobert Mustacchi {
519*eef4f27bSRobert Mustacchi int rc;
520*eef4f27bSRobert Mustacchi
521*eef4f27bSRobert Mustacchi mac_init_ops(&bnx_dev_ops, "bnx");
522*eef4f27bSRobert Mustacchi
523*eef4f27bSRobert Mustacchi /* Install module information with O/S */
524*eef4f27bSRobert Mustacchi rc = mod_install(&bnx_modlinkage);
525*eef4f27bSRobert Mustacchi if (rc != 0) {
526*eef4f27bSRobert Mustacchi cmn_err(CE_WARN, "%s:_init - mod_install returned 0x%x", "bnx",
527*eef4f27bSRobert Mustacchi rc);
528*eef4f27bSRobert Mustacchi return (rc);
529*eef4f27bSRobert Mustacchi }
530*eef4f27bSRobert Mustacchi
531*eef4f27bSRobert Mustacchi cmn_err(CE_NOTE, "!%s", BNX_PRODUCT_BANNER);
532*eef4f27bSRobert Mustacchi
533*eef4f27bSRobert Mustacchi return (rc);
534*eef4f27bSRobert Mustacchi }
535*eef4f27bSRobert Mustacchi
536*eef4f27bSRobert Mustacchi
537*eef4f27bSRobert Mustacchi
538*eef4f27bSRobert Mustacchi /*
539*eef4f27bSRobert Mustacchi * Name: _fini
540*eef4f27bSRobert Mustacchi *
541*eef4f27bSRobert Mustacchi * Input: None
542*eef4f27bSRobert Mustacchi *
543*eef4f27bSRobert Mustacchi * Return: SUCCESS or FAILURE.
544*eef4f27bSRobert Mustacchi *
545*eef4f27bSRobert Mustacchi * Description: OS determined driver module unload entry point.
546*eef4f27bSRobert Mustacchi */
547*eef4f27bSRobert Mustacchi int
_fini(void)548*eef4f27bSRobert Mustacchi _fini(void)
549*eef4f27bSRobert Mustacchi {
550*eef4f27bSRobert Mustacchi int rc;
551*eef4f27bSRobert Mustacchi
552*eef4f27bSRobert Mustacchi rc = mod_remove(&bnx_modlinkage);
553*eef4f27bSRobert Mustacchi
554*eef4f27bSRobert Mustacchi if (rc == 0) {
555*eef4f27bSRobert Mustacchi mac_fini_ops(&bnx_dev_ops);
556*eef4f27bSRobert Mustacchi }
557*eef4f27bSRobert Mustacchi
558*eef4f27bSRobert Mustacchi return (rc);
559*eef4f27bSRobert Mustacchi }
560*eef4f27bSRobert Mustacchi
561*eef4f27bSRobert Mustacchi /*
562*eef4f27bSRobert Mustacchi * Name: _info
563*eef4f27bSRobert Mustacchi *
564*eef4f27bSRobert Mustacchi * Input: None
565*eef4f27bSRobert Mustacchi *
566*eef4f27bSRobert Mustacchi * Return: SUCCESS or FAILURE.
567*eef4f27bSRobert Mustacchi *
568*eef4f27bSRobert Mustacchi * Description: OS determined module info entry point.
569*eef4f27bSRobert Mustacchi */
570*eef4f27bSRobert Mustacchi int
_info(struct modinfo * modinfop)571*eef4f27bSRobert Mustacchi _info(struct modinfo *modinfop)
572*eef4f27bSRobert Mustacchi {
573*eef4f27bSRobert Mustacchi int rc;
574*eef4f27bSRobert Mustacchi
575*eef4f27bSRobert Mustacchi rc = mod_info(&bnx_modlinkage, modinfop);
576*eef4f27bSRobert Mustacchi
577*eef4f27bSRobert Mustacchi return (rc);
578*eef4f27bSRobert Mustacchi }
579