FreeBSD/sys/dev/twe/twe_freebsd.c
/********************************************************************************
 * Allocate resources, initialise the controller.
 */
Allocate resources, initialise the controller.
Allocate resources initialise the controller .
static int
twe_attach(device_t dev)
{
    struct twe_softc	*sc;
    struct sysctl_oid	*sysctl_tree;
    int			rid, error;
    debug_called(4);
    sc = device_get_softc(dev);
    sc->twe_dev = dev;
    mtx_init(&sc->twe_io_lock, "twe I/O", NULL, MTX_DEF);
    sx_init(&sc->twe_config_lock, "twe config");
    sysctl_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev),
	SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
	device_get_nameunit(dev), CTLFLAG_RD, 0, "");
    if (sysctl_tree == NULL) {
	twe_printf(sc, "cannot add sysctl tree node\n");
	return (ENXIO);
    }
    SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(sysctl_tree),
	OID_AUTO, "driver_version", CTLFLAG_RD, TWE_DRIVER_VERSION_STRING, 0,
	"TWE driver version");
    pci_enable_busmaster(dev);
    rid = TWE_IO_CONFIG_REG;
    if ((sc->twe_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 
        RF_ACTIVE)) == NULL) {
	twe_printf(sc, "can't allocate register window\n");
	twe_free(sc);
	return(ENXIO);
    }
    if (bus_dma_tag_create(bus_get_dma_tag(dev),		
			   1, 0, 				
			   BUS_SPACE_MAXADDR_32BIT, 		
			   BUS_SPACE_MAXADDR, 			
			   NULL, NULL, 				
			   BUS_SPACE_MAXSIZE_32BIT,		
			   BUS_SPACE_UNRESTRICTED,		
			   BUS_SPACE_MAXSIZE_32BIT,		
			   0,					
			   NULL,				
			   NULL,				
			   &sc->twe_parent_dmat)) {
	twe_printf(sc, "can't allocate parent DMA tag\n");
	twe_free(sc);
	return(ENOMEM);
    }
    rid = 0;
    if ((sc->twe_irq = bus_alloc_resource_any(sc->twe_dev, SYS_RES_IRQ,
        &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
	twe_printf(sc, "can't allocate interrupt\n");
	twe_free(sc);
	return(ENXIO);
    }
    if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE,  
		       NULL, twe_pci_intr, sc, &sc->twe_intr)) {
	twe_printf(sc, "can't set up interrupt\n");
	twe_free(sc);
	return(ENXIO);
    }
    if (bus_dma_tag_create(sc->twe_parent_dmat, 	
			   1, 0, 			
			   BUS_SPACE_MAXADDR_32BIT,	
			   BUS_SPACE_MAXADDR, 		
			   NULL, NULL, 			
			   sizeof(TWE_Command) *
			   TWE_Q_LENGTH, 1,		
			   BUS_SPACE_MAXSIZE_32BIT,	
			   0,				
			   NULL,			
			   NULL,			
			   &sc->twe_cmd_dmat)) {
	twe_printf(sc, "can't allocate data buffer DMA tag\n");
	twe_free(sc);
	return(ENOMEM);
    }
    if (bus_dmamem_alloc(sc->twe_cmd_dmat, (void **)&sc->twe_cmd,
			 BUS_DMA_NOWAIT, &sc->twe_cmdmap)) {
	twe_printf(sc, "can't allocate command memory\n");
	return(ENOMEM);
    }
    bus_dmamap_load(sc->twe_cmd_dmat, sc->twe_cmdmap, sc->twe_cmd,
		    sizeof(TWE_Command) * TWE_Q_LENGTH,
		    twe_setup_request_dmamap, sc, 0);
    bzero(sc->twe_cmd, sizeof(TWE_Command) * TWE_Q_LENGTH);
    if (bus_dma_tag_create(sc->twe_parent_dmat, 	
			   1, 0, 			
			   BUS_SPACE_MAXADDR_32BIT,	
			   BUS_SPACE_MAXADDR, 		
			   NULL, NULL, 			
			   (TWE_MAX_SGL_LENGTH - 1) * PAGE_SIZE,
			   TWE_MAX_SGL_LENGTH,		
			   BUS_SPACE_MAXSIZE_32BIT,	
			   BUS_DMA_ALLOCNOW,		
			   busdma_lock_mutex,		
			   &sc->twe_io_lock,		
			   &sc->twe_buffer_dmat)) {
	twe_printf(sc, "can't allocate data buffer DMA tag\n");
	twe_free(sc);
	return(ENOMEM);
    }
    if (bus_dma_tag_create(sc->twe_parent_dmat, 	
			   1, 0, 			
			   BUS_SPACE_MAXADDR_32BIT,	
			   BUS_SPACE_MAXADDR, 		
			   NULL, NULL, 			
			   DFLTPHYS, 1,			
			   BUS_SPACE_MAXSIZE_32BIT,	
			   0,				
			   NULL,			
			   NULL,			
			   &sc->twe_immediate_dmat)) {
	twe_printf(sc, "can't allocate data buffer DMA tag\n");
	twe_free(sc);
	return(ENOMEM);
    }
     if (bus_dmamem_alloc(sc->twe_immediate_dmat, (void **)&sc->twe_immediate,
			  BUS_DMA_NOWAIT, &sc->twe_immediate_map)) {
	twe_printf(sc, "can't allocate memory for immediate requests\n");
	return(ENOMEM);
     }
    if ((error = twe_setup(sc))) {
	twe_free(sc);
	return(error);
    }
    twe_describe_controller(sc);
    sc->twe_dev_t = make_dev(&twe_cdevsw, device_get_unit(sc->twe_dev), UID_ROOT, GID_OPERATOR,
			     S_IRUSR | S_IWUSR, "twe%d", device_get_unit(sc->twe_dev));
    sc->twe_dev_t->si_drv1 = sc;
    sc->twe_ich.ich_func = twe_intrhook;
    sc->twe_ich.ich_arg = sc;
    if (config_intrhook_establish(&sc->twe_ich) != 0) {
	twe_printf(sc, "can't establish configuration hook\n");
	twe_free(sc);
	return(ENXIO);
    }
    return(0);
}
static int twe_attach ( device_t dev ) { struct twe_softc * sc ; struct sysctl_oid * sysctl_tree ; int rid , error ; debug_called ( 4 ) ; sc = device_get_softc ( dev ) ; sc -> twe_dev = dev ; mtx_init ( & sc -> twe_io_lock , " " , NULL , MTX_DEF ) ; sx_init ( & sc -> twe_config_lock , " " ) ; sysctl_tree = SYSCTL_ADD_NODE ( device_get_sysctl_ctx ( dev ) , SYSCTL_STATIC_CHILDREN ( _hw ) , OID_AUTO , device_get_nameunit ( dev ) , CTLFLAG_RD , 0 , " " ) ; if ( sysctl_tree == NULL ) { twe_printf ( sc , " \n " ) ; return ( ENXIO ) ; } SYSCTL_ADD_STRING ( device_get_sysctl_ctx ( dev ) , SYSCTL_CHILDREN ( sysctl_tree ) , OID_AUTO , " " , CTLFLAG_RD , TWE_DRIVER_VERSION_STRING , 0 , " " ) ; pci_enable_busmaster ( dev ) ; rid = TWE_IO_CONFIG_REG ; if ( ( sc -> twe_io = bus_alloc_resource_any ( dev , SYS_RES_IOPORT , & rid , RF_ACTIVE ) ) == NULL ) { twe_printf ( sc , " \n " ) ; twe_free ( sc ) ; return ( ENXIO ) ; } if ( bus_dma_tag_create ( bus_get_dma_tag ( dev ) , 1 , 0 , BUS_SPACE_MAXADDR_32BIT , BUS_SPACE_MAXADDR , NULL , NULL , BUS_SPACE_MAXSIZE_32BIT , BUS_SPACE_UNRESTRICTED , BUS_SPACE_MAXSIZE_32BIT , 0 , NULL , NULL , & sc -> twe_parent_dmat ) ) { twe_printf ( sc , " \n " ) ; twe_free ( sc ) ; return ( ENOMEM ) ; } rid = 0 ; if ( ( sc -> twe_irq = bus_alloc_resource_any ( sc -> twe_dev , SYS_RES_IRQ , & rid , RF_SHAREABLE | RF_ACTIVE ) ) == NULL ) { twe_printf ( sc , " \n " ) ; twe_free ( sc ) ; return ( ENXIO ) ; } if ( bus_setup_intr ( sc -> twe_dev , sc -> twe_irq , INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE , NULL , twe_pci_intr , sc , & sc -> twe_intr ) ) { twe_printf ( sc , " \n " ) ; twe_free ( sc ) ; return ( ENXIO ) ; } if ( bus_dma_tag_create ( sc -> twe_parent_dmat , 1 , 0 , BUS_SPACE_MAXADDR_32BIT , BUS_SPACE_MAXADDR , NULL , NULL , sizeof ( TWE_Command ) * TWE_Q_LENGTH , 1 , BUS_SPACE_MAXSIZE_32BIT , 0 , NULL , NULL , & sc -> twe_cmd_dmat ) ) { twe_printf ( sc , " \n " ) ; twe_free ( sc ) ; return ( ENOMEM ) ; } if ( bus_dmamem_alloc ( sc -> twe_cmd_dmat , ( void * * ) & sc -> twe_cmd , BUS_DMA_NOWAIT , & sc -> twe_cmdmap ) ) { twe_printf ( sc , " \n " ) ; return ( ENOMEM ) ; } bus_dmamap_load ( sc -> twe_cmd_dmat , sc -> twe_cmdmap , sc -> twe_cmd , sizeof ( TWE_Command ) * TWE_Q_LENGTH , twe_setup_request_dmamap , sc , 0 ) ; bzero ( sc -> twe_cmd , sizeof ( TWE_Command ) * TWE_Q_LENGTH ) ; if ( bus_dma_tag_create ( sc -> twe_parent_dmat , 1 , 0 , BUS_SPACE_MAXADDR_32BIT , BUS_SPACE_MAXADDR , NULL , NULL , ( TWE_MAX_SGL_LENGTH - 1 ) * PAGE_SIZE , TWE_MAX_SGL_LENGTH , BUS_SPACE_MAXSIZE_32BIT , BUS_DMA_ALLOCNOW , busdma_lock_mutex , & sc -> twe_io_lock , & sc -> twe_buffer_dmat ) ) { twe_printf ( sc , " \n " ) ; twe_free ( sc ) ; return ( ENOMEM ) ; } if ( bus_dma_tag_create ( sc -> twe_parent_dmat , 1 , 0 , BUS_SPACE_MAXADDR_32BIT , BUS_SPACE_MAXADDR , NULL , NULL , DFLTPHYS , 1 , BUS_SPACE_MAXSIZE_32BIT , 0 , NULL , NULL , & sc -> twe_immediate_dmat ) ) { twe_printf ( sc , " \n " ) ; twe_free ( sc ) ; return ( ENOMEM ) ; } if ( bus_dmamem_alloc ( sc -> twe_immediate_dmat , ( void * * ) & sc -> twe_immediate , BUS_DMA_NOWAIT , & sc -> twe_immediate_map ) ) { twe_printf ( sc , " \n " ) ; return ( ENOMEM ) ; } if ( ( error = twe_setup ( sc ) ) ) { twe_free ( sc ) ; return ( error ) ; } twe_describe_controller ( sc ) ; sc -> twe_dev_t = make_dev ( & twe_cdevsw , device_get_unit ( sc -> twe_dev ) , UID_ROOT , GID_OPERATOR , S_IRUSR | S_IWUSR , " " , device_get_unit ( sc -> twe_dev ) ) ; sc -> twe_dev_t -> si_drv1 = sc ; sc -> twe_ich . ich_func = twe_intrhook ; sc -> twe_ich . ich_arg = sc ; if ( config_intrhook_establish ( & sc -> twe_ich ) != 0 ) { twe_printf ( sc , " \n " ) ; twe_free ( sc ) ; return ( ENXIO ) ; } return ( 0 ) ; }
Allocate resources, initialise the controller.
Allocate resources initialise the controller .
/*
     * Initialise the softc structure.
     */ /*
     * XXX: This sysctl tree must stay at hw.tweX rather than using
     * the device_get_sysctl_tree() created by new-bus because
     * existing 3rd party binary tools such as tw_cli and 3dm2 use the
     * existence of this sysctl node to discover controllers.
     */ /*
     * Force the busmaster enable bit on, in case the BIOS forgot.
     */ /*
     * Allocate the PCI register window.
     */ /*
     * Allocate the parent bus DMA tag appropriate for PCI.
     */ /* PCI parent */ /* alignment, boundary */ /* lowaddr */ /* highaddr */ /* filter, filterarg */ /* maxsize */ /* nsegments */ /* maxsegsize */ /* flags */ /* lockfunc */ /* lockarg */ /* 
     * Allocate and connect our interrupt.
     */ /*
     * Create DMA tag for mapping command's into controller-addressable space.
     */ /* parent */ /* alignment, boundary */ /* lowaddr */ /* highaddr */ /* filter, filterarg */ /* maxsize, nsegments */ /* maxsegsize */ /* flags */ /* lockfunc */ /* lockarg */ /*
     * Allocate memory and make it available for DMA.
     */ /*
     * Create DMA tag for mapping objects into controller-addressable space.
     */ /* parent */ /* alignment, boundary */ /* lowaddr */ /* highaddr */ /* filter, filterarg */ /* maxsize */ /* nsegments */ /* maxsegsize */ /* flags */ /* lockfunc */ /* lockarg */ /*
     * Create DMA tag for mapping objects into controller-addressable space.
     */ /* parent */ /* alignment, boundary */ /* lowaddr */ /* highaddr */ /* filter, filterarg */ /* maxsize, nsegments */ /* maxsegsize */ /* flags */ /* lockfunc */ /* lockarg */ /*
     * Allocate memory for requests which cannot sleep or support continuation.
     */ /*
     * Initialise the controller and driver core.
     */ /*
     * Print some information about the controller and configuration.
     */ /*
     * Create the control device.
     */ /*
     * Schedule ourselves to bring the controller up once interrupts are available.
     * This isn't strictly necessary, since we disable interrupts while probing the
     * controller, but it is more in keeping with common practice for other disk 
     * devices.
     */