/*************************************************************************** * NAME: DMA.C ** COPYRIGHT: ** "Copyright (c) 1992, by FORTE ** ** "This software is furnished under a license and may be used, ** copied, or disclosed only in accordance with the terms of such ** license and with the inclusion of the above copyright notice. ** This software or any other copies thereof may not be provided or ** otherwise made available to any other person. No title to and ** ownership of the software is hereby transfered." **************************************************************************** * CREATION DATE: 11/18/92 *--------------------------------------------------------------------------* * VERSION DATE NAME DESCRIPTION *> 1.0 11/18/92 Original ***************************************************************************/ #include #include #include #include #include "forte.h" #include "gf1hware.h" #include "extern.h" #include "gf1os.h" #include "dma.h" /* Hardware defs for PC's dma controllers */ #include "gf1proto.h" #include "osproto.h" #include "ultraerr.h" extern DMA_ENTRY _gf1_dma[]; /* Structure that holds data on PC's dma chan */ extern ULTRA_DATA _gf1_data; /* OS data structure */ /*************************************************************** * This function will start up a DMA transfer to the UltraSound ***************************************************************/ void UltraStartDramDma(unsigned char control)/* bits for card (see gf1hware.h) */ { /* make sure only right bits are on. Ignore others. */ control = control & (DMA_READ|DMA_16|DMA_CVT_2); /* Set xfer speed. */ control = control | DMA_R0; /* FAST ..... */ control = control | (DMA_ENABLE|DMA_IRQ_ENABLE); /* Enable & turn IRQ on */ if (_gf1_data.dram_dma_chan >= 4) control |= DMA_WIDTH_16; /* 16 bit dma channel */ /* DMA xfer. begins here. */ ENTER_CRITICAL; outp(_gf1_data.reg_select,DMA_CONTROL); outp(_gf1_data.data_hi,control); LEAVE_CRITICAL; } void UltraStartRecordDma(unsigned char control) { /* make sure only right bits are on. Ignore others. */ control = control & (ADC_MODE|ADC_TWOS_COMP); control = control | (ENABLE_ADC|ADC_IRQ_ENABLE); /* Enable & turn IRQ on */ if (_gf1_data.adc_dma_chan >= 4) control |= ADC_DMA_WIDTH; /* 16 bit dma channel */ /* DMA xfer. begins here. */ ENTER_CRITICAL; outp(_gf1_data.reg_select,SAMPLE_CONTROL); outp(_gf1_data.data_hi,control); LEAVE_CRITICAL; } void UltraDmaNext(DMA_ENTRY *tdma,int record) { unsigned int tcount; tdma->flags &= ~TWO_FLAG; /* shut off rollover */ tdma->amnt_sent = tdma->cur_size; /* save the amount xferred */ tdma->cur_size = tdma->nxt_size; /* set up for next buffer */ tcount = tdma->nxt_size; outp(tdma->single,tdma->dma_disable); /* disable chan */ outp(tdma->clear_ff,0); /* clear f/f */ outp(tdma->addr,tdma->nxt_addr&0xff); /* LSB */ outp(tdma->addr,(tdma->nxt_addr>>8)&0xff); /* MSB */ outp(tdma->page,tdma->nxt_page); /* page # */ outp(tdma->mode,tdma->cur_mode); /* set mode */ outp(tdma->clear_ff,0); /* clear f/f */ outp(tdma->count,tcount&0x0ff); /* LSB count */ outp(tdma->count,(tcount>>8)&0x0ff); /* MSB count */ outp(tdma->single,tdma->dma_enable); /* enable */ /* Now start up xfer ... */ if (record) UltraStartRecordDma(tdma->cur_control); else UltraStartDramDma(tdma->cur_control); } int PrimeDma(void far *pc_ptr,int type,unsigned int size,unsigned int channel) { DMA_ENTRY *tdma; unsigned long s_20bit,e_20bit; unsigned int spage,saddr,tcount; unsigned int epage,eaddr; #ifndef FLAT_MODEL unsigned int sseg,soff; #endif int i; unsigned char *tptr; tdma = &_gf1_dma[channel-1]; /* point to this dma data */ if (tdma->flags & DMA_PENDING) return(DMA_BUSY); tdma->flags |= DMA_PENDING; tdma->flags |= CALIB_COUNT; /* Convert the pc address to a 20 bit physical address that the DMA */ /* controller needs */ #ifdef FLAT_MODEL s_20bit = (unsigned long)pc_ptr; #else /* !FLAT_MODEL */ sseg = FP_SEG((void far*)pc_ptr); soff = FP_OFF((void far*)pc_ptr); s_20bit = (unsigned long)((((unsigned long)sseg)<< 4) + (unsigned long)soff); #endif /* FLAT_MODEL */ e_20bit = s_20bit + size - 1; spage = (unsigned int)((s_20bit & 0xffff0000L)>>16); epage = (unsigned int)((e_20bit & 0xffff0000L)>>16); if (channel >= 4) { /* if 16-bit xfer, then addr,count & size are divided by 2 */ s_20bit = s_20bit >> 1; e_20bit = e_20bit >> 1; size = size >> 1; } saddr = (unsigned int)(s_20bit & 0x0000ffffL); eaddr = (unsigned int)(e_20bit & 0x0000ffffL); #ifdef NEVER printf("saddr = %x eaddr = %x\n",saddr,eaddr); printf("s_20bit = %lx e_20bit = %lx\n",s_20bit,e_20bit); printf("spage = %d epage = %d\n",spage,epage); tptr = (unsigned char *)pc_ptr; for (i=0;i<10;i++) printf("%02x ",tptr[i]); printf("\n"); #endif /* In case the buffer goes over a page, save the data for the irq */ /* handler to use to finish sending the data */ if (spage != epage) { tdma->flags |= TWO_FLAG; tdma->nxt_page = epage; if (channel >= 4) { if (tdma->nxt_page & 0x01) tdma->nxt_addr = 0x8000; else tdma->nxt_addr = 0; eaddr &= 0x7fff; } else tdma->nxt_addr = 0; tdma->nxt_size = eaddr; size = size - eaddr - 1; /* only supposed to send this much */ } else { tdma->flags &= ~TWO_FLAG; } if ((type == INDEF_READ) && (tdma->flags & TWO_FLAG)) { return(BAD_DMA_ADDR); } tdma->cur_page = spage; tdma->cur_addr = saddr; tdma->amnt_sent = 0; /* init the amount xferred so far */ tdma->cur_size = size; /* show how big THIS part of buffer is */ tcount = size-1; switch (type) { case READ_DMA: tdma->cur_mode = tdma->read; break; case WRITE_DMA: tdma->cur_mode = tdma->write; break; case INDEF_READ: /* with this mode, all we have to do is kick off the gf1 */ /* sample control to restart the dma recording .... */ tdma->cur_mode = tdma->read | 0x10; /* turn on auto init */ break; case INDEF_WRITE: tdma->cur_mode = tdma->write | 0x10; /* turn on auto init */ break; } outp(tdma->single,tdma->dma_disable); /* disable channel */ outp(tdma->mode,tdma->cur_mode); /* set mode */ outp(tdma->clear_ff,0); /* clear f/f */ outp(tdma->addr,tdma->cur_addr&0xff); /* LSB */ outp(tdma->addr,(tdma->cur_addr>>8)&0xff); /* MSB */ outp(tdma->page,tdma->cur_page); /* page # */ outp(tdma->clear_ff,0); /* clear f/f */ outp(tdma->count,tcount&0x0ff); /* LSB count */ outp(tdma->count,(tcount>>8)&0x0ff); /* MSB count */ outp(tdma->single,tdma->dma_enable); /* enable */ return(ULTRA_OK); } void UltraStopRecordDma(void) { DMA_ENTRY *tdma; unsigned char val; ENTER_CRITICAL; outp(_gf1_data.reg_select,SAMPLE_CONTROL); val = inp(_gf1_data.data_hi); val &= ~ENABLE_ADC; outp(_gf1_data.data_hi,val); tdma = &_gf1_dma[_gf1_data.adc_dma_chan-1]; /* point to this dma data */ outp(tdma->single,tdma->dma_disable); /* disable chan */ tdma->flags &= ~DMA_PENDING; /* Clear flag that irq handler clears when the xfer is complete */ _gf1_data.flags &= ~ADC_DMA_BUSY; LEAVE_CRITICAL; } void UltraStopPlayDma(void) { DMA_ENTRY *tdma; unsigned char val; ENTER_CRITICAL; outp(_gf1_data.reg_select,DMA_CONTROL); val = inp(_gf1_data.data_hi); val &= ~DMA_ENABLE; outp(_gf1_data.data_hi,val); tdma = &_gf1_dma[_gf1_data.dram_dma_chan-1]; /* point to this dma data */ outp(tdma->single,tdma->dma_disable); /* disable chan */ tdma->flags &= ~DMA_PENDING; /* Clear flag that irq handler clears when the xfer is complete */ _gf1_data.flags &= ~DRAM_DMA_BUSY; LEAVE_CRITICAL; }