/*ARGSUSED*/ static int keyspan_pre_attach(dev_info_t *dip, ddi_attach_cmd_t cmd, void *statep) { int instance = ddi_get_instance(dip); keyspan_pre_state_t *kbp = NULL; usb_client_dev_data_t *dev_data = NULL; int rval = DDI_FAILURE; switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } /* attach driver to USBA */ if (usb_client_attach(dip, USBDRV_VERSION, 0) == USB_SUCCESS) { (void) usb_get_dev_data(dip, &dev_data, USB_PARSE_LVL_IF, 0); } if (dev_data == NULL) { goto fail; } /* * If 19HS, needn't download firmware, but need check the current cfg. * If 49WLC, need check the current cfg before download fw. And after * download, the product id will change to KEYSPAN_USA49WLC_PID. */ if (dev_data->dev_descr->idProduct == KEYSPAN_USA19HS_PID || dev_data->dev_descr->idProduct == KEYSPAN_USA49WLC_PID) { if (keyspan_set_cfg(dip) == USB_SUCCESS) { /* Go to keyspan_attach() by return DDI_ECONTEXT. */ rval = DDI_ECONTEXT; } goto fail; } /* * By checking KEYSPAN_FW_FLAG, we can check whether the firmware * has been downloaded. * If firmware is already there, then do normal attach. */ if (!keyspan_need_fw(dev_data)) { /* Go to keyspan_attach() by return DDI_ECONTEXT. */ rval = DDI_ECONTEXT; goto fail; } /* Go on to download firmware. */ if (ddi_soft_state_zalloc(statep, instance) == DDI_SUCCESS) { kbp = ddi_get_soft_state(statep, instance); } if (kbp) { kbp->kb_dip = dip; kbp->kb_instance = instance; kbp->kb_dev_data = dev_data; kbp->kb_def_pipe.pipe_handle = kbp->kb_dev_data->dev_default_ph; kbp->kb_lh = usb_alloc_log_hdl(kbp->kb_dip, "keyspan[*].", &keyspan_pre_errlevel, &keyspan_pre_errmask, &keyspan_pre_instance_debug, 0); kbp->kb_def_pipe.pipe_lh = kbp->kb_lh; if (keyspan_download_firmware(kbp) == USB_SUCCESS) { USB_DPRINTF_L4(DPRINT_ATTACH, kbp->kb_lh, "keyspan_pre_attach: completed."); /* keyspan download firmware done. */ return (DDI_SUCCESS); } } fail: if (kbp) { usb_free_log_hdl(kbp->kb_lh); ddi_soft_state_free(statep, instance); } usb_client_detach(dip, dev_data); return (rval); }
/* * wusb_df_attach: * Attach or resume. * * For attach, initialize state and device, including: * state variables, locks, device node * device registration with system * power management, hotplugging * For resume, restore device and state */ static int wusb_df_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { int instance = ddi_get_instance(dip); char *devinst; int devinstlen; wusb_df_state_t *wusb_dfp = NULL; usb_ep_data_t *ep_datap; int status; switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: wusb_df_cpr_resume(dip); /* * Always return success to work around enumeration failures. * This works around an issue where devices which are present * before a suspend and absent upon resume could cause a system * panic on resume. */ return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (ddi_soft_state_zalloc(wusb_df_statep, instance) == DDI_SUCCESS) { wusb_dfp = ddi_get_soft_state(wusb_df_statep, instance); } if (wusb_dfp == NULL) { return (DDI_FAILURE); } wusb_dfp->wusb_df_dip = dip; devinst = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); devinstlen = snprintf(devinst, USB_MAXSTRINGLEN, "%s%d: ", ddi_driver_name(dip), instance); wusb_dfp->wusb_df_devinst = kmem_zalloc(devinstlen + 1, KM_SLEEP); (void) strncpy(wusb_dfp->wusb_df_devinst, devinst, devinstlen); kmem_free(devinst, USB_MAXSTRINGLEN); wusb_dfp->wusb_df_log_hdl = usb_alloc_log_hdl(dip, "wusb_df", &wusb_df_errlevel, &wusb_df_errmask, &wusb_df_instance_debug, 0); USB_DPRINTF_L4(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl, "Attach: enter for attach"); if ((status = usb_client_attach(dip, USBDRV_VERSION, 0)) != USB_SUCCESS) { USB_DPRINTF_L2(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl, "attach: usb_client_attach failed, error code:%d", status); goto fail; } if ((status = usb_get_dev_data(dip, &wusb_dfp->wusb_df_reg, USB_PARSE_LVL_ALL, 0)) != USB_SUCCESS) { USB_DPRINTF_L2(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl, "attach: usb_get_dev_data failed, error code:%d", status); goto fail; } /* * Get the descriptor for an intr pipe at alt 0 of current interface. * This will be used later to open the pipe. */ if ((ep_datap = usb_lookup_ep_data(dip, wusb_dfp->wusb_df_reg, wusb_dfp->wusb_df_reg->dev_curr_if, 0, 0, USB_EP_ATTR_INTR, USB_EP_DIR_IN)) == NULL) { USB_DPRINTF_L2(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl, "attach: Error getting intr endpoint descriptor"); goto fail; } wusb_dfp->wusb_df_intr_ep_descr = ep_datap->ep_descr; usb_free_descr_tree(dip, wusb_dfp->wusb_df_reg); mutex_init(&wusb_dfp->wusb_df_mutex, NULL, MUTEX_DRIVER, wusb_dfp->wusb_df_reg->dev_iblock_cookie); cv_init(&wusb_dfp->wusb_df_serial_cv, NULL, CV_DRIVER, NULL); wusb_dfp->wusb_df_serial_inuse = B_FALSE; wusb_dfp->wusb_df_locks_initialized = B_TRUE; /* create minor node */ if (ddi_create_minor_node(dip, name, S_IFCHR, instance, "wusb_df", 0) != DDI_SUCCESS) { USB_DPRINTF_L2(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl, "attach: Error creating minor node"); goto fail; } /* Put online before PM init as can get power managed afterward. */ wusb_dfp->wusb_df_dev_state = USB_DEV_ONLINE; /* initialize power management */ wusb_df_init_power_mgmt(wusb_dfp); if (usb_register_hotplug_cbs(dip, wusb_df_disconnect_callback, wusb_df_reconnect_callback) != USB_SUCCESS) { goto fail; } /* Report device */ ddi_report_dev(dip); (void) wusb_df_firmware_download(wusb_dfp); if (usb_reset_device(dip, USB_RESET_LVL_REATTACH) != USB_SUCCESS) { USB_DPRINTF_L2(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl, "reset device failed"); return (USB_FAILURE); } return (DDI_SUCCESS); fail: if (wusb_dfp) { (void) wusb_df_cleanup(dip, wusb_dfp); } return (DDI_FAILURE); }
/* * ds_attach */ static int uftdi_attach(ds_attach_info_t *aip) { uftdi_state_t *uf; usb_dev_descr_t *dd; int recognized; uf = kmem_zalloc(sizeof (*uf), KM_SLEEP); uf->uf_dip = aip->ai_dip; uf->uf_usb_events = aip->ai_usb_events; *aip->ai_hdl = (ds_hdl_t)uf; /* only one port */ *aip->ai_port_cnt = 1; if (usb_client_attach(uf->uf_dip, USBDRV_VERSION, 0) != USB_SUCCESS) { uftdi_cleanup(uf, 1); return (USB_FAILURE); } if (usb_get_dev_data(uf->uf_dip, &uf->uf_dev_data, USB_PARSE_LVL_IF, 0) != USB_SUCCESS) { uftdi_cleanup(uf, 2); return (USB_FAILURE); } uf->uf_hwport = FTDI_PIT_SIOA + uf->uf_dev_data->dev_curr_if; mutex_init(&uf->uf_lock, NULL, MUTEX_DRIVER, uf->uf_dev_data->dev_iblock_cookie); cv_init(&uf->uf_tx_cv, NULL, CV_DRIVER, NULL); uf->uf_lh = usb_alloc_log_hdl(uf->uf_dip, "uftdi", &uftdi_errlevel, &uftdi_errmask, &uftdi_instance_debug, 0); /* * This device and its clones has numerous physical instantiations. */ recognized = B_TRUE; dd = uf->uf_dev_data->dev_descr; switch (dd->idVendor) { case USB_VENDOR_FTDI: switch (dd->idProduct) { case USB_PRODUCT_FTDI_SERIAL_8U232AM: case USB_PRODUCT_FTDI_SEMC_DSS20: case USB_PRODUCT_FTDI_CFA_631: case USB_PRODUCT_FTDI_CFA_632: case USB_PRODUCT_FTDI_CFA_633: case USB_PRODUCT_FTDI_CFA_634: case USB_PRODUCT_FTDI_CFA_635: case USB_PRODUCT_FTDI_USBSERIAL: case USB_PRODUCT_FTDI_MX2_3: case USB_PRODUCT_FTDI_MX4_5: case USB_PRODUCT_FTDI_LK202: case USB_PRODUCT_FTDI_LK204: case USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13M: case USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13S: case USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13U: case USB_PRODUCT_FTDI_EISCOU: case USB_PRODUCT_FTDI_UOPTBR: case USB_PRODUCT_FTDI_EMCU2D: case USB_PRODUCT_FTDI_PCMSFU: case USB_PRODUCT_FTDI_EMCU2H: break; default: recognized = B_FALSE; break; } break; case USB_VENDOR_SIIG2: switch (dd->idProduct) { case USB_PRODUCT_SIIG2_US2308: break; default: recognized = B_FALSE; break; } break; case USB_VENDOR_INTREPIDCS: switch (dd->idProduct) { case USB_PRODUCT_INTREPIDCS_VALUECAN: case USB_PRODUCT_INTREPIDCS_NEOVI: break; default: recognized = B_FALSE; break; } break; case USB_VENDOR_BBELECTRONICS: switch (dd->idProduct) { case USB_PRODUCT_BBELECTRONICS_USOTL4: break; default: recognized = B_FALSE; break; } break; case USB_VENDOR_MELCO: switch (dd->idProduct) { case USB_PRODUCT_MELCO_PCOPRS1: break; default: recognized = B_FALSE; break; } break; case USB_VENDOR_MARVELL: switch (dd->idProduct) { case USB_PRODUCT_MARVELL_SHEEVAPLUG_JTAG: break; default: recognized = B_FALSE; break; } break; default: recognized = B_FALSE; break; } /* * Set 'uftdi_attach_unrecognized' to non-zero to * experiment with newer devices .. */ if (!recognized && !uftdi_attach_unrecognized) { uftdi_cleanup(uf, 3); return (USB_FAILURE); } USB_DPRINTF_L3(DPRINT_ATTACH, uf->uf_lh, "uftdi: matched vendor 0x%x product 0x%x port %d", dd->idVendor, dd->idProduct, uf->uf_hwport); uf->uf_def_ph = uf->uf_dev_data->dev_default_ph; mutex_enter(&uf->uf_lock); uf->uf_dev_state = USB_DEV_ONLINE; uf->uf_port_state = UFTDI_PORT_CLOSED; mutex_exit(&uf->uf_lock); if (uftdi_create_pm_components(uf) != USB_SUCCESS) { uftdi_cleanup(uf, 3); return (USB_FAILURE); } if (usb_register_event_cbs(uf->uf_dip, uf->uf_usb_events, 0) != USB_SUCCESS) { uftdi_cleanup(uf, 4); return (USB_FAILURE); } if (usb_pipe_get_max_bulk_transfer_size(uf->uf_dip, &uf->uf_xfer_sz) != USB_SUCCESS) { uftdi_cleanup(uf, 5); return (USB_FAILURE); } /* * TODO: modern ftdi devices have deeper (and asymmetric) * fifos than this minimal 64 bytes .. but how to tell * -safely- ? */ #define FTDI_MAX_XFERSIZE 64 if (uf->uf_xfer_sz > FTDI_MAX_XFERSIZE) uf->uf_xfer_sz = FTDI_MAX_XFERSIZE; if (uftdi_dev_attach(uf) != USB_SUCCESS) { uftdi_cleanup(uf, 5); return (USB_FAILURE); } return (USB_SUCCESS); }