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

📄 1553_junk_bm-5_bu69080s1.c

📁 BU-65550M2-605 PCMCIA card (1553) 的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			((pACE53_CARD)dwParam)->dwChanMemLen       = m_aCards[bCardNum].dwChanMemLen;
			((pACE53_CARD)dwParam)->wIrq               = m_aCards[bCardNum].wIrq;		
			((pACE53_CARD)dwParam)->bNumChnls          = m_aCards[bCardNum].bNumChnls;
			((pACE53_CARD)dwParam)->dwMemWndPcmciaAddr = m_aCards[bCardNum].dwMemWndPcmciaAddr;
			((pACE53_CARD)dwParam)->dwRegWndPcmciaAddr = m_aCards[bCardNum].dwRegWndPcmciaAddr;
			((pACE53_CARD)dwParam)->dwRegWndKrnAddr    = m_aCards[bCardNum].dwRegWndKrnAddr;
			((pACE53_CARD)dwParam)->Channel[0]         = m_aCards[bCardNum].Channel[0];
			((pACE53_CARD)dwParam)->Channel[1]         = m_aCards[bCardNum].Channel[1];
			break;

		/* Get Specific channel's information */
		case    IOCTL_ACE53_GET_CHANNEL_INFO:
			((pACE_CHANNEL)dwParam)->bCardNum = 
				m_aCards[bCardNum].Channel[bChanNum].bCardNum;
			((pACE_CHANNEL)dwParam)->bChanNum = 
				m_aCards[bCardNum].Channel[bChanNum].bChanNum;
			((pACE_CHANNEL)dwParam)->dwMemWndUsrAddr = 
				m_aCards[bCardNum].Channel[bChanNum].dwMemWndUsrAddr;
			((pACE_CHANNEL)dwParam)->dwRegWndUsrAddr = 
				m_aCards[bCardNum].Channel[bChanNum].dwRegWndUsrAddr;
			((pACE_CHANNEL)dwParam)->wIrq = 
				m_aCards[bCardNum].wIrq;
			((pACE_CHANNEL)dwParam)->bBlocked = 
				m_aCards[bCardNum].Channel[bChanNum].bBlocked;	
			((pACE_CHANNEL)dwParam)->bMmapWinNum = 
				m_aCards[bCardNum].Channel[bChanNum].bMmapWinNum;    
			((pACE_CHANNEL)dwParam)->bIsrEnabled = 
				m_aCards[bCardNum].Channel[bChanNum].bIsrEnabled;
			((pACE_CHANNEL)dwParam)->bOpen = 
				m_aCards[bCardNum].Channel[bChanNum].bOpen;
			break;

		/* Block Driver (Sleep Thread) */
		case	IOCTL_ACE53_BLOCK_IN_DRIVER: 
			save_flags(dwFlags); /* Save processor state */
			cli();               /* Disable interrupts */
			
			/* If interrupts are disabled.. */
			if( !m_aCards[bCardNum].Channel[bChanNum].bIsrEnabled )
			{                  
				restore_flags(dwFlags);  /* Restore processor state */
				sti();                   /* Enable interrupts */
				printk("%s: bu69080s1_fops_ioctl(): STATUS_ACE53_IOCTL_INTERRUPT_NOT_ENABLED\n", MODULE_NAME);
				nResult = STATUS_ACE53_IOCTL_INTERRUPT_NOT_ENABLED;
				break;
			}
			/* Interrupts are enabled... */
			restore_flags(dwFlags); /* Restore processor state */
			sti();                  /* flags and enable interrupts */

			DEBUG(1, "%s: bu69080s1_fops_ioctl(): Block in Driver SLEEPING [Card %d, Channel %d]\n", MODULE_NAME, (unsigned int)bCardNum,(unsigned int)bChanNum);
			/* Put to sleep until interrupt or uninstall wakes us */
			interruptible_sleep_on(&m_apWaitQue[bSystemNum]);

			DEBUG(1, "%s: bu69080s1_fops_ioctl(): Block in Driver WOKE [Card %d, Channel %d]\n", MODULE_NAME, (unsigned int)bCardNum,(unsigned int)bChanNum);
			/* Save Interrupt Status Register */
			*(__u16 *)dwParam = m_aCards[bCardNum].Channel[bChanNum].wIntStatus;
			break;
	
		/* Install Interrupt support */
		case    IOCTL_ACE53_INSTALL_IRQ:
			save_flags(dwFlags);   /* Save processor state */
			cli();                 /* Disable interrupts */

			/* If already enabled, return error. */
			if( m_aCards[bCardNum].Channel[bChanNum].bIsrEnabled )
			{
				/* restore state and return error */
				restore_flags(dwFlags);
				sti();
				printk("%s: bu69080s1_fops_ioctl(): STATUS_ACE53_IOCTL_IRQ_ALREADY_INSTALLED\n", MODULE_NAME);
				nResult =  STATUS_ACE53_IOCTL_IRQ_ALREADY_INSTALLED;
				break;
			}

			/* Otherwise, flag status as enabled and install. */
			m_aCards[bCardNum].Channel[bChanNum].bIsrEnabled = 1;
			restore_flags(dwFlags);
			sti();

			/* Create the device string name for use in '/proc/interrupts' */
			//m_sDevName[6] = 'a' + bCardNum;
			//m_sDevName[6] = '0' + bChanNum;
			//m_sDevName[8] = '\0';

			/* Register the IRQ with the kernel. */
