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

📄 plx9052-26.c

📁 关于linux中pci驱动的一些代码,实现了一些功能
💻 C
📖 第 1 页 / 共 2 页
字号:
}static int plx9052_suspend(struct pcmcia_socket *sock){	plx9052_set_socket(sock, &dead_socket);	return 0;}static int plx9052_get_status(struct pcmcia_socket *sock, u_int *value){	struct plx9052_socket *socket =	    container_of(sock, struct plx9052_socket, socket);	*value = 0;	if (plx9052_card_present(socket))		*value |= SS_READY | SS_POWERON | SS_IOCARD | SS_DETECT;	return 0;}static int plx9052_get_socket(struct pcmcia_socket *sock,			      socket_state_t *state){	struct plx9052_socket *socket =	    container_of(sock, struct plx9052_socket, socket);	*state = socket->state;	return 0;}static int plx9052_set_socket(struct pcmcia_socket *sock,			      socket_state_t *state){	u32 reg;	struct plx9052_socket *socket =	    container_of(sock, struct plx9052_socket, socket);	if (state->flags & SS_RESET) {		plx9052_disable_irq(socket);		reg = plx9052_inl(socket, PLX_CNTRL);		reg |= PLX_CNTRL_RESET;		plx9052_outl(socket, PLX_CNTRL, reg);	} else {		reg = plx9052_inl(socket, PLX_CNTRL);		reg &= ~PLX_CNTRL_RESET;		plx9052_outl(socket, PLX_CNTRL, reg);		plx9052_enable_irq(socket);	}	socket->state = *state;	return 0;}static int plx9052_set_io_map(struct pcmcia_socket *sock,			      struct pccard_io_map *io){	struct plx9052_socket *socket =	    container_of(sock, struct plx9052_socket, socket);	unsigned int len;	/* requested length */	unsigned int len2;	/* length adjusted to power of two */	unsigned int start2;	/* start adjusted to power of two */	unsigned int split;	/* split point for unaligned windows */	unsigned int tmp;	int err;	/* Disable mapping before changing it */	plx9052_disable_areas(socket, 1, io->map);	if (!(io->flags & MAP_ACTIVE))		return 0;	len = io->stop + 1 - io->start;	if (len > PLX_IOWIN_MAX) {		printk(KERN_ERR		       "Requested I/O area 0x%x-0x%x is too long\n",		       io->start, io->stop);		return -EINVAL;	}	/* Simplest case - size aligned window */	if (!plx9052_align_check(io->start, len)) {		err =		    plx9052_program_area(socket, 1, io->map, io->start,					 len, 0, io->flags);		return err;	}	/* Find the highest address line that needs to be opened */	tmp = io->stop ^ io->start;	for (len2 = PLX_IOWIN_MIN; len2 <= PLX_IOWIN_MAX; len2 <<= 1) {		if (len2 > tmp)			break;	}	/* Split the requested window into at most two size-aligned windows */	start2 = ~(len2 - 1) & io->start;	split = start2 + (len2 >> 1);	if (plx9052_align_check(io->start, split - io->start) ||	    plx9052_align_check(split, io->stop + 1 - split)) {		printk(KERN_ERR		       "I/O area 0x%x-0x%x is too badly unaligned\n",		       io->start, io->stop);		return -ENOTSUPP;	}	err = plx9052_program_area(socket, 1, io->map, io->start,				   split - io->start, 0, io->flags);	if (err)		return err;	err = plx9052_program_area(socket, 1, io->map, split,				   io->stop + 1 - split, 0, io->flags);	return err;}static int plx9052_set_mem_map(struct pcmcia_socket *sock,			       struct pccard_mem_map *mem){	struct plx9052_socket *socket =	    container_of(sock, struct plx9052_socket, socket);	unsigned long len;	/* requested length */	int err;	/* Disable mapping before changing it */	plx9052_disable_areas(socket, 0, mem->map);	if (!(mem->flags & MAP_ACTIVE))		return 0;	/* Memory allocation in the first megabyte is problematic on	 * some machines with Intel chipset.  */	if (mem->sys_start < 0x100000)		return -EINVAL;	len = mem->sys_stop + 1 - mem->sys_start;	if (len > PLX_MEMWIN_MAX) {		printk(KERN_ERR "Memory map 0x%lx-0x%lx is too long\n",		       mem->sys_start, mem->sys_stop);		return -EINVAL;	}	if (plx9052_align_check(mem->sys_start, len)) {		printk(KERN_ERR		       "Memory map 0x%lx-0x%lx is not size-aligned\n",		       mem->sys_start, mem->sys_stop);		return -EINVAL;	}	err =	    plx9052_program_area(socket, 0, mem->map, mem->sys_start, len,				 mem->card_start | PLX_CIS_START,				 mem->flags);	return err;}static irqreturn_t plx9052_interrupt(int irq, void *dev_id,				     struct pt_regs *regs){	struct plx9052_socket *socket = (struct plx9052_socket *) dev_id;	if (!plx9052_irq_active(socket))		return IRQ_NONE;	if (!(socket->state.csc_mask & SS_DETECT))		return IRQ_HANDLED;	if (!plx9052_card_present(socket)) {		socket->event |= SS_DETECT;		plx9052_disable_irq(socket);		schedule_work(&socket->event_work);	}	return IRQ_HANDLED;}static struct pccard_operations plx9052_operations = {	.init = plx9052_init,	.suspend = plx9052_suspend,	.get_status = plx9052_get_status,	.get_socket = plx9052_get_socket,	.set_socket = plx9052_set_socket,	.set_io_map = plx9052_set_io_map,	.set_mem_map = plx9052_set_mem_map,};static int plx9052_probe(struct pci_dev *pdev,			 const struct pci_device_id *ent){	int err = 0;	struct plx9052_socket *socket = NULL;	socket = kmalloc(sizeof(struct plx9052_socket), GFP_KERNEL);	if (!socket)		return -ENOMEM;	memset(socket, 0, sizeof(struct plx9052_socket));	socket->pdev = pdev;	pci_set_drvdata(pdev, socket);	spin_lock_init(&socket->event_lock);	INIT_WORK(&socket->event_work, (void (*)(void *)) plx9052_event,		  socket);	err = pci_enable_device(pdev);	if (err)		return -EIO;	/* Resource 1 is control registers of PLX9052 */	socket->plxctl_addr = pci_resource_start(pdev, 1);	socket->plxctl_len = pci_resource_len(pdev, 1);	if (!request_region	    (socket->plxctl_addr, socket->plxctl_len, DEVICE_NAME)) {		printk(KERN_ERR "plx9052: I/O at 0x%x-0x%x busy\n",		       socket->plxctl_addr,		       socket->plxctl_addr + socket->plxctl_len - 1);		socket->plxctl_addr = 0;		err = -EBUSY;		goto fail;	}	/* Resource 2 is mapped to the PCMCIA memory space, starting with CIS */	socket->mem_phys = pci_resource_start(pdev, 2);	socket->mem_len = pci_resource_len(pdev, 2);	if (!request_mem_region	    (socket->mem_phys, socket->mem_len, DEVICE_NAME)) {		printk(KERN_ERR "plx9052: memory at 0x%lx-0x%lx busy\n",		       socket->mem_phys,		       socket->mem_phys + socket->mem_len - 1);		socket->mem_phys = 0;		err = -EBUSY;		goto fail;	}	socket->mem_virt = ioremap(socket->mem_phys, socket->mem_len);	if (!socket->mem_virt) {		printk(KERN_ERR		       "plx9052: cannot map memory at 0x%lx-0x%lx\n",		       socket->mem_phys,		       socket->mem_phys + socket->mem_len - 1);		err = -ENOMEM;		goto fail;	}	err =	    request_irq(pdev->irq, plx9052_interrupt, SA_SHIRQ,			DEVICE_NAME, socket);	if (err) {		printk(KERN_ERR "plx9052: cannot allocate IRQ %d.\n",		       pdev->irq);		err = -EBUSY;		goto fail;	}	socket->socket.ops = &plx9052_operations;	socket->socket.dev.dev = &pdev->dev;	socket->socket.driver_data = socket;	socket->socket.owner = THIS_MODULE;	socket->socket.features =	    SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_PAGE_REGS;	socket->socket.map_size = PLX_MEMWIN_MIN;	/* minimum window size */	socket->socket.pci_irq = pdev->irq;	pcmcia_register_socket(&socket->socket);	printk(KERN_INFO "plx9052: socket enabled, IRQ %d\n",	       socket->pdev->irq);	return 0;		/* succeeded */      fail:	plx9052_close(pdev);	return err;}static void plx9052_close(struct pci_dev *pdev){	struct plx9052_socket *socket = pci_get_drvdata(pdev);	pcmcia_unregister_socket(&socket->socket);	if (pdev->irq)		free_irq(pdev->irq, socket);	if (socket->plxctl_addr)		release_region(socket->plxctl_addr, socket->plxctl_len);	if (socket->mem_virt)		iounmap(socket->mem_virt);	if (socket->mem_phys)		release_mem_region(socket->mem_phys, socket->mem_len);	socket->pdev = NULL;	pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);	kfree(socket);}/* PCI ID table, from orinoco_plx.c */static struct pci_device_id plx9052_pci_id_table[] __devinitdata = {	{0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,},	/* Siemens SpeedStream SS1023 */	{0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,},	/* Netgear MA301 */	{0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,},	/* Correga  - does this work? */	{0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},	/* SMC EZConnect SMC2602W,							   Eumitcom PCI WL11000,							   Addtron AWA-100 */	{0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},	/* Global Sun Tech GL24110P */	{0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,},	/* Reported working, but unknown */	{0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,},	/* Linksys WDT11 */	{0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,},	/* USR 2415 */	{0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,},	/* Belkin F5D6000 tested by							   Brendan W. McAdams <rit@jacked-in.org> */	{0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,},	/* 3Com AirConnect PCI tested by							   Damien Persohn <damien@persohn.net> */	{0,},};MODULE_DEVICE_TABLE(pci, plx9052_pci_id_table);static int plx9052_socket_suspend(struct pci_dev *pdev, u32 state){	return pcmcia_socket_dev_suspend(&pdev->dev, state);}static int plx9052_socket_resume(struct pci_dev *pdev){	return pcmcia_socket_dev_resume(&pdev->dev);}static struct pci_driver plx9052_driver = {	.name = DEVICE_NAME,	.id_table = plx9052_pci_id_table,	.probe = plx9052_probe,	.remove = plx9052_close,	.suspend = plx9052_socket_suspend,	.resume = plx9052_socket_resume,};static int __init init_plx9052(void){	pci_module_init(&plx9052_driver);	return 0;}extern void __exit exit_plx9052(void){	pci_unregister_driver(&plx9052_driver);}module_init(init_plx9052);module_exit(exit_plx9052);

⌨️ 快捷键说明

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