reshandle_t rs_add_todb(const char* filepath, void* ptr, pfn_unload_res unload_func) { static uint global_id = 0; global_id ++; reshandle_t res_hdl; struct rs_resource* rs; /* if we have freeslots in free-stack, pop it and re-update it */ struct stack* sitem = stack_pop(&g_rs.freeslots); if (sitem != NULL) { uptr_t idx = (uptr_t)sitem->data; res_hdl = MAKE_HANDLE(idx, global_id); rs = &((struct rs_resource*)g_rs.ress.buffer)[idx]; } else { res_hdl = MAKE_HANDLE(g_rs.ress.item_cnt, global_id); rs = (struct rs_resource*)arr_add(&g_rs.ress); ASSERT(rs); } rs->hdl = res_hdl; rs->ptr = ptr; rs->ref_cnt = 1; rs->unload_func = unload_func; ASSERT(strlen(filepath) < 128); str_safecpy(rs->filepath, sizeof(rs->filepath), filepath); return res_hdl; }
int dma_init(void) { int rc = 0; int controllerIdx; int channelIdx; DMA_Device_t devIdx; DMA_Channel_t *channel; DMA_Handle_t dedicatedHandle; memset(&gDMA, 0, sizeof(gDMA)); sema_init(&gDMA.lock, 0); init_waitqueue_head(&gDMA.freeChannelQ); /* */ dmacHw_initDma(); /* */ for (controllerIdx = 0; controllerIdx < DMA_NUM_CONTROLLERS; controllerIdx++) { for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS; channelIdx++) { channel = &gDMA.controller[controllerIdx].channel[channelIdx]; channel->flags = 0; channel->devType = DMA_DEVICE_NONE; channel->lastDevType = DMA_DEVICE_NONE; #if (DMA_DEBUG_TRACK_RESERVATION) channel->fileName = ""; channel->lineNum = 0; #endif channel->dmacHwHandle = dmacHw_getChannelHandle(dmacHw_MAKE_CHANNEL_ID (controllerIdx, channelIdx)); dmacHw_initChannel(channel->dmacHwHandle); } } /* */ gDMA.controller[0].channel[0].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO; gDMA.controller[0].channel[1].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO; gDMA.controller[1].channel[0].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO; gDMA.controller[1].channel[1].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO; /* */ for (devIdx = 0; devIdx < DMA_NUM_DEVICE_ENTRIES; devIdx++) { DMA_DeviceAttribute_t *devAttr = &DMA_gDeviceAttribute[devIdx]; if (((devAttr->flags & DMA_DEVICE_FLAG_NO_ISR) != 0) && ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) == 0)) { printk(KERN_ERR "DMA Device: %s Can only request NO_ISR for dedicated devices\n", devAttr->name); rc = -EINVAL; goto out; } if ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) != 0) { /* */ if (devAttr->dedicatedController >= DMA_NUM_CONTROLLERS) { printk(KERN_ERR "DMA Device: %s DMA Controller %d is out of range\n", devAttr->name, devAttr->dedicatedController); rc = -EINVAL; goto out; } if (devAttr->dedicatedChannel >= DMA_NUM_CHANNELS) { printk(KERN_ERR "DMA Device: %s DMA Channel %d is out of range\n", devAttr->name, devAttr->dedicatedChannel); rc = -EINVAL; goto out; } dedicatedHandle = MAKE_HANDLE(devAttr->dedicatedController, devAttr->dedicatedChannel); channel = HandleToChannel(dedicatedHandle); if ((channel->flags & DMA_CHANNEL_FLAG_IS_DEDICATED) != 0) { printk ("DMA Device: %s attempting to use same DMA Controller:Channel (%d:%d) as %s\n", devAttr->name, devAttr->dedicatedController, devAttr->dedicatedChannel, DMA_gDeviceAttribute[channel->devType]. name); rc = -EBUSY; goto out; } channel->flags |= DMA_CHANNEL_FLAG_IS_DEDICATED; channel->devType = devIdx; if (devAttr->flags & DMA_DEVICE_FLAG_NO_ISR) { channel->flags |= DMA_CHANNEL_FLAG_NO_ISR; } /* */ /* */ ConfigChannel(dedicatedHandle); } } /* */ for (controllerIdx = 0; controllerIdx < DMA_NUM_CONTROLLERS; controllerIdx++) { for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS; channelIdx++) { channel = &gDMA.controller[controllerIdx].channel[channelIdx]; if ((channel->flags & DMA_CHANNEL_FLAG_NO_ISR) == 0) { snprintf(channel->name, sizeof(channel->name), "dma %d:%d %s", controllerIdx, channelIdx, channel->devType == DMA_DEVICE_NONE ? "" : DMA_gDeviceAttribute[channel->devType]. name); rc = request_irq(IRQ_DMA0C0 + (controllerIdx * DMA_NUM_CHANNELS) + channelIdx, dma_interrupt_handler, IRQF_DISABLED, channel->name, channel); if (rc != 0) { printk(KERN_ERR "request_irq for IRQ_DMA%dC%d failed\n", controllerIdx, channelIdx); } } } } /* */ gDmaDir = proc_mkdir("dma", NULL); if (gDmaDir == NULL) { printk(KERN_ERR "Unable to create /proc/dma\n"); } else { create_proc_read_entry("channels", 0, gDmaDir, dma_proc_read_channels, NULL); create_proc_read_entry("devices", 0, gDmaDir, dma_proc_read_devices, NULL); } out: up(&gDMA.lock); return rc; }
DMA_Handle_t dma_request_channel(DMA_Device_t dev) #endif { DMA_Handle_t handle; DMA_DeviceAttribute_t *devAttr; DMA_Channel_t *channel; int controllerIdx; int controllerIdx2; int channelIdx; if (down_interruptible(&gDMA.lock) < 0) { return -ERESTARTSYS; } if ((dev < 0) || (dev >= DMA_NUM_DEVICE_ENTRIES)) { handle = -ENODEV; goto out; } devAttr = &DMA_gDeviceAttribute[dev]; #if (DMA_DEBUG_TRACK_RESERVATION) { char *s; s = strrchr(fileName, '/'); if (s != NULL) { fileName = s + 1; } } #endif if ((devAttr->flags & DMA_DEVICE_FLAG_IN_USE) != 0) { /* */ printk(KERN_ERR "%s: device %s is already requested\n", __func__, devAttr->name); handle = -EBUSY; goto out; } if ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) != 0) { /* */ channel = &gDMA.controller[devAttr->dedicatedController]. channel[devAttr->dedicatedChannel]; if ((channel->flags & DMA_CHANNEL_FLAG_IN_USE) != 0) { handle = -EBUSY; goto out; } channel->flags |= DMA_CHANNEL_FLAG_IN_USE; devAttr->flags |= DMA_DEVICE_FLAG_IN_USE; #if (DMA_DEBUG_TRACK_RESERVATION) channel->fileName = fileName; channel->lineNum = lineNum; #endif handle = MAKE_HANDLE(devAttr->dedicatedController, devAttr->dedicatedChannel); goto out; } /* */ handle = DMA_INVALID_HANDLE; while (handle == DMA_INVALID_HANDLE) { /* */ for (controllerIdx2 = 0; controllerIdx2 < DMA_NUM_CONTROLLERS; controllerIdx2++) { /* */ controllerIdx = controllerIdx2; if ((devAttr-> flags & DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST) != 0) { controllerIdx = 1 - controllerIdx; } /* */ if ((devAttr-> flags & (DMA_DEVICE_FLAG_ON_DMA0 << controllerIdx)) != 0) { for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS; channelIdx++) { channel = &gDMA.controller[controllerIdx]. channel[channelIdx]; if (((channel-> flags & DMA_CHANNEL_FLAG_IS_DEDICATED) == 0) && ((channel-> flags & DMA_CHANNEL_FLAG_IN_USE) == 0)) { if (((channel-> flags & DMA_CHANNEL_FLAG_LARGE_FIFO) != 0) && ((devAttr-> flags & DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO) == 0)) { /* */ /* */ continue; } channel->flags |= DMA_CHANNEL_FLAG_IN_USE; channel->devType = dev; devAttr->flags |= DMA_DEVICE_FLAG_IN_USE; #if (DMA_DEBUG_TRACK_RESERVATION) channel->fileName = fileName; channel->lineNum = lineNum; #endif handle = MAKE_HANDLE(controllerIdx, channelIdx); /* */ if (ConfigChannel(handle) != 0) { handle = -EIO; printk(KERN_ERR "dma_request_channel: ConfigChannel failed\n"); } goto out; } } } } /* */ { DEFINE_WAIT(wait); prepare_to_wait(&gDMA.freeChannelQ, &wait, TASK_INTERRUPTIBLE); up(&gDMA.lock); schedule(); finish_wait(&gDMA.freeChannelQ, &wait); if (signal_pending(current)) { /* */ return -ERESTARTSYS; } } if (down_interruptible(&gDMA.lock)) { return -ERESTARTSYS; } } out: up(&gDMA.lock); return handle; }
DMA_Handle_t dma_request_channel(DMA_Device_t dev) #endif { DMA_Handle_t handle; DMA_DeviceAttribute_t *devAttr; DMA_Channel_t *channel; int controllerIdx; int controllerIdx2; int channelIdx; if (down_interruptible(&gDMA.lock) < 0) { return -ERESTARTSYS; } if ((dev < 0) || (dev >= DMA_NUM_DEVICE_ENTRIES)) { handle = -ENODEV; goto out; } devAttr = &DMA_gDeviceAttribute[dev]; #if (DMA_DEBUG_TRACK_RESERVATION) { char *s; s = strrchr(fileName, '/'); if (s != NULL) { fileName = s + 1; } } #endif if ((devAttr->flags & DMA_DEVICE_FLAG_IN_USE) != 0) { /* This device has already been requested and not been freed */ printk(KERN_ERR "%s: device %s is already requested\n", __func__, devAttr->name); handle = -EBUSY; goto out; } if ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) != 0) { /* This device has a dedicated channel. */ channel = &gDMA.controller[devAttr->dedicatedController]. channel[devAttr->dedicatedChannel]; if ((channel->flags & DMA_CHANNEL_FLAG_IN_USE) != 0) { handle = -EBUSY; goto out; } channel->flags |= DMA_CHANNEL_FLAG_IN_USE; devAttr->flags |= DMA_DEVICE_FLAG_IN_USE; #if (DMA_DEBUG_TRACK_RESERVATION) channel->fileName = fileName; channel->lineNum = lineNum; #endif handle = MAKE_HANDLE(devAttr->dedicatedController, devAttr->dedicatedChannel); goto out; } /* This device needs to use one of the shared channels. */ handle = DMA_INVALID_HANDLE; while (handle == DMA_INVALID_HANDLE) { /* Scan through the shared channels and see if one is available */ for (controllerIdx2 = 0; controllerIdx2 < DMA_NUM_CONTROLLERS; controllerIdx2++) { /* Check to see if we should try on controller 1 first. */ controllerIdx = controllerIdx2; if ((devAttr-> flags & DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST) != 0) { controllerIdx = 1 - controllerIdx; } /* See if the device is available on the controller being tested */ if ((devAttr-> flags & (DMA_DEVICE_FLAG_ON_DMA0 << controllerIdx)) != 0) { for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS; channelIdx++) { channel = &gDMA.controller[controllerIdx]. channel[channelIdx]; if (((channel-> flags & DMA_CHANNEL_FLAG_IS_DEDICATED) == 0) && ((channel-> flags & DMA_CHANNEL_FLAG_IN_USE) == 0)) { if (((channel-> flags & DMA_CHANNEL_FLAG_LARGE_FIFO) != 0) && ((devAttr-> flags & DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO) == 0)) { /* This channel is a large fifo - don't tie it up */ /* with devices that we don't want using it. */ continue; } channel->flags |= DMA_CHANNEL_FLAG_IN_USE; channel->devType = dev; devAttr->flags |= DMA_DEVICE_FLAG_IN_USE; #if (DMA_DEBUG_TRACK_RESERVATION) channel->fileName = fileName; channel->lineNum = lineNum; #endif handle = MAKE_HANDLE(controllerIdx, channelIdx); /* Now that we've reserved the channel - we can go ahead and configure it */ if (ConfigChannel(handle) != 0) { handle = -EIO; printk(KERN_ERR "dma_request_channel: ConfigChannel failed\n"); } goto out; } } } } /* No channels are currently available. Let's wait for one to free up. */ { DEFINE_WAIT(wait); prepare_to_wait(&gDMA.freeChannelQ, &wait, TASK_INTERRUPTIBLE); up(&gDMA.lock); schedule(); finish_wait(&gDMA.freeChannelQ, &wait); if (signal_pending(current)) { /* We don't currently hold gDMA.lock, so we return directly */ return -ERESTARTSYS; } } if (down_interruptible(&gDMA.lock)) { return -ERESTARTSYS; } } out: up(&gDMA.lock); return handle; }