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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  * Copyright (C) 2001 Silicon Graphics, Inc. All rights reserved.
  8.  */
  9. #include <linux/types.h>
  10. #include <linux/config.h>
  11. #include <linux/slab.h>
  12. #include <linux/module.h>
  13. #include <asm/sn/sgi.h>
  14. #include <asm/sn/sn_cpuid.h>
  15. #include <asm/sn/addrs.h>
  16. #include <asm/sn/arch.h>
  17. #include <asm/sn/iograph.h>
  18. #include <asm/sn/invent.h>
  19. #include <asm/sn/hcl.h>
  20. #include <asm/sn/labelcl.h>
  21. #include <asm/sn/xtalk/xwidget.h>
  22. #include <asm/sn/pci/bridge.h>
  23. #include <asm/sn/pci/pciio.h>
  24. #include <asm/sn/pci/pcibr.h>
  25. #include <asm/sn/pci/pcibr_private.h>
  26. #include <asm/sn/pci/pci_defs.h>
  27. #include <asm/sn/prio.h>
  28. #include <asm/sn/xtalk/xbow.h>
  29. #include <asm/sn/ioc3.h>
  30. #include <asm/sn/eeprom.h>
  31. #include <asm/sn/io.h>
  32. #include <asm/sn/sn_private.h>
  33. #ifdef __ia64
  34. #define rmallocmap atemapalloc
  35. #define rmfreemap atemapfree
  36. #define rmfree atefree
  37. #define rmalloc atealloc
  38. #endif
  39. unsigned pcibr_intr_bits(pciio_info_t info, pciio_intr_line_t lines);
  40. pcibr_intr_t            pcibr_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t);
  41. void                    pcibr_intr_free(pcibr_intr_t);
  42. void              pcibr_setpciint(xtalk_intr_t);
  43. int                     pcibr_intr_connect(pcibr_intr_t);
  44. void                    pcibr_intr_disconnect(pcibr_intr_t);
  45. devfs_handle_t            pcibr_intr_cpu_get(pcibr_intr_t);
  46. void                    pcibr_xintr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);
  47. void                    pcibr_intr_func(intr_arg_t);
  48. extern pcibr_info_t      pcibr_info_get(devfs_handle_t);
  49. /* =====================================================================
  50.  *    INTERRUPT MANAGEMENT
  51.  */
  52. unsigned
  53. pcibr_intr_bits(pciio_info_t info,
  54. pciio_intr_line_t lines)
  55. {
  56.     pciio_slot_t            slot = pciio_info_slot_get(info);
  57.     unsigned     bbits = 0;
  58.     /*
  59.      * Currently favored mapping from PCI
  60.      * slot number and INTA/B/C/D to Bridge
  61.      * PCI Interrupt Bit Number:
  62.      *
  63.      *     SLOT     A B C D
  64.      *      0       0 4 0 4
  65.      *      1       1 5 1 5
  66.      *      2       2 6 2 6
  67.      *      3       3 7 3 7
  68.      *      4       4 0 4 0
  69.      *      5       5 1 5 1
  70.      *      6       6 2 6 2
  71.      *      7       7 3 7 3
  72.      */
  73.     if (slot < 8) {
  74. if (lines & (PCIIO_INTR_LINE_A| PCIIO_INTR_LINE_C))
  75.     bbits |= 1 << slot;
  76. if (lines & (PCIIO_INTR_LINE_B| PCIIO_INTR_LINE_D))
  77.     bbits |= 1 << (slot ^ 4);
  78.     }
  79.     return bbits;
  80. }
  81. /*
  82.  * Get the next wrapper pointer queued in the interrupt circular buffer.
  83.  */
  84. pcibr_intr_wrap_t
  85. pcibr_wrap_get(pcibr_intr_cbuf_t cbuf)
  86. {
  87.     pcibr_intr_wrap_t wrap;
  88. if (cbuf->ib_in == cbuf->ib_out)
  89.     PRINT_PANIC( "pcibr intr circular buffer empty, cbuf=0x%p, ib_in=ib_out=%dn",
  90. (void *)cbuf, cbuf->ib_out);
  91. wrap = cbuf->ib_cbuf[cbuf->ib_out++];
  92. cbuf->ib_out = cbuf->ib_out % IBUFSIZE;
  93. return(wrap);
  94. }
  95. /* 
  96.  * Queue a wrapper pointer in the interrupt circular buffer.
  97.  */
  98. void
  99. pcibr_wrap_put(pcibr_intr_wrap_t wrap, pcibr_intr_cbuf_t cbuf)
  100. {
  101. int in;
  102. int s;
  103. /*
  104.  * Multiple CPUs could be executing this code simultaneously
  105.  * if a handler has registered multiple interrupt lines and
  106.  * the interrupts are directed to different CPUs.
  107.  */
  108. s = mutex_spinlock(&cbuf->ib_lock);
  109. in = (cbuf->ib_in + 1) % IBUFSIZE;
  110. if (in == cbuf->ib_out) 
  111.     PRINT_PANIC( "pcibr intr circular buffer full, cbuf=0x%p, ib_in=%dn",
  112. (void *)cbuf, cbuf->ib_in);
  113. cbuf->ib_cbuf[cbuf->ib_in] = wrap;
  114. cbuf->ib_in = in;
  115. mutex_spinunlock(&cbuf->ib_lock, s);
  116. return;
  117. }
  118. /*
  119.  * There are end cases where a deadlock can occur if interrupt 
  120.  * processing completes and the Bridge b_int_status bit is still set.
  121.  *
  122.  * One scenerio is if a second PCI interrupt occurs within 60ns of
  123.  * the previous interrupt being cleared. In this case the Bridge
  124.  * does not detect the transition, the Bridge b_int_status bit
  125.  * remains set, and because no transition was detected no interrupt
  126.  * packet is sent to the Hub/Heart.
  127.  *
  128.  * A second scenerio is possible when a b_int_status bit is being
  129.  * shared by multiple devices:
  130.  * Device #1 generates interrupt
  131.  * Bridge b_int_status bit set
  132.  * Device #2 generates interrupt
  133.  * interrupt processing begins
  134.  *   ISR for device #1 runs and
  135.  * clears interrupt
  136.  * Device #1 generates interrupt
  137.  *   ISR for device #2 runs and
  138.  * clears interrupt
  139.  * (b_int_status bit still set)
  140.  * interrupt processing completes
  141.  *   
  142.  * Interrupt processing is now complete, but an interrupt is still
  143.  * outstanding for Device #1. But because there was no transition of
  144.  * the b_int_status bit, no interrupt packet will be generated and
  145.  * a deadlock will occur.
  146.  *
  147.  * To avoid these deadlock situations, this function is used
  148.  * to check if a specific Bridge b_int_status bit is set, and if so,
  149.  * cause the setting of the corresponding interrupt bit.
  150.  *
  151.  * On a XBridge (IP35), we do this by writing the appropriate Bridge Force 
  152.  * Interrupt register.
  153.  */
  154. void
  155. pcibr_force_interrupt(pcibr_intr_wrap_t wrap)
  156. {
  157. unsigned bit;
  158. pcibr_soft_t    pcibr_soft = wrap->iw_soft;
  159. bridge_t       *bridge = pcibr_soft->bs_base;
  160. cpuid_t cpuvertex_to_cpuid(devfs_handle_t vhdl);
  161. bit = wrap->iw_intr;
  162. if (pcibr_soft->bs_xbridge) {
  163.     bridge->b_force_pin[bit].intr = 1;
  164. } else if ((1 << bit) & *wrap->iw_stat) {
  165.     cpuid_t     cpu;
  166.     unsigned        intr_bit;
  167.     xtalk_intr_t    xtalk_intr =
  168. pcibr_soft->bs_intr[bit].bsi_xtalk_intr;
  169.     intr_bit = (short) xtalk_intr_vector_get(xtalk_intr);
  170.     cpu = cpuvertex_to_cpuid(xtalk_intr_cpu_get(xtalk_intr));
  171. #if defined(CONFIG_IA64_SGI_SN1)
  172.     REMOTE_CPU_SEND_INTR(cpu, intr_bit);
  173. #endif
  174. }
  175. }
  176. /*ARGSUSED */
  177. pcibr_intr_t
  178. pcibr_intr_alloc(devfs_handle_t pconn_vhdl,
  179.  device_desc_t dev_desc,
  180.  pciio_intr_line_t lines,
  181.  devfs_handle_t owner_dev)
  182. {
  183.     pcibr_info_t            pcibr_info = pcibr_info_get(pconn_vhdl);
  184.     pciio_slot_t            pciio_slot = pcibr_info->f_slot;
  185.     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast;
  186.     devfs_handle_t            xconn_vhdl = pcibr_soft->bs_conn;
  187.     bridge_t               *bridge = pcibr_soft->bs_base;
  188.     int                     is_threaded = 0;
  189.     int                     thread_swlevel;
  190.     xtalk_intr_t           *xtalk_intr_p;
  191.     pcibr_intr_t           *pcibr_intr_p;
  192.     pcibr_intr_list_t      *intr_list_p;
  193.     unsigned                pcibr_int_bits;
  194.     unsigned                pcibr_int_bit;
  195.     xtalk_intr_t            xtalk_intr = (xtalk_intr_t)0;
  196.     hub_intr_t     hub_intr;
  197.     pcibr_intr_t            pcibr_intr;
  198.     pcibr_intr_list_t       intr_entry;
  199.     pcibr_intr_list_t       intr_list;
  200.     bridgereg_t             int_dev;
  201. #if DEBUG && INTR_DEBUG
  202.     printk("%v: pcibr_intr_allocn"
  203.     "%v:%s%s%s%s%sn",
  204.     owner_dev, pconn_vhdl,
  205.     !(lines & 15) ? " No INTs?" : "",
  206.     lines & 1 ? " INTA" : "",
  207.     lines & 2 ? " INTB" : "",
  208.     lines & 4 ? " INTC" : "",
  209.     lines & 8 ? " INTD" : "");
  210. #endif
  211.     NEW(pcibr_intr);
  212.     if (!pcibr_intr)
  213. return NULL;
  214.     if (dev_desc) {
  215. cpuid_t intr_target_from_desc(device_desc_t, int);
  216.     } else {
  217. extern int default_intr_pri;
  218. is_threaded = 1; /* PCI interrupts are threaded, by default */
  219. thread_swlevel = default_intr_pri;
  220.     }
  221.     pcibr_intr->bi_dev = pconn_vhdl;
  222.     pcibr_intr->bi_lines = lines;
  223.     pcibr_intr->bi_soft = pcibr_soft;
  224.     pcibr_intr->bi_ibits = 0; /* bits will be added below */
  225.     pcibr_intr->bi_flags = is_threaded ? 0 : PCIIO_INTR_NOTHREAD;
  226.     pcibr_intr->bi_mustruncpu = CPU_NONE;
  227.     pcibr_intr->bi_ibuf.ib_in = 0;
  228.     pcibr_intr->bi_ibuf.ib_out = 0;
  229.     mutex_spinlock_init(&pcibr_intr->bi_ibuf.ib_lock);
  230.     pcibr_int_bits = pcibr_soft->bs_intr_bits((pciio_info_t)pcibr_info, lines);
  231.     /*
  232.      * For each PCI interrupt line requested, figure
  233.      * out which Bridge PCI Interrupt Line it maps
  234.      * to, and make sure there are xtalk resources
  235.      * allocated for it.
  236.      */
  237. #if DEBUG && INTR_DEBUG
  238.     printk("pcibr_int_bits: 0x%Xn", pcibr_int_bits);
  239. #endif 
  240.     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit ++) {
  241. if (pcibr_int_bits & (1 << pcibr_int_bit)) {
  242.     xtalk_intr_p = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr;
  243.     xtalk_intr = *xtalk_intr_p;
  244.     if (xtalk_intr == NULL) {
  245. /*
  246.  * This xtalk_intr_alloc is constrained for two reasons:
  247.  * 1) Normal interrupts and error interrupts need to be delivered
  248.  *    through a single xtalk target widget so that there aren't any
  249.  *    ordering problems with DMA, completion interrupts, and error
  250.  *    interrupts. (Use of xconn_vhdl forces this.)
  251.  *
  252.  * 2) On IP35, addressing constraints on IP35 and Bridge force
  253.  *    us to use a single PI number for all interrupts from a
  254.  *    single Bridge. (IP35-specific code forces this, and we
  255.  *    verify in pcibr_setwidint.)
  256.  */
  257. /*
  258.  * All code dealing with threaded PCI interrupt handlers
  259.  * is located at the pcibr level. Because of this,
  260.  * we always want the lower layers (hub/heart_intr_alloc, 
  261.  * intr_level_connect) to treat us as non-threaded so we
  262.  * don't set up a duplicate threaded environment. We make
  263.  * this happen by calling a special xtalk interface.
  264.  */
  265. xtalk_intr = xtalk_intr_alloc_nothd(xconn_vhdl, dev_desc, 
  266. owner_dev);
  267. #if DEBUG && INTR_DEBUG
  268. printk("%v: xtalk_intr=0x%Xn", xconn_vhdl, xtalk_intr);
  269. #endif
  270. /* both an assert and a runtime check on this:
  271.  * we need to check in non-DEBUG kernels, and
  272.  * the ASSERT gets us more information when
  273.  * we use DEBUG kernels.
  274.  */
  275. ASSERT(xtalk_intr != NULL);
  276. if (xtalk_intr == NULL) {
  277.     /* it is quite possible that our
  278.      * xtalk_intr_alloc failed because
  279.      * someone else got there first,
  280.      * and we can find their results
  281.      * in xtalk_intr_p.
  282.      */
  283.     if (!*xtalk_intr_p) {
  284. #ifdef SUPPORT_PRINTING_V_FORMAT
  285. printk(KERN_ALERT  
  286. "pcibr_intr_alloc %v: unable to get xtalk interrupt resources",
  287. xconn_vhdl);
  288. #else
  289. printk(KERN_ALERT  
  290. "pcibr_intr_alloc 0x%p: unable to get xtalk interrupt resources",
  291. (void *)xconn_vhdl);
  292. #endif
  293. /* yes, we leak resources here. */
  294. return 0;
  295.     }
  296. } else if (compare_and_swap_ptr((void **) xtalk_intr_p, NULL, xtalk_intr)) {
  297.     /*
  298.      * now tell the bridge which slot is
  299.      * using this interrupt line.
  300.      */
  301.     int_dev = bridge->b_int_device;
  302.     int_dev &= ~BRIDGE_INT_DEV_MASK(pcibr_int_bit);
  303.     int_dev |= pciio_slot << BRIDGE_INT_DEV_SHFT(pcibr_int_bit);
  304.     bridge->b_int_device = int_dev; /* XXXMP */
  305. #if DEBUG && INTR_DEBUG
  306.     printk("%v: bridge intr bit %d clears my wrbn",
  307.     pconn_vhdl, pcibr_int_bit);
  308. #endif
  309. } else {
  310.     /* someone else got one allocated first;
  311.      * free the one we just created, and
  312.      * retrieve the one they allocated.
  313.      */
  314.     xtalk_intr_free(xtalk_intr);
  315.     xtalk_intr = *xtalk_intr_p;
  316. #if PARANOID
  317.     /* once xtalk_intr is set, we never clear it,
  318.      * so if the CAS fails above, this condition
  319.      * can "never happen" ...
  320.      */
  321.     if (!xtalk_intr) {
  322. printk(KERN_ALERT  
  323. "pcibr_intr_alloc %v: unable to set xtalk interrupt resources",
  324. xconn_vhdl);
  325. /* yes, we leak resources here. */
  326. return 0;
  327.     }
  328. #endif
  329. }
  330.     }
  331.     pcibr_intr->bi_ibits |= 1 << pcibr_int_bit;
  332.     NEW(intr_entry);
  333.     intr_entry->il_next = NULL;
  334.     intr_entry->il_intr = pcibr_intr;
  335.     intr_entry->il_wrbf = &(bridge->b_wr_req_buf[pciio_slot].reg);
  336.     intr_list_p = 
  337. &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_list;
  338. #if DEBUG && INTR_DEBUG
  339. #if defined(SUPPORT_PRINTING_V_FORMAT)
  340.     printk("0x%x: Bridge bit %d wrap=0x%xn",
  341. pconn_vhdl, pcibr_int_bit,
  342. pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap);
  343. #else
  344.     printk("%v: Bridge bit %d wrap=0x%xn",
  345. pconn_vhdl, pcibr_int_bit,
  346. pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap);
  347. #endif
  348. #endif
  349.     if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {
  350. /* we are the first interrupt on this bridge bit.
  351.  */
  352. #if DEBUG && INTR_DEBUG
  353. printk("%v INT 0x%x (bridge bit %d) allocated [FIRST]n",
  354. pconn_vhdl, pcibr_int_bits, pcibr_int_bit);
  355. #endif
  356. continue;
  357.     }
  358.     intr_list = *intr_list_p;
  359.     pcibr_intr_p = &intr_list->il_intr;
  360.     if (compare_and_swap_ptr((void **) pcibr_intr_p, NULL, pcibr_intr)) {
  361. /* first entry on list was erased,
  362.  * and we replaced it, so we
  363.  * don't need our intr_entry.
  364.  */
  365. DEL(intr_entry);
  366. #if DEBUG && INTR_DEBUG
  367. printk("%v INT 0x%x (bridge bit %d) replaces erased firstn",
  368. pconn_vhdl, pcibr_int_bits, pcibr_int_bit);
  369. #endif
  370. continue;
  371.     }
  372.     intr_list_p = &intr_list->il_next;
  373.     if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {
  374. /* we are the new second interrupt on this bit.
  375.  */
  376. pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared = 1;
  377. #if DEBUG && INTR_DEBUG
  378. printk("%v INT 0x%x (bridge bit %d) is new SECONDn",
  379. pconn_vhdl, pcibr_int_bits, pcibr_int_bit);
  380. #endif
  381. continue;
  382.     }
  383.     while (1) {
  384. pcibr_intr_p = &intr_list->il_intr;
  385. if (compare_and_swap_ptr((void **) pcibr_intr_p, NULL, pcibr_intr)) {
  386.     /* an entry on list was erased,
  387.      * and we replaced it, so we
  388.      * don't need our intr_entry.
  389.      */
  390.     DEL(intr_entry);
  391. #if DEBUG && INTR_DEBUG
  392.     printk("%v INT 0x%x (bridge bit %d) replaces erased Nthn",
  393.     pconn_vhdl, pcibr_int_bits, pcibr_int_bit);
  394. #endif
  395.     break;
  396. }
  397. intr_list_p = &intr_list->il_next;
  398. if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {
  399.     /* entry appended to share list
  400.      */
  401. #if DEBUG && INTR_DEBUG
  402.     printk("%v INT 0x%x (bridge bit %d) is new Nthn",
  403.     pconn_vhdl, pcibr_int_bits, pcibr_int_bit);
  404. #endif
  405.     break;
  406. }
  407. /* step to next record in chain
  408.  */
  409. intr_list = *intr_list_p;
  410.     }
  411. }
  412.     }
  413. #if DEBUG && INTR_DEBUG
  414.     printk("%v pcibr_intr_alloc completen", pconn_vhdl);
  415. #endif
  416.     hub_intr = (hub_intr_t)xtalk_intr;
  417.     pcibr_intr->bi_irq = hub_intr->i_bit;
  418.     pcibr_intr->bi_cpu = hub_intr->i_cpuid;
  419.     return pcibr_intr;
  420. }
  421. /*ARGSUSED */
  422. void
  423. pcibr_intr_free(pcibr_intr_t pcibr_intr)
  424. {
  425.     unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;
  426.     pcibr_soft_t            pcibr_soft = pcibr_intr->bi_soft;
  427.     unsigned                pcibr_int_bit;
  428.     pcibr_intr_list_t       intr_list;
  429.     int     intr_shared;
  430.     xtalk_intr_t     *xtalk_intrp;
  431.     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++) {
  432. if (pcibr_int_bits & (1 << pcibr_int_bit)) {
  433.     for (intr_list = 
  434.      pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_list;
  435.  intr_list != NULL;
  436.  intr_list = intr_list->il_next)
  437. if (compare_and_swap_ptr((void **) &intr_list->il_intr, 
  438.  pcibr_intr, 
  439.  NULL)) {
  440. #if DEBUG && INTR_DEBUG
  441.     printk("%s: cleared a handler from bit %dn",
  442.     pcibr_soft->bs_name, pcibr_int_bit);
  443. #endif
  444. }
  445.     /* If this interrupt line is not being shared between multiple
  446.      * devices release the xtalk interrupt resources.
  447.      */
  448.     intr_shared = 
  449. pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared;
  450.     xtalk_intrp = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr;
  451.     if ((!intr_shared) && (*xtalk_intrp)) {
  452. bridge_t  *bridge = pcibr_soft->bs_base;
  453. bridgereg_t int_dev;
  454. xtalk_intr_free(*xtalk_intrp);
  455. *xtalk_intrp = 0;
  456. /* Clear the PCI device interrupt to bridge interrupt pin
  457.  * mapping.
  458.  */
  459. int_dev = bridge->b_int_device;
  460. int_dev &= ~BRIDGE_INT_DEV_MASK(pcibr_int_bit);
  461. bridge->b_int_device = int_dev;
  462.     }
  463. }
  464.     }
  465.     DEL(pcibr_intr);
  466. }
  467. void
  468. pcibr_setpciint(xtalk_intr_t xtalk_intr)
  469. {
  470.     iopaddr_t               addr = xtalk_intr_addr_get(xtalk_intr);
  471.     xtalk_intr_vector_t     vect = xtalk_intr_vector_get(xtalk_intr);
  472.     bridgereg_t            *int_addr = (bridgereg_t *)
  473.     xtalk_intr_sfarg_get(xtalk_intr);
  474.     *int_addr = ((BRIDGE_INT_ADDR_HOST & (addr >> 30)) |
  475.  (BRIDGE_INT_ADDR_FLD & vect));
  476. }
  477. /*ARGSUSED */
  478. int
  479. pcibr_intr_connect(pcibr_intr_t pcibr_intr)
  480. {
  481.     pcibr_soft_t            pcibr_soft = pcibr_intr->bi_soft;
  482.     bridge_t               *bridge = pcibr_soft->bs_base;
  483.     unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;
  484.     unsigned                pcibr_int_bit;
  485.     bridgereg_t             b_int_enable;
  486.     unsigned long           s;
  487.     if (pcibr_intr == NULL)
  488. return -1;
  489. #if DEBUG && INTR_DEBUG
  490.     printk("%v: pcibr_intr_connectn",
  491.     pcibr_intr->bi_dev);
  492. #endif
  493.     *((volatile unsigned *)&pcibr_intr->bi_flags) |= PCIIO_INTR_CONNECTED;
  494.     /*
  495.      * For each PCI interrupt line requested, figure
  496.      * out which Bridge PCI Interrupt Line it maps
  497.      * to, and make sure there are xtalk resources
  498.      * allocated for it.
  499.      */
  500.     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)
  501. if (pcibr_int_bits & (1 << pcibr_int_bit)) {
  502.     xtalk_intr_t            xtalk_intr;
  503.     xtalk_intr = pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr;
  504.     /*
  505.      * If this interrupt line is being shared and the connect has
  506.      * already been done, no need to do it again.
  507.      */
  508.     if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected)
  509. continue;
  510.     /*
  511.      * Use the pcibr wrapper function to handle all Bridge interrupts
  512.      * regardless of whether the interrupt line is shared or not.
  513.      */
  514.     xtalk_intr_connect(xtalk_intr, (xtalk_intr_setfunc_t) pcibr_setpciint,
  515.        (void *)&(bridge->b_int_addr[pcibr_int_bit].addr));
  516.     pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected = 1;
  517. #if DEBUG && INTR_DEBUG
  518.     printk("%v bridge bit %d wrapper connectedn",
  519.     pcibr_intr->bi_dev, pcibr_int_bit);
  520. #endif
  521. }
  522.     s = pcibr_lock(pcibr_soft);
  523.     b_int_enable = bridge->b_int_enable;
  524.     b_int_enable |= pcibr_int_bits;
  525.     bridge->b_int_enable = b_int_enable;
  526.     bridge->b_wid_tflush; /* wait until Bridge PIO complete */
  527.     pcibr_unlock(pcibr_soft, s);
  528.     return 0;
  529. }
  530. /*ARGSUSED */
  531. void
  532. pcibr_intr_disconnect(pcibr_intr_t pcibr_intr)
  533. {
  534.     pcibr_soft_t            pcibr_soft = pcibr_intr->bi_soft;
  535.     bridge_t               *bridge = pcibr_soft->bs_base;
  536.     unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;
  537.     unsigned                pcibr_int_bit;
  538.     bridgereg_t             b_int_enable;
  539.     unsigned long           s;
  540.     /* Stop calling the function. Now.
  541.      */
  542.     *((volatile unsigned *)&pcibr_intr->bi_flags) &= ~PCIIO_INTR_CONNECTED;
  543.     /*
  544.      * For each PCI interrupt line requested, figure
  545.      * out which Bridge PCI Interrupt Line it maps
  546.      * to, and disconnect the interrupt.
  547.      */
  548.     /* don't disable interrupts for lines that
  549.      * are shared between devices.
  550.      */
  551.     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)
  552. if ((pcibr_int_bits & (1 << pcibr_int_bit)) &&
  553.     (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared))
  554.     pcibr_int_bits &= ~(1 << pcibr_int_bit);
  555.     if (!pcibr_int_bits)
  556. return;
  557.     s = pcibr_lock(pcibr_soft);
  558.     b_int_enable = bridge->b_int_enable;
  559.     b_int_enable &= ~pcibr_int_bits;
  560.     bridge->b_int_enable = b_int_enable;
  561.     bridge->b_wid_tflush; /* wait until Bridge PIO complete */
  562.     pcibr_unlock(pcibr_soft, s);
  563.     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)
  564. if (pcibr_int_bits & (1 << pcibr_int_bit)) {
  565.     /* if the interrupt line is now shared,
  566.      * do not disconnect it.
  567.      */
  568.     if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared)
  569. continue;
  570.     xtalk_intr_disconnect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr);
  571.     pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected = 0;
  572. #if DEBUG && INTR_DEBUG
  573.     printk("%s: xtalk disconnect done for Bridge bit %dn",
  574. pcibr_soft->bs_name, pcibr_int_bit);
  575. #endif
  576.     /* if we are sharing the interrupt line,
  577.      * connect us up; this closes the hole
  578.      * where the another pcibr_intr_alloc()
  579.      * was in progress as we disconnected.
  580.      */
  581.     if (!pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared)
  582. continue;
  583.     xtalk_intr_connect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr,
  584.        (xtalk_intr_setfunc_t)pcibr_setpciint,
  585.        (void *) &(bridge->b_int_addr[pcibr_int_bit].addr));
  586. }
  587. }
  588. /*ARGSUSED */
  589. devfs_handle_t
  590. pcibr_intr_cpu_get(pcibr_intr_t pcibr_intr)
  591. {
  592.     pcibr_soft_t            pcibr_soft = pcibr_intr->bi_soft;
  593.     unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;
  594.     unsigned                pcibr_int_bit;
  595.     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)
  596. if (pcibr_int_bits & (1 << pcibr_int_bit))
  597.     return xtalk_intr_cpu_get(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr);
  598.     return 0;
  599. }
  600. /* =====================================================================
  601.  *    INTERRUPT HANDLING
  602.  */
  603. void
  604. pcibr_clearwidint(bridge_t *bridge)
  605. {
  606.     bridge->b_wid_int_upper = 0;
  607.     bridge->b_wid_int_lower = 0;
  608. }
  609. void
  610. pcibr_setwidint(xtalk_intr_t intr)
  611. {
  612.     xwidgetnum_t            targ = xtalk_intr_target_get(intr);
  613.     iopaddr_t               addr = xtalk_intr_addr_get(intr);
  614.     xtalk_intr_vector_t     vect = xtalk_intr_vector_get(intr);
  615.     widgetreg_t     NEW_b_wid_int_upper, NEW_b_wid_int_lower;
  616.     widgetreg_t     OLD_b_wid_int_upper, OLD_b_wid_int_lower;
  617.     bridge_t               *bridge = (bridge_t *)xtalk_intr_sfarg_get(intr);
  618.     NEW_b_wid_int_upper = ( (0x000F0000 & (targ << 16)) |
  619.        XTALK_ADDR_TO_UPPER(addr));
  620.     NEW_b_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);
  621.     OLD_b_wid_int_upper = bridge->b_wid_int_upper;
  622.     OLD_b_wid_int_lower = bridge->b_wid_int_lower;
  623.     /* Verify that all interrupts from this Bridge are using a single PI */
  624.     if ((OLD_b_wid_int_upper != 0) && (OLD_b_wid_int_lower != 0)) {
  625. /*
  626.  * Once set, these registers shouldn't change; they should
  627.  * be set multiple times with the same values.
  628.  *
  629.  * If we're attempting to change these registers, it means
  630.  * that our heuristics for allocating interrupts in a way
  631.  * appropriate for IP35 have failed, and the admin needs to
  632.  * explicitly direct some interrupts (or we need to make the
  633.  * heuristics more clever).
  634.  *
  635.  * In practice, we hope this doesn't happen very often, if
  636.  * at all.
  637.  */
  638. if ((OLD_b_wid_int_upper != NEW_b_wid_int_upper) ||
  639.     (OLD_b_wid_int_lower != NEW_b_wid_int_lower)) {
  640. printk(KERN_WARNING  "Interrupt allocation is too complex.n");
  641. printk(KERN_WARNING  "Use explicit administrative interrupt targetting.n");
  642. printk(KERN_WARNING  "bridge=0x%lx targ=0x%xn", (unsigned long)bridge, targ);
  643. printk(KERN_WARNING  "NEW=0x%x/0x%x  OLD=0x%x/0x%xn",
  644. NEW_b_wid_int_upper, NEW_b_wid_int_lower,
  645. OLD_b_wid_int_upper, OLD_b_wid_int_lower);
  646. PRINT_PANIC("PCI Bridge interrupt targetting errorn");
  647. }
  648.     }
  649.     bridge->b_wid_int_upper = NEW_b_wid_int_upper;
  650.     bridge->b_wid_int_lower = NEW_b_wid_int_lower;
  651.     bridge->b_int_host_err = vect;
  652. }
  653. /*
  654.  * pcibr_intr_preset: called during mlreset time
  655.  * if the platform specific code needs to route
  656.  * one of the Bridge's xtalk interrupts before the
  657.  * xtalk infrastructure is available.
  658.  */
  659. void
  660. pcibr_xintr_preset(void *which_widget,
  661.    int which_widget_intr,
  662.    xwidgetnum_t targ,
  663.    iopaddr_t addr,
  664.    xtalk_intr_vector_t vect)
  665. {
  666.     bridge_t               *bridge = (bridge_t *) which_widget;
  667.     if (which_widget_intr == -1) {
  668. /* bridge widget error interrupt */
  669. bridge->b_wid_int_upper = ( (0x000F0000 & (targ << 16)) |
  670.    XTALK_ADDR_TO_UPPER(addr));
  671. bridge->b_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);
  672. bridge->b_int_host_err = vect;
  673. /* turn on all interrupts except
  674.  * the PCI interrupt requests,
  675.  * at least at heart.
  676.  */
  677. bridge->b_int_enable |= ~BRIDGE_IMR_INT_MSK;
  678.     } else {
  679. /* routing a PCI device interrupt.
  680.  * targ and low 38 bits of addr must
  681.  * be the same as the already set
  682.  * value for the widget error interrupt.
  683.  */
  684. bridge->b_int_addr[which_widget_intr].addr =
  685.     ((BRIDGE_INT_ADDR_HOST & (addr >> 30)) |
  686.      (BRIDGE_INT_ADDR_FLD & vect));
  687. /*
  688.  * now bridge can let it through;
  689.  * NB: still should be blocked at
  690.  * xtalk provider end, until the service
  691.  * function is set.
  692.  */
  693. bridge->b_int_enable |= 1 << vect;
  694.     }
  695.     bridge->b_wid_tflush; /* wait until Bridge PIO complete */
  696. }
  697. /*
  698.  * pcibr_intr_func()
  699.  *
  700.  * This is the pcibr interrupt "wrapper" function that is called,
  701.  * in interrupt context, to initiate the interrupt handler(s) registered
  702.  * (via pcibr_intr_alloc/connect) for the occuring interrupt. Non-threaded 
  703.  * handlers will be called directly, and threaded handlers will have their 
  704.  * thread woken up.
  705.  */
  706. void
  707. pcibr_intr_func(intr_arg_t arg)
  708. {
  709.     pcibr_intr_wrap_t       wrap = (pcibr_intr_wrap_t) arg;
  710.     reg_p                   wrbf;
  711.     pcibr_intr_t            intr;
  712.     pcibr_intr_list_t       list;
  713.     int                     clearit;
  714.     int     do_nonthreaded = 1;
  715.     int     is_threaded = 0;
  716.     int     x = 0;
  717. /*
  718.  * If any handler is still running from a previous interrupt
  719.  * just return. If there's a need to call the handler(s) again,
  720.  * another interrupt will be generated either by the device or by
  721.  * pcibr_force_interrupt().
  722.  */
  723. if (wrap->iw_hdlrcnt) {
  724. return;
  725. }
  726.     /*
  727.      * Call all interrupt handlers registered.
  728.      * First, the pcibr_intrd threads for any threaded handlers will be
  729.      * awoken, then any non-threaded handlers will be called sequentially.
  730.      */
  731. clearit = 1;
  732. while (do_nonthreaded) {
  733.     for (list = wrap->iw_list; list != NULL; list = list->il_next) {
  734. if ((intr = list->il_intr) &&
  735.     (intr->bi_flags & PCIIO_INTR_CONNECTED)) {
  736. /*
  737.  * This device may have initiated write
  738.  * requests since the bridge last saw
  739.  * an edge on this interrupt input; flushing
  740.  * the buffer prior to invoking the handler
  741.  * should help but may not be sufficient if we 
  742.  * get more requests after the flush, followed
  743.  * by the card deciding it wants service, before
  744.  * the interrupt handler checks to see if things need
  745.  * to be done.
  746.  *
  747.  * There is a similar race condition if
  748.  * an interrupt handler loops around and
  749.  * notices further service is required.
  750.  * Perhaps we need to have an explicit
  751.  * call that interrupt handlers need to
  752.  * do between noticing that DMA to memory
  753.  * has completed, but before observing the
  754.  * contents of memory?
  755.  */
  756. if ((do_nonthreaded) && (!is_threaded)) {
  757. /* Non-threaded. 
  758.  * Call the interrupt handler at interrupt level
  759.  */
  760. /* Only need to flush write buffers if sharing */
  761. if ((wrap->iw_shared) && (wrbf = list->il_wrbf)) {
  762.     if ((x = *wrbf)) /* write request buffer flush */
  763. #ifdef SUPPORT_PRINTING_V_FORMAT
  764. printk(KERN_ALERT  "pcibr_intr_func %v: n"
  765.     "write buffer flush failed, wrbf=0x%xn", 
  766.     list->il_intr->bi_dev, wrbf);
  767. #else
  768. printk(KERN_ALERT  "pcibr_intr_func %p: n"
  769.     "write buffer flush failed, wrbf=0x%lxn", 
  770.     (void *)list->il_intr->bi_dev, (long) wrbf);
  771. #endif
  772. }
  773.     }
  774.     clearit = 0;
  775. }
  776.     }
  777. do_nonthreaded = 0;
  778. /*
  779.  * If the non-threaded handler was the last to complete,
  780.  * (i.e., no threaded handlers still running) force an
  781.  * interrupt to avoid a potential deadlock situation.
  782.  */
  783. if (wrap->iw_hdlrcnt == 0) {
  784. pcibr_force_interrupt(wrap);
  785. }
  786. }
  787. /* If there were no handlers,
  788.  * disable the interrupt and return.
  789.  * It will get enabled again after
  790.  * a handler is connected.
  791.  * If we don't do this, we would
  792.  * sit here and spin through the
  793.  * list forever.
  794.  */
  795. if (clearit) {
  796.     pcibr_soft_t            pcibr_soft = wrap->iw_soft;
  797.     bridge_t               *bridge = pcibr_soft->bs_base;
  798.     bridgereg_t             b_int_enable;
  799.     bridgereg_t     mask = 1 << wrap->iw_intr;
  800.     unsigned long           s;
  801.     s = pcibr_lock(pcibr_soft);
  802.     b_int_enable = bridge->b_int_enable;
  803.     b_int_enable &= ~mask;
  804.     bridge->b_int_enable = b_int_enable;
  805.     bridge->b_wid_tflush; /* wait until Bridge PIO complete */
  806.     pcibr_unlock(pcibr_soft, s);
  807.     return;
  808. }
  809. }