/* NB this function blocks until the transfer is complete */ static void smi_dma_read_sgl(struct bcm2835_smi_instance *inst, struct scatterlist *sgl, size_t sg_len, size_t n_bytes) { struct dma_async_tx_descriptor *desc; /* Disable SMI and set to read before dispatching DMA - if SMI is in * write mode and TX fifo is empty, it will generate a DREQ which may * cause the read DMA to complete before the SMI read command is even * dispatched! We want to dispatch DMA before SMI read so that reading * is gapless, for logic analyser. */ smi_disable(inst, DMA_DEV_TO_MEM); desc = smi_dma_submit_sgl(inst, sgl, sg_len, DMA_DEV_TO_MEM, NULL); dma_async_issue_pending(inst->dma_chan); if (inst->settings.data_width == SMI_WIDTH_8BIT) smi_init_programmed_read(inst, n_bytes); else smi_init_programmed_read(inst, n_bytes / 2); if (dma_wait_for_async_tx(desc) == DMA_ERROR) smi_dump_context_labelled(inst, "DMA timeout!"); }
ssize_t bcm2835_smi_user_dma( struct bcm2835_smi_instance *inst, enum dma_transfer_direction dma_dir, char __user *user_ptr, size_t count, struct bcm2835_smi_bounce_info **bounce) { int chunk_no = 0, chunk_size, count_left = count; struct scatterlist *sgl; void (*init_trans_func)(struct bcm2835_smi_instance *, int); spin_lock(&inst->transaction_lock); if (dma_dir == DMA_DEV_TO_MEM) init_trans_func = smi_init_programmed_read; else init_trans_func = smi_init_programmed_write; smi_disable(inst, dma_dir); sema_init(&inst->bounce.callback_sem, 0); if (bounce) *bounce = &inst->bounce; while (count_left) { chunk_size = count_left > DMA_BOUNCE_BUFFER_SIZE ? DMA_BOUNCE_BUFFER_SIZE : count_left; if (chunk_size == DMA_BOUNCE_BUFFER_SIZE) { sgl = &inst->bounce.sgl[chunk_no % DMA_BOUNCE_BUFFER_COUNT]; } else { sgl = smi_scatterlist_from_buffer( inst, inst->bounce.phys[ chunk_no % DMA_BOUNCE_BUFFER_COUNT], chunk_size, &inst->buffer_sgl); } if (!smi_dma_submit_sgl(inst, sgl, 1, dma_dir, smi_dma_callback_user_copy )) { dev_err(inst->dev, "sgl submit failed"); count = 0; goto out; } count_left -= chunk_size; chunk_no++; } dma_async_issue_pending(inst->dma_chan); if (inst->settings.data_width == SMI_WIDTH_8BIT) init_trans_func(inst, count); else if (inst->settings.data_width == SMI_WIDTH_16BIT) init_trans_func(inst, count / 2); out: spin_unlock(&inst->transaction_lock); return count; }
void smi_init() { smram_state_t smram; pci_driver_t **driver; smram = smram_save_state(); smram_tseg_set_state(SMRAM_TSEG_OPEN); outputf("NetWatch running"); /* Turn on the SMIs we want */ smi_disable(); eth_init(); crc32_init(); /* After everything is initialized, load drivers. */ for (driver = drivers; *driver; driver++) { outputf("Probing driver: %s", (*driver)->name); if (pci_probe_driver(*driver)) output("Found a card"); } outputf("Driver probe complete"); /* Load in fonts. */ text_init(); smi_register_handler(SMI_EVENT_FAST_TIMER, timer_handler); smi_enable_event(SMI_EVENT_FAST_TIMER); smi_register_handler(SMI_EVENT_DEVTRAP_KBC, kbc_handler); smi_enable_event(SMI_EVENT_DEVTRAP_KBC); smi_register_handler(SMI_EVENT_GBL_RLS, gbl_rls_handler); smi_enable_event(SMI_EVENT_GBL_RLS); smi_enable(); vga_flush_imm(1); smram_restore_state(smram); }
void c_start(unsigned int magic, struct mb_info *mbinfo) { struct mod_info *mods = mbinfo->mods; smram_state_t old_smramc; struct info_section * info; int i; void (*realmode)() = (void (*)()) 0x4000; show_cursor(); outputf("NetWatch loader"); if (magic != MULTIBOOT_LOADER_MAGIC) panic("Bootloader was not multiboot compliant; cannot continue."); for (i = 0; i < mbinfo->mod_cnt; i++) { outputf("Module found:"); outputf(" Start: %08x", (unsigned long) mods[i].mod_start); outputf(" Size: %08x", (unsigned long)mods[i].mod_end - (unsigned long)mods[i].mod_start); outputf(" Name: %s", mods[i].mod_string); } if (mbinfo->mod_cnt != 1) panic("Expected exactly one module; cannot continue."); outputf("Current SMRAMC state is: %02x", (unsigned char)smram_save_state()); outputf("Current SMI state is: %08x", inl(0x830)); // XXX ICH2 specific smi_disable(); /* Open the SMRAM aperture and load our ELF. */ old_smramc = smram_save_state(); if (smram_aseg_set_state(SMRAM_ASEG_OPEN) != 0) panic("Opening SMRAM failed; cannot load ELF."); load_elf(mods[0].mod_start, (unsigned long)mods[0].mod_end - (unsigned long)mods[0].mod_start); info = (struct info_section *)0x10000; if (info->signature != INFO_SIGNATURE) { smram_restore_state(old_smramc); /* Restore so that video ram is touchable again. */ panic("Info section signature mismatch."); } info->firstrun(); smram_restore_state(old_smramc); outputf("New SMRAMC state is: %02x", (unsigned char)smram_save_state()); puts("Waiting for a bit before returning to real mode..."); for (i=0; i<0x500000; i++) { if ((i % 0x100000) == 0) puts("."); inb(0x80); } puts("\n"); outputf("Now returning to real mode."); memcpy((void *)0x4000, _binary_realmode_bin_start, (int)&_binary_realmode_bin_size); realmode(); // goodbye! }