acpiphp_pci.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:19k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * ACPI PCI HotPlug PCI configuration space management
  3.  *
  4.  * Copyright (c) 1995,2001 Compaq Computer Corporation
  5.  * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
  6.  * Copyright (c) 2001,2002 IBM Corp.
  7.  * Copyright (c) 2002 Takayoshi Kochi (t-kouchi@cq.jp.nec.com)
  8.  * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)
  9.  * Copyright (c) 2002 NEC Corporation
  10.  *
  11.  * All rights reserved.
  12.  *
  13.  * This program is free software; you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation; either version 2 of the License, or (at
  16.  * your option) any later version.
  17.  *
  18.  * This program is distributed in the hope that it will be useful, but
  19.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  21.  * NON INFRINGEMENT.  See the GNU General Public License for more
  22.  * details.
  23.  *
  24.  * You should have received a copy of the GNU General Public License
  25.  * along with this program; if not, write to the Free Software
  26.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  27.  *
  28.  * Send feedback to <t-kouchi@cq.jp.nec.com>
  29.  *
  30.  */
  31. #include <linux/config.h>
  32. #include <linux/kernel.h>
  33. #include <linux/module.h>
  34. #include <linux/pci.h>
  35. #include <linux/init.h>
  36. #include "pci_hotplug.h"
  37. #include "acpiphp.h"
  38. static int debug = 1; /* XXX set 0 after debug */
  39. #define MY_NAME "acpiphp_pci"
  40. static void acpiphp_configure_irq (struct pci_dev *dev);
  41. /* allocate mem/pmem/io resource to a new function */
  42. static int alloc_resource (struct acpiphp_func *func)
  43. {
  44. u64 base;
  45. u32 bar, len;
  46. u32 address[] = {
  47. PCI_BASE_ADDRESS_0,
  48. PCI_BASE_ADDRESS_1,
  49. PCI_BASE_ADDRESS_2,
  50. PCI_BASE_ADDRESS_3,
  51. PCI_BASE_ADDRESS_4,
  52. PCI_BASE_ADDRESS_5,
  53. 0
  54. };
  55. int count;
  56. struct acpiphp_bridge *bridge;
  57. struct pci_resource *res;
  58. struct pci_ops *ops;
  59. int bus, device, function;
  60. bridge = func->slot->bridge;
  61. bus = bridge->bus;
  62. device = func->slot->device;
  63. function = func->function;
  64. ops = bridge->pci_ops;
  65. for (count = 0; address[count]; count++) { /* for 6 BARs */
  66. pci_write_config_dword_nodev (ops, bus, device, function, address[count], 0xFFFFFFFF);
  67. pci_read_config_dword_nodev(ops, bus, device, function, address[count], &bar);
  68. if (!bar) /* This BAR is not implemented */
  69. continue;
  70. dbg("Device %02x.%02x BAR %d wants %x", device, function, count, bar);
  71. if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
  72. /* This is IO */
  73. len = bar & 0xFFFFFFFC;
  74. len = ~len + 1;
  75. dbg ("len in IO %x, BAR %d", len, count);
  76. spin_lock(&bridge->res_lock);
  77. res = acpiphp_get_io_resource(&bridge->io_head, len);
  78. spin_unlock(&bridge->res_lock);
  79. if (!res) {
  80. err("cannot allocate requested io for %02x:%02x.%d len %xn",
  81.     bus, device, function, len);
  82. return -1;
  83. }
  84. pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)res->base);
  85. res->next = func->io_head;
  86. func->io_head = res;
  87. } else {
  88. /* This is Memory */
  89. if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {
  90. /* pfmem */
  91. len = bar & 0xFFFFFFF0;
  92. len = ~len + 1;
  93. dbg("len in PFMEM %x, BAR %d", len, count);
  94. spin_lock(&bridge->res_lock);
  95. res = acpiphp_get_resource(&bridge->p_mem_head, len);
  96. spin_unlock(&bridge->res_lock);
  97. if (!res) {
  98. err("cannot allocate requested pfmem for %02x:%02x.%d len %xn",
  99.     bus, device, function, len);
  100. return -1;
  101. }
  102. pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)res->base);
  103. if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
  104. dbg ("inside the pfmem 64 case, count %d", count);
  105. count += 1;
  106. pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)(res->base >> 32));
  107. }
  108. res->next = func->p_mem_head;
  109. func->p_mem_head = res;
  110. } else {
  111. /* regular memory */
  112. len = bar & 0xFFFFFFF0;
  113. len = ~len + 1;
  114. dbg("len in MEM %x, BAR %d", len, count);
  115. spin_lock(&bridge->res_lock);
  116. res = acpiphp_get_resource(&bridge->mem_head, len);
  117. spin_unlock(&bridge->res_lock);
  118. if (!res) {
  119. err("cannot allocate requested pfmem for %02x:%02x.%d len %xn",
  120.     bus, device, function, len);
  121. return -1;
  122. }
  123. pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)res->base);
  124. if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {
  125. /* takes up another dword */
  126. dbg ("inside mem 64 case, reg. mem, count %d", count);
  127. count += 1;
  128. pci_write_config_dword_nodev(ops, bus, device, function, address[count], (u32)(res->base >> 32));
  129. }
  130. res->next = func->mem_head;
  131. func->mem_head = res;
  132. }
  133. }
  134. }
  135. /* disable expansion rom */
  136. pci_write_config_dword_nodev(ops, bus, device, function, PCI_ROM_ADDRESS, 0x00000000);
  137. return 0;
  138. }
  139. /* enable pci_dev */
  140. static int configure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
  141. {
  142. u16 tmp;
  143. struct acpiphp_func *func;
  144. struct acpiphp_bridge *bridge;
  145. struct pci_dev *dev;
  146. func = (struct acpiphp_func *)wrapped_dev->data;
  147. bridge = (struct acpiphp_bridge *)wrapped_bus->data;
  148. dev = wrapped_dev->dev;
  149. /* TBD: support PCI-to-PCI bridge case */
  150. if (!func || !bridge)
  151. return 0;
  152. pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, bridge->hpp.cache_line_size);
  153. pci_write_config_byte(dev, PCI_LATENCY_TIMER, bridge->hpp.latency_timer);
  154. pci_read_config_word(dev, PCI_COMMAND, &tmp);
  155. if (bridge->hpp.enable_SERR)
  156. tmp |= PCI_COMMAND_SERR;
  157. if (bridge->hpp.enable_PERR)
  158. tmp |= PCI_COMMAND_PARITY;
  159. //tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
  160. pci_write_config_word(dev, PCI_COMMAND, tmp);
  161. acpiphp_configure_irq(dev);
  162. #ifdef CONFIG_PROC_FS
  163. pci_proc_attach_device(dev);
  164. #endif
  165. pci_announce_device_to_drivers(dev);
  166. return 0;
  167. }
  168. static int is_pci_dev_in_use (struct pci_dev* dev) 
  169. {
  170. /* 
  171.  * dev->driver will be set if the device is in use by a new-style 
  172.  * driver -- otherwise, check the device's regions to see if any
  173.  * driver has claimed them
  174.  */
  175. int i, inuse=0;
  176. if (dev->driver) return 1; //assume driver feels responsible
  177. for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
  178. if (!pci_resource_start(dev, i))
  179. continue;
  180. if (pci_resource_flags(dev, i) & IORESOURCE_IO)
  181. inuse = check_region(pci_resource_start(dev, i),
  182.      pci_resource_len(dev, i));
  183. else if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
  184. inuse = check_mem_region(pci_resource_start(dev, i),
  185.  pci_resource_len(dev, i));
  186. }
  187. return inuse;
  188. }
  189. static int pci_hp_remove_device (struct pci_dev *dev)
  190. {
  191. if (is_pci_dev_in_use(dev)) {
  192. err("***Cannot safely power down device -- "
  193.        "it appears to be in use***n");
  194. return -EBUSY;
  195. }
  196. pci_remove_device(dev);
  197. return 0;
  198. }
  199. /* remove device driver */
  200. static int unconfigure_pci_dev_driver (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
  201. {
  202. struct pci_dev *dev = wrapped_dev->dev;
  203. dbg("attempting removal of driver for device %s", dev->slot_name);
  204. /* Now, remove the Linux Driver Representation */
  205. if (dev->driver) {
  206. if (dev->driver->remove) {
  207. dev->driver->remove(dev);
  208. dbg("driver was properly removed");
  209. }
  210. dev->driver = NULL;
  211. }
  212. return is_pci_dev_in_use(dev);
  213. }
  214. /* remove pci_dev itself from system */
  215. static int unconfigure_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus)
  216. {
  217. struct pci_dev *dev = wrapped_dev->dev;
  218. /* Now, remove the Linux Representation */
  219. if (dev) {
  220. if (pci_hp_remove_device(dev) == 0) {
  221. kfree(dev); /* Now, remove */
  222. } else {
  223. return -1; /* problems while freeing, abort visitation */
  224. }
  225. }
  226. return 0;
  227. }
  228. /* remove pci_bus itself from system */
  229. static int unconfigure_pci_bus (struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_dev)
  230. {
  231. struct pci_bus *bus = wrapped_bus->bus;
  232. #ifdef CONFIG_PROC_FS
  233. /* Now, remove the Linux Representation */
  234. if (bus->procdir) {
  235. pci_proc_detach_bus(bus);
  236. }
  237. #endif
  238. /* the cleanup code should live in the kernel ... */
  239. bus->self->subordinate = NULL;
  240. /* unlink from parent bus */
  241. list_del(&bus->node);
  242. /* Now, remove */
  243. if (bus)
  244. kfree(bus);
  245. return 0;
  246. }
  247. /* detect_used_resource - subtract resource under dev from bridge */
  248. static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)
  249. {
  250. u32 bar, len, pin;
  251. u64 base;
  252. u32 address[] = {
  253. PCI_BASE_ADDRESS_0,
  254. PCI_BASE_ADDRESS_1,
  255. PCI_BASE_ADDRESS_2,
  256. PCI_BASE_ADDRESS_3,
  257. PCI_BASE_ADDRESS_4,
  258. PCI_BASE_ADDRESS_5,
  259. 0
  260. };
  261. int count;
  262. struct pci_resource *res;
  263. dbg("Device %s", dev->slot_name);
  264. for (count = 0; address[count]; count++) { /* for 6 BARs */
  265. pci_read_config_dword(dev, address[count], &bar);
  266. if (!bar) /* This BAR is not implemented */
  267. continue;
  268. pci_write_config_dword(dev, address[count], 0xFFFFFFFF);
  269. pci_read_config_dword(dev, address[count], &len);
  270. if (len & PCI_BASE_ADDRESS_SPACE_IO) {
  271. /* This is IO */
  272. base = bar & 0xFFFFFFFC;
  273. len &= 0xFFFFFFFC;
  274. len = ~len + 1;
  275. dbg("BAR[%d] %08x - %08x (IO)", count, (u32)base, (u32)base + len - 1);
  276. spin_lock(&bridge->res_lock);
  277. res = acpiphp_get_resource_with_base(&bridge->io_head, base, len);
  278. spin_unlock(&bridge->res_lock);
  279. if (res)
  280. kfree(res);
  281. } else {
  282. /* This is Memory */
  283. base = bar & 0xFFFFFFF0;
  284. if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
  285. /* pfmem */
  286. len &= 0xFFFFFFF0;
  287. len = ~len + 1;
  288. if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
  289. dbg ("prefetch mem 64");
  290. count += 1;
  291. }
  292. dbg("BAR[%d] %08x - %08x (PMEM)", count, (u32)base, (u32)base + len - 1);
  293. spin_lock(&bridge->res_lock);
  294. res = acpiphp_get_resource_with_base(&bridge->p_mem_head, base, len);
  295. spin_unlock(&bridge->res_lock);
  296. if (res)
  297. kfree(res);
  298. } else {
  299. /* regular memory */
  300. len &= 0xFFFFFFF0;
  301. len = ~len + 1;
  302. if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
  303. /* takes up another dword */
  304. dbg ("mem 64");
  305. count += 1;
  306. }
  307. dbg("BAR[%d] %08x - %08x (MEM)", count, (u32)base, (u32)base + len - 1);
  308. spin_lock(&bridge->res_lock);
  309. res = acpiphp_get_resource_with_base(&bridge->mem_head, base, len);
  310. spin_unlock(&bridge->res_lock);
  311. if (res)
  312. kfree(res);
  313. }
  314. }
  315. pci_write_config_dword(dev, address[count], bar);
  316. }
  317. return 0;
  318. }
  319. /* detect_pci_resource_bus - subtract resource under pci_bus */
  320. static void detect_used_resource_bus(struct acpiphp_bridge *bridge, struct pci_bus *bus)
  321. {
  322. struct list_head *l;
  323. struct pci_dev *dev;
  324. list_for_each(l, &bus->devices) {
  325. dev = pci_dev_b(l);
  326. detect_used_resource(bridge, dev);
  327. /* XXX recursive call */
  328. if (dev->subordinate)
  329. detect_used_resource_bus(bridge, dev->subordinate);
  330. }
  331. }
  332. /**
  333.  * acpiphp_detect_pci_resource - detect resources under bridge
  334.  * @bridge: detect all resources already used under this bridge
  335.  *
  336.  * collect all resources already allocated for all devices under a bridge.
  337.  */
  338. int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)
  339. {
  340. struct list_head *l;
  341. struct pci_dev *dev;
  342. detect_used_resource_bus(bridge, bridge->pci_bus);
  343. return 0;
  344. }
  345. /**
  346.  * acpiphp_init_slot_resource - gather resource usage information of a slot
  347.  * @slot: ACPI slot object to be checked, should have valid pci_dev member
  348.  *
  349.  * TBD: PCI-to-PCI bridge case
  350.  *      use pci_dev->resource[]
  351.  */
  352. int acpiphp_init_func_resource (struct acpiphp_func *func)
  353. {
  354. u64 base;
  355. u32 bar, len;
  356. u32 address[] = {
  357. PCI_BASE_ADDRESS_0,
  358. PCI_BASE_ADDRESS_1,
  359. PCI_BASE_ADDRESS_2,
  360. PCI_BASE_ADDRESS_3,
  361. PCI_BASE_ADDRESS_4,
  362. PCI_BASE_ADDRESS_5,
  363. 0
  364. };
  365. int count;
  366. struct pci_resource *res;
  367. struct pci_ops *ops;
  368. struct pci_dev *dev;
  369. dev = func->pci_dev;
  370. dbg("Hot-pluggable device %s", dev->slot_name);
  371. for (count = 0; address[count]; count++) { /* for 6 BARs */
  372. pci_read_config_dword (dev, address[count], &bar);
  373. if (!bar) /* This BAR is not implemented */
  374. continue;
  375. pci_write_config_dword (dev, address[count], 0xFFFFFFFF);
  376. pci_read_config_dword (dev, address[count], &len);
  377. if (len & PCI_BASE_ADDRESS_SPACE_IO) {
  378. /* This is IO */
  379. base = bar & 0xFFFFFFFC;
  380. len &= 0xFFFFFFFC;
  381. len = ~len + 1;
  382. dbg("BAR[%d] %08x - %08x (IO)", count, (u32)base, (u32)base + len - 1);
  383. res = acpiphp_make_resource(base, len);
  384. if (!res)
  385. goto no_memory;
  386. res->next = func->io_head;
  387. func->io_head = res;
  388. } else {
  389. /* This is Memory */
  390. base = bar & 0xFFFFFFF0;
  391. if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {
  392. /* pfmem */
  393. len &= 0xFFFFFFF0;
  394. len = ~len + 1;
  395. if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */
  396. dbg ("prefetch mem 64");
  397. count += 1;
  398. }
  399. dbg("BAR[%d] %08x - %08x (PMEM)", count, (u32)base, (u32)base + len - 1);
  400. res = acpiphp_make_resource(base, len);
  401. if (!res)
  402. goto no_memory;
  403. res->next = func->p_mem_head;
  404. func->p_mem_head = res;
  405. } else {
  406. /* regular memory */
  407. len &= 0xFFFFFFF0;
  408. len = ~len + 1;
  409. if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {
  410. /* takes up another dword */
  411. dbg ("mem 64");
  412. count += 1;
  413. }
  414. dbg("BAR[%d] %08x - %08x (MEM)", count, (u32)base, (u32)base + len - 1);
  415. res = acpiphp_make_resource(base, len);
  416. if (!res)
  417. goto no_memory;
  418. res->next = func->mem_head;
  419. func->mem_head = res;
  420. }
  421. }
  422. pci_write_config_dword (dev, address[count], bar);
  423. }
  424. #if 1
  425. acpiphp_dump_func_resource(func);
  426. #endif
  427. return 0;
  428.  no_memory:
  429. err("out of memory");
  430. acpiphp_free_resource(&func->io_head);
  431. acpiphp_free_resource(&func->mem_head);
  432. acpiphp_free_resource(&func->p_mem_head);
  433. return -1;
  434. }
  435. /**
  436.  * acpiphp_configure_slot - allocate PCI resources
  437.  * @slot: slot to be configured
  438.  *
  439.  * initializes a PCI functions on a device inserted
  440.  * into the slot
  441.  *
  442.  */
  443. int acpiphp_configure_slot (struct acpiphp_slot *slot)
  444. {
  445. struct acpiphp_func *func;
  446. struct list_head *l;
  447. u8 hdr;
  448. u32 dvid;
  449. int retval = 0;
  450. int is_multi = 0;
  451. pci_read_config_byte_nodev(slot->bridge->pci_ops,
  452.    slot->bridge->bus, slot->device, 0,
  453.    PCI_HEADER_TYPE, &hdr);
  454. if (hdr & 0x80)
  455. is_multi = 1;
  456. list_for_each(l, &slot->funcs) {
  457. func = list_entry(l, struct acpiphp_func, sibling);
  458. if (is_multi || func->function == 0) {
  459. pci_read_config_dword_nodev(slot->bridge->pci_ops,
  460.     slot->bridge->bus,
  461.     slot->device,
  462.     func->function,
  463.     PCI_VENDOR_ID, &dvid);
  464. if (dvid != 0xffffffff) {
  465. retval = alloc_resource(func);
  466. if (retval)
  467. break;
  468. }
  469. }
  470. }
  471. return retval;
  472. }
  473. /* for pci_visit_dev() */
  474. static struct pci_visit configure_functions = {
  475. post_visit_pci_dev: configure_pci_dev
  476. };
  477. static struct pci_visit unconfigure_functions_phase1 = {
  478. post_visit_pci_dev: unconfigure_pci_dev_driver
  479. };
  480. static struct pci_visit unconfigure_functions_phase2 = {
  481. post_visit_pci_bus: unconfigure_pci_bus,
  482. post_visit_pci_dev: unconfigure_pci_dev
  483. };
  484. /**
  485.  * acpiphp_configure_function - configure PCI function
  486.  * @func: function to be configured
  487.  *
  488.  * initializes a PCI functions on a device inserted
  489.  * into the slot
  490.  *
  491.  */
  492. int acpiphp_configure_function (struct acpiphp_func *func)
  493. {
  494. int retval = 0;
  495. struct pci_dev_wrapped wrapped_dev;
  496. struct pci_bus_wrapped wrapped_bus;
  497. struct acpiphp_bridge *bridge;
  498. /* if pci_dev is NULL, ignore it */
  499. if (!func->pci_dev)
  500. goto err_exit;
  501. bridge = func->slot->bridge;
  502. memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
  503. memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
  504. wrapped_dev.dev = func->pci_dev;
  505. wrapped_dev.data = func;
  506. wrapped_bus.bus = bridge->pci_bus;
  507. wrapped_bus.data = bridge;
  508. retval = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
  509. if (retval)
  510. goto err_exit;
  511.  err_exit:
  512. return retval;
  513. }
  514. /**
  515.  * acpiphp_unconfigure_function - unconfigure PCI function
  516.  * @func: function to be unconfigured
  517.  *
  518.  */
  519. int acpiphp_unconfigure_function (struct acpiphp_func *func)
  520. {
  521. struct acpiphp_bridge *bridge;
  522. struct pci_resource *tmp;
  523. struct pci_dev_wrapped wrapped_dev;
  524. struct pci_bus_wrapped wrapped_bus;
  525. int retval = 0;
  526. /* if pci_dev is NULL, ignore it */
  527. if (!func->pci_dev)
  528. goto err_exit;
  529. memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
  530. memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
  531. wrapped_dev.dev = func->pci_dev;
  532. //wrapped_dev.data = func;
  533. wrapped_bus.bus = func->slot->bridge->pci_bus;
  534. //wrapped_bus.data = func->slot->bridge;
  535. retval = pci_visit_dev(&unconfigure_functions_phase1, &wrapped_dev, &wrapped_bus);
  536. if (retval)
  537. goto err_exit;
  538. retval = pci_visit_dev(&unconfigure_functions_phase2, &wrapped_dev, &wrapped_bus);
  539. if (retval)
  540. goto err_exit;
  541. /* free all resources */
  542. bridge = func->slot->bridge;
  543. spin_lock(&bridge->res_lock);
  544. acpiphp_move_resource(&func->io_head, &bridge->io_head);
  545. acpiphp_move_resource(&func->mem_head, &bridge->mem_head);
  546. acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);
  547. acpiphp_move_resource(&func->bus_head, &bridge->bus_head);
  548. spin_unlock(&bridge->res_lock);
  549.  err_exit:
  550. return retval;
  551. }
  552. /* XXX IA64 specific */
  553. #ifdef CONFIG_IA64
  554. static int ia64_get_irq(struct pci_dev *dev, int pin)
  555. {
  556. extern int pci_pin_to_vector(int bus, int slot, int pci_pin);
  557. int irq;
  558. irq = pci_pin_to_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
  559. if (irq < 0 && dev->bus->parent) {
  560. /* go back to the bridge */
  561. struct pci_dev *bridge = dev->bus->self;
  562. if (bridge) {
  563. /* allow for multiple bridges on an adapter */
  564. do {
  565. /* do the bridge swizzle... */
  566. pin = (pin + PCI_SLOT(dev->devfn)) % 4;
  567. irq = pci_pin_to_vector(bridge->bus->number,
  568. PCI_SLOT(bridge->devfn),
  569.    pin);
  570. } while (irq < 0 && (bridge = bridge->bus->self));
  571. }
  572. if (irq >= 0)
  573. printk(KERN_WARNING
  574.        "PCI: using PPB(B%d,I%d,P%d) to get vector %02xn",
  575.        dev->bus->number, PCI_SLOT(dev->devfn),
  576.        pin, irq);
  577. else
  578. printk(KERN_WARNING
  579.        "PCI: Couldn't map irq for (B%d,I%d,P%d)n",
  580.        dev->bus->number, PCI_SLOT(dev->devfn), pin);
  581. }
  582. return irq;
  583. }
  584. #endif
  585. /*
  586.  * acpiphp_configure_irq - configure PCI_INTERRUPT_PIN
  587.  *
  588.  * for x86 platforms, pcibios_enable_device calls pcibios_enable_irq,
  589.  * which allocates irq for pci_dev
  590.  *
  591.  * for IA64 platforms, we have to program dev->irq from pci IRQ routing
  592.  * information derived from ACPI table
  593.  *
  594.  * TBD:
  595.  * separate architecture dependent part
  596.  * (preferably, pci_enable_device() cares for allocating irq...)
  597.  */
  598. static void acpiphp_configure_irq (struct pci_dev *dev)
  599. {
  600. #if CONFIG_IA64     /* XXX IA64 specific, need i386 version */
  601. int bus, device, function, irq;
  602. u8 tmp;
  603. bus = dev->bus->number;
  604. device = PCI_SLOT(dev->devfn);
  605. function = PCI_FUNC(dev->devfn);
  606. pci_read_config_byte (dev, PCI_INTERRUPT_PIN, &tmp);
  607. if ((tmp > 0x00) && (tmp < 0x05)) {
  608. irq = ia64_get_irq(dev, tmp - 1);
  609. if (irq > 0) {
  610. dev->irq = irq;
  611. pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
  612. } else {
  613. err("Couldn't get IRQ for INT%c", 'A' + tmp - 1);
  614. }
  615. }
  616. #endif
  617. }