FreeBSD/sys/dev/tws/tws.c
/* Attach function is only called if the probe is successful. */
Attach function is only called if the probe is successful.
Attach function is only called if the probe is successful .
static int
tws_attach(device_t dev)
{
    struct tws_softc *sc = device_get_softc(dev);
    u_int32_t bar;
    int error=0,i;
    sc->tws_dev = dev;
    sc->device_id = pci_get_device(dev);
    sc->subvendor_id = pci_get_subvendor(dev);
    sc->subdevice_id = pci_get_subdevice(dev);
    mtx_init( &sc->q_lock, "tws_q_lock", NULL, MTX_DEF);
    mtx_init( &sc->sim_lock,  "tws_sim_lock", NULL, MTX_DEF);
    mtx_init( &sc->gen_lock,  "tws_gen_lock", NULL, MTX_DEF);
    mtx_init( &sc->io_lock,  "tws_io_lock", NULL, MTX_DEF | MTX_RECURSE);
    callout_init(&sc->stats_timer, 1);
    if ( tws_init_trace_q(sc) == FAILURE )
        printf("trace init failure\n");
    mtx_lock(&sc->gen_lock);
    tws_send_event(sc, TWS_INIT_START);
    mtx_unlock(&sc->gen_lock);
#if _BYTE_ORDER == _BIG_ENDIAN
    TWS_TRACE(sc, "BIG endian", 0, 0);
#endif
    sysctl_ctx_init(&sc->tws_clist);
    sc->tws_oidp = SYSCTL_ADD_NODE(&sc->tws_clist,
                                   SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
                                   device_get_nameunit(dev), 
                                   CTLFLAG_RD, 0, "");
    if ( sc->tws_oidp == NULL ) {
        tws_log(sc, SYSCTL_TREE_NODE_ADD);
        goto attach_fail_1;
    }
    SYSCTL_ADD_STRING(&sc->tws_clist, SYSCTL_CHILDREN(sc->tws_oidp),
                      OID_AUTO, "driver_version", CTLFLAG_RD,
                      TWS_DRIVER_VERSION_STRING, 0, "TWS driver version");
    pci_enable_busmaster(dev);
    bar = pci_read_config(dev, TWS_PCI_BAR0, 4);
    TWS_TRACE_DEBUG(sc, "bar0 ", bar, 0);
    bar = pci_read_config(dev, TWS_PCI_BAR1, 4);
    bar = bar & ~TWS_BIT2;
    TWS_TRACE_DEBUG(sc, "bar1 ", bar, 0);
#ifndef TWS_PULL_MODE_ENABLE
    sc->mfa_base = (u_int64_t)pci_read_config(dev, TWS_PCI_BAR2, 4);
    sc->mfa_base = sc->mfa_base & ~TWS_BIT2;
    TWS_TRACE_DEBUG(sc, "bar2 ", sc->mfa_base, 0);
#endif
    sc->reg_res_id = TWS_PCI_BAR1; 
    if ((sc->reg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
                                &(sc->reg_res_id), RF_ACTIVE))
                                == NULL) {
        tws_log(sc, ALLOC_MEMORY_RES);
        goto attach_fail_1;
    }
    sc->bus_tag = rman_get_bustag(sc->reg_res);
    sc->bus_handle = rman_get_bushandle(sc->reg_res);
#ifndef TWS_PULL_MODE_ENABLE
    sc->mfa_res_id = TWS_PCI_BAR2; 
    if ((sc->mfa_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
                          &(sc->mfa_res_id), RF_ACTIVE))
                                == NULL) {
        tws_log(sc, ALLOC_MEMORY_RES);
        goto attach_fail_2;
    }
    sc->bus_mfa_tag = rman_get_bustag(sc->mfa_res);
    sc->bus_mfa_handle = rman_get_bushandle(sc->mfa_res);
#endif
    sc->intr_type = TWS_INTx; 
    if ( tws_enable_msi )
        sc->intr_type = TWS_MSI;
    if ( tws_setup_irq(sc) == FAILURE ) {
        tws_log(sc, ALLOC_MEMORY_RES);
        goto attach_fail_3;
    }
    sc->tws_cdev = make_dev(&tws_cdevsw, device_get_unit(dev),
        UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, "tws%u", 
        device_get_unit(dev));
    sc->tws_cdev->si_drv1 = sc;
    if ( tws_init(sc) == FAILURE ) {
        tws_log(sc, TWS_INIT_FAILURE);
        goto attach_fail_4;
    }
    if ( tws_init_ctlr(sc) == FAILURE ) {
        tws_log(sc, TWS_CTLR_INIT_FAILURE);
        goto attach_fail_4;
    }
    if ((error = tws_cam_attach(sc))) {
        tws_log(sc, TWS_CAM_ATTACH);
        goto attach_fail_4;
    }
    mtx_lock(&sc->gen_lock);
    tws_send_event(sc, TWS_INIT_COMPLETE);
    mtx_unlock(&sc->gen_lock);
    TWS_TRACE_DEBUG(sc, "attached successfully", 0, sc->device_id);
    return(0);
