mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-22 02:45:38 +08:00
committed by
Kinsey Moore
parent
f7737a09b0
commit
4ac38c5427
+422
-341
File diff suppressed because it is too large
Load Diff
@@ -53,228 +53,224 @@ extern drvmgr_drv_reg_func drvmgr_drivers[];
|
||||
#ifdef CONFIGURE_INIT
|
||||
|
||||
/*** AMBA Plug & Play Drivers ***/
|
||||
extern void gptimer_register_drv(void);
|
||||
extern void apbuart_cons_register_drv(void);
|
||||
extern void greth_register_drv(void);
|
||||
extern void grspw_register_drv(void);
|
||||
extern void grspw2_register_drv(void);
|
||||
extern void grcan_register_drv(void);
|
||||
extern void occan_register_drv(void);
|
||||
extern void gr1553_register(void);
|
||||
extern void gr1553bc_register(void);
|
||||
extern void gr1553bm_register(void);
|
||||
extern void gr1553rt_register(void);
|
||||
extern void b1553brm_register_drv(void);
|
||||
extern void b1553rt_register_drv(void);
|
||||
extern void grtm_register_drv(void);
|
||||
extern void grtc_register_drv(void);
|
||||
extern void pcif_register_drv(void);
|
||||
extern void grpci_register_drv(void);
|
||||
extern void mctrl_register_drv(void);
|
||||
extern void l2cache_register_drv(void);
|
||||
extern void griommu_register_drv(void);
|
||||
extern void grpci2_register_drv(void);
|
||||
extern void spictrl_register_drv(void);
|
||||
extern void i2cmst_register_drv(void);
|
||||
extern void grgpio_register_drv(void);
|
||||
extern void grpwm_register_drv(void);
|
||||
extern void gradcdac_register_drv(void);
|
||||
extern void spwcuc_register(void);
|
||||
extern void grctm_register(void);
|
||||
extern void router_register_drv(void);
|
||||
extern void ahbstat_register_drv(void);
|
||||
extern void memscrub_register_drv(void);
|
||||
extern void l4stat_register_drv(void);
|
||||
extern void spwtdp_register_drv(void);
|
||||
|
||||
extern void gptimer_register_drv( void );
|
||||
extern void apbuart_cons_register_drv( void );
|
||||
extern void greth_register_drv( void );
|
||||
extern void grspw_register_drv( void );
|
||||
extern void grspw2_register_drv( void );
|
||||
extern void grcan_register_drv( void );
|
||||
extern void occan_register_drv( void );
|
||||
extern void gr1553_register( void );
|
||||
extern void gr1553bc_register( void );
|
||||
extern void gr1553bm_register( void );
|
||||
extern void gr1553rt_register( void );
|
||||
extern void b1553brm_register_drv( void );
|
||||
extern void b1553rt_register_drv( void );
|
||||
extern void grtm_register_drv( void );
|
||||
extern void grtc_register_drv( void );
|
||||
extern void pcif_register_drv( void );
|
||||
extern void grpci_register_drv( void );
|
||||
extern void mctrl_register_drv( void );
|
||||
extern void l2cache_register_drv( void );
|
||||
extern void griommu_register_drv( void );
|
||||
extern void grpci2_register_drv( void );
|
||||
extern void spictrl_register_drv( void );
|
||||
extern void i2cmst_register_drv( void );
|
||||
extern void grgpio_register_drv( void );
|
||||
extern void grpwm_register_drv( void );
|
||||
extern void gradcdac_register_drv( void );
|
||||
extern void spwcuc_register( void );
|
||||
extern void grctm_register( void );
|
||||
extern void router_register_drv( void );
|
||||
extern void ahbstat_register_drv( void );
|
||||
extern void memscrub_register_drv( void );
|
||||
extern void l4stat_register_drv( void );
|
||||
extern void spwtdp_register_drv( void );
|
||||
|
||||
/*** LEON2 AMBA Hard coded bus Drivers ***/
|
||||
extern void at697pci_register_drv(void);
|
||||
extern void ambapp_leon2_register(void);
|
||||
|
||||
extern void at697pci_register_drv( void );
|
||||
extern void ambapp_leon2_register( void );
|
||||
|
||||
/*** PCI Bus Drivers (PCI Target drivers) ***/
|
||||
extern void gr_rasta_adcdac_register_drv(void);
|
||||
extern void gr_rasta_io_register_drv(void);
|
||||
extern void gr_rasta_tmtc_register_drv(void);
|
||||
extern void gr701_register_drv(void);
|
||||
extern void gr_tmtc_1553_register_drv(void);
|
||||
extern void gr_rasta_spw_router_register_drv(void);
|
||||
extern void gr_cpci_leon4_n2x_register_drv(void);
|
||||
extern void gr_cpci_gr740_register_drv(void);
|
||||
|
||||
extern void gr_rasta_adcdac_register_drv( void );
|
||||
extern void gr_rasta_io_register_drv( void );
|
||||
extern void gr_rasta_tmtc_register_drv( void );
|
||||
extern void gr701_register_drv( void );
|
||||
extern void gr_tmtc_1553_register_drv( void );
|
||||
extern void gr_rasta_spw_router_register_drv( void );
|
||||
extern void gr_cpci_leon4_n2x_register_drv( void );
|
||||
extern void gr_cpci_gr740_register_drv( void );
|
||||
|
||||
/* CONFIGURE DRIVER MANAGER */
|
||||
drvmgr_drv_reg_func drvmgr_drivers[] = {
|
||||
/*** AMBA Plug & Play Drivers ***/
|
||||
/*** AMBA Plug & Play Drivers ***/
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GPTIMER
|
||||
gptimer_register_drv,
|
||||
gptimer_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_APBUART
|
||||
apbuart_cons_register_drv,
|
||||
apbuart_cons_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRETH
|
||||
greth_register_drv,
|
||||
greth_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRSPW
|
||||
grspw_register_drv,
|
||||
grspw_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRSPW2
|
||||
grspw2_register_drv,
|
||||
grspw2_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRCAN
|
||||
grcan_register_drv,
|
||||
grcan_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_OCCAN
|
||||
occan_register_drv,
|
||||
occan_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GR1553B
|
||||
gr1553_register,
|
||||
gr1553_register,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GR1553BC
|
||||
gr1553bc_register,
|
||||
gr1553bc_register,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GR1553BM
|
||||
gr1553bm_register,
|
||||
gr1553bm_register,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GR1553RT
|
||||
gr1553rt_register,
|
||||
gr1553rt_register,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_B1553BRM
|
||||
b1553brm_register_drv,
|
||||
b1553brm_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_B1553RT
|
||||
b1553rt_register_drv,
|
||||
b1553rt_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRTM
|
||||
grtm_register_drv,
|
||||
grtm_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRTC
|
||||
grtc_register_drv,
|
||||
grtc_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_PCIF
|
||||
pcif_register_drv,
|
||||
pcif_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRPCI
|
||||
grpci_register_drv,
|
||||
grpci_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRPCI2
|
||||
grpci2_register_drv,
|
||||
grpci2_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_MCTRL
|
||||
mctrl_register_drv,
|
||||
mctrl_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_L2CACHE
|
||||
l2cache_register_drv,
|
||||
l2cache_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRIOMMU
|
||||
griommu_register_drv,
|
||||
griommu_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_SPICTRL
|
||||
spictrl_register_drv,
|
||||
spictrl_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_I2CMST
|
||||
i2cmst_register_drv,
|
||||
i2cmst_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRGPIO
|
||||
grgpio_register_drv,
|
||||
grgpio_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRPWM
|
||||
grpwm_register_drv,
|
||||
grpwm_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRADCDAC
|
||||
gradcdac_register_drv,
|
||||
gradcdac_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_SPWCUC
|
||||
spwcuc_register,
|
||||
spwcuc_register,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_GRCTM
|
||||
grctm_register,
|
||||
grctm_register,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_SPW_ROUTER
|
||||
router_register_drv,
|
||||
router_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_AHBSTAT
|
||||
ahbstat_register_drv,
|
||||
ahbstat_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_MEMSCRUB
|
||||
memscrub_register_drv,
|
||||
memscrub_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_L4STAT
|
||||
l4stat_register_drv,
|
||||
l4stat_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_AMBAPP_GAISLER_SPWTDP
|
||||
spwtdp_register_drv,
|
||||
spwtdp_register_drv,
|
||||
#endif
|
||||
|
||||
/*** LEON2 AMBA Drivers ***/
|
||||
/*** LEON2 AMBA Drivers ***/
|
||||
#ifdef CONFIGURE_DRIVER_LEON2_AT697PCI
|
||||
at697pci_register_drv,
|
||||
at697pci_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_LEON2_AMBAPP
|
||||
ambapp_leon2_register,
|
||||
ambapp_leon2_register,
|
||||
#endif
|
||||
|
||||
/*** PCI Target Drivers ***/
|
||||
/*** PCI Target Drivers ***/
|
||||
#ifdef CONFIGURE_DRIVER_PCI_GR_RASTA_ADCDAC
|
||||
gr_rasta_adcdac_register_drv,
|
||||
gr_rasta_adcdac_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_PCI_GR_RASTA_IO
|
||||
gr_rasta_io_register_drv,
|
||||
gr_rasta_io_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_PCI_GR_RASTA_TMTC
|
||||
gr_rasta_tmtc_register_drv,
|
||||
gr_rasta_tmtc_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_PCI_GR_701
|
||||
gr701_register_drv,
|
||||
gr701_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_PCI_GR_TMTC_1553
|
||||
gr_tmtc_1553_register_drv,
|
||||
gr_tmtc_1553_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_PCI_GR_RASTA_SPW_ROUTER
|
||||
gr_rasta_spw_router_register_drv,
|
||||
gr_rasta_spw_router_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_PCI_GR_LEON4_N2X
|
||||
gr_cpci_leon4_n2x_register_drv,
|
||||
gr_cpci_leon4_n2x_register_drv,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_PCI_GR_CPCI_GR740
|
||||
gr_cpci_gr740_register_drv,
|
||||
gr_cpci_gr740_register_drv,
|
||||
#endif
|
||||
|
||||
|
||||
/* Macros for adding custom drivers without needing to recompile
|
||||
* kernel.
|
||||
*/
|
||||
#ifdef CONFIGURE_DRIVER_CUSTOM1
|
||||
DRIVER_CUSTOM1_REG,
|
||||
DRIVER_CUSTOM1_REG,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_CUSTOM2
|
||||
DRIVER_CUSTOM2_REG,
|
||||
DRIVER_CUSTOM2_REG,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_CUSTOM3
|
||||
DRIVER_CUSTOM3_REG,
|
||||
DRIVER_CUSTOM3_REG,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_CUSTOM4
|
||||
DRIVER_CUSTOM4_REG,
|
||||
DRIVER_CUSTOM4_REG,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_CUSTOM5
|
||||
DRIVER_CUSTOM5_REG,
|
||||
DRIVER_CUSTOM5_REG,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_CUSTOM6
|
||||
DRIVER_CUSTOM6_REG,
|
||||
DRIVER_CUSTOM6_REG,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_CUSTOM7
|
||||
DRIVER_CUSTOM7_REG,
|
||||
DRIVER_CUSTOM7_REG,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_CUSTOM8
|
||||
DRIVER_CUSTOM8_REG,
|
||||
DRIVER_CUSTOM8_REG,
|
||||
#endif
|
||||
#ifdef CONFIGURE_DRIVER_CUSTOM9
|
||||
DRIVER_CUSTOM9_REG,
|
||||
DRIVER_CUSTOM9_REG,
|
||||
#endif
|
||||
|
||||
/* End array with NULL */
|
||||
NULL
|
||||
/* End array with NULL */
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* CONFIGURE_INIT */
|
||||
|
||||
@@ -46,31 +46,34 @@ extern "C" {
|
||||
|
||||
/*! List description, Singly link list with head and tail pointers. */
|
||||
struct drvmgr_list {
|
||||
void *head; /*!< First entry in queue */
|
||||
void *tail; /*!< Last entry in queue */
|
||||
int ofs; /*!< Offset into head and tail to find next field */
|
||||
void *head; /*!< First entry in queue */
|
||||
void *tail; /*!< Last entry in queue */
|
||||
int ofs; /*!< Offset into head and tail to find next field */
|
||||
};
|
||||
|
||||
/* Static initialization of list */
|
||||
#define LIST_INITIALIZER(type, field) {NULL, NULL, offsetof(type, field)}
|
||||
#define LIST_INITIALIZER( type, field ) { NULL, NULL, offsetof( type, field ) }
|
||||
|
||||
/* Return the first element in list */
|
||||
#define LIST_HEAD(list, type) ((type *)(list)->head)
|
||||
#define LIST_HEAD( list, type ) ( (type *) ( list )->head )
|
||||
|
||||
/* Return the last element in list */
|
||||
#define LIST_TAIL(list, type) ((type *)(list)->tail)
|
||||
#define LIST_TAIL( list, type ) ( (type *) ( list )->tail )
|
||||
|
||||
/* Get the next pointer of an entry */
|
||||
#define LIST_FIELD(list, entry) (*(void **)((char *)(entry) + (list)->ofs))
|
||||
#define LIST_FIELD( list, entry ) \
|
||||
( *(void **) ( (char *) ( entry ) + ( list )->ofs ) )
|
||||
|
||||
/* Return the next emlement in list */
|
||||
#define LIST_NEXT(list, entry, type) ((type *)(LIST_FIELD(list, entry)))
|
||||
#define LIST_NEXT( list, entry, type ) \
|
||||
( (type *) ( LIST_FIELD( list, entry ) ) )
|
||||
|
||||
/* Iterate through all entries in list */
|
||||
#define LIST_FOR_EACH(list, entry, type) \
|
||||
for (entry = LIST_HEAD(list, type); \
|
||||
entry; \
|
||||
entry = LIST_NEXT(list, entry, type))
|
||||
#define LIST_FOR_EACH( list, entry, type ) \
|
||||
for ( \
|
||||
entry = LIST_HEAD( list, type ); entry; \
|
||||
entry = LIST_NEXT( list, entry, type ) \
|
||||
)
|
||||
|
||||
/*! Initialize a list during runtime
|
||||
*
|
||||
@@ -78,22 +81,22 @@ struct drvmgr_list {
|
||||
* \param offset The number of bytes into the entry structure the next pointer
|
||||
* is found
|
||||
*/
|
||||
extern void drvmgr_list_init(struct drvmgr_list *list, int offset);
|
||||
extern void drvmgr_list_init( struct drvmgr_list *list, int offset );
|
||||
|
||||
/*! Clear list */
|
||||
extern void drvmgr_list_empty(struct drvmgr_list *list);
|
||||
extern void drvmgr_list_empty( struct drvmgr_list *list );
|
||||
|
||||
/*! Add entry to front of list */
|
||||
extern void drvmgr_list_add_head(struct drvmgr_list *list, void *entry);
|
||||
extern void drvmgr_list_add_head( struct drvmgr_list *list, void *entry );
|
||||
|
||||
/*! Add entry to end of list */
|
||||
extern void drvmgr_list_add_tail(struct drvmgr_list *list, void *entry);
|
||||
extern void drvmgr_list_add_tail( struct drvmgr_list *list, void *entry );
|
||||
|
||||
/*! Remove entry from front of list */
|
||||
extern void drvmgr_list_remove_head(struct drvmgr_list *list);
|
||||
extern void drvmgr_list_remove_head( struct drvmgr_list *list );
|
||||
|
||||
/*! Remove entry from anywhere in list */
|
||||
extern void drvmgr_list_remove(struct drvmgr_list *list, void *entry);
|
||||
extern void drvmgr_list_remove( struct drvmgr_list *list, void *entry );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -55,120 +55,134 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* PCI Driver ID generation (VENDOR: 16-bit, DEVICE: 16-bit) */
|
||||
#define DRIVER_PCI_ID(vendor, device) \
|
||||
DRIVER_ID(DRVMGR_BUS_TYPE_PCI, \
|
||||
((((vendor) & 0xffff) << 16) | ((device) & 0xffff)))
|
||||
#define DRIVER_PCI_ID( vendor, device ) \
|
||||
DRIVER_ID( \
|
||||
DRVMGR_BUS_TYPE_PCI, \
|
||||
( ( ( ( vendor ) & 0xffff ) << 16 ) | ( ( device ) & 0xffff ) ) \
|
||||
)
|
||||
|
||||
/* PCI Driver ID generation (CLASS: 24-bit) */
|
||||
#define DRIVER_PCI_CLASS(class) \
|
||||
DRIVER_ID(DRVMGR_BUS_TYPE_PCI, ((1 << 32) | ((class) & 0xffffff)))
|
||||
#define DRIVER_PCI_CLASS( class ) \
|
||||
DRIVER_ID( DRVMGR_BUS_TYPE_PCI, ( ( 1 << 32 ) | ( ( class ) & 0xffffff ) ) )
|
||||
|
||||
/* PCI driver IDs (DRIVER_PCI_VENDOR_DEVICE or DRIVER_PCI_CLASS_NAME) */
|
||||
#define DRIVER_PCI_GAISLER_RASTAIO_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_IO)
|
||||
#define DRIVER_PCI_GAISLER_RASTATMTC_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_TMTC)
|
||||
#define DRIVER_PCI_GAISLER_GR701_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_701)
|
||||
#define DRIVER_PCI_GAISLER_RASTAADCDAC_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_ADCDAC)
|
||||
#define DRIVER_PCI_GAISLER_TMTC_1553_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_TMTC_1553)
|
||||
#define DRIVER_PCI_GAISLER_RASTA_SPW_ROUTER_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_SPW_RTR)
|
||||
#define DRIVER_PCI_GAISLER_LEON4_N2X_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_LEON4_N2X)
|
||||
#define DRIVER_PCI_GAISLER_CPCI_GR740_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_CPCI_GR740)
|
||||
#define DRIVER_PCI_GAISLER_RASTAIO_ID \
|
||||
DRIVER_PCI_ID( PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_IO )
|
||||
#define DRIVER_PCI_GAISLER_RASTATMTC_ID \
|
||||
DRIVER_PCI_ID( PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_TMTC )
|
||||
#define DRIVER_PCI_GAISLER_GR701_ID \
|
||||
DRIVER_PCI_ID( PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_701 )
|
||||
#define DRIVER_PCI_GAISLER_RASTAADCDAC_ID \
|
||||
DRIVER_PCI_ID( PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_ADCDAC )
|
||||
#define DRIVER_PCI_GAISLER_TMTC_1553_ID \
|
||||
DRIVER_PCI_ID( PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_TMTC_1553 )
|
||||
#define DRIVER_PCI_GAISLER_RASTA_SPW_ROUTER_ID \
|
||||
DRIVER_PCI_ID( PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_SPW_RTR )
|
||||
#define DRIVER_PCI_GAISLER_LEON4_N2X_ID \
|
||||
DRIVER_PCI_ID( PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_LEON4_N2X )
|
||||
#define DRIVER_PCI_GAISLER_CPCI_GR740_ID \
|
||||
DRIVER_PCI_ID( PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_CPCI_GR740 )
|
||||
|
||||
struct pci_dev_id {
|
||||
uint16_t vendor;
|
||||
uint16_t device;
|
||||
uint16_t subvendor;
|
||||
uint16_t subdevice;
|
||||
uint32_t class; /* 24 lower bits */
|
||||
uint16_t vendor;
|
||||
uint16_t device;
|
||||
uint16_t subvendor;
|
||||
uint16_t subdevice;
|
||||
uint32_t class; /* 24 lower bits */
|
||||
};
|
||||
|
||||
struct pci_dev_id_match {
|
||||
uint16_t vendor;
|
||||
uint16_t device;
|
||||
uint16_t subvendor;
|
||||
uint16_t subdevice;
|
||||
uint32_t class; /* 24 lower bits */
|
||||
uint32_t class_mask; /* 24 lower bits */
|
||||
uint16_t vendor;
|
||||
uint16_t device;
|
||||
uint16_t subvendor;
|
||||
uint16_t subdevice;
|
||||
uint32_t class; /* 24 lower bits */
|
||||
uint32_t class_mask; /* 24 lower bits */
|
||||
};
|
||||
#define PCIID_DEVVEND(vendor, device) \
|
||||
{vendor, device, PCI_ID_ANY, PCI_ID_ANY, 0, 0}
|
||||
#define PCIID_END_TABLE {0, 0, 0, 0, 0, 0}
|
||||
#define PCIID_DEVVEND( vendor, device ) \
|
||||
{ vendor, device, PCI_ID_ANY, PCI_ID_ANY, 0, 0 }
|
||||
#define PCIID_END_TABLE { 0, 0, 0, 0, 0, 0 }
|
||||
|
||||
enum {
|
||||
/* A Device has up to 6 BARs and an optional ROM BAR */
|
||||
PCIDEV_RES_BAR1 = 0,
|
||||
PCIDEV_RES_BAR2 = 1,
|
||||
PCIDEV_RES_BAR3 = 2,
|
||||
PCIDEV_RES_BAR4 = 3,
|
||||
PCIDEV_RES_BAR5 = 4,
|
||||
PCIDEV_RES_BAR6 = 5,
|
||||
PCIDEV_RES_ROM = 6,
|
||||
/* A Device has up to 6 BARs and an optional ROM BAR */
|
||||
PCIDEV_RES_BAR1 = 0,
|
||||
PCIDEV_RES_BAR2 = 1,
|
||||
PCIDEV_RES_BAR3 = 2,
|
||||
PCIDEV_RES_BAR4 = 3,
|
||||
PCIDEV_RES_BAR5 = 4,
|
||||
PCIDEV_RES_BAR6 = 5,
|
||||
PCIDEV_RES_ROM = 6,
|
||||
};
|
||||
/* Maximum Number of Resources of a device */
|
||||
#define PCIDEV_RES_CNT (PCIDEV_RES_ROM + 1)
|
||||
#define PCIDEV_RES_CNT ( PCIDEV_RES_ROM + 1 )
|
||||
|
||||
/* IO, MEMIO or MEM resource. Can be BAR, ROM or Bridge Window */
|
||||
struct pcibus_res {
|
||||
uint32_t address; /* Base Address, CPU accessible */
|
||||
uint32_t size; /* 0=Unimplemented, 0!=Resource Size */
|
||||
struct pci_res *res; /* PCI-layer resource */
|
||||
uint32_t address; /* Base Address, CPU accessible */
|
||||
uint32_t size; /* 0=Unimplemented, 0!=Resource Size */
|
||||
struct pci_res *res; /* PCI-layer resource */
|
||||
};
|
||||
|
||||
struct pci_dev_info {
|
||||
struct pci_dev_id id;
|
||||
uint8_t rev;
|
||||
uint8_t irq; /* 0 = NO IRQ */
|
||||
pci_dev_t pcidev;
|
||||
struct pcibus_res resources[PCIDEV_RES_CNT];
|
||||
struct pci_dev *pci_device;
|
||||
struct pci_dev_id id;
|
||||
uint8_t rev;
|
||||
uint8_t irq; /* 0 = NO IRQ */
|
||||
pci_dev_t pcidev;
|
||||
struct pcibus_res resources[ PCIDEV_RES_CNT ];
|
||||
struct pci_dev *pci_device;
|
||||
};
|
||||
|
||||
struct pci_drv_info {
|
||||
struct drvmgr_drv general; /* General bus info */
|
||||
/* PCI specific bus information */
|
||||
struct pci_dev_id_match *ids; /* Supported hardware */
|
||||
struct drvmgr_drv general; /* General bus info */
|
||||
/* PCI specific bus information */
|
||||
struct pci_dev_id_match *ids; /* Supported hardware */
|
||||
};
|
||||
|
||||
/* Access routines */
|
||||
struct pcibus_regmem_ops {
|
||||
drvmgr_r8 r8;
|
||||
drvmgr_r16 r16;
|
||||
drvmgr_r32 r32;
|
||||
drvmgr_r64 r64;
|
||||
drvmgr_w8 w8;
|
||||
drvmgr_w16 w16;
|
||||
drvmgr_w32 w32;
|
||||
drvmgr_w64 w64;
|
||||
drvmgr_r8 r8;
|
||||
drvmgr_r16 r16;
|
||||
drvmgr_r32 r32;
|
||||
drvmgr_r64 r64;
|
||||
drvmgr_w8 w8;
|
||||
drvmgr_w16 w16;
|
||||
drvmgr_w32 w32;
|
||||
drvmgr_w64 w64;
|
||||
};
|
||||
|
||||
/* Let driver configure PCI bus driver */
|
||||
struct pcibus_config {
|
||||
struct drvmgr_map_entry *maps_up;
|
||||
struct drvmgr_map_entry *maps_down;
|
||||
struct drvmgr_map_entry *maps_up;
|
||||
struct drvmgr_map_entry *maps_down;
|
||||
};
|
||||
|
||||
/* PCI Configuration Space Access - Not implemented (use PCI Lib directly) */
|
||||
#define PCI_FUNC_CFG_R8 DRVMGR_RWFUNC(RW_SIZE_1|RW_READ|RW_CFG)
|
||||
#define PCI_FUNC_CFG_R16 DRVMGR_RWFUNC(RW_SIZE_2|RW_READ|RW_CFG)
|
||||
#define PCI_FUNC_CFG_R32 DRVMGR_RWFUNC(RW_SIZE_4|RW_READ|RW_CFG)
|
||||
#define PCI_FUNC_CFG_W8 DRVMGR_RWFUNC(RW_SIZE_1|RW_WRITE|RW_CFG)
|
||||
#define PCI_FUNC_CFG_W16 DRVMGR_RWFUNC(RW_SIZE_2|RW_WRITE|RW_CFG)
|
||||
#define PCI_FUNC_CFG_W32 DRVMGR_RWFUNC(RW_SIZE_4|RW_WRITE|RW_CFG)
|
||||
#define PCI_FUNC_CFG_R8 DRVMGR_RWFUNC( RW_SIZE_1 | RW_READ | RW_CFG )
|
||||
#define PCI_FUNC_CFG_R16 DRVMGR_RWFUNC( RW_SIZE_2 | RW_READ | RW_CFG )
|
||||
#define PCI_FUNC_CFG_R32 DRVMGR_RWFUNC( RW_SIZE_4 | RW_READ | RW_CFG )
|
||||
#define PCI_FUNC_CFG_W8 DRVMGR_RWFUNC( RW_SIZE_1 | RW_WRITE | RW_CFG )
|
||||
#define PCI_FUNC_CFG_W16 DRVMGR_RWFUNC( RW_SIZE_2 | RW_WRITE | RW_CFG )
|
||||
#define PCI_FUNC_CFG_W32 DRVMGR_RWFUNC( RW_SIZE_4 | RW_WRITE | RW_CFG )
|
||||
|
||||
/* PCI I/O Register Access - Not implemented (use PCI Lib directly) */
|
||||
#define PCI_FUNC_IO_R8 DRVMGR_RWFUNC(RW_SIZE_1|RW_READ|RW_IO)
|
||||
#define PCI_FUNC_IO_R16 DRVMGR_RWFUNC(RW_SIZE_2|RW_READ|RW_IO)
|
||||
#define PCI_FUNC_IO_R32 DRVMGR_RWFUNC(RW_SIZE_4|RW_READ|RW_IO)
|
||||
#define PCI_FUNC_IO_W8 DRVMGR_RWFUNC(RW_SIZE_1|RW_WRITE|RW_IO)
|
||||
#define PCI_FUNC_IO_W16 DRVMGR_RWFUNC(RW_SIZE_2|RW_WRITE|RW_IO)
|
||||
#define PCI_FUNC_IO_W32 DRVMGR_RWFUNC(RW_SIZE_4|RW_WRITE|RW_IO)
|
||||
#define PCI_FUNC_IO_R8 DRVMGR_RWFUNC( RW_SIZE_1 | RW_READ | RW_IO )
|
||||
#define PCI_FUNC_IO_R16 DRVMGR_RWFUNC( RW_SIZE_2 | RW_READ | RW_IO )
|
||||
#define PCI_FUNC_IO_R32 DRVMGR_RWFUNC( RW_SIZE_4 | RW_READ | RW_IO )
|
||||
#define PCI_FUNC_IO_W8 DRVMGR_RWFUNC( RW_SIZE_1 | RW_WRITE | RW_IO )
|
||||
#define PCI_FUNC_IO_W16 DRVMGR_RWFUNC( RW_SIZE_2 | RW_WRITE | RW_IO )
|
||||
#define PCI_FUNC_IO_W32 DRVMGR_RWFUNC( RW_SIZE_4 | RW_WRITE | RW_IO )
|
||||
|
||||
/* PCI Register Access over Memory Space (Little Endian) */
|
||||
#define PCI_FUNC_MREG_R8 DRVMGR_RWFUNC(RW_SIZE_1|RW_READ|RW_MEMREG)
|
||||
#define PCI_FUNC_MREG_R16 DRVMGR_RWFUNC(RW_SIZE_2|RW_READ|RW_MEMREG|RW_LITTLE)
|
||||
#define PCI_FUNC_MREG_R32 DRVMGR_RWFUNC(RW_SIZE_4|RW_READ|RW_MEMREG|RW_LITTLE)
|
||||
#define PCI_FUNC_MREG_W8 DRVMGR_RWFUNC(RW_SIZE_1|RW_WRITE|RW_MEMREG)
|
||||
#define PCI_FUNC_MREG_W16 DRVMGR_RWFUNC(RW_SIZE_2|RW_WRITE|RW_MEMREG|RW_LITTLE)
|
||||
#define PCI_FUNC_MREG_W32 DRVMGR_RWFUNC(RW_SIZE_4|RW_WRITE|RW_MEMREG|RW_LITTLE)
|
||||
#define PCI_FUNC_MREG_R8 DRVMGR_RWFUNC( RW_SIZE_1 | RW_READ | RW_MEMREG )
|
||||
#define PCI_FUNC_MREG_R16 \
|
||||
DRVMGR_RWFUNC( RW_SIZE_2 | RW_READ | RW_MEMREG | RW_LITTLE )
|
||||
#define PCI_FUNC_MREG_R32 \
|
||||
DRVMGR_RWFUNC( RW_SIZE_4 | RW_READ | RW_MEMREG | RW_LITTLE )
|
||||
#define PCI_FUNC_MREG_W8 DRVMGR_RWFUNC( RW_SIZE_1 | RW_WRITE | RW_MEMREG )
|
||||
#define PCI_FUNC_MREG_W16 \
|
||||
DRVMGR_RWFUNC( RW_SIZE_2 | RW_WRITE | RW_MEMREG | RW_LITTLE )
|
||||
#define PCI_FUNC_MREG_W32 \
|
||||
DRVMGR_RWFUNC( RW_SIZE_4 | RW_WRITE | RW_MEMREG | RW_LITTLE )
|
||||
|
||||
/* Weak default PCI driver resources, override this from project configuration
|
||||
* to set PCI Bus resources used to configure PCI device drivers.
|
||||
@@ -176,7 +190,10 @@ struct pcibus_config {
|
||||
extern struct drvmgr_bus_res pcibus_drv_resources;
|
||||
|
||||
/* Attach a PCI bus on top of a PCI Host device */
|
||||
extern int pcibus_register(struct drvmgr_dev *dev, struct pcibus_config *cfg);
|
||||
extern int pcibus_register(
|
||||
struct drvmgr_dev *dev,
|
||||
struct pcibus_config *cfg
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+366
-353
File diff suppressed because it is too large
Load Diff
@@ -30,22 +30,23 @@
|
||||
#include "drvmgr_internal.h"
|
||||
|
||||
/* Get driver from driver name */
|
||||
struct drvmgr_drv *drvmgr_drv_by_id(uint64_t id)
|
||||
struct drvmgr_drv *drvmgr_drv_by_id( uint64_t id )
|
||||
{
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_drv *drv = NULL;
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_drv *drv = NULL;
|
||||
|
||||
/* NOTE: No locking is needed here since Driver list is supposed to be
|
||||
/* NOTE: No locking is needed here since Driver list is supposed to be
|
||||
* initialized once during startup, we treat it as a static
|
||||
* read-only list
|
||||
*/
|
||||
|
||||
drv = DRV_LIST_HEAD(&mgr->drivers);
|
||||
while (drv) {
|
||||
if (drv->drv_id == id)
|
||||
break;
|
||||
drv = drv->next;
|
||||
}
|
||||
drv = DRV_LIST_HEAD( &mgr->drivers );
|
||||
while ( drv ) {
|
||||
if ( drv->drv_id == id ) {
|
||||
break;
|
||||
}
|
||||
drv = drv->next;
|
||||
}
|
||||
|
||||
return drv;
|
||||
return drv;
|
||||
}
|
||||
|
||||
@@ -31,25 +31,27 @@
|
||||
#include "drvmgr_internal.h"
|
||||
|
||||
/* Get driver from driver name */
|
||||
struct drvmgr_drv *drvmgr_drv_by_name(const char *name)
|
||||
struct drvmgr_drv *drvmgr_drv_by_name( const char *name )
|
||||
{
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_drv *drv = NULL;
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_drv *drv = NULL;
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
if ( !name ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* NOTE: No locking is needed here since Driver list is supposed to be
|
||||
/* NOTE: No locking is needed here since Driver list is supposed to be
|
||||
* initialized once during startup, we treat it as a static
|
||||
* read-only list
|
||||
*/
|
||||
|
||||
drv = DRV_LIST_HEAD(&mgr->drivers);
|
||||
while (drv) {
|
||||
if (drv->name && (strcmp(drv->name, name) == 0))
|
||||
break;
|
||||
drv = drv->next;
|
||||
}
|
||||
drv = DRV_LIST_HEAD( &mgr->drivers );
|
||||
while ( drv ) {
|
||||
if ( drv->name && ( strcmp( drv->name, name ) == 0 ) ) {
|
||||
break;
|
||||
}
|
||||
drv = drv->next;
|
||||
}
|
||||
|
||||
return drv;
|
||||
return drv;
|
||||
}
|
||||
|
||||
@@ -31,22 +31,25 @@
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include "drvmgr_internal.h"
|
||||
|
||||
static intptr_t dev_name_compare(struct drvmgr_dev *dev, void *arg)
|
||||
static intptr_t dev_name_compare( struct drvmgr_dev *dev, void *arg )
|
||||
{
|
||||
const char *name = arg;
|
||||
const char *name = arg;
|
||||
|
||||
if (dev->name && (strcmp(dev->name, name) == 0))
|
||||
return (intptr_t)dev;
|
||||
else
|
||||
return 0;
|
||||
if ( dev->name && ( strcmp( dev->name, name ) == 0 ) ) {
|
||||
return (intptr_t) dev;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get device by device name or bus name */
|
||||
struct drvmgr_dev *drvmgr_dev_by_name(const char *name)
|
||||
struct drvmgr_dev *drvmgr_dev_by_name( const char *name )
|
||||
{
|
||||
if (!name)
|
||||
return NULL;
|
||||
if ( !name ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (struct drvmgr_dev *)
|
||||
drvmgr_for_each_dev(dev_name_compare, (void *)name, 0);
|
||||
return (
|
||||
struct drvmgr_dev *
|
||||
) drvmgr_for_each_dev( dev_name_compare, (void *) name, 0 );
|
||||
}
|
||||
|
||||
@@ -44,136 +44,152 @@
|
||||
* that was assigned to it
|
||||
*/
|
||||
int drvmgr_get_dev(
|
||||
struct drvmgr_drv *drv,
|
||||
int minor,
|
||||
struct drvmgr_dev **pdev)
|
||||
struct drvmgr_drv *drv,
|
||||
int minor,
|
||||
struct drvmgr_dev **pdev
|
||||
)
|
||||
{
|
||||
struct drvmgr_dev *dev;
|
||||
if (!drv)
|
||||
return -1;
|
||||
struct drvmgr_dev *dev;
|
||||
if ( !drv ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
DRVMGR_LOCK_READ();
|
||||
dev = drv->dev;
|
||||
while (dev) {
|
||||
if (dev->minor_drv == minor)
|
||||
break;
|
||||
dev = dev->next_in_drv;
|
||||
}
|
||||
DRVMGR_UNLOCK();
|
||||
if (!dev)
|
||||
return -1;
|
||||
if (pdev)
|
||||
*pdev = dev;
|
||||
return 0;
|
||||
DRVMGR_LOCK_READ();
|
||||
dev = drv->dev;
|
||||
while ( dev ) {
|
||||
if ( dev->minor_drv == minor ) {
|
||||
break;
|
||||
}
|
||||
dev = dev->next_in_drv;
|
||||
}
|
||||
DRVMGR_UNLOCK();
|
||||
if ( !dev ) {
|
||||
return -1;
|
||||
}
|
||||
if ( pdev ) {
|
||||
*pdev = dev;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get Bus frequency in HZ from bus driver */
|
||||
int drvmgr_freq_get(
|
||||
struct drvmgr_dev *dev,
|
||||
int options,
|
||||
unsigned int *freq_hz)
|
||||
struct drvmgr_dev *dev,
|
||||
int options,
|
||||
unsigned int *freq_hz
|
||||
)
|
||||
{
|
||||
if (!dev || !dev->parent || !dev->parent->ops->get_freq)
|
||||
return -1;
|
||||
if ( !dev || !dev->parent || !dev->parent->ops->get_freq ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->parent->ops->get_freq(dev, options, freq_hz);
|
||||
return dev->parent->ops->get_freq( dev, options, freq_hz );
|
||||
}
|
||||
|
||||
/* Get driver prefix */
|
||||
int drvmgr_get_dev_prefix(struct drvmgr_dev *dev, char *dev_prefix)
|
||||
int drvmgr_get_dev_prefix( struct drvmgr_dev *dev, char *dev_prefix )
|
||||
{
|
||||
struct drvmgr_bus_params params;
|
||||
if (!dev || !dev->parent || !dev->parent->ops->get_params)
|
||||
return -1;
|
||||
struct drvmgr_bus_params params;
|
||||
if ( !dev || !dev->parent || !dev->parent->ops->get_params ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev->parent->ops->get_params(dev, ¶ms);
|
||||
if (!params.dev_prefix)
|
||||
return -1;
|
||||
if (dev_prefix)
|
||||
strcpy(dev_prefix, params.dev_prefix);
|
||||
return 0;
|
||||
dev->parent->ops->get_params( dev, ¶ms );
|
||||
if ( !params.dev_prefix ) {
|
||||
return -1;
|
||||
}
|
||||
if ( dev_prefix ) {
|
||||
strcpy( dev_prefix, params.dev_prefix );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Register an interrupt */
|
||||
int drvmgr_interrupt_register(
|
||||
struct drvmgr_dev *dev,
|
||||
int index,
|
||||
const char *info,
|
||||
drvmgr_isr isr,
|
||||
void *arg)
|
||||
struct drvmgr_dev *dev,
|
||||
int index,
|
||||
const char *info,
|
||||
drvmgr_isr isr,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
if (!dev || !dev->parent || !dev->parent->ops->int_register)
|
||||
return -1;
|
||||
if ( !dev || !dev->parent || !dev->parent->ops->int_register ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!isr)
|
||||
return -1;
|
||||
if ( !isr ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->parent->ops->int_register(dev, index, info, isr, arg);
|
||||
return dev->parent->ops->int_register( dev, index, info, isr, arg );
|
||||
}
|
||||
|
||||
/* Unregister an interrupt */
|
||||
int drvmgr_interrupt_unregister(
|
||||
struct drvmgr_dev *dev,
|
||||
int index,
|
||||
drvmgr_isr isr,
|
||||
void *arg)
|
||||
struct drvmgr_dev *dev,
|
||||
int index,
|
||||
drvmgr_isr isr,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
if (!dev || !dev->parent || !dev->parent->ops->int_unregister)
|
||||
return -1;
|
||||
if ( !dev || !dev->parent || !dev->parent->ops->int_unregister ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!isr)
|
||||
return -1;
|
||||
if ( !isr ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->parent->ops->int_unregister(dev, index, isr, arg);
|
||||
return dev->parent->ops->int_unregister( dev, index, isr, arg );
|
||||
}
|
||||
|
||||
int drvmgr_interrupt_clear(
|
||||
struct drvmgr_dev *dev,
|
||||
int index)
|
||||
int drvmgr_interrupt_clear( struct drvmgr_dev *dev, int index )
|
||||
{
|
||||
if (!dev || !dev->parent || !dev->parent->ops->int_clear)
|
||||
return -1;
|
||||
if ( !dev || !dev->parent || !dev->parent->ops->int_clear ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->parent->ops->int_clear(dev, index);
|
||||
return dev->parent->ops->int_clear( dev, index );
|
||||
}
|
||||
|
||||
int drvmgr_interrupt_unmask(
|
||||
struct drvmgr_dev *dev,
|
||||
int index)
|
||||
int drvmgr_interrupt_unmask( struct drvmgr_dev *dev, int index )
|
||||
{
|
||||
if (!dev || !dev->parent || !dev->parent->ops->int_unmask)
|
||||
return -1;
|
||||
if ( !dev || !dev->parent || !dev->parent->ops->int_unmask ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->parent->ops->int_unmask(dev, index);
|
||||
return dev->parent->ops->int_unmask( dev, index );
|
||||
}
|
||||
|
||||
int drvmgr_interrupt_mask(
|
||||
struct drvmgr_dev *dev,
|
||||
int index)
|
||||
int drvmgr_interrupt_mask( struct drvmgr_dev *dev, int index )
|
||||
{
|
||||
if (!dev || !dev->parent || !dev->parent->ops->int_mask)
|
||||
return -1;
|
||||
if ( !dev || !dev->parent || !dev->parent->ops->int_mask ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->parent->ops->int_mask(dev, index);
|
||||
return dev->parent->ops->int_mask( dev, index );
|
||||
}
|
||||
|
||||
#ifdef RTEMS_SMP
|
||||
int drvmgr_interrupt_set_affinity(
|
||||
struct drvmgr_dev *dev,
|
||||
int index,
|
||||
const Processor_mask *cpus)
|
||||
struct drvmgr_dev *dev,
|
||||
int index,
|
||||
const Processor_mask *cpus
|
||||
)
|
||||
{
|
||||
if (!dev || !dev->parent || !dev->parent->ops->int_set_affinity)
|
||||
return -1;
|
||||
if ( !dev || !dev->parent || !dev->parent->ops->int_set_affinity ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->parent->ops->int_set_affinity(dev, index, cpus);
|
||||
return dev->parent->ops->int_set_affinity( dev, index, cpus );
|
||||
}
|
||||
#endif
|
||||
|
||||
int drvmgr_on_rootbus(struct drvmgr_dev *dev)
|
||||
int drvmgr_on_rootbus( struct drvmgr_dev *dev )
|
||||
{
|
||||
if (dev->parent && dev->parent->dev && dev->parent->dev->parent)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
if ( dev->parent && dev->parent->dev && dev->parent->dev->parent ) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,90 +33,96 @@
|
||||
|
||||
/* Traverse device tree breadth-first. Supports up to 31 buses */
|
||||
static intptr_t drvmgr_for_each_dev_breadth(
|
||||
intptr_t (*func)(struct drvmgr_dev *dev, void *arg),
|
||||
void *arg
|
||||
)
|
||||
intptr_t ( *func )( struct drvmgr_dev *dev, void *arg ),
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
int ret = 0, i, pos;
|
||||
struct drvmgr_bus *bus, *buses[32];
|
||||
struct drvmgr_dev *dev;
|
||||
int ret = 0, i, pos;
|
||||
struct drvmgr_bus *bus, *buses[ 32 ];
|
||||
struct drvmgr_dev *dev;
|
||||
|
||||
pos = 0;
|
||||
memset(&buses[0], 0, sizeof(buses));
|
||||
buses[pos++] = drvmgr.root_dev.bus; /* Get root bus */
|
||||
pos = 0;
|
||||
memset( &buses[ 0 ], 0, sizeof( buses ) );
|
||||
buses[ pos++ ] = drvmgr.root_dev.bus; /* Get root bus */
|
||||
|
||||
for (i = 0, bus = buses[0]; buses[i]; i++, bus = buses[i]) {
|
||||
dev = bus->children;
|
||||
while (dev) {
|
||||
ret = func(dev, arg);
|
||||
if (ret != 0)
|
||||
break;
|
||||
if (dev->bus && pos < 31)
|
||||
buses[pos++] = dev->bus;
|
||||
for ( i = 0, bus = buses[ 0 ]; buses[ i ]; i++, bus = buses[ i ] ) {
|
||||
dev = bus->children;
|
||||
while ( dev ) {
|
||||
ret = func( dev, arg );
|
||||
if ( ret != 0 ) {
|
||||
break;
|
||||
}
|
||||
if ( dev->bus && pos < 31 ) {
|
||||
buses[ pos++ ] = dev->bus;
|
||||
}
|
||||
|
||||
dev = dev->next_in_bus;
|
||||
}
|
||||
}
|
||||
dev = dev->next_in_bus;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Traverse device tree depth-first. */
|
||||
static intptr_t drvmgr_for_each_dev_depth(
|
||||
intptr_t (*func)(struct drvmgr_dev *dev, void *arg),
|
||||
void *arg
|
||||
)
|
||||
intptr_t ( *func )( struct drvmgr_dev *dev, void *arg ),
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
int ret = 0;
|
||||
struct drvmgr_dev *dev;
|
||||
int ret = 0;
|
||||
struct drvmgr_dev *dev;
|
||||
|
||||
/* Get first device */
|
||||
dev = drvmgr.root_dev.bus->children;
|
||||
/* Get first device */
|
||||
dev = drvmgr.root_dev.bus->children;
|
||||
|
||||
while (dev) {
|
||||
ret = func(dev, arg);
|
||||
if (ret != 0)
|
||||
break;
|
||||
if (dev->bus && dev->bus->children) {
|
||||
dev = dev->bus->children;
|
||||
} else {
|
||||
next_dev:
|
||||
if (dev->next_in_bus == NULL) {
|
||||
/* Step up one level... back to parent bus */
|
||||
dev = dev->parent->dev;
|
||||
if (dev == &drvmgr.root_dev)
|
||||
break;
|
||||
goto next_dev;
|
||||
} else {
|
||||
dev = dev->next_in_bus;
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( dev ) {
|
||||
ret = func( dev, arg );
|
||||
if ( ret != 0 ) {
|
||||
break;
|
||||
}
|
||||
if ( dev->bus && dev->bus->children ) {
|
||||
dev = dev->bus->children;
|
||||
} else {
|
||||
next_dev:
|
||||
if ( dev->next_in_bus == NULL ) {
|
||||
/* Step up one level... back to parent bus */
|
||||
dev = dev->parent->dev;
|
||||
if ( dev == &drvmgr.root_dev ) {
|
||||
break;
|
||||
}
|
||||
goto next_dev;
|
||||
} else {
|
||||
dev = dev->next_in_bus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Traverse device tree depth-first or breadth-first */
|
||||
intptr_t drvmgr_for_each_dev(
|
||||
intptr_t (*func)(struct drvmgr_dev *dev, void *arg),
|
||||
void *arg,
|
||||
int options
|
||||
)
|
||||
intptr_t ( *func )( struct drvmgr_dev *dev, void *arg ),
|
||||
void *arg,
|
||||
int options
|
||||
)
|
||||
{
|
||||
intptr_t ret;
|
||||
intptr_t ret;
|
||||
|
||||
DRVMGR_LOCK_READ();
|
||||
DRVMGR_LOCK_READ();
|
||||
|
||||
/* Get Root Device */
|
||||
if (drvmgr.root_dev.bus->children != NULL) {
|
||||
if (options & DRVMGR_FED_BF)
|
||||
ret = drvmgr_for_each_dev_breadth(func, arg);
|
||||
else
|
||||
ret = drvmgr_for_each_dev_depth(func, arg);
|
||||
} else
|
||||
ret = 0;
|
||||
/* Get Root Device */
|
||||
if ( drvmgr.root_dev.bus->children != NULL ) {
|
||||
if ( options & DRVMGR_FED_BF ) {
|
||||
ret = drvmgr_for_each_dev_breadth( func, arg );
|
||||
} else {
|
||||
ret = drvmgr_for_each_dev_depth( func, arg );
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
DRVMGR_UNLOCK();
|
||||
DRVMGR_UNLOCK();
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -31,32 +31,37 @@
|
||||
#include "drvmgr_internal.h"
|
||||
|
||||
int drvmgr_for_each_listdev(
|
||||
struct drvmgr_list *devlist,
|
||||
unsigned int state_set_mask,
|
||||
unsigned int state_clr_mask,
|
||||
int (*func)(struct drvmgr_dev *dev, void *arg),
|
||||
void *arg
|
||||
)
|
||||
struct drvmgr_list *devlist,
|
||||
unsigned int state_set_mask,
|
||||
unsigned int state_clr_mask,
|
||||
int ( *func )( struct drvmgr_dev *dev, void *arg ),
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
struct drvmgr_dev *dev;
|
||||
int ret = 0;
|
||||
struct drvmgr_dev *dev;
|
||||
int ret = 0;
|
||||
|
||||
DRVMGR_LOCK_READ();
|
||||
DRVMGR_LOCK_READ();
|
||||
|
||||
/* Get First Device */
|
||||
dev = DEV_LIST_HEAD(devlist);
|
||||
while (dev) {
|
||||
if (((state_set_mask != 0) && ((dev->state & state_set_mask) == state_set_mask)) ||
|
||||
((state_clr_mask != 0) && ((dev->state & state_clr_mask) == 0)) ||
|
||||
((state_set_mask == 0) && (state_clr_mask == 0))) {
|
||||
ret = func(dev, arg);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
dev = dev->next;
|
||||
}
|
||||
/* Get First Device */
|
||||
dev = DEV_LIST_HEAD( devlist );
|
||||
while ( dev ) {
|
||||
if (
|
||||
( ( state_set_mask != 0 ) &&
|
||||
( ( dev->state & state_set_mask ) == state_set_mask ) ) ||
|
||||
( ( state_clr_mask != 0 ) &&
|
||||
( ( dev->state & state_clr_mask ) == 0 ) ) ||
|
||||
( ( state_set_mask == 0 ) && ( state_clr_mask == 0 ) )
|
||||
) {
|
||||
ret = func( dev, arg );
|
||||
if ( ret != 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
dev = dev->next;
|
||||
}
|
||||
|
||||
DRVMGR_UNLOCK();
|
||||
DRVMGR_UNLOCK();
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -29,32 +29,35 @@
|
||||
#include <drvmgr/drvmgr.h>
|
||||
|
||||
/* Get Function from Function ID */
|
||||
int drvmgr_func_get(void *obj, int funcid, void **func)
|
||||
int drvmgr_func_get( void *obj, int funcid, void **func )
|
||||
{
|
||||
int objtype;
|
||||
struct drvmgr_func *f;
|
||||
int objtype;
|
||||
struct drvmgr_func *f;
|
||||
|
||||
if (!obj)
|
||||
return DRVMGR_FAIL;
|
||||
objtype = *(int *)obj;
|
||||
if ( !obj ) {
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
objtype = *(int *) obj;
|
||||
|
||||
if (objtype == DRVMGR_OBJ_BUS)
|
||||
f = ((struct drvmgr_bus *)obj)->funcs;
|
||||
else if (objtype == DRVMGR_OBJ_DRV)
|
||||
f = ((struct drvmgr_drv *)obj)->funcs;
|
||||
else
|
||||
return DRVMGR_FAIL;
|
||||
if ( objtype == DRVMGR_OBJ_BUS ) {
|
||||
f = ( (struct drvmgr_bus *) obj )->funcs;
|
||||
} else if ( objtype == DRVMGR_OBJ_DRV ) {
|
||||
f = ( (struct drvmgr_drv *) obj )->funcs;
|
||||
} else {
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
|
||||
if (f == NULL)
|
||||
return DRVMGR_FAIL;
|
||||
if ( f == NULL ) {
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
|
||||
while (f->funcid != DRVMGR_FUNCID_NONE) {
|
||||
if (f->funcid == funcid) {
|
||||
*func = f->func;
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
f++;
|
||||
}
|
||||
while ( f->funcid != DRVMGR_FUNCID_NONE ) {
|
||||
if ( f->funcid == funcid ) {
|
||||
*func = f->func;
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
f++;
|
||||
}
|
||||
|
||||
return DRVMGR_FAIL;
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,19 @@
|
||||
#include <drvmgr/drvmgr.h>
|
||||
|
||||
/* Lookup function from function ID and call it using given arguments */
|
||||
int drvmgr_func_call(void *obj, int funcid, void *a, void *b, void *c, void *d)
|
||||
int drvmgr_func_call(
|
||||
void *obj,
|
||||
int funcid,
|
||||
void *a,
|
||||
void *b,
|
||||
void *c,
|
||||
void *d
|
||||
)
|
||||
{
|
||||
int (*func)(void *arg1, void *arg2, void *arg3, void *arg4) = NULL;
|
||||
int ( *func )( void *arg1, void *arg2, void *arg3, void *arg4 ) = NULL;
|
||||
|
||||
if (drvmgr_func_get(obj, funcid, (void *)&func) != DRVMGR_OK)
|
||||
return DRVMGR_FAIL;
|
||||
return func(a, b, c, d);
|
||||
if ( drvmgr_func_get( obj, funcid, (void *) &func ) != DRVMGR_OK ) {
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
return func( a, b, c, d );
|
||||
}
|
||||
|
||||
@@ -31,14 +31,15 @@
|
||||
/* Init driver manager - all in one go. Typically called from Init task when
|
||||
* user wants to initilize driver manager after startup, otherwise not used.
|
||||
*/
|
||||
int drvmgr_init(void)
|
||||
int drvmgr_init( void )
|
||||
{
|
||||
int level;
|
||||
int level;
|
||||
|
||||
_DRV_Manager_initialization();
|
||||
_DRV_Manager_initialization();
|
||||
|
||||
for (level = 1; level <= DRVMGR_LEVEL_MAX; level++)
|
||||
_DRV_Manager_init_level(level);
|
||||
for ( level = 1; level <= DRVMGR_LEVEL_MAX; level++ ) {
|
||||
_DRV_Manager_init_level( level );
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,56 +32,56 @@
|
||||
* internally by Driver Manager routines.
|
||||
*/
|
||||
struct drvmgr {
|
||||
int level;
|
||||
int initializing_objs;
|
||||
int level;
|
||||
int initializing_objs;
|
||||
|
||||
/* Device tree Lock */
|
||||
API_Mutex_Control lock;
|
||||
/* Device tree Lock */
|
||||
API_Mutex_Control lock;
|
||||
|
||||
/* The first device - The root device and it's driver */
|
||||
struct drvmgr_drv *root_drv;
|
||||
struct drvmgr_dev root_dev;
|
||||
/* The first device - The root device and it's driver */
|
||||
struct drvmgr_drv *root_drv;
|
||||
struct drvmgr_dev root_dev;
|
||||
|
||||
/*!< Linked list of all registered drivers */
|
||||
struct drvmgr_list drivers;
|
||||
/*!< Linked list of all registered drivers */
|
||||
struct drvmgr_list drivers;
|
||||
|
||||
/* Buses that reached a certain initialization level.
|
||||
/* Buses that reached a certain initialization level.
|
||||
* Lists by Level:
|
||||
* N=0 - Not intialized, just registered
|
||||
* N=1..MAX-1 - Reached init level N
|
||||
* N=MAX - Successfully initialized bus
|
||||
*/
|
||||
struct drvmgr_list buses[DRVMGR_LEVEL_MAX+1];
|
||||
/* Buses failed to initialize or has been removed by not freed */
|
||||
struct drvmgr_list buses_inactive;
|
||||
struct drvmgr_list buses[ DRVMGR_LEVEL_MAX + 1 ];
|
||||
/* Buses failed to initialize or has been removed by not freed */
|
||||
struct drvmgr_list buses_inactive;
|
||||
|
||||
/* Devices that reached a certain initialization level.
|
||||
/* Devices that reached a certain initialization level.
|
||||
* Lists by Level:
|
||||
* N=0 - Not intialized, just registered
|
||||
* N=1..MAX-1 - Reached init level N
|
||||
* N=MAX - Successfully initialized device
|
||||
*/
|
||||
struct drvmgr_list devices[DRVMGR_LEVEL_MAX+1];
|
||||
/*!< Devices failed to initialize, removed, ignored, no driver */
|
||||
struct drvmgr_list devices_inactive;
|
||||
struct drvmgr_list devices[ DRVMGR_LEVEL_MAX + 1 ];
|
||||
/*!< Devices failed to initialize, removed, ignored, no driver */
|
||||
struct drvmgr_list devices_inactive;
|
||||
};
|
||||
|
||||
extern struct drvmgr drvmgr;
|
||||
|
||||
extern void _DRV_Manager_Lock(void);
|
||||
extern void _DRV_Manager_Unlock(void);
|
||||
extern void _DRV_Manager_Lock( void );
|
||||
extern void _DRV_Manager_Unlock( void );
|
||||
|
||||
/* The best solution is to implement the locking with a RW lock, however there
|
||||
* is no such API available. Care must be taken so that dead-lock isn't created
|
||||
* for example in recursive functions.
|
||||
*/
|
||||
#if defined(DRVMGR_USE_LOCKS) && (DRVMGR_USE_LOCKS == 1)
|
||||
#if defined( DRVMGR_USE_LOCKS ) && ( DRVMGR_USE_LOCKS == 1 )
|
||||
#define DRVMGR_LOCK_WRITE() _DRV_Manager_Lock()
|
||||
#define DRVMGR_LOCK_READ() _DRV_Manager_Lock()
|
||||
#define DRVMGR_UNLOCK() _DRV_Manager_Unlock()
|
||||
#define DRVMGR_LOCK_READ() _DRV_Manager_Lock()
|
||||
#define DRVMGR_UNLOCK() _DRV_Manager_Unlock()
|
||||
#else
|
||||
/* no locking */
|
||||
#define DRVMGR_LOCK_WRITE()
|
||||
#define DRVMGR_LOCK_READ()
|
||||
#define DRVMGR_UNLOCK()
|
||||
#define DRVMGR_LOCK_WRITE()
|
||||
#define DRVMGR_LOCK_READ()
|
||||
#define DRVMGR_UNLOCK()
|
||||
#endif
|
||||
|
||||
@@ -31,55 +31,59 @@
|
||||
|
||||
/* LIST interface */
|
||||
|
||||
void drvmgr_list_init(struct drvmgr_list *list, int offset)
|
||||
void drvmgr_list_init( struct drvmgr_list *list, int offset )
|
||||
{
|
||||
list->head = list->tail = NULL;
|
||||
list->ofs = offset;
|
||||
list->head = list->tail = NULL;
|
||||
list->ofs = offset;
|
||||
}
|
||||
|
||||
void drvmgr_list_empty(struct drvmgr_list *list)
|
||||
void drvmgr_list_empty( struct drvmgr_list *list )
|
||||
{
|
||||
list->head = list->tail = NULL;
|
||||
list->head = list->tail = NULL;
|
||||
}
|
||||
|
||||
void drvmgr_list_add_head(struct drvmgr_list *list, void *entry)
|
||||
void drvmgr_list_add_head( struct drvmgr_list *list, void *entry )
|
||||
{
|
||||
LIST_FIELD(list, entry) = list->head;
|
||||
if (list->head == NULL)
|
||||
list->tail = entry;
|
||||
list->head = entry;
|
||||
LIST_FIELD( list, entry ) = list->head;
|
||||
if ( list->head == NULL ) {
|
||||
list->tail = entry;
|
||||
}
|
||||
list->head = entry;
|
||||
}
|
||||
|
||||
void drvmgr_list_add_tail(struct drvmgr_list *list, void *entry)
|
||||
void drvmgr_list_add_tail( struct drvmgr_list *list, void *entry )
|
||||
{
|
||||
if (list->tail == NULL)
|
||||
list->head = entry;
|
||||
else
|
||||
LIST_FIELD(list, list->tail) = entry;
|
||||
LIST_FIELD(list, entry) = NULL;
|
||||
list->tail = entry;
|
||||
if ( list->tail == NULL ) {
|
||||
list->head = entry;
|
||||
} else {
|
||||
LIST_FIELD( list, list->tail ) = entry;
|
||||
}
|
||||
LIST_FIELD( list, entry ) = NULL;
|
||||
list->tail = entry;
|
||||
}
|
||||
|
||||
void drvmgr_list_remove_head(struct drvmgr_list *list)
|
||||
void drvmgr_list_remove_head( struct drvmgr_list *list )
|
||||
{
|
||||
list->head = LIST_FIELD(list, list->head);
|
||||
if (list->head == NULL)
|
||||
list->tail = NULL;
|
||||
list->head = LIST_FIELD( list, list->head );
|
||||
if ( list->head == NULL ) {
|
||||
list->tail = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void drvmgr_list_remove(struct drvmgr_list *list, void *entry)
|
||||
void drvmgr_list_remove( struct drvmgr_list *list, void *entry )
|
||||
{
|
||||
void **prevptr = &list->head;
|
||||
void *curr, *prev;
|
||||
void **prevptr = &list->head;
|
||||
void *curr, *prev;
|
||||
|
||||
prev = NULL;
|
||||
curr = list->head;
|
||||
while (curr != entry) {
|
||||
prev = curr;
|
||||
prevptr = &LIST_FIELD(list, curr);
|
||||
curr = LIST_FIELD(list, curr);
|
||||
}
|
||||
*prevptr = LIST_FIELD(list, entry);
|
||||
if (list->tail == entry)
|
||||
list->tail = prev;
|
||||
prev = NULL;
|
||||
curr = list->head;
|
||||
while ( curr != entry ) {
|
||||
prev = curr;
|
||||
prevptr = &LIST_FIELD( list, curr );
|
||||
curr = LIST_FIELD( list, curr );
|
||||
}
|
||||
*prevptr = LIST_FIELD( list, entry );
|
||||
if ( list->tail == entry ) {
|
||||
list->tail = prev;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ void _DRV_Manager_Lock( void )
|
||||
}
|
||||
}
|
||||
|
||||
void _DRV_Manager_Unlock(void)
|
||||
void _DRV_Manager_Unlock( void )
|
||||
{
|
||||
if ( !_System_state_Is_before_initialization( _System_state_Get() ) ) {
|
||||
_API_Mutex_Unlock( &drvmgr.lock );
|
||||
|
||||
+386
-328
File diff suppressed because it is too large
Load Diff
@@ -30,92 +30,100 @@
|
||||
#include <drvmgr/drvmgr.h>
|
||||
|
||||
/* Find all the resource keys for a device among all bus resources */
|
||||
int drvmgr_keys_get(struct drvmgr_dev *dev, struct drvmgr_key **keys)
|
||||
int drvmgr_keys_get( struct drvmgr_dev *dev, struct drvmgr_key **keys )
|
||||
{
|
||||
struct drvmgr_bus *bus;
|
||||
struct drvmgr_bus_res *node;
|
||||
struct drvmgr_drv_res *res;
|
||||
uint64_t drv_id;
|
||||
struct drvmgr_bus *bus;
|
||||
struct drvmgr_bus_res *node;
|
||||
struct drvmgr_drv_res *res;
|
||||
uint64_t drv_id;
|
||||
|
||||
bus = dev->parent;
|
||||
if (!bus || !dev->drv)
|
||||
return -1;
|
||||
bus = dev->parent;
|
||||
if ( !bus || !dev->drv ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
drv_id = dev->drv->drv_id;
|
||||
drv_id = dev->drv->drv_id;
|
||||
|
||||
/* Loop all resource arrays */
|
||||
node = bus->reslist;
|
||||
while (node) {
|
||||
/* Find driver ID in resource array */
|
||||
res = &node->resource[0];
|
||||
while (res->drv_id) {
|
||||
if (res->drv_id == drv_id) {
|
||||
/* Found resource matching driver, now check
|
||||
/* Loop all resource arrays */
|
||||
node = bus->reslist;
|
||||
while ( node ) {
|
||||
/* Find driver ID in resource array */
|
||||
res = &node->resource[ 0 ];
|
||||
while ( res->drv_id ) {
|
||||
if ( res->drv_id == drv_id ) {
|
||||
/* Found resource matching driver, now check
|
||||
* that this resource is for this device.
|
||||
*/
|
||||
if (dev->minor_bus == res->minor_bus) {
|
||||
/* Matching driver and core number */
|
||||
if (keys)
|
||||
*keys = res->keys;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
res++;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
if (keys)
|
||||
*keys = NULL;
|
||||
return 1;
|
||||
if ( dev->minor_bus == res->minor_bus ) {
|
||||
/* Matching driver and core number */
|
||||
if ( keys ) {
|
||||
*keys = res->keys;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
res++;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
if ( keys ) {
|
||||
*keys = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return key that matches key name */
|
||||
struct drvmgr_key *drvmgr_key_get(
|
||||
struct drvmgr_key *keys,
|
||||
char *key_name)
|
||||
struct drvmgr_key *drvmgr_key_get( struct drvmgr_key *keys, char *key_name )
|
||||
{
|
||||
struct drvmgr_key *key;
|
||||
struct drvmgr_key *key;
|
||||
|
||||
if (!keys)
|
||||
return NULL;
|
||||
if ( !keys ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key = keys;
|
||||
while (key->key_type != DRVMGR_KT_NONE) {
|
||||
if (strcmp(key_name, key->key_name) == 0)
|
||||
return key;
|
||||
key++;
|
||||
}
|
||||
return NULL;
|
||||
key = keys;
|
||||
while ( key->key_type != DRVMGR_KT_NONE ) {
|
||||
if ( strcmp( key_name, key->key_name ) == 0 ) {
|
||||
return key;
|
||||
}
|
||||
key++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
union drvmgr_key_value *drvmgr_key_val_get(
|
||||
struct drvmgr_key *keys,
|
||||
char *key_name,
|
||||
enum drvmgr_kt key_type)
|
||||
struct drvmgr_key *keys,
|
||||
char *key_name,
|
||||
enum drvmgr_kt key_type
|
||||
)
|
||||
{
|
||||
struct drvmgr_key *key_match;
|
||||
struct drvmgr_key *key_match;
|
||||
|
||||
key_match = drvmgr_key_get(keys, key_name);
|
||||
if (key_match) {
|
||||
/* Found key, put pointer to value into */
|
||||
if ((key_type == DRVMGR_KT_ANY) ||
|
||||
(key_match->key_type == key_type))
|
||||
return &key_match->key_value;
|
||||
}
|
||||
return NULL;
|
||||
key_match = drvmgr_key_get( keys, key_name );
|
||||
if ( key_match ) {
|
||||
/* Found key, put pointer to value into */
|
||||
if (
|
||||
( key_type == DRVMGR_KT_ANY ) || ( key_match->key_type == key_type )
|
||||
) {
|
||||
return &key_match->key_value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
union drvmgr_key_value *drvmgr_dev_key_get(
|
||||
struct drvmgr_dev *dev,
|
||||
char *key_name,
|
||||
enum drvmgr_kt key_type)
|
||||
struct drvmgr_dev *dev,
|
||||
char *key_name,
|
||||
enum drvmgr_kt key_type
|
||||
)
|
||||
{
|
||||
struct drvmgr_key *keys = NULL;
|
||||
struct drvmgr_key *keys = NULL;
|
||||
|
||||
/* Find first entry in key array for the device */
|
||||
if (drvmgr_keys_get(dev, &keys))
|
||||
return NULL;
|
||||
/* Find first entry in key array for the device */
|
||||
if ( drvmgr_keys_get( dev, &keys ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find a specific key among the device keys */
|
||||
return drvmgr_key_val_get(keys, key_name, key_type);
|
||||
/* Find a specific key among the device keys */
|
||||
return drvmgr_key_val_get( keys, key_name, key_type );
|
||||
}
|
||||
|
||||
@@ -33,38 +33,41 @@
|
||||
* This call will take 128 bytes for buffer on stack
|
||||
*/
|
||||
void drvmgr_rw_memset(
|
||||
void *dstadr,
|
||||
int c,
|
||||
size_t n,
|
||||
void *a,
|
||||
drvmgr_wmem_arg wmem
|
||||
)
|
||||
void *dstadr,
|
||||
int c,
|
||||
size_t n,
|
||||
void *a,
|
||||
drvmgr_wmem_arg wmem
|
||||
)
|
||||
{
|
||||
unsigned long long buf[16+1]; /* Extra bytes after data are reserved
|
||||
unsigned long long buf[ 16 + 1 ]; /* Extra bytes after data are reserved
|
||||
* for optimizations by write_mem */
|
||||
int txlen;
|
||||
char *adr;
|
||||
int txlen;
|
||||
char *adr;
|
||||
|
||||
if (n <= 0)
|
||||
return;
|
||||
if ( n <= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (n > sizeof(unsigned long long)*16)
|
||||
txlen = sizeof(unsigned long long)*16;
|
||||
else
|
||||
txlen = n;
|
||||
if ( n > sizeof( unsigned long long ) * 16 ) {
|
||||
txlen = sizeof( unsigned long long ) * 16;
|
||||
} else {
|
||||
txlen = n;
|
||||
}
|
||||
|
||||
memset(buf, c, txlen);
|
||||
memset( buf, c, txlen );
|
||||
|
||||
adr = dstadr;
|
||||
do {
|
||||
wmem(adr, (const void *)&buf[0], txlen, a);
|
||||
adr += txlen;
|
||||
n -= txlen;
|
||||
adr = dstadr;
|
||||
do {
|
||||
wmem( adr, (const void *) &buf[ 0 ], txlen, a );
|
||||
adr += txlen;
|
||||
n -= txlen;
|
||||
|
||||
/* next length to transmitt */
|
||||
if (n > 16*sizeof(unsigned long long))
|
||||
txlen = 16*sizeof(unsigned long long);
|
||||
else
|
||||
txlen = n;
|
||||
} while (n > 0);
|
||||
/* next length to transmitt */
|
||||
if ( n > 16 * sizeof( unsigned long long ) ) {
|
||||
txlen = 16 * sizeof( unsigned long long );
|
||||
} else {
|
||||
txlen = n;
|
||||
}
|
||||
} while ( n > 0 );
|
||||
}
|
||||
|
||||
@@ -49,119 +49,130 @@
|
||||
#include "drvmgr_internal.h"
|
||||
|
||||
unsigned int drvmgr_translate_bus(
|
||||
struct drvmgr_bus *from,
|
||||
struct drvmgr_bus *to,
|
||||
int reverse,
|
||||
void *src_address,
|
||||
void **dst_address)
|
||||
struct drvmgr_bus *from,
|
||||
struct drvmgr_bus *to,
|
||||
int reverse,
|
||||
void *src_address,
|
||||
void **dst_address
|
||||
)
|
||||
{
|
||||
struct drvmgr_bus *path[16];
|
||||
int dir, levels, i;
|
||||
void *dst, *from_adr, *to_adr;
|
||||
struct drvmgr_map_entry *map;
|
||||
struct drvmgr_bus *bus;
|
||||
ssize_t sz;
|
||||
struct drvmgr_bus *bus_bot, *bus_top;
|
||||
struct drvmgr_bus *path[ 16 ];
|
||||
int dir, levels, i;
|
||||
void *dst, *from_adr, *to_adr;
|
||||
struct drvmgr_map_entry *map;
|
||||
struct drvmgr_bus *bus;
|
||||
ssize_t sz;
|
||||
struct drvmgr_bus *bus_bot, *bus_top;
|
||||
|
||||
dst = src_address;
|
||||
sz = 0xffffffff;
|
||||
dst = src_address;
|
||||
sz = 0xffffffff;
|
||||
|
||||
if (from == to) /* no need translating addresses when on same bus */
|
||||
goto out;
|
||||
if ( from == to ) { /* no need translating addresses when on same bus */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Always find translation path from remote bus towards root bus. All
|
||||
/* Always find translation path from remote bus towards root bus. All
|
||||
* buses have root bus has parent at some level
|
||||
*/
|
||||
if (from->depth > to->depth) {
|
||||
bus_bot = from;
|
||||
bus_top = to;
|
||||
dir = 0;
|
||||
} else {
|
||||
bus_bot = to;
|
||||
bus_top = from;
|
||||
dir = 1;
|
||||
}
|
||||
levels = bus_bot->depth - bus_top->depth;
|
||||
if (levels >= 16)
|
||||
return 0; /* Does not support such a big depth */
|
||||
i = 0;
|
||||
while ((bus_bot != NULL) && bus_bot != bus_top) {
|
||||
if (dir)
|
||||
path[(levels - 1) - i] = bus_bot;
|
||||
else
|
||||
path[i] = bus_bot;
|
||||
i++;
|
||||
bus_bot = bus_bot->dev->parent;
|
||||
}
|
||||
if (bus_bot == NULL)
|
||||
return 0; /* from -> to is not linearly connected */
|
||||
if ( from->depth > to->depth ) {
|
||||
bus_bot = from;
|
||||
bus_top = to;
|
||||
dir = 0;
|
||||
} else {
|
||||
bus_bot = to;
|
||||
bus_top = from;
|
||||
dir = 1;
|
||||
}
|
||||
levels = bus_bot->depth - bus_top->depth;
|
||||
if ( levels >= 16 ) {
|
||||
return 0; /* Does not support such a big depth */
|
||||
}
|
||||
i = 0;
|
||||
while ( ( bus_bot != NULL ) && bus_bot != bus_top ) {
|
||||
if ( dir ) {
|
||||
path[ ( levels - 1 ) - i ] = bus_bot;
|
||||
} else {
|
||||
path[ i ] = bus_bot;
|
||||
}
|
||||
i++;
|
||||
bus_bot = bus_bot->dev->parent;
|
||||
}
|
||||
if ( bus_bot == NULL ) {
|
||||
return 0; /* from -> to is not linearly connected */
|
||||
}
|
||||
|
||||
for (i = 0; i < levels; i++) {
|
||||
bus = path[i];
|
||||
for ( i = 0; i < levels; i++ ) {
|
||||
bus = path[ i ];
|
||||
|
||||
if ((dir && reverse) || (!dir && !reverse))
|
||||
map = bus->maps_up;
|
||||
else
|
||||
map = bus->maps_down;
|
||||
if ( ( dir && reverse ) || ( !dir && !reverse ) ) {
|
||||
map = bus->maps_up;
|
||||
} else {
|
||||
map = bus->maps_down;
|
||||
}
|
||||
|
||||
if (map == NULL)
|
||||
continue; /* No translation needed - 1:1 mapping */
|
||||
if ( map == NULL ) {
|
||||
continue; /* No translation needed - 1:1 mapping */
|
||||
}
|
||||
|
||||
if (map == DRVMGR_TRANSLATE_NO_BRIDGE) {
|
||||
sz = 0;
|
||||
break; /* No bridge interface in this direction */
|
||||
}
|
||||
if ( map == DRVMGR_TRANSLATE_NO_BRIDGE ) {
|
||||
sz = 0;
|
||||
break; /* No bridge interface in this direction */
|
||||
}
|
||||
|
||||
while (map->size != 0) {
|
||||
if (reverse) {
|
||||
/* Opposite direction */
|
||||
from_adr = map->to_adr;
|
||||
to_adr = map->from_adr;
|
||||
} else {
|
||||
from_adr = map->from_adr;
|
||||
to_adr = map->to_adr;
|
||||
}
|
||||
while ( map->size != 0 ) {
|
||||
if ( reverse ) {
|
||||
/* Opposite direction */
|
||||
from_adr = map->to_adr;
|
||||
to_adr = map->from_adr;
|
||||
} else {
|
||||
from_adr = map->from_adr;
|
||||
to_adr = map->to_adr;
|
||||
}
|
||||
|
||||
if ((dst >= from_adr) &&
|
||||
(dst <= (from_adr + (map->size - 1)))) {
|
||||
if (((from_adr + (map->size - 1)) - dst) < sz)
|
||||
sz = (from_adr + (map->size - 1)) - dst;
|
||||
dst = (dst - from_adr) + to_adr;
|
||||
break;
|
||||
}
|
||||
map++;
|
||||
}
|
||||
/* quit if no matching translation information */
|
||||
if (map->size == 0) {
|
||||
sz = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (
|
||||
( dst >= from_adr ) && ( dst <= ( from_adr + ( map->size - 1 ) ) )
|
||||
) {
|
||||
if ( ( ( from_adr + ( map->size - 1 ) ) - dst ) < sz ) {
|
||||
sz = ( from_adr + ( map->size - 1 ) ) - dst;
|
||||
}
|
||||
dst = ( dst - from_adr ) + to_adr;
|
||||
break;
|
||||
}
|
||||
map++;
|
||||
}
|
||||
/* quit if no matching translation information */
|
||||
if ( map->size == 0 ) {
|
||||
sz = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (dst_address)
|
||||
*dst_address = dst;
|
||||
if ( dst_address ) {
|
||||
*dst_address = dst;
|
||||
}
|
||||
|
||||
return sz;
|
||||
return sz;
|
||||
}
|
||||
|
||||
unsigned int drvmgr_translate(
|
||||
struct drvmgr_dev *dev,
|
||||
unsigned int options,
|
||||
void *src_address,
|
||||
void **dst_address)
|
||||
struct drvmgr_dev *dev,
|
||||
unsigned int options,
|
||||
void *src_address,
|
||||
void **dst_address
|
||||
)
|
||||
{
|
||||
struct drvmgr_bus *to, *from;
|
||||
int rev = 0;
|
||||
struct drvmgr_bus *to, *from;
|
||||
int rev = 0;
|
||||
|
||||
rev = (~options) & 1;
|
||||
if ((options == CPUMEM_TO_DMA) || (options == DMAMEM_FROM_CPU)) {
|
||||
from = drvmgr.root_dev.bus;
|
||||
to = dev->parent;
|
||||
} else { /* CPUMEM_FROM_DMA || DMAMEM_TO_CPU */
|
||||
from = dev->parent;
|
||||
to = drvmgr.root_dev.bus;
|
||||
}
|
||||
rev = ( ~options ) & 1;
|
||||
if ( ( options == CPUMEM_TO_DMA ) || ( options == DMAMEM_FROM_CPU ) ) {
|
||||
from = drvmgr.root_dev.bus;
|
||||
to = dev->parent;
|
||||
} else { /* CPUMEM_FROM_DMA || DMAMEM_TO_CPU */
|
||||
from = dev->parent;
|
||||
to = drvmgr.root_dev.bus;
|
||||
}
|
||||
|
||||
return drvmgr_translate_bus(from, to, rev, src_address, dst_address);
|
||||
return drvmgr_translate_bus( from, to, rev, src_address, dst_address );
|
||||
}
|
||||
|
||||
@@ -36,20 +36,25 @@
|
||||
* If size=0 only the starting address is not checked.
|
||||
*/
|
||||
int drvmgr_translate_check(
|
||||
struct drvmgr_dev *dev,
|
||||
unsigned int options,
|
||||
void *src_address,
|
||||
void **dst_address,
|
||||
unsigned int size)
|
||||
struct drvmgr_dev *dev,
|
||||
unsigned int options,
|
||||
void *src_address,
|
||||
void **dst_address,
|
||||
unsigned int size
|
||||
)
|
||||
{
|
||||
unsigned int max;
|
||||
unsigned int max;
|
||||
|
||||
max = drvmgr_translate(dev, options, src_address, dst_address);
|
||||
if (max == 0 || (max < size && (size != 0))) {
|
||||
printk(" ### dev %p (%s) failed mapping %p\n",
|
||||
dev, dev->name ? dev->name : "unnamed", src_address);
|
||||
return -1;
|
||||
}
|
||||
max = drvmgr_translate( dev, options, src_address, dst_address );
|
||||
if ( max == 0 || ( max < size && ( size != 0 ) ) ) {
|
||||
printk(
|
||||
" ### dev %p (%s) failed mapping %p\n",
|
||||
dev,
|
||||
dev->name ? dev->name : "unnamed",
|
||||
src_address
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,20 +37,20 @@
|
||||
* This function is called from the bus driver, from a "safe" state where
|
||||
* devices will not be added or removed on this particular bus at this time
|
||||
*/
|
||||
int drvmgr_children_unregister(struct drvmgr_bus *bus)
|
||||
int drvmgr_children_unregister( struct drvmgr_bus *bus )
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
|
||||
while (bus->children != NULL) {
|
||||
err = drvmgr_dev_unregister(bus->children);
|
||||
if (err != DRVMGR_OK) {
|
||||
/* An error occurred */
|
||||
bus->children->error = err;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
while ( bus->children != NULL ) {
|
||||
err = drvmgr_dev_unregister( bus->children );
|
||||
if ( err != DRVMGR_OK ) {
|
||||
/* An error occurred */
|
||||
bus->children->error = err;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return DRVMGR_OK;
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
/* Unregister a BUS and all it's devices.
|
||||
@@ -59,105 +59,112 @@ int drvmgr_children_unregister(struct drvmgr_bus *bus)
|
||||
* one by one calling drvmgr_dev_unregister(), or by letting the driver
|
||||
* manager unregister all children by calling drvmgr_children_unregister().
|
||||
*/
|
||||
int drvmgr_bus_unregister(struct drvmgr_bus *bus)
|
||||
int drvmgr_bus_unregister( struct drvmgr_bus *bus )
|
||||
{
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_list *list;
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_list *list;
|
||||
|
||||
if (bus->ops->remove == NULL)
|
||||
return DRVMGR_ENOSYS;
|
||||
if ( bus->ops->remove == NULL ) {
|
||||
return DRVMGR_ENOSYS;
|
||||
}
|
||||
|
||||
/* Call Bus driver to clean things up, it must remove all children */
|
||||
bus->error = bus->ops->remove(bus);
|
||||
if (bus->error != DRVMGR_OK)
|
||||
return bus->error;
|
||||
/* Check that bus driver has done its job and removed all children */
|
||||
if (bus->children != NULL)
|
||||
return DRVMGR_FAIL;
|
||||
/* Remove References to bus */
|
||||
bus->dev->bus = NULL;
|
||||
/* Call Bus driver to clean things up, it must remove all children */
|
||||
bus->error = bus->ops->remove( bus );
|
||||
if ( bus->error != DRVMGR_OK ) {
|
||||
return bus->error;
|
||||
}
|
||||
/* Check that bus driver has done its job and removed all children */
|
||||
if ( bus->children != NULL ) {
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
/* Remove References to bus */
|
||||
bus->dev->bus = NULL;
|
||||
|
||||
DRVMGR_LOCK_WRITE();
|
||||
DRVMGR_LOCK_WRITE();
|
||||
|
||||
/* Remove bus from bus-list */
|
||||
if (bus->state & BUS_STATE_LIST_INACTIVE)
|
||||
list = &mgr->buses_inactive;
|
||||
else
|
||||
list = &mgr->buses[bus->level];
|
||||
drvmgr_list_remove(list, bus);
|
||||
/* Remove bus from bus-list */
|
||||
if ( bus->state & BUS_STATE_LIST_INACTIVE ) {
|
||||
list = &mgr->buses_inactive;
|
||||
} else {
|
||||
list = &mgr->buses[ bus->level ];
|
||||
}
|
||||
drvmgr_list_remove( list, bus );
|
||||
|
||||
DRVMGR_UNLOCK();
|
||||
DRVMGR_UNLOCK();
|
||||
|
||||
/* All references to this bus has been removed at this point */
|
||||
free(bus);
|
||||
/* All references to this bus has been removed at this point */
|
||||
free( bus );
|
||||
|
||||
return DRVMGR_OK;
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
/* Separate Driver and Device from each other */
|
||||
int drvmgr_dev_drv_separate(struct drvmgr_dev *dev)
|
||||
int drvmgr_dev_drv_separate( struct drvmgr_dev *dev )
|
||||
{
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_dev *subdev, **pprev;
|
||||
int rc;
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_dev *subdev, **pprev;
|
||||
int rc;
|
||||
|
||||
/* Remove children if this device exports a bus of devices. All
|
||||
/* Remove children if this device exports a bus of devices. All
|
||||
* children must be removed first as they depend upon the bus
|
||||
* services this bridge provide.
|
||||
*/
|
||||
if (dev->bus) {
|
||||
rc = drvmgr_bus_unregister(dev->bus);
|
||||
if (rc != DRVMGR_OK)
|
||||
return rc;
|
||||
}
|
||||
if ( dev->bus ) {
|
||||
rc = drvmgr_bus_unregister( dev->bus );
|
||||
if ( rc != DRVMGR_OK ) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->drv == NULL)
|
||||
return DRVMGR_OK;
|
||||
if ( dev->drv == NULL ) {
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
/* Remove device by letting assigned driver take care of hardware
|
||||
/* Remove device by letting assigned driver take care of hardware
|
||||
* issues
|
||||
*/
|
||||
if (!dev->drv->ops->remove) {
|
||||
/* No remove function is considered severe when someone
|
||||
if ( !dev->drv->ops->remove ) {
|
||||
/* No remove function is considered severe when someone
|
||||
* is trying to remove the device
|
||||
*/
|
||||
return DRVMGR_ENOSYS;
|
||||
}
|
||||
dev->error = dev->drv->ops->remove(dev);
|
||||
if (dev->error != DRVMGR_OK)
|
||||
return DRVMGR_FAIL;
|
||||
return DRVMGR_ENOSYS;
|
||||
}
|
||||
dev->error = dev->drv->ops->remove( dev );
|
||||
if ( dev->error != DRVMGR_OK ) {
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
|
||||
DRVMGR_LOCK_WRITE();
|
||||
DRVMGR_LOCK_WRITE();
|
||||
|
||||
/* Delete device from driver's device list */
|
||||
pprev = &dev->drv->dev;
|
||||
subdev = dev->drv->dev;
|
||||
while (subdev != dev) {
|
||||
pprev = &subdev->next_in_drv;
|
||||
subdev = subdev->next_in_drv;
|
||||
}
|
||||
*pprev = subdev->next_in_drv;
|
||||
dev->drv->dev_cnt--;
|
||||
/* Delete device from driver's device list */
|
||||
pprev = &dev->drv->dev;
|
||||
subdev = dev->drv->dev;
|
||||
while ( subdev != dev ) {
|
||||
pprev = &subdev->next_in_drv;
|
||||
subdev = subdev->next_in_drv;
|
||||
}
|
||||
*pprev = subdev->next_in_drv;
|
||||
dev->drv->dev_cnt--;
|
||||
|
||||
/* Move device to inactive list */
|
||||
drvmgr_list_remove(&mgr->devices[dev->level], dev);
|
||||
dev->level = 0;
|
||||
dev->state &= ~(DEV_STATE_UNITED|DEV_STATE_INIT_DONE);
|
||||
dev->state |= DEV_STATE_LIST_INACTIVE;
|
||||
drvmgr_list_add_tail(&mgr->devices_inactive, dev);
|
||||
/* Move device to inactive list */
|
||||
drvmgr_list_remove( &mgr->devices[ dev->level ], dev );
|
||||
dev->level = 0;
|
||||
dev->state &= ~( DEV_STATE_UNITED | DEV_STATE_INIT_DONE );
|
||||
dev->state |= DEV_STATE_LIST_INACTIVE;
|
||||
drvmgr_list_add_tail( &mgr->devices_inactive, dev );
|
||||
|
||||
DRVMGR_UNLOCK();
|
||||
DRVMGR_UNLOCK();
|
||||
|
||||
/* Free Device Driver Private memory if allocated previously by
|
||||
/* Free Device Driver Private memory if allocated previously by
|
||||
* Driver manager.
|
||||
*/
|
||||
if (dev->drv->dev_priv_size && dev->priv) {
|
||||
free(dev->priv);
|
||||
dev->priv = NULL;
|
||||
}
|
||||
dev->drv = NULL;
|
||||
if ( dev->drv->dev_priv_size && dev->priv ) {
|
||||
free( dev->priv );
|
||||
dev->priv = NULL;
|
||||
}
|
||||
dev->drv = NULL;
|
||||
|
||||
return DRVMGR_OK;
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
/* Unregister device,
|
||||
@@ -166,39 +173,40 @@ int drvmgr_dev_drv_separate(struct drvmgr_dev *dev)
|
||||
* - remove from driver list
|
||||
* - remove from bus list
|
||||
*/
|
||||
int drvmgr_dev_unregister(struct drvmgr_dev *dev)
|
||||
int drvmgr_dev_unregister( struct drvmgr_dev *dev )
|
||||
{
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_dev *subdev, **pprev;
|
||||
int err;
|
||||
struct drvmgr *mgr = &drvmgr;
|
||||
struct drvmgr_dev *subdev, **pprev;
|
||||
int err;
|
||||
|
||||
/* Separate device from driver, if the device is united with a driver.
|
||||
/* Separate device from driver, if the device is united with a driver.
|
||||
*
|
||||
* If this device is a bridge all child buses/devices are also removed.
|
||||
*/
|
||||
err = drvmgr_dev_drv_separate(dev);
|
||||
if (err != DRVMGR_OK)
|
||||
return err;
|
||||
err = drvmgr_dev_drv_separate( dev );
|
||||
if ( err != DRVMGR_OK ) {
|
||||
return err;
|
||||
}
|
||||
|
||||
DRVMGR_LOCK_WRITE();
|
||||
DRVMGR_LOCK_WRITE();
|
||||
|
||||
/* Remove it from inactive list */
|
||||
drvmgr_list_remove(&mgr->devices_inactive, dev);
|
||||
/* Remove it from inactive list */
|
||||
drvmgr_list_remove( &mgr->devices_inactive, dev );
|
||||
|
||||
/* Remove device from parent bus list (no check if dev not in list) */
|
||||
pprev = &dev->parent->children;
|
||||
subdev = dev->parent->children;
|
||||
while (subdev != dev) {
|
||||
pprev = &subdev->next_in_bus;
|
||||
subdev = subdev->next_in_bus;
|
||||
}
|
||||
*pprev = subdev->next_in_bus;
|
||||
dev->parent->dev_cnt--;
|
||||
/* Remove device from parent bus list (no check if dev not in list) */
|
||||
pprev = &dev->parent->children;
|
||||
subdev = dev->parent->children;
|
||||
while ( subdev != dev ) {
|
||||
pprev = &subdev->next_in_bus;
|
||||
subdev = subdev->next_in_bus;
|
||||
}
|
||||
*pprev = subdev->next_in_bus;
|
||||
dev->parent->dev_cnt--;
|
||||
|
||||
DRVMGR_UNLOCK();
|
||||
DRVMGR_UNLOCK();
|
||||
|
||||
/* All references to this device has been removed at this point */
|
||||
free(dev);
|
||||
/* All references to this device has been removed at this point */
|
||||
free( dev );
|
||||
|
||||
return DRVMGR_OK;
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user