#if 0
			if( request_irq( m_aCards[bCardNum].wIrq, 		/* IRQ Number */
					   (void*)bu69080s1_isr,			/* ISR Function */
					   SA_SHIRQ,				/* Slow ISR */
					   m_sDevName,				/* string for 'proc' */
					   bpChanNum ))			/* device indentifier */

#else
//------- begin of insert (A.Lebedev) -----------------------------------------

    if (request_irq(m_aCards[bCardNum].wIrq,     // IRQ Number
                    (void*)bu69080s1_isr,        // ISR Function
                    SA_SHIRQ | SA_INTERRUPT,     // shared and fast ISR
                    m_sDevName,                  // string for 'proc'
                    bpChanNum))                  // device indentifier

//------- end of insert (A.Lebedev) -------------------------------------------
#endif
			{
				/* if request fails.... */
				save_flags(dwFlags);
				cli();
				m_aCards[bCardNum].Channel[bChanNum].bIsrEnabled = 0;
				restore_flags(dwFlags);
				sti();
				printk("%s: bu69080s1_fops_ioctl(): STATUS_ACE53_IOCTL_REQUEST_IRQ_FAIL\n", MODULE_NAME);
				nResult = STATUS_ACE53_IOCTL_REQUEST_IRQ_FAIL;
				break;
			}
			break;
		case	IOCTL_ACE53_UNINSTALL_IRQ:	/* Cleanup an installed IRQ. */
			/* If the interrupt is not enabled, return error. */
			save_flags(dwFlags);
			cli();
			if( !m_aCards[bCardNum].Channel[bChanNum].bIsrEnabled )
			{
				restore_flags(dwFlags);
				sti();

				printk("%s: bu69080s1_fops_ioctl(): UNINSTALL_ISR: Not installed.\n", MODULE_NAME);
				nResult = STATUS_ACE53_IOCTL_IRQ_NOT_INSTALLED;
				break;
			}
			/* Flag card status as disabled. */
			m_aCards[bCardNum].Channel[bChanNum].bIsrEnabled = 0;

			restore_flags(dwFlags);
			sti();


			DEBUG(1, "%s: bu69080s1_fops_ioctl(): UNINSTALL_ISR: About to free irq.\n", MODULE_NAME);
			/* Deregister the interrupt and free the IRQ. */
			free_irq(m_aCards[bCardNum].wIrq, bpChanNum);
			DEBUG(1, "%s: bu69080s1_fops_ioctl(): UNINSTALL_ISR: Freed irq.  About to wake.\n", MODULE_NAME);

			/* Wake up the blocked IRQ thread so it can terminate. */
			DEBUG(1, "%s: bu69080s1_fops_ioctl(): Waking up via Uninstall [Card %d, Channel %d]\n", MODULE_NAME, (unsigned int)bCardNum,(unsigned int)bChanNum);
			wake_up_interruptible(&m_apWaitQue[bSystemNum]);
			DEBUG(1, "%s: bu69080s1_fops_ioctl(): Interrupts UN-Installed.\n", MODULE_NAME);
			break;

		default:
			printk("%s: bu69080s1_fops_ioctl(): Not implemented\n", MODULE_NAME);
			return STATUS_ACE53_IOCTL_NOT_IMPLEMENTED;
			break;
	}
	
	return nResult;
}







/*******************************************************************
 * Function: bu69080s1_vmops_close                                 *
 *                                                                 *
 * Description: Used in junction with unmapping memory             *
 *                                                                 *
 * Parameters:   vma - information about the vma                   *
 *******************************************************************/
