📄 kllad.c
字号:
return -EFAULT; rc = kdmapool_check_valid((struct llad *)NULL,param.dmapool_id); if (rc == 0){ param.buffer_count = kdmapool_get_available_buffer_count((struct llad *) NULL, param.dmapool_id); if (ctu((char *) arg, ¶m, sizeof(param)) != 0) return -EFAULT; } } break; case DIRECT_IOCTL_DMAPOOL_GET_PHYSICAL_ADDRESS: { struct kdmapool_userbuffer param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; rc = kdmapool_check_valid((struct llad*)NULL,param.dmapool_id); if (rc == 0) { param.physical_address = kdmapool_get_bus_address((struct llad *) NULL, param.dmapool_id, param.ptr, param.size); if (ctu((char *) arg, ¶m, sizeof(param)) != 0) return -EFAULT; } } break; case DIRECT_IOCTL_DMAPOOL_GET_VIRTUAL_ADDRESS: { struct kdmapool_userbuffer param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; rc = kdmapool_check_valid((struct llad *)NULL,param.dmapool_id); if (rc == 0) { param.ptr = kdmapool_get_virt_address((struct llad *) NULL, param.dmapool_id, param.physical_address, param.size); if (ctu((char *) arg, ¶m, sizeof(param)) != 0) return -EFAULT; } } break; case DIRECT_IOCTL_DMAPOOL_ACQUIRE: { struct kdmapool_physbuffer param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; rc = kdmapool_check_valid((struct llad *)NULL,param.dmapool_id); if (rc == 0) rc = kdmapool_acquire((struct llad *) NULL, param.dmapool_id, param.physical_address); } break; case DIRECT_IOCTL_DMAPOOL_RELEASE: { struct kdmapool_physbuffer param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; rc = kdmapool_check_valid((struct llad *)NULL,param.dmapool_id); if (rc == 0) rc = kdmapool_release((struct llad *) NULL, param.dmapool_id, param.physical_address); } break; case DIRECT_IOCTL_DMAPOOL_FLUSH_CACHE: { struct kdmapool_userbuffer param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; kc_flush_cache((void *)param.physical_address, param.size); rc = 0; } break; case DIRECT_IOCTL_DMAPOOL_INVALIDATE_CACHE: { struct kdmapool_userbuffer param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; kc_invalidate_cache((void *)param.physical_address, param.size); rc = 0; } break; #if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2) case DIRECT_IOCTL_GBUS_READ_UINT8: { struct gbus_uint8 param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; param.data = gbus_read_uint8(pGBus, param.byte_address); rc = ctu((char *) arg, ¶m, sizeof(param)); if (rc != 0) rc=-EFAULT; } break; case DIRECT_IOCTL_GBUS_READ_UINT16: { struct gbus_uint16 param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; param.data = gbus_read_uint16(pGBus, param.byte_address); rc = ctu((char *) arg, ¶m, sizeof(param)); if (rc != 0) rc=-EFAULT; } break; case DIRECT_IOCTL_GBUS_READ_UINT32: { struct gbus_uint32 param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; param.data = gbus_read_uint32(pGBus, param.byte_address); rc = ctu((char *) arg, ¶m, sizeof(param)); if (rc != 0) rc=-EFAULT; } break; case DIRECT_IOCTL_GBUS_READ_DATA8: { struct gbus_data8 param; RMuint32 xfer_size, xfer_offset; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; xfer_offset = 0; rc = 0; if (down_interruptible(&gbus_buf_sem)) { rc = -ERESTARTSYS; goto done; } while (xfer_offset < param.count) { xfer_size = RMmin(param.count - xfer_offset, GBUS_BUF_SIZE / sizeof(RMuint8)); gbus_read_data8(pGBus, param.byte_address + xfer_offset * sizeof(RMuint8), (RMuint8 *) gbus_buf, xfer_size * sizeof(RMuint8)); if (ctu(param.data + xfer_offset, gbus_buf, xfer_size * sizeof(RMuint8)) != 0) { rc = -EFAULT; break; } xfer_offset += xfer_size; } up(&gbus_buf_sem); } break; case DIRECT_IOCTL_GBUS_READ_DATA16: { struct gbus_data16 param; RMuint32 xfer_size, xfer_offset; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; xfer_offset = 0; rc = 0; if (down_interruptible(&gbus_buf_sem)) { rc = -ERESTARTSYS; goto done; } while (xfer_offset < param.count) { xfer_size = RMmin(param.count - xfer_offset, GBUS_BUF_SIZE / sizeof(RMuint16)); gbus_read_data16(pGBus, param.byte_address + xfer_offset * sizeof(RMuint16), (RMuint16 *) gbus_buf, xfer_size); if (ctu(param.data + xfer_offset, gbus_buf, xfer_size * sizeof(RMuint16)) != 0) { rc = -EFAULT; break; } xfer_offset += xfer_size; } up(&gbus_buf_sem); } break; case DIRECT_IOCTL_GBUS_READ_DATA32: { struct gbus_data32 param; RMuint32 xfer_size, xfer_offset; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; xfer_offset = 0; rc = 0; if (down_interruptible(&gbus_buf_sem)) { rc = -ERESTARTSYS; goto done; } while (xfer_offset < param.count) { xfer_size = RMmin(param.count - xfer_offset, GBUS_BUF_SIZE / sizeof(RMuint32)); gbus_read_data32(pGBus, param.byte_address + xfer_offset * sizeof(RMuint32), (RMuint32 *) gbus_buf, xfer_size); if (ctu(param.data + xfer_offset, gbus_buf, xfer_size * sizeof(RMuint32)) != 0) { rc = -EFAULT; break; } xfer_offset += xfer_size; } up(&gbus_buf_sem); } break; case DIRECT_IOCTL_GBUS_WRITE_UINT8: { struct gbus_uint8 param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; gbus_write_uint8(pGBus, param.byte_address, param.data); rc = 0; } break; case DIRECT_IOCTL_GBUS_WRITE_UINT16: { struct gbus_uint16 param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; gbus_write_uint16(pGBus, param.byte_address, param.data); rc = 0; } break; case DIRECT_IOCTL_GBUS_WRITE_UINT32: { struct gbus_uint32 param; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; gbus_write_uint32(pGBus, param.byte_address, param.data); rc = 0; } break; case DIRECT_IOCTL_GBUS_WRITE_DATA8: { struct gbus_data8 param; RMuint32 xfer_size, xfer_offset; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; xfer_offset = 0; rc = 0; if (down_interruptible(&gbus_buf_sem)) { rc = -ERESTARTSYS; goto done; } while (xfer_offset < param.count) { xfer_size = RMmin(param.count - xfer_offset, GBUS_BUF_SIZE / sizeof(RMuint8)); if (cfu(gbus_buf, param.data + xfer_offset, sizeof(RMuint8) * xfer_size) != 0) { rc = -EFAULT; break; } gbus_write_data8(pGBus, param.byte_address + xfer_offset * sizeof(RMuint8), (RMuint8 *) gbus_buf, xfer_size); xfer_offset += xfer_size; } up(&gbus_buf_sem); } break; case DIRECT_IOCTL_GBUS_WRITE_DATA16: { struct gbus_data16 param; RMuint32 xfer_size, xfer_offset; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; xfer_offset = 0; rc = 0; if (down_interruptible(&gbus_buf_sem)) { rc = -ERESTARTSYS; goto done; } while (xfer_offset < param.count) { xfer_size = RMmin(param.count - xfer_offset, GBUS_BUF_SIZE / sizeof(RMuint16)); if (cfu(gbus_buf, param.data + xfer_offset, sizeof(RMuint16) * xfer_size) != 0) { rc = -EFAULT; break; } gbus_write_data16(pGBus, param.byte_address + xfer_offset * sizeof(RMuint16), (RMuint16 *) gbus_buf, xfer_size); xfer_offset += xfer_size; } up(&gbus_buf_sem); } break; case DIRECT_IOCTL_GBUS_WRITE_DATA32: { struct gbus_data32 param; RMuint32 xfer_size, xfer_offset; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; xfer_offset = 0; rc = 0; if (down_interruptible(&gbus_buf_sem)) { rc = -ERESTARTSYS; goto done; } while (xfer_offset < param.count) { xfer_size = RMmin(param.count - xfer_offset, GBUS_BUF_SIZE / sizeof(RMuint32)); if (cfu(gbus_buf, param.data + xfer_offset, sizeof(RMuint32) * xfer_size) != 0) { rc = -EFAULT; break; } gbus_write_data32(pGBus, param.byte_address + xfer_offset * sizeof(RMuint32), (RMuint32 *) gbus_buf, xfer_size); xfer_offset += xfer_size; } up(&gbus_buf_sem); } break; case DIRECT_IOCTL_GBUS_GET_REGIONS_INFO: { struct gbus_regions_info param; param.region_size = DIRECT_REGION_SIZE; param.region_count = DIRECT_REGION_COUNT; // printk("DIRECT_IOCTL_GBUS_GET_REGION_INFO: param.region_size=%lu param.region_count=%lu\n", param.region_size, param.region_count); if (ctu((char *) arg, ¶m, sizeof(param)) != 0) { rc = -EFAULT; break; } rc = 0; } break; case DIRECT_IOCTL_GBUS_LOCK_AREA: { struct gbus_lock_area param, local_param; int i, size, addr, do_map=1, region_count; if (cfu(¶m, (char *)arg, sizeof(param)) != 0) return -EFAULT; if (param.region_index >= DIRECT_REGION_COUNT) return -EINVAL; /* locking is done on multiple of KERNEL_PAGE_SIZE bytes */ //get address offset from page param.offset = param.byte_address & (KERNEL_PAGE_SIZE - 1); //get page base address addr = param.byte_address & ~(KERNEL_PAGE_SIZE - 1); //get the system pages region count param.region_count = (param.size + param.offset+ KERNEL_PAGE_SIZE - 1) / KERNEL_PAGE_SIZE; region_count=param.region_count; //number of kernel pages for this region /* keep track of orignial parameters */ local_param = param; if (param.region_index == 0) { //region_index is a parameter /* try to get an already locked area */ param.region_index = get_locked_area(¶m); /* printk("lock_area: get_locked= %p %d %d %u\n", param.byte_address, param.offset, param.size, param.region_index); */ if (param.region_index<DIRECT_REGION_COUNT) { do_map = 0; //add lock on this zone goto end_lock_area; } /* restore original parameters */ param = local_param; //look for first available free region for (i=0 ; i<DIRECT_REGION_COUNT ; i++) { if (unlocked_regions(i, 1)) break; } if (i==DIRECT_REGION_COUNT) //no more available return -EINVAL; param.region_index = i;/* printk("lock_area: found unlocked region %i\n", i); */ } else { if (!unlocked_regions(param.region_index, 1)) return -EINVAL; } end_lock_area: /* printk("end_lock_area:this area will take %i system pages (0x%x bytes)\n", param.region_count, param.region_count*KERNEL_PAGE_SIZE); */ i = param.region_index; size = param.size +param.offset; /* printk("end_lock_area:R.region_info[%i].direct_map = 0x%x\n",i,addr); */ if (do_map) R.region_info[i].direct_map = addr; R.region_info[i].map_refcount ++; R.region_info[i].region_count=region_count; R.region_info[i].area_byte_address=param.byte_address; R.region_info[i].area_size=param.size; R.region_info[i].area_offset=param.offset; /* printk("end_lock_area: locked @%p off:%d size:%d index:%d sys pages count=%d\n", param.byte_address, param.offset, param.size, param.region_index, param.region_count); */ if (ctu((char *) arg, ¶m, sizeof(param)) != 0) return -EFAULT; rc = 0; } break; case DIRECT_IOCTL_GBUS_UNLOCK_REGION: { unsigned long region_index; if (cfu(®ion_index, (char *)arg, sizeof(region_index)) != 0) return -EFAULT; if (region_index >= DIRECT_REGION_COUNT) return -EINVAL; if (R.region_info[region_index].region_count == 0) return -EINVAL; /* printk("unlock_region: R.region_info[%i].region_count=%i -> 0\n",region_index,R.region_info[region_index].region_count); */ R.region_info[region_index].map_refcount--; if (R.region_info[region_index].map_refcount == 0) { /* printk("unlock_region:area unlocked %d\n", region_index); */ R.region_info[region_index].direct_map = 0; R.region_info[region_index].region_count=0; } rc = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -