static void pxa_uart_dma_uninit(struct uart_pxa_port *up)
{
	struct uart_pxa_dma *pxa_dma;
	pxa_dma = &up->uart_dma;

#ifdef CONFIG_PM
	kfree(pxa_dma->tx_buf_save);
#endif

	stop_dma(up, PXA_UART_TX);
	stop_dma(up, PXA_UART_RX);
	if (pxa_dma->txdma_addr != NULL) {
		dma_free_coherent(up->port.dev, DMA_BLOCK, pxa_dma->txdma_addr,
				  pxa_dma->txdma_addr_phys);
		pxa_dma->txdma_addr = NULL;
	}
	if (pxa_dma->txdma_chan != NULL) {
		dma_release_channel(pxa_dma->txdma_chan);
		pxa_dma->txdma_chan = NULL;
	}

	if (pxa_dma->rxdma_addr != NULL) {
		dma_free_coherent(up->port.dev, DMA_BLOCK, pxa_dma->rxdma_addr,
				  pxa_dma->rxdma_addr_phys);
		pxa_dma->rxdma_addr = NULL;
	}

	if (pxa_dma->rxdma_chan != NULL) {
		dma_release_channel(pxa_dma->rxdma_chan);
		pxa_dma->rxdma_chan = NULL;
	}

	return;
}
static int serial_pxa_suspend(struct device *dev)
{
        struct uart_pxa_port *sport = dev_get_drvdata(dev);
	struct uart_pxa_dma *pxa_dma = &sport->uart_dma;
	struct dma_tx_state dma_state;

	if (sport && (sport->ier & UART_IER_DMAE)) {
		int sent = 0;
		unsigned long flags;

		local_irq_save(flags);
		/*
		 * tx stop and suspend and when resume,
		 * tx startup would be called and set it to 0
		*/
		pxa_dma->tx_stop = 1;
		pxa_dma->rx_stop = 1;
		pxa_dma->tx_saved_len = 0;
		if (dma_async_is_tx_complete(pxa_dma->txdma_chan,
					     pxa_dma->tx_cookie, NULL, NULL)
			!= DMA_SUCCESS) {
			dmaengine_pause(pxa_dma->txdma_chan);
			dmaengine_tx_status(pxa_dma->txdma_chan,
					    pxa_dma->tx_cookie, &dma_state);
			sent = pxa_dma->tx_size - dma_state.residue;
			pxa_dma->tx_saved_len = dma_state.residue;
			memcpy(pxa_dma->tx_buf_save, pxa_dma->txdma_addr + sent,
			       dma_state.residue);
			stop_dma(sport, PXA_UART_TX);
		}
		if (dma_async_is_tx_complete(pxa_dma->rxdma_chan,
					     pxa_dma->rx_cookie, NULL, NULL)
			!= DMA_SUCCESS) {
			dmaengine_pause(pxa_dma->rxdma_chan);
			pxa_uart_receive_dma_cb(sport);
			stop_dma(sport, PXA_UART_RX);
		}
		local_irq_restore(flags);
	}

	if (sport)
		uart_suspend_port(&serial_pxa_reg, &sport->port);

	/* Remove uart rx constraint which will block system entering D1p. */
	if (del_timer_sync(&sport->pxa_timer))
		pxa_timer_handler((unsigned long)sport);

        return 0;
}
Esempio n. 3
0
File: RpiTx.c Progetto: JE6HBC/rpitx
static void terminate(int dummy)
{
	stop_dma();
	//munmap(virtbase,NUM_PAGES * PAGE_SIZE); 
	printf("END OF PiTx\n");
	exit(1);
}
static void serial_pxa_stop_rx(struct uart_port *port)
{
	struct uart_pxa_port *up = (struct uart_pxa_port *)port;

	if (up->dma_enable) {
		if (up->ier & UART_IER_DMAE) {
			spin_unlock_irqrestore(&up->port.lock, up->flags);
			stop_dma(up, PXA_UART_RX);
			spin_lock_irqsave(&up->port.lock, up->flags);
		}
		up->uart_dma.rx_stop = 1;
	} else {
		up->ier &= ~UART_IER_RLSI;
		up->port.read_status_mask &= ~UART_LSR_DR;
		serial_out(up, UART_IER, up->ier);
	}
}
Esempio n. 5
0
static int hd_read_udma(block_dev_t *bdev, char *buffer, size_t count, blkno_t blkno) {
	hd_t *hd;
	hdc_t *hdc;
	int sectsleft;
	int nsects;
	int result = 0;
	char *bufp;

	if (count == 0) {
		return 0;
	}
	bufp = (char *) buffer;

	hd = (hd_t *) bdev->privdata;
	hdc = hd->hdc;
	sectsleft = count / SECTOR_SIZE;


	while (sectsleft > 0) {
		/* Select drive */
		ide_select_drive(hd);

		/* Wait for controller ready */
		result = ide_wait(hdc, HDCS_DRDY, HDTIMEOUT_DRDY);
		if (result != 0) {
			result = -EIO;
			break;
		}

		/* Calculate maximum number of sectors we can transfer */
		if (sectsleft > 256) {
			nsects = 256;
		} else {
			nsects = sectsleft;
		}

		if (nsects > MAX_DMA_XFER_SIZE / SECTOR_SIZE) {
			nsects = MAX_DMA_XFER_SIZE / SECTOR_SIZE;
		}

		/* Prepare transfer */
		result = 0;
		hdc->dir = HD_XFER_DMA;
		hdc->active = hd;

		hd_setup_transfer(hd, blkno, nsects);

		/* Setup DMA */
		setup_dma(hdc, bufp, nsects * SECTOR_SIZE, BM_CR_WRITE);

		/* Start read */
		outb(HDCMD_READDMA, hdc->iobase + HDC_COMMAND);
		start_dma(hdc);

		/* Stop DMA channel and check DMA status */
		result = stop_dma(hdc);
		if (result < 0) {
			break;
		}

		/* Check controller status */
		if (hdc->status & HDCS_ERR) {
			result = -EIO;
			break;
		}

		/* Advance to next */
		sectsleft -= nsects;
		bufp += nsects * SECTOR_SIZE;
	}

	/* Cleanup */
	hdc->dir = HD_XFER_IDLE;
	hdc->active = NULL;

	return result == 0 ? count : result;
}
Esempio n. 6
0
File: RpiTx.c Progetto: JE6HBC/rpitx
int pitx_run(
	const char Mode,
	int SampleRate,
	const float SetFrequency,
	const float ppmpll,
	const char NoUsePwmFrequency,
	ssize_t (*readWrapper)(void *buffer, size_t count),
	void (*reset)(void),
	int* skipSignals) 
{
	int i;
	//char pagemap_fn[64];

	int OffsetModulation=1000;//TBR
	int MicGain=100;
	//unsigned char *data;

	//Specific to ModeIQ
	static signed short *IQArray=NULL;

	//Specific to ModeIQ_FLOAT
	static float *IQFloatArray=NULL;

	//Specific to Mode RF
	typedef struct {
		double Frequency;
		uint32_t WaitForThisSample;
	} samplerf_t;
	samplerf_t *TabRfSample=NULL;

	fprintf(stdout,"rpitx Version %s compiled %s (F5OEO Evariste) running on ",PROGRAM_VERSION,__DATE__);

	// Init Plls Frequency using ppm (or default)

	PllFreq500MHZ=PLL_FREQ_500MHZ;
	PllFreq500MHZ+=PllFreq500MHZ * (ppmpll / 1000000.0);

	PllFreq1GHZ=PLL_FREQ_1GHZ;
	PllFreq1GHZ+=PllFreq1GHZ * (ppmpll / 1000000.0);

	PllFreq19MHZ=PLLFREQ_192;
	PllFreq19MHZ+=PllFreq19MHZ * (ppmpll / 1000000.0);

	//End of Init Plls

	if(Mode==MODE_IQ)
	{
		IQArray=malloc(DmaSampleBurstSize*2*sizeof(signed short)); // TODO A FREE AT THE END OF SOFTWARE
		reset();
	} 
	if(Mode==MODE_IQ_FLOAT)
	{
		IQFloatArray=malloc(DmaSampleBurstSize*2*sizeof(float)); // TODO A FREE AT THE END OF SOFTWARE
	}
	if((Mode==MODE_RF)||(Mode==MODE_RFA))
	{
		//TabRfSample=malloc(DmaSampleBurstSize*sizeof(samplerf_t));
		SampleRate=100000L; //NOT USED BUT BY CALCULATING TIMETOSLEEP IN RF MODE
	}
	if(Mode==MODE_VFO)
		SampleRate=50000L; //50000 BY EXPERIMENT

	if(Mode==MODE_IQ)
	{
		printf(" Frequency=%f ",GlobalTuningFrequency);
		printf(" SampleRate=%d ",SampleRate);	
	}

	pitx_SetTuneFrequency(SetFrequency*1000.0);
	pitx_init(SampleRate, GlobalTuningFrequency, skipSignals);
	
	static volatile uint32_t cur_cb,last_cb;
	int last_sample;
	int this_sample; 
	int free_slots;
	//int SumDelay=0;
	
	long int start_time;
	static long time_difference=0;
	struct timespec gettime_now;

	cur_cb = (uint32_t)virtbase+ (NUM_SAMPLES-DmaSampleBurstSize)* sizeof(dma_cb_t) *CBS_SIZE_BY_SAMPLE;
	
	last_cb=(uint32_t)virtbase /*+ 965* sizeof(dma_cb_t) *CBS_SIZE_BY_SAMPLE*/ ;


	dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]=mem_virt_to_phys((void*)cur_cb);

	unsigned char Init=1;

