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

📄 cardbus.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 2 页
字号:
	list_add_tail(&c[i].dev.global_list, &pci_devices);#else	if (i < fn-1) {	    c[i].dev.sibling = c[i].dev.next = &c[i+1].dev;	}#endif    }#ifdef NEWER_LINUX_PCI    list_del(&tmp.global_list);#else    s->cap.cb_bus->devices = &c[0].dev;    /* Link into PCI device chain */    c[fn-1].dev.next = tmp.next;    pci_devices = &c[0].dev;#endif    for (i = 0; i < fn; i++) {	c[i].dev.vendor = vend;	pci_readw(&c[i].dev, PCI_DEVICE_ID, &c[i].dev.device);	pci_readl(&c[i].dev, PCI_CLASS_REVISION, &c[i].dev.class);	c[i].dev.class >>= 8;#ifdef NEW_LINUX_PCI	c[i].dev.hdr_type = hdr;#endif#ifdef HAS_PROC_BUS	pci_proc_attach_device(&c[i].dev);#endif    }    return CS_SUCCESS;}void cb_free(socket_info_t *s){    cb_config_t *c = s->cb_config;    if (c) {#ifdef NEWER_LINUX_PCI	int i;	for (i = 0; i < s->functions; i++)	    list_del(&c[i].dev.global_list);	INIT_LIST_HEAD(&s->cap.cb_bus->devices);#else	struct pci_dev **p, *q;	/* Unlink from PCI device chain */	for (p = &pci_devices; *p; p = &((*p)->next))	    if (*p == &c[0].dev) break;	for (q = *p; q; q = q->next) {	    if (q->bus != (*p)->bus) break;#ifdef HAS_PROC_BUS	    pci_proc_detach_device(q);#endif	}	if (*p) *p = q;	s->cap.cb_bus->devices = NULL;#endif	kfree(s->cb_config);	s->cb_config = NULL;	printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cardbus);    }}/*=====================================================================    cb_config() has the job of allocating all system resources that    a Cardbus card requires.  Rather than using the CIS (which seems    to not always be present), it treats the card as an ordinary PCI    device, and probes the base address registers to determine each    function's IO and memory space needs.    It is called from the RequestIO card service.    ======================================================================*/int cb_config(socket_info_t *s){    cb_config_t *c = s->cb_config;    u_char fn = s->functions;    u_char i, j, *name;    u_int sz, align, m, mask[3], num[3], base[3];    int irq;    printk(KERN_INFO "cs: cb_config(bus %d)\n", s->cap.cardbus);    /* Determine IO and memory space needs */    num[B_IO] = num[B_M1] = num[B_M2] = 0;    mask[B_IO] = mask[B_M1] = mask[B_M2] = 0;    for (i = 0; i < fn; i++) {	for (j = 0; j < 6; j++) {	    pci_writel(&c[i].dev, CB_BAR(j), 0xffffffff);	    pci_readl(&c[i].dev, CB_BAR(j), &sz);	    if (sz == 0) continue;	    if (sz & PCI_BASE_ADDRESS_SPACE) {		m = B_IO;		sz &= PCI_BASE_ADDRESS_IO_MASK;	    } else {		m = (sz & PCI_BASE_ADDRESS_MEM_PREFETCH) ? B_M2 : B_M1;		sz &= PCI_BASE_ADDRESS_MEM_MASK;	    }	    sz = FIND_FIRST_BIT(sz);	    c[i].size[j] = sz | m;	    if (m && (sz < PAGE_SIZE)) sz = PAGE_SIZE;	    num[m] += sz; mask[m] |= sz;	}	pci_writel(&c[i].dev, CB_ROM_BASE, 0xffffffff);	pci_readl(&c[i].dev, CB_ROM_BASE, &sz);	if (sz != 0) {	    sz = FIND_FIRST_BIT(sz & ~0x00000001);	    c[i].size[6] = sz | B_M1;	    if (sz < PAGE_SIZE) sz = PAGE_SIZE;	    num[B_M1] += sz; mask[B_M1] |= sz;	}    }    /* Allocate system resources */    name = "cb_enabler";    s->io[0].NumPorts = num[B_IO];    s->io[0].BasePort = 0;    if (num[B_IO]) {	for (align = 1; align < mask[B_IO]; align <<= 1) ;	if (find_io_region(&s->io[0].BasePort, num[B_IO],			   align, name) != 0) {	    printk(KERN_NOTICE "cs: could not allocate %d IO ports for"		   " CardBus socket %d\n", num[B_IO], s->sock);	    goto failed;	}	base[B_IO] = s->io[0].BasePort + num[B_IO];    }    s->win[0].size = num[B_M1];    s->win[0].base = 0;    if (num[B_M1]) {	for (align = 1; align < mask[B_M1]; align <<= 1) ;	if (find_mem_region(&s->win[0].base, num[B_M1], align,			    0, name) != 0) {	    printk(KERN_NOTICE "cs: could not allocate %dK memory for"		   " CardBus socket %d\n", num[B_M1]/1024, s->sock);	    goto failed;	}	base[B_M1] = s->win[0].base + num[B_M1];    }    s->win[1].size = num[B_M2];    s->win[1].base = 0;    if (num[B_M2]) {	for (align = 1; align < mask[B_M2]; align <<= 1) ;	if (find_mem_region(&s->win[1].base, num[B_M2], align,			    0, name) != 0) {	    printk(KERN_NOTICE "cs: could not allocate %dK memory for"		   " CardBus socket %d\n", num[B_M2]/1024, s->sock);	    goto failed;	}	base[B_M2] = s->win[1].base + num[B_M2];    }        /* Set up base address registers */    while (mask[B_IO] | mask[B_M1] | mask[B_M2]) {	num[B_IO] = FIND_FIRST_BIT(mask[B_IO]); mask[B_IO] -= num[B_IO];	num[B_M1] = FIND_FIRST_BIT(mask[B_M1]); mask[B_M1] -= num[B_M1];	num[B_M2] = FIND_FIRST_BIT(mask[B_M2]); mask[B_M2] -= num[B_M2];	for (i = 0; i < fn; i++) {	    for (j = 0; j < 7; j++) {		sz = c[i].size[j];		m = sz & 3; sz &= ~3;		align = (m && (sz < PAGE_SIZE)) ? PAGE_SIZE : sz;		if (sz && (align == num[m])) {		    base[m] -= align;		    if (j < 6)			printk(KERN_INFO "  fn %d bar %d: ", i, j+1);		    else			printk(KERN_INFO "  fn %d rom: ", i);		    printk("%s 0x%x-0x%x\n", (m) ? "mem" : "io",			   base[m], base[m]+sz-1);		    BASE(c[i], j) = base[m];		    FLAGS(c[i], j) |= map_flags[m];		}	    }	}    }        /* Allocate interrupt if needed */    s->irq.AssignedIRQ = irq = 0;    for (i = 0; i < fn; i++) {	pci_readb(&c[i].dev, PCI_INTERRUPT_PIN, &j);	if (j == 0) continue;	if ((irq == 0) && s->cap.pci_irq)	    irq = s->cap.pci_irq;#ifdef CONFIG_ISA	if (irq == 0) {	    int try;	    for (try = 0; try < 2; try++) {		for (irq = 0; irq < 32; irq++)		    if (((s->cap.irq_mask >> irq) & 1) &&			(try_irq(IRQ_TYPE_EXCLUSIVE, irq, try) == 0))			break;		if (irq < 32) break;	    }	    if (irq == 32) irq = 0;	}	if (irq == 0) {	    printk(KERN_NOTICE "cs: could not allocate interrupt"		   " for CardBus socket %d\n", s->sock);	    goto failed;	}#endif    }    if (irq)	printk(KERN_INFO "  irq %d\n", irq);    s->irq.AssignedIRQ = irq;    for (i = 0; i < fn; i++)	c[i].dev.irq = irq;        return CS_SUCCESS;failed:    cb_release(s);    return CS_OUT_OF_RESOURCE;}/*======================================================================    cb_release() releases all the system resources (IO and memory    space, and interrupt) committed for a Cardbus card by a prior call    to cb_config().    It is called from the ReleaseIO() service.    ======================================================================*/void cb_release(socket_info_t *s){    cb_config_t *c = s->cb_config;        DEBUG(0, "cs: cb_release(bus %d)\n", s->cap.cardbus);        if (s->win[0].size > 0)	release_mem_region(s->win[0].base, s->win[0].size);    if (s->win[1].size > 0)	release_mem_region(s->win[1].base, s->win[1].size);    if (s->io[0].NumPorts > 0)	release_region(s->io[0].BasePort, s->io[0].NumPorts);    s->io[0].NumPorts = 0;#ifdef CONFIG_ISA    if ((c[0].dev.irq != 0) && (c[0].dev.irq != s->cap.pci_irq))	undo_irq(IRQ_TYPE_EXCLUSIVE, c[0].dev.irq);#endif}/*=====================================================================    cb_enable() has the job of configuring a socket for a Cardbus    card, and initializing the card's PCI configuration registers.    It first sets up the Cardbus bridge windows, for IO and memory    accesses.  Then, it initializes each card function's base address    registers, interrupt line register, and command register.    It is called as part of the RequestConfiguration card service.    It should be called after a previous call to cb_config() (via the    RequestIO service).    ======================================================================*/void cb_enable(socket_info_t *s){    u_char i, j, bus = s->cap.cardbus;    cb_config_t *c = s->cb_config;        DEBUG(0, "cs: cb_enable(bus %d)\n", bus);        /* Configure bridge */    if (s->cb_cis_virt)	cb_release_cis_mem(s);    for (i = 0; i < 3; i++) {	cb_bridge_map m;	switch (i) {	case B_IO:	    m.map = 0; m.flags = MAP_IOSPACE | MAP_ACTIVE;	    m.start = s->io[0].BasePort;	    m.stop = m.start + s->io[0].NumPorts - 1;	    break;	case B_M1:	    m.map = 0; m.flags = MAP_ACTIVE;	    m.start = s->win[0].base;	    m.stop = m.start + s->win[0].size - 1;	    break;	case B_M2:	    m.map = 1; m.flags = MAP_PREFETCH | MAP_ACTIVE;	    m.start = s->win[1].base;	    m.stop = m.start + s->win[1].size - 1;	    break;	}	if (m.start == 0) continue;	DEBUG(0, "  bridge %s map %d (flags 0x%x): 0x%x-0x%x\n",	      (m.flags & MAP_IOSPACE) ? "io" : "mem",	      m.map, m.flags, m.start, m.stop);	s->ss_entry(s->sock, SS_SetBridge, &m);    }    /* Set up base address registers */    for (i = 0; i < s->functions; i++) {	for (j = 0; j < 6; j++) {	    if (BASE(c[i], j) != 0)		pci_writel(&c[i].dev, CB_BAR(j),			   BASE(c[i], j) | FLAGS(c[i], j));	}	if (ROM(c[i]) != 0)	    pci_writel(&c[i].dev, CB_ROM_BASE, ROM(c[i]) | 1);    }    /* Set up a few basic PCI registers */    for (i = 0; i < s->functions; i++) {	pci_writeb(&c[i].dev, PCI_COMMAND, PCI_COMMAND_MASTER |		   PCI_COMMAND_IO | PCI_COMMAND_MEMORY);	/* These are lame but I don't know how to do any better */	pci_writeb(&c[i].dev, PCI_CACHE_LINE_SIZE, 8);	pci_writeb(&c[i].dev, PCI_LATENCY_TIMER, 64);    }        if (s->irq.AssignedIRQ) {	for (i = 0; i < s->functions; i++)	    pci_writeb(&c[i].dev, PCI_INTERRUPT_LINE,		       s->irq.AssignedIRQ);	s->socket.io_irq = s->irq.AssignedIRQ;	s->ss_entry(s->sock, SS_SetSocket, &s->socket);    }}/*======================================================================    cb_disable() unconfigures a Cardbus card previously set up by    cb_enable().    It is called from the ReleaseConfiguration service.    ======================================================================*/void cb_disable(socket_info_t *s){    u_char i;    cb_bridge_map m = { 0, 0, 0, 0xffff };        DEBUG(0, "cs: cb_disable(bus %d)\n", s->cap.cardbus);        /* Turn off bridge windows */    if (s->cb_cis_virt)	cb_release_cis_mem(s);    for (i = 0; i < 3; i++) {	switch (i) {	case B_IO: m.map = 0; m.flags = MAP_IOSPACE; break;	case B_M1: m.map = m.flags = 0; break;	case B_M2: m.map = 1; m.flags = 0; break;	}	s->ss_entry(s->sock, SS_SetBridge, &m);    }}

⌨️ 快捷键说明

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