From 3907f7ee4428acad7daf4758e275c33399bc5444 Mon Sep 17 00:00:00 2001 From: Gerd Zellweger Date: Tue, 27 Jun 2017 13:20:05 +0200 Subject: [PATCH] Commit SDMA driver changes. Signed-off-by: Gerd Zellweger --- usr/drivers/omap44xx/sdma/Hakefile | 13 +++- usr/drivers/omap44xx/sdma/main.c | 98 +++++++++++++++++++---------- usr/drivers/omap44xx/sdma/omap_sdma.c | 106 +++++++++++++++---------------- usr/drivers/omap44xx/sdma/omap_sdma.h | 33 ++++++++-- usr/drivers/omap44xx/sdma/sdma.h | 11 ++-- usr/drivers/omap44xx/sdma/sdma_domain.c | 82 ++++++++++++++++++++++++ usr/drivers/omap44xx/sdma/service.c | 14 ++-- 7 files changed, 246 insertions(+), 111 deletions(-) create mode 100644 usr/drivers/omap44xx/sdma/sdma_domain.c diff --git a/usr/drivers/omap44xx/sdma/Hakefile b/usr/drivers/omap44xx/sdma/Hakefile index 726a94e..7219f2d 100644 --- a/usr/drivers/omap44xx/sdma/Hakefile +++ b/usr/drivers/omap44xx/sdma/Hakefile @@ -11,8 +11,8 @@ -------------------------------------------------------------------------- [ - build application { target = "sdma", - cFiles = (find withSuffices [".c"]), + build library { target = "sdma_module", + cFiles = ["main.c", "omap_sdma.c", "service.c"], mackerelDevices = [ "omap/omap44xx_sdma" ], flounderDefs = [ "omap_sdma" ], @@ -21,5 +21,12 @@ addLibraries = ["driverkit", "thc"], architectures = ["armv7"] - } + }, + + build application { + target = "sdma", + cFiles = [ "sdma_domain.c"], + addModules = ["sdma_module"], + addLinkFlags = ["-T" ++ Config.source_dir ++ "/lib/driverkit/bfdrivers.ld" ] + } ] diff --git a/usr/drivers/omap44xx/sdma/main.c b/usr/drivers/omap44xx/sdma/main.c index 21f7019..f2e03c0 100644 --- a/usr/drivers/omap44xx/sdma/main.c +++ b/usr/drivers/omap44xx/sdma/main.c @@ -23,12 +23,6 @@ #include "sdma.h" #include "omap_sdma.h" -// Channel State. Filled by the interrupt callback, read by the request task. -static struct { - awe_t *request; - errval_t err; -} channel_state[OMAP44XX_SDMA_NUM_CHANNEL]; - /** * \brief Interrupt callback which will be called when a channel interrupt * occurs. @@ -36,10 +30,10 @@ static struct { * \param channel Channel which triggered the interrupt * \param err State of the channel, SYS_ERR_OK if transfer completed */ -static void sdma_irq_handler(omap_sdma_channel_t channel, errval_t err) +static void sdma_irq_handler(struct sdma_driver_state* st, omap_sdma_channel_t channel, errval_t err) { - channel_state[channel].err = err; - THCSchedule(channel_state[channel].request); + st->channel_state[channel].err = err; + THCSchedule(st->channel_state[channel].request); } /** @@ -48,25 +42,25 @@ static void sdma_irq_handler(omap_sdma_channel_t channel, errval_t err) * * \param conf Pointer to valid & initialized channel configuration */ -static errval_t run_omap_sdma_transfer(struct omap_sdma_channel_conf *conf) +static errval_t run_omap_sdma_transfer(struct sdma_driver_state* st, struct omap_sdma_channel_conf *conf) { errval_t err; omap_sdma_channel_t channel; - err = omap_sdma_allocate_channel(&channel); + err = omap_sdma_allocate_channel(st, &channel); if (err_is_fail(err)) return err; // configure and enable allocated channel - omap_sdma_set_channel_conf(channel, conf); - omap_sdma_enable_channel(channel, true); + omap_sdma_set_channel_conf(st, channel, conf); + omap_sdma_enable_channel(st, channel, true); // this task will be rescheduled by the IRQ handler - THCSuspend(&channel_state[channel].request); + THCSuspend(&st->channel_state[channel].request); // read status flag set by IRQ handler - err = channel_state[channel].err; + err = st->channel_state[channel].err; - omap_sdma_free_channel(channel); + omap_sdma_free_channel(st, channel); return err; } @@ -311,7 +305,7 @@ static errval_t frame_address_2d(struct capref cap, omap_sdma_addr_2d_t *addr, * \brief Stub to perform simple frame-to-frame memory copy * \see Flounder definition in if/omap_sdma.if */ -errval_t mem_copy(struct capref dst_cap, struct capref src_cap) +errval_t mem_copy(struct sdma_driver_state* st, struct capref dst_cap, struct capref src_cap) { errval_t err; omap_sdma_count_2d_t count; @@ -331,7 +325,7 @@ errval_t mem_copy(struct capref dst_cap, struct capref src_cap) struct omap_sdma_channel_conf conf; init_channel_conf(&conf, dst_id.base, src_id.base, 1, 1, 1, 1, count, omap44xx_sdma_DISABLE_COLOR_MODE, 0); - err = run_omap_sdma_transfer(&conf); + err = run_omap_sdma_transfer(st, &conf); return err; } @@ -340,7 +334,7 @@ errval_t mem_copy(struct capref dst_cap, struct capref src_cap) * \brief Stub to fill a memory frame with a constant value * \see Flounder definition in if/omap_sdma.if */ -errval_t mem_fill(struct capref dst_cap, uint8_t color) +errval_t mem_fill(struct sdma_driver_state* st, struct capref dst_cap, uint8_t color) { errval_t err; omap_sdma_count_2d_t count; @@ -355,7 +349,7 @@ errval_t mem_fill(struct capref dst_cap, uint8_t color) struct omap_sdma_channel_conf conf; init_channel_conf(&conf, dst_id.base, 0, 1, 1, 1, 1, count, omap44xx_sdma_CONSTANT_FILL, color); - err = run_omap_sdma_transfer(&conf); + err = run_omap_sdma_transfer(st, &conf); return err; } @@ -364,8 +358,8 @@ errval_t mem_fill(struct capref dst_cap, uint8_t color) * \brief Stub to perform a two-dimensional memory copy * \see Flounder definition in if/omap_sdma.if */ -errval_t mem_copy_2d(omap_sdma_addr_2d_t dst, omap_sdma_addr_2d_t src, - omap_sdma_count_2d_t count, bool transparent, uint32_t color) +errval_t mem_copy_2d(struct sdma_driver_state* st, omap_sdma_addr_2d_t dst, omap_sdma_addr_2d_t src, + omap_sdma_count_2d_t count, bool transparent, uint32_t color) { errval_t err; lpaddr_t src_start, dst_start; @@ -388,7 +382,7 @@ errval_t mem_copy_2d(omap_sdma_addr_2d_t dst, omap_sdma_addr_2d_t src, src.x_modify, src.y_modify, count, color_mode, color); - err = run_omap_sdma_transfer(&conf); + err = run_omap_sdma_transfer(st, &conf); return err; } @@ -396,7 +390,7 @@ errval_t mem_copy_2d(omap_sdma_addr_2d_t dst, omap_sdma_addr_2d_t src, * \brief Stub to fill parts of a frame using two-dimensional indeces * \see Flounder definition in if/omap_sdma.if */ -errval_t mem_fill_2d(omap_sdma_addr_2d_t dst, omap_sdma_count_2d_t count, uint32_t color) +errval_t mem_fill_2d(struct sdma_driver_state* st, omap_sdma_addr_2d_t dst, omap_sdma_count_2d_t count, uint32_t color) { errval_t err; lpaddr_t dst_start; @@ -409,24 +403,60 @@ errval_t mem_fill_2d(omap_sdma_addr_2d_t dst, omap_sdma_count_2d_t count, uint32 dst.x_modify, dst.y_modify, 0, 0, count, omap44xx_sdma_CONSTANT_FILL, color); - err = run_omap_sdma_transfer(&conf); + err = run_omap_sdma_transfer(st, &conf); return err; } -int main(int argc, char **argv) -{ + +static errval_t init(struct bfdriver_instance* bfi, const char* name, uint64_t flags, + struct capref* caps, size_t caps_len, char** args, size_t args_len, iref_t* dev) { + + bfi->dstate = malloc(sizeof(struct sdma_driver_state)); + if (bfi->dstate == NULL) { + return LIB_ERR_MALLOC_FAIL; + } + assert(bfi->dstate != NULL); + + // 1. Initialize the device: errval_t err; lvaddr_t dev_base; - - err = map_device_register( OMAP44XX_MAP_L4_CFG_SDMA, - OMAP44XX_MAP_L4_CFG_SDMA_SIZE, - &dev_base); + err = map_device_cap(caps[0], &dev_base); if (err_is_fail(err)) { USER_PANIC_ERR(err, "unable to map SDMA registers"); } + omap_sdma_init(bfi->dstate, (mackerel_addr_t)dev_base, sdma_irq_handler); + + // 2. Export service to talk to the device: + start_service(bfi->dstate); + + // 3. Set iref of your exported service (this is reported back to Kaluga) + *dev = 0x00; + + return SYS_ERR_OK; +} + +static errval_t attach(struct bfdriver_instance* bfi) { + return SYS_ERR_OK; +} + +static errval_t detach(struct bfdriver_instance* bfi) { + return SYS_ERR_OK; +} - omap_sdma_init((mackerel_addr_t)dev_base, sdma_irq_handler); - start_service(); +static errval_t set_sleep_level(struct bfdriver_instance* bfi, uint32_t level) { + struct sdma_driver_state* uds = bfi->dstate; + uds->level = level; + return SYS_ERR_OK; +} - return 0; +static errval_t destroy(struct bfdriver_instance* bfi) { + struct sdma_driver_state* uds = bfi->dstate; + free(uds); + bfi->dstate = NULL; + // XXX: Tear-down the service + bfi->device = 0x0; + return SYS_ERR_OK; } + + +DEFINE_MODULE(sdma, init, attach, detach, set_sleep_level, destroy); diff --git a/usr/drivers/omap44xx/sdma/omap_sdma.c b/usr/drivers/omap44xx/sdma/omap_sdma.c index d5f6971..e970e5d 100644 --- a/usr/drivers/omap44xx/sdma/omap_sdma.c +++ b/usr/drivers/omap44xx/sdma/omap_sdma.c @@ -25,11 +25,6 @@ #include "omap_sdma.h" #include -static omap44xx_sdma_t devsdma; -static bool allocated_channel[OMAP44XX_SDMA_NUM_CHANNEL]; - -static omap_sdma_irq_handler_t irq_callback; - static inline errval_t omap_sdma_read_csr(omap44xx_sdma_dma4_csr_t csr) { if (omap44xx_sdma_dma4_csr_misaligned_adrs_err_extract(csr)) { @@ -45,7 +40,8 @@ static inline errval_t omap_sdma_read_csr(omap44xx_sdma_dma4_csr_t csr) static void omap_sdma_irq_handler(void *arg) { - uint32_t irqstatus = omap44xx_sdma_dma4_irqstatus_line_rd(&devsdma, OMAP44XX_SDMA_IRQ_LINE); + struct sdma_driver_state* st = (struct sdma_driver_state*) arg; + uint32_t irqstatus = omap44xx_sdma_dma4_irqstatus_line_rd(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE); for (omap_sdma_channel_t channel=0; channel> channel) & 0x1; @@ -54,7 +50,7 @@ static void omap_sdma_irq_handler(void *arg) SDMA_PRINT("interrupt on channel %u\n", channel); // read out status flags - omap44xx_sdma_dma4_csr_t csr = omap44xx_sdma_dma4_csr_rd(&devsdma, channel); + omap44xx_sdma_dma4_csr_t csr = omap44xx_sdma_dma4_csr_rd(&st->devsdma, channel); // check for errors errval_t err = omap_sdma_read_csr(csr); @@ -62,27 +58,27 @@ static void omap_sdma_irq_handler(void *arg) if (err_is_ok(err)) { // no error found, check for "End of Block" event if(omap44xx_sdma_dma4_csr_block_extract(csr)) { - irq_callback(channel, err); + st->irq_callback(st, channel, err); } } else { // OMAP4460 Multimedia Device Silicon Errata, Revision A: // 1.7 sDMA Channel Is Not Disabled After A Transaction Error if (err_no(err) == OMAP_SDMA_ERR_TRANSACTION) { // Workaround: disable channel by software - omap44xx_sdma_dma4_ccr_enable_wrf(&devsdma, channel, 0); + omap44xx_sdma_dma4_ccr_enable_wrf(&st->devsdma, channel, 0); } - irq_callback(channel, err); + st->irq_callback(st, channel, err); } // clear all read status flags - omap44xx_sdma_dma4_csr_wr(&devsdma, channel, csr); + omap44xx_sdma_dma4_csr_wr(&st->devsdma, channel, csr); } SDMA_PRINT("interrupt finished\n"); // clear all set status bits - omap44xx_sdma_dma4_irqstatus_line_wr(&devsdma, OMAP44XX_SDMA_IRQ_LINE, irqstatus); + omap44xx_sdma_dma4_irqstatus_line_wr(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE, irqstatus); } @@ -103,9 +99,9 @@ static void omap_sdma_kernel_irq_handler(void) } #endif -static void omap_sdma_irq_config(omap_sdma_channel_t channel) +static void omap_sdma_irq_config(struct sdma_driver_state* st, omap_sdma_channel_t channel) { - omap44xx_sdma_dma4_cicr_t dma4_cicr = omap44xx_sdma_dma4_cicr_rd(&devsdma, channel); + omap44xx_sdma_dma4_cicr_t dma4_cicr = omap44xx_sdma_dma4_cicr_rd(&st->devsdma, channel); dma4_cicr = omap44xx_sdma_dma4_cicr_super_block_ie_insert(dma4_cicr, 0x0); dma4_cicr = omap44xx_sdma_dma4_cicr_drain_ie_insert(dma4_cicr, 0x0); @@ -119,7 +115,7 @@ static void omap_sdma_irq_config(omap_sdma_channel_t channel) dma4_cicr = omap44xx_sdma_dma4_cicr_half_ie_insert(dma4_cicr, 0x0); dma4_cicr = omap44xx_sdma_dma4_cicr_drop_ie_insert(dma4_cicr, 0x0); - omap44xx_sdma_dma4_cicr_wr(&devsdma, channel, dma4_cicr); + omap44xx_sdma_dma4_cicr_wr(&st->devsdma, channel, dma4_cicr); } /** @@ -307,7 +303,7 @@ static void inline omap_sdma_channel_conf_assert_transfer_conf( * but is it the callers responsibility to ensure that the configuration is * sane and valid. */ -void omap_sdma_set_channel_conf(omap_sdma_channel_t channel, +void omap_sdma_set_channel_conf(struct sdma_driver_state* st, omap_sdma_channel_t channel, struct omap_sdma_channel_conf *conf) { // check transfer config and size parameters @@ -321,48 +317,48 @@ void omap_sdma_set_channel_conf(omap_sdma_channel_t channel, // Channel Control Register omap44xx_sdma_dma4_ccr_t dma4_ccr; - dma4_ccr = omap44xx_sdma_dma4_ccr_rd(&devsdma, channel); + dma4_ccr = omap44xx_sdma_dma4_ccr_rd(&st->devsdma, channel); dma4_ccr = omap_sdma_channel_conf_ccr(dma4_ccr, conf); - omap44xx_sdma_dma4_ccr_wr(&devsdma, channel, dma4_ccr); + omap44xx_sdma_dma4_ccr_wr(&st->devsdma, channel, dma4_ccr); // Channel Color Register omap44xx_sdma_dma4_color_t dma4_color; - dma4_color = omap44xx_sdma_dma4_color_rd(&devsdma, channel); + dma4_color = omap44xx_sdma_dma4_color_rd(&st->devsdma, channel); dma4_color = omap_sdma_channel_conf_color(channel, conf); - omap44xx_sdma_dma4_color_wr(&devsdma, channel, dma4_color); + omap44xx_sdma_dma4_color_wr(&st->devsdma, channel, dma4_color); // Channel Link Control Register omap44xx_sdma_dma4_clnk_ctrl_t dma4_clnk_ctrl; - dma4_clnk_ctrl = omap44xx_sdma_dma4_clnk_ctrl_rd(&devsdma, channel); + dma4_clnk_ctrl = omap44xx_sdma_dma4_clnk_ctrl_rd(&st->devsdma, channel); dma4_clnk_ctrl = omap_sdma_channel_conf_clnk_ctrl(channel, conf); - omap44xx_sdma_dma4_clnk_ctrl_wr(&devsdma, channel, dma4_clnk_ctrl); + omap44xx_sdma_dma4_clnk_ctrl_wr(&st->devsdma, channel, dma4_clnk_ctrl); // Channel Source Destination Parameters omap44xx_sdma_dma4_csdp_t dma4_csdp; - dma4_csdp = omap44xx_sdma_dma4_csdp_rd(&devsdma, channel); + dma4_csdp = omap44xx_sdma_dma4_csdp_rd(&st->devsdma, channel); dma4_csdp = omap_sdma_channel_conf_csdp(channel, conf); - omap44xx_sdma_dma4_csdp_wr(&devsdma, channel, dma4_csdp); + omap44xx_sdma_dma4_csdp_wr(&st->devsdma, channel, dma4_csdp); // Channel Element Number - omap44xx_sdma_dma4_cen_wr(&devsdma, channel, conf->transfer_size.element_number); + omap44xx_sdma_dma4_cen_wr(&st->devsdma, channel, conf->transfer_size.element_number); // Channel Frame Number - omap44xx_sdma_dma4_cfn_wr(&devsdma, channel, conf->transfer_size.frame_number); + omap44xx_sdma_dma4_cfn_wr(&st->devsdma, channel, conf->transfer_size.frame_number); // Channel Source Element Index - omap44xx_sdma_dma4_csei_wr(&devsdma, channel, conf->src_conf.element_index); + omap44xx_sdma_dma4_csei_wr(&st->devsdma, channel, conf->src_conf.element_index); // Channel Source Frame Index - omap44xx_sdma_dma4_csfi_wr(&devsdma, channel, conf->src_conf.frame_index); + omap44xx_sdma_dma4_csfi_wr(&st->devsdma, channel, conf->src_conf.frame_index); // Channel Destination Element Index - omap44xx_sdma_dma4_cdei_wr(&devsdma, channel, conf->dst_conf.element_index); + omap44xx_sdma_dma4_cdei_wr(&st->devsdma, channel, conf->dst_conf.element_index); // Channel Destination Frame Index - omap44xx_sdma_dma4_cdfi_wr(&devsdma, channel, conf->dst_conf.frame_index); + omap44xx_sdma_dma4_cdfi_wr(&st->devsdma, channel, conf->dst_conf.frame_index); // Channel Source Start Address - omap44xx_sdma_dma4_cssa_wr(&devsdma, channel, conf->src_conf.start_address); + omap44xx_sdma_dma4_cssa_wr(&st->devsdma, channel, conf->src_conf.start_address); // Channel Source Destination Address - omap44xx_sdma_dma4_cdsa_wr(&devsdma, channel, conf->dst_conf.start_address); + omap44xx_sdma_dma4_cdsa_wr(&st->devsdma, channel, conf->dst_conf.start_address); } /** @@ -374,42 +370,42 @@ void omap_sdma_set_channel_conf(omap_sdma_channel_t channel, * It is the callers responsibility to ensure that the channel was configured * properly before this function is called. */ -void omap_sdma_enable_channel(omap_sdma_channel_t channel, bool interrupt) +void omap_sdma_enable_channel(struct sdma_driver_state* st, omap_sdma_channel_t channel, bool interrupt) { assert(channel < OMAP44XX_SDMA_NUM_CHANNEL); // clear all channel status flags - omap44xx_sdma_dma4_csr_wr(&devsdma, channel, 0xFFFFFFFF); + omap44xx_sdma_dma4_csr_wr(&st->devsdma, channel, 0xFFFFFFFF); - uint32_t irqenable = omap44xx_sdma_dma4_irqenable_rd(&devsdma, OMAP44XX_SDMA_IRQ_LINE); + uint32_t irqenable = omap44xx_sdma_dma4_irqenable_rd(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE); if (interrupt) { // set channel irqenable |= 1 << channel; // reset irq status for this channel - omap44xx_sdma_dma4_irqstatus_line_wr(&devsdma, OMAP44XX_SDMA_IRQ_LINE, 1 << channel); + omap44xx_sdma_dma4_irqstatus_line_wr(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE, 1 << channel); } else { // clear channel irqenable &= ~(1 << channel); } - omap44xx_sdma_dma4_irqenable_wr(&devsdma, OMAP44XX_SDMA_IRQ_LINE, irqenable); + omap44xx_sdma_dma4_irqenable_wr(&st->devsdma, OMAP44XX_SDMA_IRQ_LINE, irqenable); - omap44xx_sdma_dma4_ccr_enable_wrf(&devsdma, channel, 1); + omap44xx_sdma_dma4_ccr_enable_wrf(&st->devsdma, channel, 1); } /** * \brief Poll a enabled channel for completion of the transfer. */ -errval_t omap_sdma_poll_channel(omap_sdma_channel_t channel) +errval_t omap_sdma_poll_channel(struct sdma_driver_state* st, omap_sdma_channel_t channel) { assert(channel < OMAP44XX_SDMA_NUM_CHANNEL); // interrupts should be disabled in polling mode assert((omap44xx_sdma_dma4_irqenable_rd( - &devsdma, OMAP44XX_SDMA_IRQ_LINE) & 1 << channel) == 0x0 + &st->devsdma, OMAP44XX_SDMA_IRQ_LINE) & 1 << channel) == 0x0 ); for (;;) { - omap44xx_sdma_dma4_csr_t csr = omap44xx_sdma_dma4_csr_rd(&devsdma, channel); + omap44xx_sdma_dma4_csr_t csr = omap44xx_sdma_dma4_csr_rd(&st->devsdma, channel); errval_t err = omap_sdma_read_csr(csr); @@ -425,13 +421,13 @@ errval_t omap_sdma_poll_channel(omap_sdma_channel_t channel) * \brief Allocate a SDMA channel. Will return an error if there are no channels * available. */ -errval_t omap_sdma_allocate_channel(omap_sdma_channel_t *channel) +errval_t omap_sdma_allocate_channel(struct sdma_driver_state* st, omap_sdma_channel_t *channel) { assert(channel != NULL); for (omap_sdma_channel_t c = 0; callocated_channel[c]) { + st->allocated_channel[c] = true; *channel = c; return SYS_ERR_OK; } @@ -442,10 +438,10 @@ errval_t omap_sdma_allocate_channel(omap_sdma_channel_t *channel) /** * \brief Frees a previously allocated SDMA channel. */ -void omap_sdma_free_channel(omap_sdma_channel_t channel) +void omap_sdma_free_channel(struct sdma_driver_state* st, omap_sdma_channel_t channel) { - assert(allocated_channel[channel]); - allocated_channel[channel] = false; + assert(st->allocated_channel[channel]); + st->allocated_channel[channel] = false; } /** @@ -459,19 +455,19 @@ void omap_sdma_free_channel(omap_sdma_channel_t channel) * an interrupt. The source channel and the the reason of the interrupt are * passed to the callback as an the argument. */ -errval_t omap_sdma_init(mackerel_addr_t dev_base, omap_sdma_irq_handler_t irq_cb) +errval_t omap_sdma_init(struct sdma_driver_state* st, mackerel_addr_t dev_base, omap_sdma_irq_handler_t irq_cb) { // init global variables STATIC_ASSERT_SIZEOF(bool, 1); - memset(allocated_channel, false, OMAP44XX_SDMA_NUM_CHANNEL); + memset(st->allocated_channel, false, OMAP44XX_SDMA_NUM_CHANNEL); - omap44xx_sdma_initialize(&devsdma, dev_base); + omap44xx_sdma_initialize(&st->devsdma, dev_base); // check if we can read the revision - assert(omap44xx_sdma_dma4_revision_rd(&devsdma) == 0x10900); + assert(omap44xx_sdma_dma4_revision_rd(&st->devsdma) == 0x10900); assert(irq_cb != NULL); - irq_callback = irq_cb; + st->irq_callback = irq_cb; errval_t err = SYS_ERR_OK; #ifdef OMAP_SDMA_KERNELBENCH @@ -489,18 +485,18 @@ errval_t omap_sdma_init(mackerel_addr_t dev_base, omap_sdma_irq_handler_t irq_cb GIC_IRQ_EDGE_TRIGGERED, GIC_IRQ_N_TO_N); #else // in userspace, register normal interrupt handler - err = inthandler_setup_arm(omap_sdma_irq_handler, NULL, OMAP44XX_SDMA_IRQ); + err = inthandler_setup_arm(omap_sdma_irq_handler, st, OMAP44XX_SDMA_IRQ); #endif // set fifo depth to maximum burst size - omap44xx_sdma_dma4_gcr_max_channel_fifo_depth_wrf(&devsdma, 64); + omap44xx_sdma_dma4_gcr_max_channel_fifo_depth_wrf(&st->devsdma, 64); // configure error and interrupt handling of the device for(omap_sdma_channel_t channel = 0; channel < OMAP44XX_SDMA_NUM_CHANNEL; channel++) { - omap_sdma_irq_config(channel); + omap_sdma_irq_config(st, channel); } return err; diff --git a/usr/drivers/omap44xx/sdma/omap_sdma.h b/usr/drivers/omap44xx/sdma/omap_sdma.h index fcb4600..f0ffb2e 100644 --- a/usr/drivers/omap44xx/sdma/omap_sdma.h +++ b/usr/drivers/omap44xx/sdma/omap_sdma.h @@ -14,8 +14,9 @@ #include typedef uint8_t omap_sdma_channel_t; +struct sdma_driver_state; -typedef void (*omap_sdma_irq_handler_t)(omap_sdma_channel_t, errval_t); +typedef void (*omap_sdma_irq_handler_t)(struct sdma_driver_state*, omap_sdma_channel_t, errval_t); typedef uint8_t omap44xx_sdma_color_mode_t; #define omap44xx_sdma_DISABLE_COLOR_MODE ((omap44xx_sdma_color_mode_t)0x0) @@ -38,6 +39,24 @@ typedef uint8_t omap44xx_sdma_color_mode_t; #define SDMA_PRINT(...) do{ } while ( false ) #endif +#include + +/// Channel State. Filled by the interrupt callback, read by the request task. +struct channel_state { + awe_t *request; + errval_t err; +}; + +struct sdma_driver_state { + omap44xx_sdma_t devsdma; + + bool allocated_channel[OMAP44XX_SDMA_NUM_CHANNEL]; + struct channel_state channel_state[OMAP44XX_SDMA_NUM_CHANNEL]; + omap_sdma_irq_handler_t irq_callback; + + uint32_t level; +}; + struct omap_sdma_transfer_conf { lpaddr_t start_address; omap44xx_sdma_addr_mode_t addr_mode; @@ -76,18 +95,18 @@ struct omap_sdma_channel_conf { omap_sdma_channel_t next_channel; }; -errval_t omap_sdma_init(mackerel_addr_t dev_base, omap_sdma_irq_handler_t); +errval_t omap_sdma_init(struct sdma_driver_state*, mackerel_addr_t, omap_sdma_irq_handler_t); -errval_t omap_sdma_allocate_channel(omap_sdma_channel_t *channel); -void omap_sdma_free_channel(omap_sdma_channel_t channel); +errval_t omap_sdma_allocate_channel(struct sdma_driver_state* st, omap_sdma_channel_t *channel); +void omap_sdma_free_channel(struct sdma_driver_state* st, omap_sdma_channel_t channel); void omap_sdma_init_channel_conf(struct omap_sdma_channel_conf *conf); -void omap_sdma_set_channel_conf(omap_sdma_channel_t channel, +void omap_sdma_set_channel_conf(struct sdma_driver_state* st, omap_sdma_channel_t channel, struct omap_sdma_channel_conf *conf); -void omap_sdma_enable_channel(omap_sdma_channel_t channel, bool interrupt); +void omap_sdma_enable_channel(struct sdma_driver_state* st, omap_sdma_channel_t channel, bool interrupt); -errval_t omap_sdma_poll_channel(omap_sdma_channel_t channel); +errval_t omap_sdma_poll_channel(struct sdma_driver_state* st, omap_sdma_channel_t channel); #endif // OMAP44XX_SDMA_H_ diff --git a/usr/drivers/omap44xx/sdma/sdma.h b/usr/drivers/omap44xx/sdma/sdma.h index b5584ef..66dc21b 100644 --- a/usr/drivers/omap44xx/sdma/sdma.h +++ b/usr/drivers/omap44xx/sdma/sdma.h @@ -13,12 +13,13 @@ #include #include -void start_service(void); +struct sdma_driver_state; +void start_service(struct sdma_driver_state* st); -errval_t mem_copy(struct capref dst_cap, struct capref src_cap); -errval_t mem_fill(struct capref dst_cap, uint8_t color); +errval_t mem_copy(struct sdma_driver_state* st, struct capref dst_cap, struct capref src_cap); +errval_t mem_fill(struct sdma_driver_state* st, struct capref dst_cap, uint8_t color); -errval_t mem_copy_2d(omap_sdma_addr_2d_t dst, omap_sdma_addr_2d_t src, +errval_t mem_copy_2d(struct sdma_driver_state* st, omap_sdma_addr_2d_t dst, omap_sdma_addr_2d_t src, omap_sdma_count_2d_t count, bool transparent, uint32_t color); -errval_t mem_fill_2d(omap_sdma_addr_2d_t dst, omap_sdma_count_2d_t count, uint32_t color); +errval_t mem_fill_2d(struct sdma_driver_state* st, omap_sdma_addr_2d_t dst, omap_sdma_count_2d_t count, uint32_t color); #endif diff --git a/usr/drivers/omap44xx/sdma/sdma_domain.c b/usr/drivers/omap44xx/sdma/sdma_domain.c new file mode 100644 index 0000000..d04908b --- /dev/null +++ b/usr/drivers/omap44xx/sdma/sdma_domain.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +/// XXX: TODO not needed once kaluga <-> driver domain communicate over dcontrol iface +static errval_t find_cap_for(lpaddr_t address, size_t size, struct capref* out) +{ + errval_t err; + struct cnoderef argcn_cnref = { + .croot = CPTR_ROOTCN, + .cnode = ROOTCN_SLOT_ADDR(ROOTCN_SLOT_ARGCN), + .level = CNODE_TYPE_OTHER, + }; + + struct capref device_cap_iter = { + .cnode = argcn_cnref, + .slot = 0 + }; + + for (; device_cap_iter.slot < L2_CNODE_SLOTS; device_cap_iter.slot++) { + // Get cap data + struct capability cap; + err = debug_cap_identify(device_cap_iter, &cap); + // If cap type was Null, kernel returns error + if (err_no(err) == SYS_ERR_IDENTIFY_LOOKUP || + err_no(err) == SYS_ERR_CAP_NOT_FOUND || + err_no(err) == SYS_ERR_LMP_CAPTRANSFER_SRC_LOOKUP) { + continue; + } + + struct frame_identity fid; + err = frame_identify(device_cap_iter, &fid); + if (err_is_fail(err)) { + DEBUG_ERR(err, "Failure in frame_identify"); + return err; + } + assert(err_is_ok(err)); + + lpaddr_t address_base = address & ~(BASE_PAGE_SIZE-1); + // XXX: should be address+size <= ... + // Need to add proper register size + if (address_base >= fid.base && + (address_base + size) <= (fid.base + fid.bytes)) { + *out = device_cap_iter; + return SYS_ERR_OK; + } + } + + return DRIVERKIT_ERR_NO_CAP_FOUND; +} + + +int main(int argc, char** argv) +{ + size_t drivers = 0; + struct bfdriver* cur = NULL; + driverkit_list(&cur, &drivers); + for (size_t i=0; iname); + cur += 1; + } + + struct capref* caps = calloc(1, sizeof(struct capref)); + errval_t err = find_cap_for(OMAP44XX_MAP_L4_CFG_SDMA, OMAP44XX_MAP_L4_CFG_SDMA_SIZE, &caps[0]); + if (err_is_fail(err)) { + USER_PANIC_ERR(err, "finding cap failed."); + } + + iref_t dev, ctrl; + driverkit_create_driver("sdma", "sdma_inst", caps, 1, NULL, 0, 0, &dev, &ctrl); + + messages_handler_loop(); + return 0; +} diff --git a/usr/drivers/omap44xx/sdma/service.c b/usr/drivers/omap44xx/sdma/service.c index ae9420c..05dad39 100644 --- a/usr/drivers/omap44xx/sdma/service.c +++ b/usr/drivers/omap44xx/sdma/service.c @@ -21,7 +21,7 @@ #include "sdma.h" -static void run_service(struct omap_sdma_thc_service_binding_t *sv) +static void run_service(struct sdma_driver_state* st, struct omap_sdma_thc_service_binding_t *sv) { omap_sdma_service_msg_t msg; bool loop = true; @@ -41,19 +41,19 @@ static void run_service(struct omap_sdma_thc_service_binding_t *sv) // dispatch it switch(msg.msg) { case omap_sdma_mem_copy: - reterr = mem_copy( + reterr = mem_copy(st, msg.args.mem_copy.in.dst, msg.args.mem_copy.in.src); sv->send.mem_copy(sv, reterr); break; case omap_sdma_mem_fill: - reterr = mem_fill( + reterr = mem_fill(st, msg.args.mem_fill.in.dst, msg.args.mem_fill.in.color); sv->send.mem_fill(sv, reterr); break; case omap_sdma_mem_copy_2d: - reterr = mem_copy_2d( + reterr = mem_copy_2d(st, msg.args.mem_copy_2d.in.dst, msg.args.mem_copy_2d.in.src, msg.args.mem_copy_2d.in.count, @@ -62,7 +62,7 @@ static void run_service(struct omap_sdma_thc_service_binding_t *sv) sv->send.mem_copy_2d(sv, reterr); break; case omap_sdma_mem_fill_2d: - reterr = mem_fill_2d( + reterr = mem_fill_2d(st, msg.args.mem_fill_2d.in.dst, msg.args.mem_fill_2d.in.count, msg.args.mem_fill_2d.in.color); @@ -78,7 +78,7 @@ static void run_service(struct omap_sdma_thc_service_binding_t *sv) free(sv); } -void start_service(void) +void start_service(struct sdma_driver_state* st) { errval_t err; @@ -110,7 +110,7 @@ void start_service(void) USER_PANIC_ERR(err, "thc init failed"); } - ASYNC({run_service(sv);}); + ASYNC({run_service(st, sv);}); } }); } -- 1.7.2.5