📄 1553_junk_bm-5_bu69080s1.c
字号:
((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 + -