void bu69080s1_vmops_close(struct vm_area_struct *vma)
{
	/* Obtain index into enumerated card list from inode. */
	__u8	u8SystemNumber   = MINOR(vma->vm_file->f_dentry->d_inode->i_rdev);
	__u8	u8CardNumber     = (__u8)u8SystemNumber  / 2;	/* Card number in system (0 - 3) */
	__u8	u8ChannelNumber  = u8SystemNumber % 2;		/* Channel number on card (0, 1) */

	DEBUG(1, "%s: bu69080s1_vmops_close(): Sys#:%02d  Card#:%02d  Chan#:%02d\n", MODULE_NAME, u8SystemNumber,u8CardNumber,u8ChannelNumber);
	
	/* Indicate error if too many 'munmap's were attempted. */
	if( 	(m_aCards[u8CardNumber].Channel[u8ChannelNumber].bMmapWinNum == 0) ||
		(m_aCards[u8CardNumber].Channel[u8ChannelNumber].bMmapWinNum > 2) )
	{
		printk("%s: bu69080s1_vmops_close(): Too many 'munmap' attempts!\n", MODULE_NAME);
		return;
	}
	
	/* Null user window pointer and decrement 'mmap' count. */
	if( vma->vm_start == m_aCards[u8CardNumber].Channel[u8ChannelNumber].dwRegWndUsrAddr )
	{
		m_aCards[u8CardNumber].Channel[u8ChannelNumber].dwRegWndUsrAddr = (__u32)NULL;
		m_aCards[u8CardNumber].Channel[u8ChannelNumber].bMmapWinNum--;
	}
	
	else if( vma->vm_start == m_aCards[u8CardNumber].Channel[u8ChannelNumber].dwMemWndUsrAddr )
	{
		m_aCards[u8CardNumber].Channel[u8ChannelNumber].dwMemWndUsrAddr = (__u32)NULL;
		m_aCards[u8CardNumber].Channel[u8ChannelNumber].bMmapWinNum--;
	}
	else
	{
		printk("%s: bu69080s1_vmops_close(): 'munmap' failed!  Bad base address.\n", MODULE_NAME);
	}
}







#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) //jmf unmap removed from vm_operations_struct in kernel 2.4.X
/*******************************************************************
 * Function: bu69080s1_vmops_unmap                                 *
 *                                                                 *
 * Description: Handles unmapping of a user space window           *
 *                                                                 *
 * Parameters:   vma  - information about the vma                  *
 *               off  - ????					                             *
 *               size - Size Parameter  			                     *
 *                                                                 *
 * Notes:        This method is called when ever part or all of    *
 *               either 'mmap'ped window is 'unmap'ped from user   *
 *               space.  It is used as an error checker for the    *
 *               size parameters passed into the 'unmap' system    *
 *               call.                                             *
 *******************************************************************/
void bu69080s1_vmops_unmap(struct vm_area_struct *vma, unsigned long off, size_t size)
{
    //DEBUG(1, "%s: bu69080s1_vmops_unmap(): Sys#:%02d  Card#:%02d  Chan#:%02d  OtherChan#:%02d\n", MODULE_NAME, u8SystemNumber,u8CardNumber,u8ChannelNumber,u8OtherChanRef);	
    if( (vma->vm_end - vma->vm_start) != size )
    {
	printk("%s: bu69080s1_vmops_unmap(): 'munmap' failed!  Bad size parameter.\n", MODULE_NAME);
    }
}
#endif

/* VM Operation overrides */
struct vm_operations_struct vm_ops = {
	close:  bu69080s1_vmops_close,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)//jmf unmpa removed from structure in kernel 2.4.X
	unmap:  bu69080s1_vmops_unmap,
#endif
};

void mmap_error_cleanup(__u32 dwPcmciaWinSize, __u8 bCardNum)
{
	__u8   u8SystemNumber   = (__u8)bCardNum;
	__u8	u8CardNumber     = (__u8)u8SystemNumber  / 2;	/* Card number in system (0 - 3) */

	__u8	u8ChannelNumber  = u8SystemNumber % 2;		/* Channel number on card (0, 1) */

	DEBUG(1, "%s: mmap_error_cleanup(): Sys#:%02d  Card#:%02d  Chan#:%02d\n", MODULE_NAME, u8SystemNumber,u8CardNumber,u8ChannelNumber);	
	switch(dwPcmciaWinSize)
	{
		case ACE_CHAN_REG_LENGTH:
			if( m_aCards[u8CardNumber].Channel[u8ChannelNumber].bMmapWinNum == 0 )
				m_aCards[u8CardNumber].Channel[u8ChannelNumber].dwRegWndUsrAddr = (__u32)NULL;
			break;
			
		case ACE_CHAN_MEM_LENGTH:
			if( m_aCards[u8CardNumber].Channel[u8ChannelNumber].bMmapWinNum == 1 )
				m_aCards[u8CardNumber].Channel[u8ChannelNumber].dwMemWndUsrAddr = (__u32)NULL;
			break;
	}
}

