⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pciio.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 4 页
字号:
voidpciio_device_info_unregister(devfs_handle_t connectpt,			     pciio_info_t pciio_info){    char		name[32];    devfs_handle_t	pconn;    if (!pciio_info)	return;    pciio_slot_func_to_name(name,			    pciio_info->c_slot,			    pciio_info->c_func);    hwgraph_edge_remove(connectpt,name,&pconn);    pciio_info_set(pconn,0);    /* Remove the link to our pci provider */    hwgraph_edge_remove(pconn, EDGE_LBL_MASTER, NULL);    hwgraph_vertex_unref(pconn);    hwgraph_vertex_destroy(pconn);    }/* Add the pci card inventory information to the hwgraph */static voidpciio_device_inventory_add(devfs_handle_t pconn_vhdl){    pciio_info_t	pciio_info = pciio_info_get(pconn_vhdl);    ASSERT(pciio_info);    ASSERT(pciio_info->c_vertex == pconn_vhdl);    /* Donot add inventory  for non-existent devices */    if ((pciio_info->c_vendor == PCIIO_VENDOR_ID_NONE)	||	(pciio_info->c_device == PCIIO_DEVICE_ID_NONE))	return;    device_inventory_add(pconn_vhdl,INV_IOBD,INV_PCIADAP,			 pciio_info->c_vendor,pciio_info->c_device,			 pciio_info->c_slot);}/*ARGSUSED */intpciio_device_attach(devfs_handle_t pconn,		    int          drv_flags){    pciio_info_t            pciio_info;    pciio_vendor_id_t       vendor_id;    pciio_device_id_t       device_id;    pciio_device_inventory_add(pconn);    pciio_info = pciio_info_get(pconn);    vendor_id = pciio_info->c_vendor;    device_id = pciio_info->c_device;    /* we don't start attaching things until     * all the driver init routines (including     * pciio_init) have been called; so we     * can assume here that we have a registry.     */    ASSERT(pciio_registry != NULL);    return(cdl_add_connpt(pciio_registry, vendor_id, device_id, pconn, drv_flags));}intpciio_device_detach(devfs_handle_t pconn,		    int          drv_flags){    pciio_info_t            pciio_info;    pciio_vendor_id_t       vendor_id;    pciio_device_id_t       device_id;    pciio_info = pciio_info_get(pconn);    vendor_id = pciio_info->c_vendor;    device_id = pciio_info->c_device;    /* we don't start attaching things until     * all the driver init routines (including     * pciio_init) have been called; so we     * can assume here that we have a registry.     */    ASSERT(pciio_registry != NULL);    return(cdl_del_connpt(pciio_registry, vendor_id, device_id,		          pconn, drv_flags));}/* SN2 *//* * Allocate (if necessary) and initialize a PCI window mapping structure. */pciio_win_map_tpciio_device_win_map_new(pciio_win_map_t win_map,			 size_t region_size,			 size_t page_size){	ASSERT((page_size & (page_size - 1)) == 0);	ASSERT((region_size & (page_size - 1)) == 0);	if (win_map == NULL)		NEW(win_map);	/*	 * The map array tracks the free ``pages'' in the region.  The worst	 * case scenario is when every other page in the region is free --	 * e.i. maximum fragmentation.  This leads to (max pages + 1) / 2 + 1	 * map entries.  The first "+1" handles the divide by 2 rounding; the	 * second handles the need for an end marker sentinel.	 */	win_map->wm_map = rmallocmap((region_size / page_size + 1) / 2 + 1);	win_map->wm_page_size = page_size;	ASSERT(win_map->wm_map != NULL);	return win_map;}/* * Free resources associated with a PCI window mapping structure. */extern voidpciio_device_win_map_free(pciio_win_map_t win_map){	rmfreemap(win_map->wm_map);	bzero(win_map, sizeof *win_map);}/* * Populate window map with specified free range. */voidpciio_device_win_populate(pciio_win_map_t win_map,                          iopaddr_t ioaddr,                          size_t size){	ASSERT((size & (win_map->wm_page_size - 1)) == 0);	ASSERT((ioaddr & (win_map->wm_page_size - 1)) == 0);	rmfree(win_map->wm_map,	       size / win_map->wm_page_size,	       (unsigned long)ioaddr / win_map->wm_page_size);	       }/* * Allocate space from the specified PCI window mapping resource.  On * success record information about the allocation in the supplied window * allocation cookie (if non-NULL) and return the address of the allocated * window.  On failure return NULL. * * The "size" parameter is usually from a PCI device's Base Address Register * (BAR) decoder.  As such, the allocation must be aligned to be a multiple of * that.  The "align" parameter acts as a ``minimum alignment'' allocation * constraint.  The alignment contraint reflects system or device addressing * restrictions such as the inability to share higher level ``windows'' * between devices, etc.  The returned PCI address allocation will be a * multiple of the alignment constraint both in alignment and size.  Thus, the * returned PCI address block is aligned to the maximum of the requested size * and alignment. */iopaddr_tpciio_device_win_alloc(pciio_win_map_t win_map,		       pciio_win_alloc_t win_alloc,		       size_t size, size_t align){	unsigned long base;#ifdef PIC_LATER	ASSERT((size & (size - 1)) == 0);	ASSERT((align & (align - 1)) == 0);	/*	 * Convert size and alignment to pages.  If size is greated than the	 * requested alignment, we bump the alignment up to size; otherwise	 * convert the size into a multiple of the alignment request.	 */	size = (size + win_map->wm_page_size - 1) / win_map->wm_page_size;	align = align / win_map->wm_page_size;	if (size > align)		align = size;	else		size = (size + align - 1) & ~(align - 1);	/* XXXX */	base = rmalloc_align(win_map->wm_map, size, align, VM_NOSLEEP);	if (base == RMALLOC_FAIL)		return((iopaddr_t)NULL);#else    int                 index_page, index_page_align;    int                 align_pages, size_pages;    int                 alloc_pages, free_pages;    int                 addr_align;    /* Convert PCI bus alignment from bytes to pages */    align_pages = align / win_map->wm_page_size;    /* Convert PCI request from bytes to pages */    size_pages = (size / win_map->wm_page_size) +                  ((size % win_map->wm_page_size) ? 1 : 0);    /* Align address with the larger of the size or the requested slot align */    if (size_pages > align_pages)        align_pages = size_pages;      /*     * Avoid wasting space by aligning - 1; this will prevent crossing     * another alignment boundary.     */    alloc_pages = size_pages + (align_pages - 1);    /* Allocate PCI bus space in pages */    index_page = (int) rmalloc(win_map->wm_map,                               (size_t) alloc_pages);    /* Error if no PCI bus address space available */    if (!index_page)        return 0;    /* PCI bus address index starts at 0 */    index_page--;    /* Align the page offset as requested */    index_page_align = (index_page + (align_pages - 1)) -                       ((index_page + (align_pages - 1)) % align_pages);    free_pages = (align_pages - 1) - (index_page_align - index_page);    /* Free unused PCI bus pages adjusting the index to start at 1 */    rmfree(win_map->wm_map,            free_pages,           (index_page_align + 1) + size_pages);    /* Return aligned PCI bus space in bytes */     addr_align = (index_page_align * win_map->wm_page_size);     base = index_page;    size = alloc_pages - free_pages;#endif	/* PIC_LATER */	/*	 * If a window allocation cookie has been supplied, use it to keep	 * track of all the allocated space assigned to this window.	 */	if (win_alloc) {		win_alloc->wa_map = win_map;		win_alloc->wa_base = base;		win_alloc->wa_pages = size;	}	return base * win_map->wm_page_size;}/* * Free the specified window allocation back into the PCI window mapping * resource.  As noted above, we keep page addresses offset by 1 ... */voidpciio_device_win_free(pciio_win_alloc_t win_alloc){	if (win_alloc->wa_pages)		rmfree(win_alloc->wa_map->wm_map,		       win_alloc->wa_pages,		       win_alloc->wa_base);}/* * pciio_error_register: * arrange for a function to be called with * a specified first parameter plus other * information when an error is encountered * and traced to the pci slot corresponding * to the connection point pconn. * * may also be called with a null function * pointer to "unregister" the error handler. * * NOTE: subsequent calls silently overwrite * previous data for this vertex. We assume that * cooperating drivers, well, cooperate ... */voidpciio_error_register(devfs_handle_t pconn,		     error_handler_f *efunc,		     error_handler_arg_t einfo){    pciio_info_t            pciio_info;    pciio_info = pciio_info_get(pconn);    ASSERT(pciio_info != NULL);    pciio_info->c_efunc = efunc;    pciio_info->c_einfo = einfo;}/* * Check if any device has been found in this slot, and return * true or false * vhdl is the vertex for the slot */intpciio_slot_inuse(devfs_handle_t pconn_vhdl){    pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);    ASSERT(pciio_info);    ASSERT(pciio_info->c_vertex == pconn_vhdl);    if (pciio_info->c_vendor) {	/*	 * Non-zero value for vendor indicate	 * a board being found in this slot.	 */	return 1;    }    return 0;}intpciio_dma_enabled(devfs_handle_t pconn_vhdl){	return DEV_FUNC(pconn_vhdl, dma_enabled)(pconn_vhdl);}/* * These are complementary Linux interfaces that takes in a pci_dev * as the  * first arguement instead of devfs_handle_t. */iopaddr_t               snia_pciio_dmatrans_addr(struct pci_dev *, device_desc_t, paddr_t, size_t, unsigned);pciio_dmamap_t          snia_pciio_dmamap_alloc(struct pci_dev *, device_desc_t, size_t, unsigned);void                    snia_pciio_dmamap_free(pciio_dmamap_t);iopaddr_t               snia_pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t);void                    snia_pciio_dmamap_done(pciio_dmamap_t);pciio_endian_t          snia_pciio_endian_set(struct pci_dev *pci_dev, pciio_endian_t device_end,					      pciio_endian_t desired_end);#include <linux/module.h>EXPORT_SYMBOL(snia_pciio_dmatrans_addr);EXPORT_SYMBOL(snia_pciio_dmamap_alloc);EXPORT_SYMBOL(snia_pciio_dmamap_free);EXPORT_SYMBOL(snia_pciio_dmamap_addr);EXPORT_SYMBOL(snia_pciio_dmamap_done);EXPORT_SYMBOL(snia_pciio_endian_set);intsnia_pcibr_rrb_alloc(struct pci_dev *pci_dev,	int *count_vchan0,	int *count_vchan1){	devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);	return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1);}EXPORT_SYMBOL(snia_pcibr_rrb_alloc);pciio_endian_tsnia_pciio_endian_set(struct pci_dev *pci_dev,	pciio_endian_t device_end,	pciio_endian_t desired_end){	devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);		return DEV_FUNC(dev, endian_set)		(dev, device_end, desired_end);}iopaddr_tsnia_pciio_dmatrans_addr(struct pci_dev *pci_dev, /* translate for this device */                    device_desc_t dev_desc,     /* device descriptor */                    paddr_t paddr,      /* system physical address */                    size_t byte_count,  /* length */                    unsigned flags){                                       /* defined in dma.h */    devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);    return DEV_FUNC(dev, dmatrans_addr)        (dev, dev_desc, paddr, byte_count, flags);}pciio_dmamap_tsnia_pciio_dmamap_alloc(struct pci_dev *pci_dev,  /* set up mappings for this device */                   device_desc_t dev_desc,      /* device descriptor */                   size_t byte_count_max,       /* max size of a mapping */                   unsigned flags){                                       /* defined in dma.h */    devfs_handle_t dev = PCIDEV_VERTEX(pci_dev);    return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc)        (dev, dev_desc, byte_count_max, flags);}voidsnia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap){    DMAMAP_FUNC(pciio_dmamap, dmamap_free)        (CAST_DMAMAP(pciio_dmamap));}iopaddr_tsnia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,  /* use these mapping resources */                  paddr_t paddr,        /* map for this address */                  size_t byte_count){                                       /* map this many bytes */    return DMAMAP_FUNC(pciio_dmamap, dmamap_addr)        (CAST_DMAMAP(pciio_dmamap), paddr, byte_count);}voidsnia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap){    DMAMAP_FUNC(pciio_dmamap, dmamap_done)        (CAST_DMAMAP(pciio_dmamap));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -