Example #1
0
/* handle interrupt for specified sub device; DmaMode == DEV_WRITE_S*/
PRIVATE void handle_int_write(int sub_dev_nr) 
{
	sub_dev_t *sub_dev_ptr;
	int r;

	sub_dev_ptr = &sub_dev[sub_dev_nr];

	dprint("Finished playing dma[%d] ", sub_dev_ptr->DmaReadNext);
	sub_dev_ptr->DmaReadNext = 
		(sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments;
	sub_dev_ptr->DmaLength -= 1;

	if (sub_dev_ptr->BufLength != 0) { /* Data in extra buf, copy to Dma buf */

		dprint(" buf[%d] -> dma[%d] ", 
				sub_dev_ptr->BufReadNext, sub_dev_ptr->DmaFillNext);
		memcpy(sub_dev_ptr->DmaPtr + 
				sub_dev_ptr->DmaFillNext * sub_dev_ptr->FragSize, 
				sub_dev_ptr->ExtraBuf + 
				sub_dev_ptr->BufReadNext * sub_dev_ptr->FragSize, 
				sub_dev_ptr->FragSize);

		sub_dev_ptr->BufReadNext = 
			(sub_dev_ptr->BufReadNext + 1) % sub_dev_ptr->NrOfExtraBuffers;
		sub_dev_ptr->DmaFillNext = 
			(sub_dev_ptr->DmaFillNext + 1) % sub_dev_ptr->NrOfDmaFragments;

		sub_dev_ptr->BufLength -= 1;
		sub_dev_ptr->DmaLength += 1;
	} 

	/* space became available, possibly copy new data from user */
	data_from_user(sub_dev_ptr);

	if(sub_dev_ptr->DmaLength == 0) { /* Dma buffer empty, stop Dma transfer */

		sub_dev_ptr->OutOfData = TRUE; /* we're out of data */
		dprint("No more work...!\n");
		if (!sub_dev_ptr->Opened) {
			close_sub_dev(sub_dev_ptr->Nr);
			dprint("Stopping sub device %d\n", sub_dev_ptr->Nr);
			return;
		}
		dprint("Pausing sub device %d\n",sub_dev_ptr->Nr);
		drv_pause(sub_dev_ptr->Nr);
		return;
	}

	dprint("\n");

	/* confirm and reenable interrupt from this sub dev */
	drv_reenable_int(sub_dev_nr);
#if 0
	/* reenable irq_hook*/
	if ((r=sys_irqenable(&irq_hook_id)) != OK) {
		error("%s Couldn't enable IRQ\n", drv.DriverName);
	}
#endif
}
PRIVATE void data_from_user(sub_dev_t *subdev) {

  if (subdev->DmaLength == subdev->NrOfDmaFragments &&
      subdev->BufLength == subdev->NrOfExtraBuffers) return; /* no space */
  
  if (!subdev->RevivePending) return; /* no new data waiting to be copied */
  
  if (subdev->RevivePending && 
      subdev->ReadyToRevive) return; /* we already got this data */
  
  
  if (subdev->DmaLength < subdev->NrOfDmaFragments) { /* room in dma buf */
    
      sys_datacopy(subdev->ReviveProcNr, 
      (vir_bytes)subdev->UserBuf, 
      SELF, 
      (vir_bytes)subdev->DmaPtr + subdev->DmaFillNext * subdev->FragSize, 
      (phys_bytes)subdev->FragSize);
  
    dprint(" user -> dma[%d]\n", subdev->DmaFillNext);
    subdev->DmaLength += 1;
    subdev->DmaFillNext = (subdev->DmaFillNext + 1) % subdev->NrOfDmaFragments;
    
  } else { /* room in extra buf */ 

		sys_datacopy(subdev->ReviveProcNr, 
      (vir_bytes)subdev->UserBuf, 
      SELF, 
      (vir_bytes)subdev->ExtraBuf + subdev->BufFillNext * subdev->FragSize, 
      (phys_bytes)subdev->FragSize);
      
		dprint(" user -> buf[%d]\n", subdev->BufFillNext);
		subdev->BufLength += 1;
		
		subdev->BufFillNext = (subdev->BufFillNext + 1) % subdev->NrOfExtraBuffers;

	}
	if(subdev->OutOfData) { /* if device paused (because of lack of data) */
    subdev->OutOfData = FALSE;
    drv_reenable_int(subdev->Nr);
    /* reenable irq_hook*/
  	if ((sys_irqenable(&irq_hook_id)) != OK) {
      error("%s: Couldn't enable IRQ", drv.DriverName);
    }
    drv_resume(subdev->Nr);  /* resume resume the sub device */
    
  }
  
	subdev->ReviveStatus = subdev->FragSize;
	subdev->ReadyToRevive = TRUE;
	notify(subdev->NotifyProcNr);
}
Example #3
0
/* handle interrupt for specified sub device; DmaMode == DEV_READ_S */
PRIVATE void handle_int_read(int sub_dev_nr) 
{
	sub_dev_t *sub_dev_ptr; int r,i;

	sub_dev_ptr = &sub_dev[sub_dev_nr];

	dprint("Device filled dma[%d]\n", sub_dev_ptr->DmaFillNext);
	sub_dev_ptr->DmaLength += 1; 
	sub_dev_ptr->DmaFillNext = 
		(sub_dev_ptr->DmaFillNext + 1) % sub_dev_ptr->NrOfDmaFragments;

	/* possibly copy data to user (if it is waiting for us) */
	data_to_user(sub_dev_ptr);

	if (sub_dev_ptr->DmaLength == sub_dev_ptr->NrOfDmaFragments) { 
		/* if dma buffer full */

		if (sub_dev_ptr->BufLength == sub_dev_ptr->NrOfExtraBuffers) {
			error("All buffers full, we have a problem.\n");
			drv_stop(sub_dev_nr);        /* stop the sub device */
			sub_dev_ptr->DmaBusy = FALSE;
			sub_dev_ptr->ReviveStatus = 0;   /* no data for user, 
												this is a sad story */
			sub_dev_ptr->ReadyToRevive = TRUE; /* wake user up */
			return;
		} 
		else { /* dma full, still room in extra buf; 
				  copy from dma to extra buf */
			dprint("dma full: going to copy buf[%d] <- dma[%d]\n", 
					sub_dev_ptr->BufFillNext, sub_dev_ptr->DmaReadNext);
			memcpy(sub_dev_ptr->ExtraBuf + 
					sub_dev_ptr->BufFillNext * sub_dev_ptr->FragSize, 
					sub_dev_ptr->DmaPtr + 
					sub_dev_ptr->DmaReadNext * sub_dev_ptr->FragSize,
					sub_dev_ptr->FragSize);
			sub_dev_ptr->DmaLength -= 1;
			sub_dev_ptr->DmaReadNext = 
				(sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments;
			sub_dev_ptr->BufFillNext = 
				(sub_dev_ptr->BufFillNext + 1) % sub_dev_ptr->NrOfExtraBuffers;
		}
	}
	/* confirm interrupt, and reenable interrupt from this sub dev*/
	drv_reenable_int(sub_dev_ptr->Nr);

#if 0
	/* reenable irq_hook*/
	if ((r=sys_irqenable(&irq_hook_id)) != OK) {
		error("%s: Couldn't reenable IRQ", drv.DriverName);
	}
#endif
}
Example #4
0
int drv_resume(int sub_dev) {
	u32_t pause_bit = 0;

	drv_reenable_int(sub_dev); /* enable interrupts */

	switch(sub_dev) {
		case DAC1_CHAN: pause_bit = P1_PAUSE;break;
		case DAC2_CHAN: pause_bit = P2_PAUSE;break;    
		default: return EINVAL;
	}

	/* clear pause bit */
	pci_outl(reg(SERIAL_INTERFACE_CTRL),
			pci_inl(reg(SERIAL_INTERFACE_CTRL)) & ~pause_bit);

	return OK;
}
Example #5
0
int drv_start(int sub_dev, int UNUSED(DmaMode)) {
	u32_t enable_bit, result = 0;

	/* Write default values to device in case user failed to configure.
	   If user did configure properly, everything is written twice.
	   please raise your hand if you object against to this strategy...*/
	result |= set_sample_rate(aud_conf[sub_dev].sample_rate, sub_dev);
	result |= set_stereo(aud_conf[sub_dev].stereo, sub_dev);
	result |= set_bits(aud_conf[sub_dev].nr_of_bits, sub_dev);
	result |= set_sign(aud_conf[sub_dev].sign, sub_dev);

	/* set the interrupt count */
	result |= set_int_cnt(sub_dev);

	if (result) {
		return EIO;
	}

	/* if device currently paused, resume */
	drv_resume(sub_dev);

	switch(sub_dev) {
		case ADC1_CHAN: enable_bit = ADC1_EN;break;
		case DAC1_CHAN: enable_bit = DAC1_EN;break;
		case DAC2_CHAN: enable_bit = DAC2_EN;break;    
		default: return EINVAL;
	}

	/* enable interrupts from 'sub device' */
	drv_reenable_int(sub_dev);

	/* this means play!!! */
	pci_outw(reg(CHIP_SEL_CTRL), pci_inw(reg(CHIP_SEL_CTRL)) | enable_bit);

	aud_conf[sub_dev].busy = 1;

	return OK;
}
Example #6
0
PRIVATE void data_from_user(sub_dev_t *subdev)
{
	int r;
	message m;

	if (subdev->DmaLength == subdev->NrOfDmaFragments &&
			subdev->BufLength == subdev->NrOfExtraBuffers) return;/* no space */

	if (!subdev->RevivePending) return; /* no new data waiting to be copied */

	if (subdev->RevivePending && 
			subdev->ReadyToRevive) return; /* we already got this data */

	if (subdev->DmaLength < subdev->NrOfDmaFragments) { /* room in dma buf */

		sys_safecopyfrom(subdev->ReviveProcNr, 
				(vir_bytes)subdev->ReviveGrant, 0, 
				(vir_bytes)subdev->DmaPtr + 
				subdev->DmaFillNext * subdev->FragSize,
				(phys_bytes)subdev->FragSize, D);


		dprint(" user -> dma[%d]\n", subdev->DmaFillNext);
		subdev->DmaLength += 1;
		subdev->DmaFillNext = 
			(subdev->DmaFillNext + 1) % subdev->NrOfDmaFragments;

	} else { /* room in extra buf */ 

		sys_safecopyfrom(subdev->ReviveProcNr, 
				(vir_bytes)subdev->ReviveGrant, 0,
				(vir_bytes)subdev->ExtraBuf + 
				subdev->BufFillNext * subdev->FragSize, 
				(phys_bytes)subdev->FragSize, D);

		dprint(" user -> buf[%d]\n", subdev->BufFillNext);
		subdev->BufLength += 1;

		subdev->BufFillNext = 
			(subdev->BufFillNext + 1) % subdev->NrOfExtraBuffers;

	}
	if(subdev->OutOfData) { /* if device paused (because of lack of data) */
		subdev->OutOfData = FALSE;
		drv_reenable_int(subdev->Nr);
		/* reenable irq_hook*/
		if ((sys_irqenable(&irq_hook_id)) != OK) {
			error("%s: Couldn't enable IRQ", drv.DriverName);
		}
		drv_resume(subdev->Nr);  /* resume resume the sub device */
	}

	subdev->ReviveStatus = subdev->FragSize;
	subdev->ReadyToRevive = TRUE;

	m.m_type = DEV_REVIVE;			/* build message */
	m.REP_ENDPT = subdev->ReviveProcNr;
	m.REP_IO_GRANT = subdev->ReviveGrant;
	m.REP_STATUS = subdev->ReviveStatus;
	r= send(subdev->NotifyProcNr, &m);		/* send the message */
	if (r != OK)
	{
		printf("audio_fw: send to %d failed: %d\n",
			subdev->NotifyProcNr, r);
	}

	/* reset variables */
	subdev->ReadyToRevive = FALSE;
	subdev->RevivePending = 0;
}