attach_fail_4:
    tws_teardown_intr(sc);
    destroy_dev(sc->tws_cdev);
    if (sc->dma_mem_phys)
	    bus_dmamap_unload(sc->cmd_tag, sc->cmd_map);
    if (sc->dma_mem)
	    bus_dmamem_free(sc->cmd_tag, sc->dma_mem, sc->cmd_map);
    if (sc->cmd_tag)
	    bus_dma_tag_destroy(sc->cmd_tag);
attach_fail_3:
    for(i=0;i<sc->irqs;i++) {
        if ( sc->irq_res[i] ){
            if (bus_release_resource(sc->tws_dev,
                 SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i]))
                TWS_TRACE(sc, "bus irq res", 0, 0);
        }
    }
#ifndef TWS_PULL_MODE_ENABLE
attach_fail_2: 
#endif
    if ( sc->mfa_res ){
        if (bus_release_resource(sc->tws_dev,
                 SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res))
            TWS_TRACE(sc, "bus release ", 0, sc->mfa_res_id);
    }
    if ( sc->reg_res ){
        if (bus_release_resource(sc->tws_dev,
                 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res))
            TWS_TRACE(sc, "bus release2 ", 0, sc->reg_res_id);
    }
attach_fail_1:
    mtx_destroy(&sc->q_lock);
    mtx_destroy(&sc->sim_lock);
    mtx_destroy(&sc->gen_lock);
    mtx_destroy(&sc->io_lock);
    sysctl_ctx_free(&sc->tws_clist);
    return (ENXIO);
}
static int tws_attach ( device_t dev ) { struct tws_softc * sc = device_get_softc ( dev ) ; u_int32_t bar ; int error = 0 , i ; sc -> tws_dev = dev ; sc -> device_id = pci_get_device ( dev ) ; sc -> subvendor_id = pci_get_subvendor ( dev ) ; sc -> subdevice_id = pci_get_subdevice ( dev ) ; mtx_init ( & sc -> q_lock , " " , NULL , MTX_DEF ) ; mtx_init ( & sc -> sim_lock , " " , NULL , MTX_DEF ) ; mtx_init ( & sc -> gen_lock , " " , NULL , MTX_DEF ) ; mtx_init ( & sc -> io_lock , " " , NULL , MTX_DEF | MTX_RECURSE ) ; callout_init ( & sc -> stats_timer , 1 ) ; if ( tws_init_trace_q ( sc ) == FAILURE ) printf ( " \n " ) ; mtx_lock ( & sc -> gen_lock ) ; tws_send_event ( sc , TWS_INIT_START ) ; mtx_unlock ( & sc -> gen_lock ) ; #if _BYTE_ORDER == _BIG_ENDIAN TWS_TRACE ( sc , " " , 0 , 0 ) ; #endif sysctl_ctx_init ( & sc -> tws_clist ) ; sc -> tws_oidp = SYSCTL_ADD_NODE ( & sc -> tws_clist , SYSCTL_STATIC_CHILDREN ( _hw ) , OID_AUTO , device_get_nameunit ( dev ) , CTLFLAG_RD , 0 , " " ) ; if ( sc -> tws_oidp == NULL ) { tws_log ( sc , SYSCTL_TREE_NODE_ADD ) ; goto attach_fail_1 ; } SYSCTL_ADD_STRING ( & sc -> tws_clist , SYSCTL_CHILDREN ( sc -> tws_oidp ) , OID_AUTO , " " , CTLFLAG_RD , TWS_DRIVER_VERSION_STRING , 0 , " " ) ; pci_enable_busmaster ( dev ) ; bar = pci_read_config ( dev , TWS_PCI_BAR0 , 4 ) ; TWS_TRACE_DEBUG ( sc , " " , bar , 0 ) ; bar = pci_read_config ( dev , TWS_PCI_BAR1 , 4 ) ; bar = bar & ~ TWS_BIT2 ; TWS_TRACE_DEBUG ( sc , " " , bar , 0 ) ; #ifndef TWS_PULL_MODE_ENABLE sc -> mfa_base = ( u_int64_t ) pci_read_config ( dev , TWS_PCI_BAR2 , 4 ) ; sc -> mfa_base = sc -> mfa_base & ~ TWS_BIT2 ; TWS_TRACE_DEBUG ( sc , " " , sc -> mfa_base , 0 ) ; #endif sc -> reg_res_id = TWS_PCI_BAR1 ; if ( ( sc -> reg_res = bus_alloc_resource_any ( dev , SYS_RES_MEMORY , & ( sc -> reg_res_id ) , RF_ACTIVE ) ) == NULL ) { tws_log ( sc , ALLOC_MEMORY_RES ) ; goto attach_fail_1 ; } sc -> bus_tag = rman_get_bustag ( sc -> reg_res ) ; sc -> bus_handle = rman_get_bushandle ( sc -> reg_res ) ; #ifndef TWS_PULL_MODE_ENABLE sc -> mfa_res_id = TWS_PCI_BAR2 ; if ( ( sc -> mfa_res = bus_alloc_resource_any ( dev , SYS_RES_MEMORY , & ( sc -> mfa_res_id ) , RF_ACTIVE ) ) == NULL ) { tws_log ( sc , ALLOC_MEMORY_RES ) ; goto attach_fail_2 ; } sc -> bus_mfa_tag = rman_get_bustag ( sc -> mfa_res ) ; sc -> bus_mfa_handle = rman_get_bushandle ( sc -> mfa_res ) ; #endif sc -> intr_type = TWS_INTx ; if ( tws_enable_msi ) sc -> intr_type = TWS_MSI ; if ( tws_setup_irq ( sc ) == FAILURE ) { tws_log ( sc , ALLOC_MEMORY_RES ) ; goto attach_fail_3 ; } sc -> tws_cdev = make_dev ( & tws_cdevsw , device_get_unit ( dev ) , UID_ROOT , GID_OPERATOR , S_IRUSR | S_IWUSR , " " , device_get_unit ( dev ) ) ; sc -> tws_cdev -> si_drv1 = sc ; if ( tws_init ( sc ) == FAILURE ) { tws_log ( sc , TWS_INIT_FAILURE ) ; goto attach_fail_4 ; } if ( tws_init_ctlr ( sc ) == FAILURE ) { tws_log ( sc , TWS_CTLR_INIT_FAILURE ) ; goto attach_fail_4 ; } if ( ( error = tws_cam_attach ( sc ) ) ) { tws_log ( sc , TWS_CAM_ATTACH ) ; goto attach_fail_4 ; } mtx_lock ( & sc -> gen_lock ) ; tws_send_event ( sc , TWS_INIT_COMPLETE ) ; mtx_unlock ( & sc -> gen_lock ) ; TWS_TRACE_DEBUG ( sc , " " , 0 , sc -> device_id ) ; return ( 0 ) ; attach_fail_4 : tws_teardown_intr ( sc ) ; destroy_dev ( sc -> tws_cdev ) ; if ( sc -> dma_mem_phys ) bus_dmamap_unload ( sc -> cmd_tag , sc -> cmd_map ) ; if ( sc -> dma_mem ) bus_dmamem_free ( sc -> cmd_tag , sc -> dma_mem , sc -> cmd_map ) ; if ( sc -> cmd_tag ) bus_dma_tag_destroy ( sc -> cmd_tag ) ; attach_fail_3 : for ( i = 0 ; i < sc -> irqs ; i ++ ) { if ( sc -> irq_res [ i ] ) { if ( bus_release_resource ( sc -> tws_dev , SYS_RES_IRQ , sc -> irq_res_id [ i ] , sc -> irq_res [ i ] ) ) TWS_TRACE ( sc , " " , 0 , 0 ) ; } } #ifndef TWS_PULL_MODE_ENABLE attach_fail_2 : #endif if ( sc -> mfa_res ) { if ( bus_release_resource ( sc -> tws_dev , SYS_RES_MEMORY , sc -> mfa_res_id , sc -> mfa_res ) ) TWS_TRACE ( sc , " " , 0 , sc -> mfa_res_id ) ; } if ( sc -> reg_res ) { if ( bus_release_resource ( sc -> tws_dev , SYS_RES_MEMORY , sc -> reg_res_id , sc -> reg_res ) ) TWS_TRACE ( sc , " " , 0 , sc -> reg_res_id ) ; } attach_fail_1 : mtx_destroy ( & sc -> q_lock ) ; mtx_destroy ( & sc -> sim_lock ) ; mtx_destroy ( & sc -> gen_lock ) ; mtx_destroy ( & sc -> io_lock ) ; sysctl_ctx_free ( & sc -> tws_clist ) ; return ( ENXIO ) ; }
Attach function is only called if the probe is successful.
Attach function is only called if the probe is successful .
/* no tracing yet */ /* Look up our softc and initialize its fields. */ /* Intialize mutexes */ /* send init event */ /* sysctl context setup */ /* MFA base address is BAR2 register used for 
     * push mode. Firmware will evatualy move to 
     * pull mode during witch this needs to change
     */ /* allocate MMIO register space */ /* BAR1 offset */ /* Allocate bus space for inbound mfa */ /* BAR2 offset */ /* Allocate and register our interrupt. */ /* default */ /*
     * Create a /dev entry for this device.  The kernel will assign us
     * a major number automatically.  We use the unit number of this
     * device as the minor number and name the character device
     * "tws<unit>".
     */ /* send init complete event */