/*===========================================================================* * dsp_dma_setup *===========================================================================*/ PRIVATE void dsp_dma_setup(phys_bytes address, int count) { pvb_pair_t pvb[9]; dprint("Setting up %d bit DMA\n", DspBits); if(DspBits == 8) { /* 8 bit sound */ count--; pv_set(pvb[0], DMA8_MASK, SB_DMA_8 | 0x04); /* Disable DMA channel */ pv_set(pvb[1], DMA8_CLEAR, 0x00); /* Clear flip flop */ /* set DMA mode */ pv_set(pvb[2], DMA8_MODE, (DmaMode == DEV_WRITE_S ? DMA8_AUTO_PLAY : DMA8_AUTO_REC)); pv_set(pvb[3], DMA8_ADDR, (address >> 0) & 0xff); /* Low_byte of address */ pv_set(pvb[4], DMA8_ADDR, (address >> 8) & 0xff); /* High byte of address */ pv_set(pvb[5], DMA8_PAGE, (address >> 16) & 0xff); /* 64K page number */ pv_set(pvb[6], DMA8_COUNT, (count >> 0) & 0xff); /* Low byte of count */ pv_set(pvb[7], DMA8_COUNT, (count >> 8) & 0xff); /* High byte of count */ pv_set(pvb[8], DMA8_MASK, SB_DMA_8); /* Enable DMA channel */ sys_voutb(pvb, 9); } else { /* 16 bit sound */
/*===========================================================================* * printer_intr * *===========================================================================*/ static void printer_intr(unsigned int UNUSED(mask)) { /* This function does the actual output to the printer. This is called on an * interrupt message sent from the generic interrupt handler that 'forwards' * interrupts to this driver. The generic handler did not reenable the printer * IRQ yet! */ u32_t status; pvb_pair_t char_out[3]; if (oleft == 0) { /* Nothing more to print. Turn off printer interrupts in case they * are level-sensitive as on the PS/2. This should be safe even * when the printer is busy with a previous character, because the * interrupt status does not affect the printer. */ if(sys_outb(port_base + 2, PR_SELECT) != OK) { printf("printer: sys_outb of %x failed\n", port_base+2); panic("sys_outb failed"); } if(sys_irqenable(&irq_hook_id) != OK) { panic("sys_irqenable failed"); } return; } do { /* Loop to handle fast (buffered) printers. It is important that * processor interrupts are not disabled here, just printer interrupts. */ if(sys_inb(port_base + 1, &status) != OK) { printf("printer: sys_inb of %x failed\n", port_base+1); panic("sys_inb failed"); } if ((status & STATUS_MASK) == BUSY_STATUS) { /* Still busy with last output. This normally happens * immediately after doing output to an unbuffered or slow * printer. It may happen after a call from prepare_output or * pr_restart, since they are not synchronized with printer * interrupts. It may happen after a spurious interrupt. */ if(sys_irqenable(&irq_hook_id) != OK) { panic("sys_irqenable failed"); } return; } if ((status & STATUS_MASK) == NORMAL_STATUS) { /* Everything is all right. Output another character. */ pv_set(char_out[0], port_base, *optr); optr++; pv_set(char_out[1], port_base+2, ASSERT_STROBE); pv_set(char_out[2], port_base+2, NEGATE_STROBE); if(sys_voutb(char_out, 3) != OK) { /* request series of port outb */ panic("sys_voutb failed"); } user_vir_d++; user_left--; } else { /* Error. This would be better ignored (treat as busy). */ done_status = status; output_done(); if(sys_irqenable(&irq_hook_id) != OK) { panic("sys_irqenable failed"); } return; } } while (--oleft != 0); /* Finished printing chunk OK. */ done_status = OK; output_done(); if(sys_irqenable(&irq_hook_id) != OK) { panic("sys_irqenable failed"); } }