int bu69080s1_fops_mmap(struct file *filp, struct vm_area_struct *vma) 
{
	/* Base address and size of PCI space window to be remapped. */
	__u32	dwPcmciaWinBaseAddr, dwPcmciaWinSize = vma->vm_end - vma->vm_start;
	
	/* Obtain index into enumerated card list from file pointer. CAN THIS BE DONE VIA 'vma' kwh */	
	__u8	u8SystemNumber   = MINOR(filp->f_dentry->d_inode->i_rdev);
	__u8	u8CardNumber     = (__u8)u8SystemNumber  / 2;	/* Card number in system (0 - 3) */
	__u8	u8ChannelNumber  = u8SystemNumber % 2;		/* Channel number on card (0, 1) */
    __u32   dwVMOffset;	
	DEBUG(1, "%s: bu69080s1_fops_mmap(): Sys#:%02d  Card#:%02d  Chan#:%02d  Size#:%04x\n", MODULE_NAME, u8SystemNumber,u8CardNumber,u8ChannelNumber,dwPcmciaWinSize);

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
    dwVMOffset = vma->vm_offset;
#else
    dwVMOffset = vma->vm_pgoff<<PAGE_SHIFT; //jmf Kernel changed structure in 2.4.X
#endif

	/* Associate our module VM operations with our 'mmap'. */
	vma->vm_ops = &vm_ops;

	/* Check that minor number corresponds to a card in the system. */
	if ( u8SystemNumber >= m_bNumberOfCards)
	{
		printk("%s: bu69080s1_fops_mmap(): Size#:%04x returned device not exist\n", MODULE_NAME, dwPcmciaWinSize);
		return STATUS_ACE53_DEVICE_NOT_EXIST;
	}
	
	/* Return error if an attempt was made to 'mmap' an unopened card. */
	if( !m_aCards[u8CardNumber].Channel[u8ChannelNumber].bOpen )
	{
		printk("%s: bu69080s1_fops_mmap(): Size#:%04x returned card not open\n", MODULE_NAME, dwPcmciaWinSize);
		return STATUS_ACE53_CARD_NOT_OPEN;
	}
	
	/* Check if 'mmap' is called more times than necessary. */
	if(m_aCards[u8CardNumber].Channel[u8ChannelNumber].bMmapWinNum == MAX_USER_MEM_WINDOWS)
	{
		printk("%s: bu69080s1_fops_mmap(): Size#:%04x returned already mapped\n", MODULE_NAME, dwPcmciaWinSize);
		return STATUS_ACE53_MMAP_CARD_ALREADY_MMAPPED;
	}
	
	/* See which window to mmap. */
	switch(dwPcmciaWinSize)
	{
		case ACE_CHAN_REG_LENGTH:
			if( !(m_aCards[u8CardNumber].Channel[u8ChannelNumber].bMmapWinNum == 0) )
			{
				printk("%s: bu69080s1_fops_mmap(): Size#:%04x returned sequence error\n", MODULE_NAME, dwPcmciaWinSize);
				return STATUS_ACE53_MMAP_SEQUENCE_ERROR;
			}
			
			dwPcmciaWinBaseAddr = m_aCards[u8CardNumber].dwRegWndPcmciaAddr;
			DEBUG(1, "%s: bu69080s1_fops_mmap(): Channel             = %02x\n", MODULE_NAME,u8ChannelNumber);
			DEBUG(1, "%s: bu69080s1_fops_mmap(): PCI Reg Addr BEFORE = %08x\n", MODULE_NAME,(unsigned int)m_aCards[u8CardNumber].dwRegWndPcmciaAddr);
			DEBUG(1, "%s: bu69080s1_fops_mmap(): PCI Reg Addr AFTER  = %08x\n", MODULE_NAME,dwPcmciaWinBaseAddr);

⌨️ 快捷键说明

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