/* * prepare playback/capture stream */ static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec, struct snd_pcm_substream *subs) { int i; volatile struct dbdma_cmd __iomem *cp; struct snd_pcm_runtime *runtime = subs->runtime; int rate_index; long offset; struct pmac_stream *astr; rec->dma_size = snd_pcm_lib_buffer_bytes(subs); rec->period_size = snd_pcm_lib_period_bytes(subs); rec->nperiods = rec->dma_size / rec->period_size; rec->cur_period = 0; rate_index = snd_pmac_rate_index(chip, rec, runtime->rate); /* set up constraints */ astr = snd_pmac_get_stream(chip, another_stream(rec->stream)); if (! astr) return -EINVAL; astr->cur_freqs = 1 << rate_index; astr->cur_formats = 1 << runtime->format; chip->rate_index = rate_index; chip->format = runtime->format; /* We really want to execute a DMA stop command, after the AWACS * is initialized. * For reasons I don't understand, it stops the hissing noise * common to many PowerBook G3 systems and random noise otherwise * captured on iBook2's about every third time. -ReneR */ spin_lock_irq(&chip->reg_lock); snd_pmac_dma_stop(rec); st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); snd_pmac_dma_set_command(rec, &chip->extra_dma); snd_pmac_dma_run(rec, RUN); spin_unlock_irq(&chip->reg_lock); mdelay(5); spin_lock_irq(&chip->reg_lock); /* continuous DMA memory type doesn't provide the physical address, * so we need to resolve the address here... */ offset = runtime->dma_addr; for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) { st_le32(&cp->phy_addr, offset); st_le16(&cp->req_count, rec->period_size); /*st_le16(&cp->res_count, 0);*/ st_le16(&cp->xfer_status, 0); offset += rec->period_size; } /* make loop */ st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS); st_le32(&cp->cmd_dep, rec->cmd.addr); snd_pmac_dma_stop(rec); snd_pmac_dma_set_command(rec, &rec->cmd); spin_unlock_irq(&chip->reg_lock); return 0; }
int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, u32 val, unsigned int bytes, int is_bigendian) { void *data = run->mmio.data; if (bytes > sizeof(run->mmio.data)) { printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, run->mmio.len); } run->mmio.phys_addr = vcpu->arch.paddr_accessed; run->mmio.len = bytes; run->mmio.is_write = 1; vcpu->mmio_needed = 1; vcpu->mmio_is_write = 1; /* Store the value at the lowest bytes in 'data'. */ if (is_bigendian) { switch (bytes) { case 4: *(u32 *)data = val; break; case 2: *(u16 *)data = val; break; case 1: *(u8 *)data = val; break; } } else { /* Store LE value into 'data'. */ switch (bytes) { case 4: st_le32(data, val); break; case 2: st_le16(data, val); break; case 1: *(u8 *)data = val; break; } } return EMULATE_DO_MMIO; }
static inline void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count) { st_le16(&cp->req_count, count); st_le16(&cp->command, cmd); st_le32(&cp->phy_addr, virt_to_bus(buf)); cp->xfer_status = 0; }
/* * handling beep */ void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long addr, int speed) { struct pmac_stream *rec = &chip->playback; snd_pmac_dma_stop(rec); st_le16(&chip->extra_dma.cmds->req_count, bytes); st_le16(&chip->extra_dma.cmds->xfer_status, 0); st_le32(&chip->extra_dma.cmds->cmd_dep, chip->extra_dma.addr); st_le32(&chip->extra_dma.cmds->phy_addr, addr); st_le16(&chip->extra_dma.cmds->command, OUTPUT_MORE + BR_ALWAYS); out_le32(&chip->awacs->control, (in_le32(&chip->awacs->control) & ~0x1f00) | (speed << 8)); out_le32(&chip->awacs->byteswap, 0); snd_pmac_dma_set_command(rec, &chip->extra_dma); snd_pmac_dma_run(rec, RUN); }
/* * Handle DEAD DMA transfers: * if the TX status comes up "DEAD" - reported on some Power Computing machines * we need to re-start the dbdma - but from a different physical start address * and with a different transfer length. It would get very messy to do this * with the normal dbdma_cmd blocks - we would have to re-write the buffer start * addresses each time. So, we will keep a single dbdma_cmd block which can be * fiddled with. * When DEAD status is first reported the content of the faulted dbdma block is * copied into the emergency buffer and we note that the buffer is in use. * we then bump the start physical address by the amount that was successfully * output before it died. * On any subsequent DEAD result we just do the bump-ups (we know that we are * already using the emergency dbdma_cmd). * CHECK: this just tries to "do it". It is possible that we should abandon * xfers when the number of residual bytes gets below a certain value - I can * see that this might cause a loop-forever if a too small transfer causes * DEAD status. However this is a TODO for now - we'll see what gets reported. * When we get a successful transfer result with the emergency buffer we just * pretend that it completed using the original dmdma_cmd and carry on. The * 'next_cmd' field will already point back to the original loop of blocks. */ static inline void snd_pmac_pcm_dead_xfer(struct pmac_stream *rec, volatile struct dbdma_cmd __iomem *cp) { unsigned short req, res ; unsigned int phy ; /* printk(KERN_WARNING "snd-powermac: DMA died - patching it up!\n"); */ /* to clear DEAD status we must first clear RUN set it to quiescent to be on the safe side */ (void)in_le32(&rec->dma->status); out_le32(&rec->dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); if (!emergency_in_use) { /* new problem */ memcpy((void *)emergency_dbdma.cmds, (void *)cp, sizeof(struct dbdma_cmd)); emergency_in_use = 1; st_le16(&cp->xfer_status, 0); st_le16(&cp->req_count, rec->period_size); cp = emergency_dbdma.cmds; } /* now bump the values to reflect the amount we haven't yet shifted */ req = ld_le16(&cp->req_count); res = ld_le16(&cp->res_count); phy = ld_le32(&cp->phy_addr); phy += (req - res); st_le16(&cp->req_count, res); st_le16(&cp->res_count, 0); st_le16(&cp->xfer_status, 0); st_le32(&cp->phy_addr, phy); st_le32(&cp->cmd_dep, rec->cmd.addr + sizeof(struct dbdma_cmd)*((rec->cur_period+1)%rec->nperiods)); st_le16(&cp->command, OUTPUT_MORE | BR_ALWAYS | INTR_ALWAYS); /* point at our patched up command block */ out_le32(&rec->dma->cmdptr, emergency_dbdma.addr); /* we must re-start the controller */ (void)in_le32(&rec->dma->status); /* should complete clearing the DEAD status */ out_le32(&rec->dma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); }
int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, u64 val, unsigned int bytes, int is_default_endian) { void *data = run->mmio.data; int idx, ret; int is_bigendian; if (kvmppc_need_byteswap(vcpu)) { /* Default endianness is "little endian". */ is_bigendian = !is_default_endian; } else { /* Default endianness is "big endian". */ is_bigendian = is_default_endian; } if (bytes > sizeof(run->mmio.data)) { printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, run->mmio.len); } run->mmio.phys_addr = vcpu->arch.paddr_accessed; run->mmio.len = bytes; run->mmio.is_write = 1; vcpu->mmio_needed = 1; vcpu->mmio_is_write = 1; /* Store the value at the lowest bytes in 'data'. */ if (is_bigendian) { switch (bytes) { case 8: *(u64 *)data = val; break; case 4: *(u32 *)data = val; break; case 2: *(u16 *)data = val; break; case 1: *(u8 *)data = val; break; } } else { /* Store LE value into 'data'. */ switch (bytes) { case 4: st_le32(data, val); break; case 2: st_le16(data, val); break; case 1: *(u8 *)data = val; break; } } idx = srcu_read_lock(&vcpu->kvm->srcu); ret = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr, bytes, &run->mmio.data); srcu_read_unlock(&vcpu->kvm->srcu, idx); if (!ret) { vcpu->mmio_needed = 0; return EMULATE_DONE; } return EMULATE_DO_MMIO; }
static inline void setup_transfer(struct floppy_state *fs) { int n; volatile struct swim3 *sw = fs->swim3; struct dbdma_cmd *cp = fs->dma_cmd; struct dbdma_regs *dr = fs->dma; if (fd_req->current_nr_sectors <= 0) { printk(KERN_ERR "swim3: transfer 0 sectors?\n"); return; } if (rq_data_dir(fd_req) == WRITE) n = 1; else { n = fs->secpertrack - fs->req_sector + 1; if (n > fd_req->current_nr_sectors) n = fd_req->current_nr_sectors; } fs->scount = n; swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0); out_8(&sw->sector, fs->req_sector); out_8(&sw->nsect, n); out_8(&sw->gap3, 0); st_le32(&dr->cmdptr, virt_to_bus(cp)); if (rq_data_dir(fd_req) == WRITE) { /* Set up 3 dma commands: write preamble, data, postamble */ init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble)); ++cp; init_dma(cp, OUTPUT_MORE, fd_req->buffer, 512); ++cp; init_dma(cp, OUTPUT_LAST, write_postamble, sizeof(write_postamble)); } else { init_dma(cp, INPUT_LAST, fd_req->buffer, n * 512); } ++cp; out_le16(&cp->command, DBDMA_STOP); out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); in_8(&sw->error); out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); if (rq_data_dir(fd_req) == WRITE) out_8(&sw->control_bis, WRITE_SECTORS); in_8(&sw->intr); out_le32(&dr->control, (RUN << 16) | RUN); /* enable intr when transfer complete */ out_8(&sw->intr_enable, TRANSFER_DONE); out_8(&sw->control_bis, DO_ACTION); set_timeout(fs, 2*HZ, xfer_timeout); /* enable timeout */ }
static void mac53c94_init(struct fsc_state *state) { volatile struct mac53c94_regs *regs = state->regs; volatile struct dbdma_regs *dma = state->dma; int x; regs->config1 = state->host->this_id | CF1_PAR_ENABLE; regs->sel_timeout = TIMO_VAL(250); /* 250ms */ regs->clk_factor = CLKF_VAL(state->clk_freq); regs->config2 = CF2_FEATURE_EN; regs->config3 = 0; regs->sync_period = 0; regs->sync_offset = 0; eieio(); x = regs->interrupt; st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); }
static void xfer_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; volatile struct swim3 *sw = fs->swim3; struct dbdma_regs *dr = fs->dma; struct dbdma_cmd *cp = fs->dma_cmd; unsigned long s; fs->timeout_pending = 0; st_le32(&dr->control, RUN << 16); out_8(&sw->intr_enable, 0); out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); out_8(&sw->select, RELAX); if (rq_data_dir(fd_req) == WRITE) ++cp; if (ld_le16(&cp->xfer_status) != 0) s = fs->scount - ((ld_le16(&cp->res_count) + 511) >> 9); else
int mac53c94_host_reset(Scsi_Cmnd *cmd) { struct fsc_state *state = (struct fsc_state *) cmd->device->host->hostdata; volatile struct mac53c94_regs *regs = state->regs; volatile struct dbdma_regs *dma = state->dma; st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); regs->command = CMD_SCSI_RESET; /* assert RST */ eieio(); udelay(100); /* leave it on for a while (>= 25us) */ regs->command = CMD_RESET; eieio(); udelay(20); mac53c94_init(state); regs->command = CMD_NOP; eieio(); return SUCCESS; }
static void mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) { struct fsc_state *state = (struct fsc_state *) dev_id; volatile struct mac53c94_regs *regs = state->regs; volatile struct dbdma_regs *dma = state->dma; Scsi_Cmnd *cmd = state->current_req; int nb, stat, seq, intr; static int mac53c94_errors; int dma_dir; /* * Apparently, reading the interrupt register unlatches * the status and sequence step registers. */ seq = regs->seqstep; stat = regs->status; intr = regs->interrupt; #if 0 printk(KERN_DEBUG "mac53c94_intr, intr=%x stat=%x seq=%x phase=%d\n", intr, stat, seq, state->phase); #endif if (intr & INTR_RESET) { /* SCSI bus was reset */ printk(KERN_INFO "external SCSI bus reset detected\n"); regs->command = CMD_NOP; st_le32(&dma->control, RUN << 16); /* stop dma */ cmd_done(state, DID_RESET << 16); return; } if (intr & INTR_ILL_CMD) { printk(KERN_ERR "53c94: invalid cmd, intr=%x stat=%x seq=%x phase=%d\n", intr, stat, seq, state->phase); cmd_done(state, DID_ERROR << 16); return; } if (stat & STAT_ERROR) { #if 0 /* XXX these seem to be harmless? */ printk("53c94: bad error, intr=%x stat=%x seq=%x phase=%d\n", intr, stat, seq, state->phase); #endif ++mac53c94_errors; regs->command = CMD_NOP + CMD_DMA_MODE; eieio(); } if (cmd == 0) { printk(KERN_DEBUG "53c94: interrupt with no command active?\n"); return; } if (stat & STAT_PARITY) { printk(KERN_ERR "mac53c94: parity error\n"); cmd_done(state, DID_PARITY << 16); return; } switch (state->phase) { case selecting: if (intr & INTR_DISCONNECT) { /* selection timed out */ cmd_done(state, DID_BAD_TARGET << 16); return; } if (intr != INTR_BUS_SERV + INTR_DONE) { printk(KERN_DEBUG "got intr %x during selection\n", intr); cmd_done(state, DID_ERROR << 16); return; } if ((seq & SS_MASK) != SS_DONE) { printk(KERN_DEBUG "seq step %x after command\n", seq); cmd_done(state, DID_ERROR << 16); return; } regs->command = CMD_NOP; /* set DMA controller going if any data to transfer */ if ((stat & (STAT_MSG|STAT_CD)) == 0 && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) { nb = cmd->SCp.this_residual; if (nb > 0xfff0) nb = 0xfff0; cmd->SCp.this_residual -= nb; regs->count_lo = nb; regs->count_mid = nb >> 8; eieio(); regs->command = CMD_DMA_MODE + CMD_NOP; eieio(); st_le32(&dma->cmdptr, virt_to_phys(state->dma_cmds)); st_le32(&dma->control, (RUN << 16) | RUN); eieio(); regs->command = CMD_DMA_MODE + CMD_XFER_DATA; state->phase = dataing; break; } else if ((stat & STAT_PHASE) == STAT_CD + STAT_IO) {
/* * pmac_ide_build_dmatable builds the DBDMA command list * for a transfer and sets the DBDMA channel to point to it. */ static int pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr) { struct dbdma_cmd *table, *tstart; int count = 0; struct request *rq = HWGROUP(drive)->rq; struct buffer_head *bh = rq->bh; unsigned int size, addr; volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs; table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(pmac_ide[ix].dma_table); out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16); while (in_le32(&dma->status) & RUN) udelay(1); do { /* * Determine addr and size of next buffer area. We assume that * individual virtual buffers are always composed linearly in * physical memory. For example, we assume that any 8kB buffer * is always composed of two adjacent physical 4kB pages rather * than two possibly non-adjacent physical 4kB pages. */ if (bh == NULL) { /* paging requests have (rq->bh == NULL) */ addr = virt_to_bus(rq->buffer); size = rq->nr_sectors << 9; } else { /* group sequential buffers into one large buffer */ addr = virt_to_bus(bh->b_data); size = bh->b_size; while ((bh = bh->b_reqnext) != NULL) { if ((addr + size) != virt_to_bus(bh->b_data)) break; size += bh->b_size; } } /* * Fill in the next DBDMA command block. * Note that one DBDMA command can transfer * at most 65535 bytes. */ while (size) { unsigned int tc = (size < 0xfe00)? size: 0xfe00; if (++count >= MAX_DCMDS) { printk(KERN_WARNING "%s: DMA table too small\n", drive->name); return 0; /* revert to PIO for this request */ } st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); st_le16(&table->req_count, tc); st_le32(&table->phy_addr, addr); table->cmd_dep = 0; table->xfer_status = 0; table->res_count = 0; addr += tc; size -= tc; ++table; } } while (bh != NULL); /* convert the last command to an input/output last command */ if (count) st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); else printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); /* add the stop command to the end of the list */ memset(table, 0, sizeof(struct dbdma_cmd)); out_le16(&table->command, DBDMA_STOP); out_le32(&dma->cmdptr, virt_to_bus(tstart)); return 1; }
/* * pmac_ide_build_dmatable builds the DBDMA command list * for a transfer and sets the DBDMA channel to point to it. */ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) { ide_hwif_t *hwif = drive->hwif; pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); struct dbdma_cmd *table; volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; struct scatterlist *sg; int wr = !!(cmd->tf_flags & IDE_TFLAG_WRITE); int i = cmd->sg_nents, count = 0; /* DMA table is already aligned */ table = (struct dbdma_cmd *) pmif->dma_table_cpu; /* Make sure DMA controller is stopped (necessary ?) */ writel((RUN|PAUSE|FLUSH|WAKE|DEAD) << 16, &dma->control); while (readl(&dma->status) & RUN) udelay(1); /* Build DBDMA commands list */ sg = hwif->sg_table; while (i && sg_dma_len(sg)) { u32 cur_addr; u32 cur_len; cur_addr = sg_dma_address(sg); cur_len = sg_dma_len(sg); if (pmif->broken_dma && cur_addr & (L1_CACHE_BYTES - 1)) { if (pmif->broken_dma_warn == 0) { printk(KERN_WARNING "%s: DMA on non aligned address, " "switching to PIO on Ohare chipset\n", drive->name); pmif->broken_dma_warn = 1; } return 0; } while (cur_len) { unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; if (count++ >= MAX_DCMDS) { printk(KERN_WARNING "%s: DMA table too small\n", drive->name); return 0; } st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); st_le16(&table->req_count, tc); st_le32(&table->phy_addr, cur_addr); table->cmd_dep = 0; table->xfer_status = 0; table->res_count = 0; cur_addr += tc; cur_len -= tc; ++table; } sg = sg_next(sg); i--; } /* convert the last command to an input/output last command */ if (count) { st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST); /* add the stop command to the end of the list */ memset(table, 0, sizeof(struct dbdma_cmd)); st_le16(&table->command, DBDMA_STOP); mb(); writel(hwif->dmatable_dma, &dma->cmdptr); return 1; } printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); return 0; /* revert to PIO for this request */ }
void _st_le32(uint32_t *addr, uint32_t val) { st_le32(addr, val); }
void pci_mem_le_st_le32(uint32_t *adr, uint32_t data) { st_le32(adr, data); }