// -----------------------------------------------------------------

	for (;;) 
	{
		int TimeToSleep;
		static int StatusCompteur=0;
			
		cur_cb = mem_phys_to_virt((uint32_t)(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]));
		this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE);
		last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE);
		free_slots = this_sample - last_sample;
		if (free_slots < 0) // WARNING : ORIGINAL CODE WAS < strictly
			free_slots += NUM_SAMPLES;
				
		//printf("last_sample %lx cur_cb %lx FreeSlots = %d Time to sleep=%d\n",last_sample,cur_cb,free_slots,TimeToSleep);
			
		if(Init==0)
		{
			TimeToSleep=(1e6*(NUM_SAMPLES-free_slots*2))/SampleRate; // Time to sleep in us
			//printf("TimeToSleep%d\n",TimeToSleep);
		}
		else
			TimeToSleep=1000;
			
		//printf("Buffer Available=%d\n",BufferAvailable());
			
		clock_gettime(CLOCK_REALTIME, &gettime_now);
		start_time = gettime_now.tv_nsec;		
		if(TimeToSleep>=(2200+KERNEL_GRANULARITY)) // 2ms : Time to process File/Canal Coding
		{
			udelay(TimeToSleep-(2200+KERNEL_GRANULARITY));
			TimeToSleep=0;
		}
		else
		{
			//udelay(TimeToSleep);
			sched_yield();
			//TimeToSleep=0;
			//if(free_slots>(NUM_SAMPLES*9/10))
			//printf("Buffer nearly empty...%d/%d\n",free_slots,NUM_SAMPLES);
		}
			
		static int free_slots_now;
		cur_cb = mem_phys_to_virt(dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]);
		this_sample = (cur_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE);
		last_sample = (last_cb - (uint32_t)virtbase) / (sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE);
		free_slots_now = this_sample - last_sample;
		if (free_slots_now < 0) // WARNING : ORIGINAL CODE WAS < strictly
			free_slots_now += NUM_SAMPLES;
			
		clock_gettime(CLOCK_REALTIME, &gettime_now);
		time_difference = gettime_now.tv_nsec - start_time;
		if(time_difference<0) time_difference+=1E9;
			
		if(StatusCompteur%10==0)
		{ 
			//printf(" DiffTime = %ld FreeSlot %d FreeSlotDiff=%d Bitrate : %f\n",time_difference,free_slots_now,free_slots_now-free_slots,(1e9*(free_slots_now-free_slots))/(float)time_difference);	
		}
		//if((1e9*(free_slots_now-free_slots))/(float)time_difference<40100.0) printf("Drift BAD\n"); else printf("Drift GOOD\n");	
		StatusCompteur++;
		free_slots=free_slots_now;
		// FIX IT : Max(freeslot et Numsample/8)
		if((Init==1)&&(free_slots < DmaSampleBurstSize /*NUM_SAMPLES/8*/))
		{
			printf("****** STARTING TRANSMIT ********\n");
			dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]=mem_virt_to_phys((void*)virtbase );
			usleep(100);
			//Start DMA PWMFrequency
				
			//dma_reg[DMA_CS+DMA_CHANNEL_PWMFREQUENCY*0x40] = 0x10880001;				

			//Start Main DMA
			dma_reg[DMA_CS+DMA_CHANNEL*0x40] = 0x10FF0001;	// go, mid priority, wait for outstanding writes :7 Seems Max Priority
				
			Init=0;
				
			continue;
		}
		clock_gettime(CLOCK_REALTIME, &gettime_now);
		start_time = gettime_now.tv_nsec;
			
		int debug=0;

		if ((free_slots>=DmaSampleBurstSize)) 
		{
		// *************************************** MODE IQ **************************************************
			if(Mode==MODE_IQ)
			{
				int NbRead=0;
				static int Max=0;
				static int Min=32767;
				static int CompteSample=0;
				CompteSample++;
				NbRead=readWrapper(IQArray,DmaSampleBurstSize*2*2/*SHORT I,SHORT Q*/);
				
				if(NbRead!=DmaSampleBurstSize*2*2) 
				{
					if(loop_mode_flag==1)
					{
						printf("Looping FileIn\n");
						reset();
						NbRead=readWrapper(IQArray,DmaSampleBurstSize*2*2);
					}
					else {
						stop_dma();
						return 0;
					}
				}
				
				for(i=0;i<DmaSampleBurstSize;i++)
				{
					//static float samplerate=48000;
					static int amp;
					static double df;
					
					int CorrectionRpiFrequency=-1000; //TODO PPM / Offset=1KHZ at 144MHZ
					
					CompteSample++;
					//printf("i%d q%d\n",IQArray[2*i],IQArray[2*i+1]);
					
					IQToFreqAmp(IQArray[2*i+1],IQArray[2*i],&df,&amp,SampleRate);
						
					// Compression have to be done in modulation (SSB not here)
						
					double A = 87.7f; // compression parameter
					double ampf=amp/32767.0;
      				ampf = (fabs(ampf) < 1.0f/A) ? A*fabs(ampf)/(1.0f+ln(A)) : (1.0f+ln(A*fabs(ampf)))/(1.0f+ln(A)); //compand
					amp= (int)(round(ampf * 32767.0f)) ;
						
					if(amp>Max) Max=amp;
					if(amp<Min) Min=amp;	
						
					/*
					if((CompteSample%4800)==0)
					{
						//printf("%d\n",((CompteSample/48000)*1024)%32767);
						//printf("Amp %d Freq %f MinAmp %d MaxAmp %d\n",amp,df,Min,Max);
						printf("%d;%d;%d;%f\n",IQArray[2*i+1],IQArray[2*i],amp,df);
						// printf(".");
						fflush(stdout);
					}
					*/
					// TEST - WARNING, REMOVE FOR RELEASE 
					//amp=((CompteSample/48000)*1024)%32767;
					//df=0;
					//amp=amp*10;
					//amp=32767;
					//if(df<OffsetModulation+100) amp=0;
					//if(amp<32767/8) df= OffsetModulation;
					//

					// FIXME : df/harmonicNumber could alterate maybe modulations
					FrequencyAmplitudeToRegister((GlobalTuningFrequency-OffsetModulation+/*(CompteSample/480)*/+df/HarmonicNumber)/HarmonicNumber,amp,last_sample++,0,SampleRate,NoUsePwmFrequency,CompteSample%2);
					// !!!!!!!!!!!!!!!!!!!! 680 is for 48KHZ , should be adpated !!!!!!!!!!!!!!!!!

					free_slots--;
					if (last_sample == NUM_SAMPLES)	last_sample = 0;
				}
			}
		// *************************************** MODE IQ FLOAT**************************************************
			if(Mode==MODE_IQ_FLOAT)
			{
				int NbRead=0;
				static int Max=0;
				static int Min=32767;
				static int CompteSample=0;
				CompteSample++;
				NbRead=readWrapper(IQFloatArray,DmaSampleBurstSize*2*sizeof(float));
				
				if(NbRead!=DmaSampleBurstSize*2*sizeof(float)) 
				{
					if(loop_mode_flag==1)
					{
						printf("Looping FileIn\n");
						reset();
					}
					else if (!useStdin) {
						stop_dma();
						return 0;
					}
				}
				
				for(i=0;i<DmaSampleBurstSize;i++)
				{
					//static float samplerate=48000;
					static int amp;
					static double df;
					
					int CorrectionRpiFrequency=-1000; //TODO PPM / Offset=1KHZ at 144MHZ
					
					CompteSample++;
					//printf("i%d q%d\n",IQArray[2*i],IQArray[2*i+1]);
					
					IQToFreqAmp(IQFloatArray[2*i+1]*32767,IQFloatArray[2*i]*32767,&df,&amp,SampleRate);

					if(amp>Max) Max=amp;
					if(amp<Min) Min=amp;
					/*	
					if((CompteSample%4800)==0)
					{
						//printf("%d\n",((CompteSample/48000)*1024)%32767);
						printf("Amp %d Freq %f MinAmp %d MaxAmp %d\n",amp,df,Min,Max);
						// printf(".");
						fflush(stdout);
					}
					*/
					// TEST - WARNING, REMOVE FOR RELEASE 
					//amp=((CompteSample/48000)*1024)%32767;
					//df=0;
					//amp=amp*10;
					//amp=32767;
					//if(df<OffsetModulation+100) amp=0;
					//
					//amp=32767;
					//if(df>SampleRate/2) df=SampleRate/2-df;
					FrequencyAmplitudeToRegister((GlobalTuningFrequency-OffsetModulation+df/HarmonicNumber)/HarmonicNumber,amp,last_sample++,0,SampleRate,NoUsePwmFrequency,CompteSample%2);
						
					free_slots--;
					if (last_sample == NUM_SAMPLES)	last_sample = 0;
				}
			}
		// *************************************** MODE RF **************************************************
			if((Mode==MODE_RF)||(Mode==MODE_RFA))
			{
				// SHOULD NOT EXEED 200 STEP*500ns; SAMPLERATE SHOULD BE MAX TO HAVE PRECISION FOR PCM 
				// BUT FIFO OF PCM IS 16 : SAMPLERATE MAYBE NOT EXCESS 16*80000 ! CAREFULL BUGS HERE
				#define MAX_DELAY_WAIT 25000 
				static int CompteSample=0;
				static uint32_t TimeRemaining=0;
				static samplerf_t SampleRf;
				static int NbRead;
				CompteSample++;
				int i;
				for(i=0;i<DmaSampleBurstSize;i++)
				{
					if(TimeRemaining==0)
					{
						NbRead=readWrapper(&SampleRf,sizeof(samplerf_t));
						if(NbRead!=sizeof(samplerf_t)) 
						{
							if(loop_mode_flag==1)
							{
								//printf("Looping FileIn\n");
								reset();
								NbRead=readWrapper(&SampleRf,sizeof(samplerf_t));
							}
							else if (!useStdin)
							{
								stop_dma();
								return 0;
							}
						}
							
						TimeRemaining=SampleRf.WaitForThisSample;
						//TimeRemaining=50000;//SampleRf.WaitForThisSample;
						debug=1;
						//printf("A=%f Time =%d \n",SampleRf.Frequency,SampleRf.WaitForThisSample);
					}
					else
						debug=0;	
					
					static int amp=32767;
					static int WaitSample=0;
					
					if(TimeRemaining>MAX_DELAY_WAIT) 
						WaitSample=MAX_DELAY_WAIT;	
					else
						WaitSample=TimeRemaining;
					
					//printf("TimeRemaining %d WaitSample %d\n",TimeRemaining,WaitSample);
					if(Mode==MODE_RF)
					{
						if(SampleRf.Frequency==0.0)
						{
							amp=0;
							SampleRf.Frequency=00.0;// TODO change that ugly frequency
						}
						else
							amp=32767;
						FrequencyAmplitudeToRegister((SampleRf.Frequency/HarmonicNumber+GlobalTuningFrequency)/HarmonicNumber,amp,last_sample++,WaitSample,0,NoUsePwmFrequency,debug);
					}
					if(Mode==MODE_RFA)
						FrequencyAmplitudeToRegister((GlobalTuningFrequency)/HarmonicNumber,SampleRf.Frequency,last_sample++,WaitSample,0,NoUsePwmFrequency,debug);

					TimeRemaining-=WaitSample;
					free_slots--;
					if (last_sample == NUM_SAMPLES)	last_sample = 0;
				}
			}
				
		// *************************************** MODE VFO **************************************************
			if(Mode==MODE_VFO)
			{
				static uint32_t CompteSample=0;
					
				int i;
				//printf("Begin free %d\n",free_slots);
				for(i=0;i<DmaSampleBurstSize;i++)
				{						
					//To be fine tuned !!!!	
					static int OutputPower=32767;
					CompteSample++;
					debug=1;//(debug+1)%2;	
					//OutputPower=(CompteSample/10)%32768;

					FrequencyAmplitudeToRegister(GlobalTuningFrequency/HarmonicNumber/*+(CompteSample*0.1)*/,OutputPower,last_sample++,25000,0,NoUsePwmFrequency,debug);
					free_slots--;
					//printf("%f \n",GlobalTuningFrequency+(((CompteSample/10)*1)%50000));	
					if (last_sample == NUM_SAMPLES)	last_sample = 0;
					if(CompteSample%40000==0)
					{
						//OutputPower=(OutputPower+1)%8;
						//pad_gpios_reg[PADS_GPIO_0] = 0x5a000000 + (OutputPower&0x7) + (1<<4) + (0<<3); // Set output power for I/Q GPIO18/GPIO19 
						//printf("Freq %d Outputpower=%d\n",CompteSample/20000,OutputPower);
					}
					//usleep(1);
				}
					//printf("End free %d\n",free_slots);
			}

		}
			
		clock_gettime(CLOCK_REALTIME, &gettime_now);
		time_difference = gettime_now.tv_nsec - start_time;
		if(time_difference<0) time_difference+=1E9;
			
		last_cb = (uint32_t)virtbase + last_sample * sizeof(dma_cb_t) * CBS_SIZE_BY_SAMPLE;
	}
				
	stop_dma();
	return(0);
}
static inline void
dma_receive_chars(struct uart_pxa_port *up, int *status)
{
	struct tty_port *port = &up->port.state->port;
	unsigned char ch;
	int max_count = 256;
	int count = 0;
	unsigned char *tmp;
	unsigned int flag = TTY_NORMAL;
	struct uart_pxa_dma *pxa_dma = &up->uart_dma;
	struct dma_tx_state dma_state;

	/*
	 * Pause DMA channel and deal with the bytes received by DMA
	 */
	dmaengine_pause(pxa_dma->rxdma_chan);
	dmaengine_tx_status(pxa_dma->rxdma_chan, pxa_dma->rx_cookie,
			    &dma_state);
	count = DMA_BLOCK - dma_state.residue;
	tmp = pxa_dma->rxdma_addr;
	if (up->port.sysrq) {
		while (count > 0) {
			if (!uart_handle_sysrq_char(&up->port, *tmp)) {
				uart_insert_char(&up->port, *status,
						 0, *tmp, flag);
				up->port.icount.rx++;
			}
			tmp++;
			count--;
		}
	} else {
		tty_insert_flip_string(port, tmp, count);
		up->port.icount.rx += count;
	}

	/* deal with the bytes in rx FIFO */
	do {
		ch = serial_in(up, UART_RX);
		flag = TTY_NORMAL;
		up->port.icount.rx++;

		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
					UART_LSR_FE | UART_LSR_OE))) {
			/*
			 * For statistics only
			 */
			if (*status & UART_LSR_BI) {
				*status &= ~(UART_LSR_FE | UART_LSR_PE);
				up->port.icount.brk++;
				/*
				 * We do the SysRQ and SAK checking
				 * here because otherwise the break
				 * may get masked by ignore_status_mask
				 * or read_status_mask.
				 */
				if (uart_handle_break(&up->port))
					goto ignore_char2;
			} else if (*status & UART_LSR_PE) {
				up->port.icount.parity++;
			} else if (*status & UART_LSR_FE) {
				up->port.icount.frame++;
			}
			if (*status & UART_LSR_OE)
				up->port.icount.overrun++;

			/*
			 * Mask off conditions which should be ignored.
			 */
			*status &= up->port.read_status_mask;

#ifdef CONFIG_SERIAL_PXA_CONSOLE
			if (up->port.line == up->port.cons->index) {
				/* Recover the break flag from console xmit */
				*status |= up->lsr_break_flag;
				up->lsr_break_flag = 0;
			}
#endif
			if (*status & UART_LSR_BI)
				flag = TTY_BREAK;
			else if (*status & UART_LSR_PE)
				flag = TTY_PARITY;
			else if (*status & UART_LSR_FE)
				flag = TTY_FRAME;
		}
		if (!uart_handle_sysrq_char(&up->port, ch))
			uart_insert_char(&up->port, *status, UART_LSR_OE,
					 ch, flag);
ignore_char2:
		*status = serial_in(up, UART_LSR);
	} while ((*status & UART_LSR_DR) && (max_count-- > 0));

	tty_schedule_flip(port);
	stop_dma(up, 1);
	if (pxa_dma->rx_stop)
		return;
	pxa_uart_receive_dma_start(up);
}