⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio_fw.c

📁 Minix比较全的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	chan = special_file_ptr->read_chan;	if (chan == NO_CHANNEL) {		error("%s: No read channel specified!\n", drv.DriverName);		reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EIO);		return;	}	/* get pointer to sub device data */	sub_dev_ptr = &sub_dev[chan];	if (!sub_dev_ptr->DmaBusy) { /* get fragment size on first read */		if (drv_get_frag_size(&(sub_dev_ptr->FragSize), sub_dev_ptr->Nr) != OK){			error("%s: Could not retrieve fragment size!\n", drv.DriverName);			reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EIO);      				return;		}	}	if(m_ptr->COUNT != sub_dev_ptr->FragSize) {		reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EINVAL);		error("fragment size does not match message size\n");		return;	}	/* if we are busy with something else than reading, reply EBUSY */	if(sub_dev_ptr->DmaBusy && sub_dev_ptr->DmaMode != DEV_READ_S) {		reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, EBUSY);		return;	}	/* unblock the FileSystem, but keep user process blocked until REVIVE*/	reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, SUSPEND);	sub_dev_ptr->RevivePending = TRUE;	sub_dev_ptr->ReviveProcNr = m_ptr->IO_ENDPT;	sub_dev_ptr->ReviveGrant = (cp_grant_id_t) m_ptr->ADDRESS;	sub_dev_ptr->NotifyProcNr = m_ptr->m_source;	if(!sub_dev_ptr->DmaBusy) { /* Dma tranfer not yet started */		get_started(sub_dev_ptr);		sub_dev_ptr->DmaMode = DEV_READ_S; /* Dma mode is reading */		return;  /* no need to get data from DMA buffer at this point */	}	/* check if data is available and possibly fill user's buffer */	data_to_user(sub_dev_ptr);}PRIVATE void msg_hardware(void) {	u32_t     i;	int j = 0;	dprint("%s: handling hardware message\n", drv.DriverName);	/* while we have an interrupt  */	while ( drv_int_sum()) {		/* loop over all sub devices */		for ( i = 0; i < drv.NrOfSubDevices; i++) {			/* if interrupt from sub device and Dma transfer 			   was actually busy, take care of business */			if( drv_int(i) && sub_dev[i].DmaBusy ) {				if (sub_dev[i].DmaMode == DEV_WRITE_S) handle_int_write(i);				if (sub_dev[i].DmaMode == DEV_READ_S) handle_int_read(i);  			}		}	}	/* As IRQ_REENABLE is not on in sys_irqsetpolicy, we must	 * re-enable out interrupt after every interrupt.	 */	if ((sys_irqenable(&irq_hook_id)) != OK) {	  error("%s: msg_hardware: Couldn't enable IRQ\n", drv.DriverName);	}}PRIVATE void msg_status(message *m_ptr){	int i; 	dprint("got a status message\n");	for (i = 0; i < drv.NrOfSubDevices; i++) {		if(sub_dev[i].ReadyToRevive) 		{			m_ptr->m_type = DEV_REVIVE;			/* build message */			m_ptr->REP_ENDPT = sub_dev[i].ReviveProcNr;			m_ptr->REP_IO_GRANT = sub_dev[i].ReviveGrant;			m_ptr->REP_STATUS = sub_dev[i].ReviveStatus;			send(m_ptr->m_source, m_ptr);			/* send the message */			/* reset variables */			sub_dev[i].ReadyToRevive = FALSE;			sub_dev[i].RevivePending = 0;			return; /* stop after one mess, 					   file system will get back for other processes */		}	}	m_ptr->m_type = DEV_NO_STATUS;	m_ptr->REP_STATUS = 0;	send(m_ptr->m_source, m_ptr);			/* send DEV_NO_STATUS message */}PRIVATE void msg_sig_stop(void) {	int i; char irq;	for (i = 0; i < drv.NrOfSubDevices; i++) {		drv_stop(i); /* stop all sub devices */	}	if (irq_hook_set) {		if (sys_irqdisable(&irq_hook_id) != OK) {			error("Could not disable IRQ\n");		}		/* get irq from device driver*/		if (drv_get_irq(&irq) != OK) {			error("Msg SIG_STOP Couldn't get IRQ");		}		/* remove the policy */		if (sys_irqrmpolicy(irq, &irq_hook_id) != OK) {			error("%s: Could not disable IRQ\n",drv.DriverName);		}	}}/* 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}/* 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}PRIVATE int get_started(sub_dev_t *sub_dev_ptr) {	u32_t i;char c;  	/* enable interrupt messages from MINIX */	if ((i=sys_irqenable(&irq_hook_id)) != OK) {		error("%s: Couldn't enable IRQs",drv.DriverName);		return EIO;	}	/* let the lower part of the driver start the device */	if (drv_start(sub_dev_ptr->Nr, sub_dev_ptr->DmaMode) != OK) {		error("%s: Could not start device %d\n", 				drv.DriverName, sub_dev_ptr->Nr);	}	sub_dev_ptr->DmaBusy = TRUE;     /* Dma is busy from now on */	sub_dev_ptr->DmaReadNext = 0;    	return OK;}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_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;	notify(subdev->NotifyProcNr);}PRIVATE void data_to_user(sub_dev_t *sub_dev_ptr) {	if (!sub_dev_ptr->RevivePending) return; /* nobody is wating for data */	if (sub_dev_ptr->ReadyToRevive) return;/* we already filled user's buffer */	if (sub_dev_ptr->BufLength == 0 && sub_dev_ptr->DmaLength == 0) return; 		/* no data for user */	if(sub_dev_ptr->BufLength != 0) { /* data in extra buffer available */		sys_safecopyto(sub_dev_ptr->ReviveProcNr, 				(vir_bytes)sub_dev_ptr->ReviveGrant,				0, (vir_bytes)sub_dev_ptr->ExtraBuf + 				sub_dev_ptr->BufReadNext * sub_dev_ptr->FragSize,				(phys_bytes)sub_dev_ptr->FragSize, D);		dprint(" copied buf[%d] to user\n", sub_dev_ptr->BufReadNext); 		/* adjust the buffer status variables */		sub_dev_ptr->BufReadNext = 			(sub_dev_ptr->BufReadNext + 1) % sub_dev_ptr->NrOfExtraBuffers;		sub_dev_ptr->BufLength -= 1;	} else { /* extra buf empty, but data in dma buf*/ 		sys_safecopyto(				sub_dev_ptr->ReviveProcNr, 				(vir_bytes)sub_dev_ptr->ReviveGrant, 0, 				(vir_bytes)sub_dev_ptr->DmaPtr + 				sub_dev_ptr->DmaReadNext * sub_dev_ptr->FragSize,				(phys_bytes)sub_dev_ptr->FragSize, D);		dprint(" copied dma[%d] to user\n", sub_dev_ptr->DmaReadNext);		/* adjust the buffer status variables */		sub_dev_ptr->DmaReadNext = 			(sub_dev_ptr->DmaReadNext + 1) % sub_dev_ptr->NrOfDmaFragments;		sub_dev_ptr->DmaLength -= 1;	}	sub_dev_ptr->ReviveStatus = sub_dev_ptr->FragSize;	sub_dev_ptr->ReadyToRevive = TRUE; 		/* drv_status will send REVIVE mess to FS*/		notify(sub_dev_ptr->NotifyProcNr);     /* notify the File Systam to make it 											  send DEV_STATUS messages*/}	PRIVATE int init_buffers(sub_dev_t *sub_dev_ptr) {#if (CHIP == INTEL)		unsigned left;		u32_t i;		/* allocate dma buffer space */		if (!(sub_dev_ptr->DmaBuf = malloc(sub_dev_ptr->DmaSize + 64 * 1024))) {			error("%s: failed to allocate dma buffer for channel %d\n", 					drv.DriverName,i);			return EIO;		}		/* allocate extra buffer space */		if (!(sub_dev_ptr->ExtraBuf = malloc(sub_dev_ptr->NrOfExtraBuffers * 						sub_dev_ptr->DmaSize / 						sub_dev_ptr->NrOfDmaFragments))) {			error("%s failed to allocate extra buffer for channel %d\n", 					drv.DriverName,i);			return EIO;		}		sub_dev_ptr->DmaPtr = sub_dev_ptr->DmaBuf;		i = sys_umap(SELF, D, 				(vir_bytes) sub_dev_ptr->DmaBuf, 				(phys_bytes) sizeof(sub_dev_ptr->DmaBuf), 				&(sub_dev_ptr->DmaPhys));		if (i != OK) {			return EIO;		}		if ((left = dma_bytes_left(sub_dev_ptr->DmaPhys)) < 				sub_dev_ptr->DmaSize) {			/* First half of buffer crosses a 64K boundary,			 * can't DMA into that */			sub_dev_ptr->DmaPtr += left;			sub_dev_ptr->DmaPhys += left;		}		/* write the physical dma address and size to the device */		drv_set_dma(sub_dev_ptr->DmaPhys, 				sub_dev_ptr->DmaSize, sub_dev_ptr->Nr);		return OK;#else /* CHIP != INTEL */		error("%s: init_buffer() failed, CHIP != INTEL", drv.DriverName);		return EIO;#endif /* CHIP == INTEL */	}PRIVATE void reply(int code, int replyee, int process, int status) {	message m;	m.m_type = code;		/* TASK_REPLY or REVIVE */	m.REP_STATUS = status;	/* result of device operation */	m.REP_ENDPT = process;	/* which user made the request */	send(replyee, &m);}PRIVATE int io_ctl_length(int io_request) {	io_request >>= 16; 	return io_request & _IOCPARM_MASK;}PRIVATE special_file_t* get_special_file(int minor_dev_nr) {	int i;	for(i = 0; i < drv.NrOfSpecialFiles; i++) {		if(special_file[i].minor_dev_nr == minor_dev_nr) {			return &special_file[i];		}	}	error("%s: No subdevice specified for minor device %d!\n", 			drv.DriverName, minor_dev_nr);	return NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -