📄 upci.c
字号:
{ if ( ioaccess <= 0 ) { /* should not be calling decr if already zero */ return; } /* decrement reference count */ ioaccess--; if ( ioaccess == 0 ) { /* release I/O priveleges */ iopl(0); }}static int incr_mem_usage ( void ){ int eno; /* make sure /dev/mem is open */ if ( memaccess == 0 ) { /* open it */ /* this needs priviliges */ if (seteuid(0) != 0) { errmsg(__func__, "need root privilges (or setuid root)"); return -1; } /* do it */ memfd = open("/dev/mem", O_RDWR); eno = errno; /* drop priviliges */ seteuid(getuid()); /* check result */ if ( memfd < 0 ) { errmsg(__func__,"can't open /dev/mem: %s", strerror(eno)); return -1; } } /* increment reference count */ memaccess++; return 0;}static void decr_mem_usage ( void ){ if ( memaccess <= 0 ) { /* should not be calling decr if already zero */ return; } /* decrement reference count */ memaccess--; if ( memaccess == 0 ) { /* close /dev/mem */ close(memfd); }}int upci_open_region(int devnum, int region_num){ struct dev_info *dev; struct region_info *reg; int rd; if (( devnum < 0 ) || ( devnum >= num_devs )) { errmsg(__func__, "device %d not found", devnum); return -1; } dev = devices[devnum]; if (( region_num < 0 ) || ( region_num >= 6 )) { errmsg(__func__, "bad region number %d", region_num); return -1; } reg = &(dev->regions[region_num]); if ( reg->size == 0 ) { errmsg(__func__, "region %d not found in device %d", region_num, devnum); return -1; } /* calculate region descriptor */ rd = devnum * 6 + region_num; if ( reg->region_is_mapped ) { /* already open, nothing to do */ return rd; } if ( reg->type == UPCI_REG_IO ) { /* region is IO, no mapping needed */ /* update reference counter */ if ( incr_io_usage() != 0 ) { errmsg(__func__, "no I/O access"); return -1; } } else { /* region is memory */ /* update reference counter */ if ( incr_mem_usage() != 0 ) { return -1; } /* map the memory region */ reg->mapped_ptr = mmap(0, reg->size, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, reg->base_addr); if ( reg->mapped_ptr == MAP_FAILED ) { reg->mapped_ptr = NULL; errmsg(__func__, "can't map /dev/mem for device %d, region %d: %s", devnum, region_num, strerror(errno)); decr_mem_usage(); return -1; } } /* mark region as mapped */ reg->region_is_mapped = 1; regions[rd] = reg; return rd;}void upci_close_region(int rd){ struct region_info *reg; if ((rd < 0 ) || ( rd >= MAX_REGIONS )) return; reg = regions[rd]; if ( reg == NULL ) return; if ( reg->type == UPCI_REG_IO ) { /* region is IO, nothing to unmap */ decr_io_usage(); } else { /* region is memory, unmap it */ munmap ( reg->mapped_ptr, reg->size ); decr_mem_usage(); } /* mark region as unmapped */ reg->region_is_mapped = 0; regions[rd] = NULL;}__u8 upci_read_u8(int rd, __u32 offset){ struct region_info *reg; int port; volatile __u8 *ptr, data; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; /* get the data */ if ( reg->type == UPCI_REG_IO ) { /* region is IO */ port = reg->base_addr + offset; data = inb(port); } else { /* region is memory */ ptr = (__u8 *)(reg->mapped_ptr + offset); data = *ptr; } return data;}__s8 upci_read_s8(int rd, __u32 offset){ struct region_info *reg; int port; volatile __s8 *ptr, data; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; /* get the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; data = inb(port); } else { ptr = (__s8 *)(reg->mapped_ptr + offset); data = *ptr; } return data;}__u16 upci_read_u16(int rd, __u32 offset){ struct region_info *reg; int port; volatile __u16 *ptr, data; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; /* get the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; data = inw(port); } else { ptr = (__u16 *)(reg->mapped_ptr + offset); data = *ptr; } return data;}__s16 upci_read_s16(int rd, __u32 offset){ struct region_info *reg; int port; volatile __s16 *ptr, data; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; /* get the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; data = inw(port); } else { ptr = (__s16 *)(reg->mapped_ptr + offset); data = *ptr; } return data;}__u32 upci_read_u32(int rd, __u32 offset){ struct region_info *reg; int port; volatile __u32 *ptr, data; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; /* get the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; data = inl(port); } else { ptr = (__u32 *)(reg->mapped_ptr + offset); data = *ptr; } return data;}__s32 upci_read_s32(int rd, __u32 offset){ struct region_info *reg; int port; volatile __s32 *ptr, data; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; /* get the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; data = inl(port); } else { ptr = (__s32 *)(reg->mapped_ptr + offset); data = *ptr; } return data;}void upci_write_u8(int rd, __u32 offset, __u8 data){ struct region_info *reg; int port; volatile __u8 *ptr; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; /* write the data */ if ( reg->type == UPCI_REG_IO ) { /* region is IO */ port = reg->base_addr + offset; outb(data, port); } else { /* region is memory */ ptr = (__u8 *)(reg->mapped_ptr + offset); *ptr = data; } return;}void upci_write_s8(int rd, __u32 offset, __s8 data){ struct region_info *reg; int port; volatile __s8 *ptr; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; /* write the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; outb(data, port); } else { ptr = (__s8 *)(reg->mapped_ptr + offset); *ptr = data; } return;}void upci_write_u16(int rd, __u32 offset, __u16 data){ struct region_info *reg; int port; volatile __u16 *ptr; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; /* write the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; outw(data, port); } else { ptr = (__u16 *)(reg->mapped_ptr + offset); *ptr = data; } return;}void upci_write_s16(int rd, __u32 offset, __s16 data){ struct region_info *reg; int port; volatile __s16 *ptr; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; /* write the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; outw(data, port); } else { ptr = (__s16 *)(reg->mapped_ptr + offset); *ptr = data; } return;}void upci_write_u32(int rd, __u32 offset, __u32 data){ struct region_info *reg; int port; volatile __u32 *ptr; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; /* write the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; outl(data, port); } else { ptr = (__u32 *)(reg->mapped_ptr + offset); *ptr = data; } return;}void upci_write_s32(int rd, __u32 offset, __s32 data){ struct region_info *reg; int port; volatile __s32 *ptr; /* test for out of range, not mapped, or offset beyond end of region */ if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; /* write the data */ if ( reg->type == UPCI_REG_IO ) { port = reg->base_addr + offset; outl(data, port); } else { ptr = (__s32 *)(reg->mapped_ptr + offset); *ptr = data; } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -