io.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:35k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id$
  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) 1992 - 1997, 2000 Silicon Graphics, Inc.
  8.  * Copyright (C) 2000 by Colin Ngam
  9.  */
  10. #include <linux/types.h>
  11. #include <linux/config.h>
  12. #include <linux/slab.h>
  13. #include <asm/sn/types.h>
  14. #include <asm/sn/sgi.h>
  15. #include <asm/sn/iobus.h>
  16. #include <asm/sn/iograph.h>
  17. #include <asm/param.h>
  18. #include <asm/sn/pio.h>
  19. #include <asm/sn/xtalk/xwidget.h>
  20. #include <asm/sn/sn_private.h>
  21. #include <asm/sn/addrs.h>
  22. #include <asm/sn/invent.h>
  23. #include <asm/sn/hcl.h>
  24. #include <asm/sn/hcl_util.h>
  25. #include <asm/sn/agent.h>
  26. #include <asm/sn/intr.h>
  27. #include <asm/sn/xtalk/xtalkaddrs.h>
  28. #include <asm/sn/klconfig.h>
  29. #include <asm/sn/io.h>
  30. #include <asm/sn/sn_cpuid.h>
  31. extern xtalk_provider_t hub_provider;
  32. /*
  33.  * Perform any initializations needed to support hub-based I/O.
  34.  * Called once during startup.
  35.  */
  36. void
  37. hubio_init(void)
  38. {
  39. #ifdef LATER
  40. /* This isn't needed unless we port the entire sio driver ... */
  41.         extern void early_brl1_port_init( void );
  42. early_brl1_port_init();
  43. #endif
  44. }
  45. /* 
  46.  * Implementation of hub iobus operations.
  47.  *
  48.  * Hub provides a crosstalk "iobus" on IP27 systems.  These routines
  49.  * provide a platform-specific implementation of xtalk used by all xtalk 
  50.  * cards on IP27 systems.
  51.  *
  52.  * Called from corresponding xtalk_* routines.
  53.  */
  54. /* PIO MANAGEMENT */
  55. /* For mapping system virtual address space to xtalk space on a specified widget */
  56. /*
  57.  * Setup pio structures needed for a particular hub.
  58.  */
  59. static void
  60. hub_pio_init(devfs_handle_t hubv)
  61. {
  62. xwidgetnum_t widget;
  63. hubinfo_t hubinfo;
  64. nasid_t nasid;
  65. int bigwin;
  66. hub_piomap_t hub_piomap;
  67. hubinfo_get(hubv, &hubinfo);
  68. nasid = hubinfo->h_nasid;
  69. /* Initialize small window piomaps for this hub */
  70. for (widget=0; widget <= HUB_WIDGET_ID_MAX; widget++) {
  71. hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
  72. hub_piomap->hpio_xtalk_info.xp_target = widget;
  73. hub_piomap->hpio_xtalk_info.xp_xtalk_addr = 0;
  74. hub_piomap->hpio_xtalk_info.xp_mapsz = SWIN_SIZE;
  75. hub_piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)NODE_SWIN_BASE(nasid, widget);
  76. hub_piomap->hpio_hub = hubv;
  77. hub_piomap->hpio_flags = HUB_PIOMAP_IS_VALID;
  78. }
  79. /* Initialize big window piomaps for this hub */
  80. for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
  81. hub_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin);
  82. hub_piomap->hpio_xtalk_info.xp_mapsz = BWIN_SIZE;
  83. hub_piomap->hpio_hub = hubv;
  84. hub_piomap->hpio_holdcnt = 0;
  85. hub_piomap->hpio_flags = HUB_PIOMAP_IS_BIGWINDOW;
  86. IIO_ITTE_DISABLE(nasid, bigwin);
  87. }
  88. hub_set_piomode(nasid, HUB_PIO_CONVEYOR);
  89. mutex_spinlock_init(&hubinfo->h_bwlock);
  90. /*
  91.  * If this lock can be acquired from interrupts or bh's, add SV_INTS or SV_BHS,
  92.  * respectively, to the flags here.
  93.  */
  94. sv_init(&hubinfo->h_bwwait, &hubinfo->h_bwlock, SV_ORDER_FIFO | SV_MON_SPIN); 
  95. }
  96. /* 
  97.  * Create a caddr_t-to-xtalk_addr mapping.
  98.  *
  99.  * Use a small window if possible (that's the usual case), but
  100.  * manage big windows if needed.  Big window mappings can be
  101.  * either FIXED or UNFIXED -- we keep at least 1 big window available
  102.  * for UNFIXED mappings.
  103.  *
  104.  * Returns an opaque pointer-sized type which can be passed to
  105.  * other hub_pio_* routines on success, or NULL if the request
  106.  * cannot be satisfied.
  107.  */
  108. /* ARGSUSED */
  109. hub_piomap_t
  110. hub_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */
  111. device_desc_t dev_desc, /* device descriptor */
  112. iopaddr_t xtalk_addr, /* map for this xtalk_addr range */
  113. size_t byte_count,
  114. size_t byte_count_max,  /* maximum size of a mapping */
  115. unsigned flags) /* defined in sys/pio.h */
  116. {
  117. xwidget_info_t widget_info = xwidget_info_get(dev);
  118. xwidgetnum_t widget = xwidget_info_id_get(widget_info);
  119. devfs_handle_t hubv = xwidget_info_master_get(widget_info);
  120. hubinfo_t hubinfo;
  121. hub_piomap_t bw_piomap;
  122. int bigwin, free_bw_index;
  123. nasid_t nasid;
  124. volatile hubreg_t junk;
  125. unsigned long s;
  126. /* sanity check */
  127. if (byte_count_max > byte_count)
  128. return(NULL);
  129. hubinfo_get(hubv, &hubinfo);
  130. /* If xtalk_addr range is mapped by a small window, we don't have 
  131.  * to do much 
  132.  */
  133. if (xtalk_addr + byte_count <= SWIN_SIZE)
  134. return(hubinfo_swin_piomap_get(hubinfo, (int)widget));
  135. /* We need to use a big window mapping.  */
  136. /*
  137.  * TBD: Allow requests that would consume multiple big windows --
  138.  * split the request up and use multiple mapping entries.
  139.  * For now, reject requests that span big windows.
  140.  */
  141. if ((xtalk_addr % BWIN_SIZE) + byte_count > BWIN_SIZE)
  142. return(NULL);
  143. /* Round xtalk address down for big window alignement */
  144. xtalk_addr = xtalk_addr & ~(BWIN_SIZE-1);
  145. /*
  146.  * Check to see if an existing big window mapping will suffice.
  147.  */
  148. tryagain:
  149. free_bw_index = -1;
  150. s = mutex_spinlock(&hubinfo->h_bwlock);
  151. for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
  152. bw_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin);
  153. /* If mapping is not valid, skip it */
  154. if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_VALID)) {
  155. free_bw_index = bigwin;
  156. continue;
  157. }
  158. /* 
  159.  * If mapping is UNFIXED, skip it.  We don't allow sharing
  160.  * of UNFIXED mappings, because this would allow starvation.
  161.  */
  162. if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED))
  163. continue;
  164. if ( xtalk_addr == bw_piomap->hpio_xtalk_info.xp_xtalk_addr &&
  165.      widget == bw_piomap->hpio_xtalk_info.xp_target) {
  166. bw_piomap->hpio_holdcnt++;
  167. mutex_spinunlock(&hubinfo->h_bwlock, s);
  168. return(bw_piomap);
  169. }
  170. }
  171. /*
  172.  * None of the existing big window mappings will work for us --
  173.  * we need to establish a new mapping.
  174.  */
  175. /* Insure that we don't consume all big windows with FIXED mappings */
  176. if (flags & PIOMAP_FIXED) {
  177. if (hubinfo->h_num_big_window_fixed < HUB_NUM_BIG_WINDOW-1) {
  178. ASSERT(free_bw_index >= 0);
  179. hubinfo->h_num_big_window_fixed++;
  180. } else {
  181. bw_piomap = NULL;
  182. goto done;
  183. }
  184. } else /* PIOMAP_UNFIXED */ {
  185. if (free_bw_index < 0) {
  186. if (flags & PIOMAP_NOSLEEP) {
  187. bw_piomap = NULL;
  188. goto done;
  189. }
  190. sv_wait(&hubinfo->h_bwwait, 0, 0);
  191. goto tryagain;
  192. }
  193. }
  194. /* OK!  Allocate big window free_bw_index for this mapping. */
  195.   /* 
  196.  * The code below does a PIO write to setup an ITTE entry.
  197.  * We need to prevent other CPUs from seeing our updated memory 
  198.  * shadow of the ITTE (in the piomap) until the ITTE entry is 
  199.  * actually set up; otherwise, another CPU might attempt a PIO 
  200.  * prematurely.  
  201.  *
  202.  * Also, the only way we can know that an entry has been received 
  203.  * by the hub and can be used by future PIO reads/writes is by 
  204.  * reading back the ITTE entry after writing it.
  205.  *
  206.  * For these two reasons, we PIO read back the ITTE entry after
  207.  * we write it.
  208.  */
  209. nasid = hubinfo->h_nasid;
  210. IIO_ITTE_PUT(nasid, free_bw_index, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
  211. junk = HUB_L(IIO_ITTE_GET(nasid, free_bw_index));
  212. bw_piomap = hubinfo_bwin_piomap_get(hubinfo, free_bw_index);
  213. bw_piomap->hpio_xtalk_info.xp_dev = dev;
  214. bw_piomap->hpio_xtalk_info.xp_target = widget;
  215. bw_piomap->hpio_xtalk_info.xp_xtalk_addr = xtalk_addr;
  216. bw_piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)NODE_BWIN_BASE(nasid, free_bw_index);
  217. bw_piomap->hpio_holdcnt++;
  218. bw_piomap->hpio_bigwin_num = free_bw_index;
  219. if (flags & PIOMAP_FIXED)
  220. bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED;
  221. else
  222. bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID;
  223. done:
  224. mutex_spinunlock(&hubinfo->h_bwlock, s);
  225. return(bw_piomap);
  226. }
  227. /*
  228.  * hub_piomap_free destroys a caddr_t-to-xtalk pio mapping and frees
  229.  * any associated mapping resources.  
  230.  *
  231.  * If this * piomap was handled with a small window, or if it was handled
  232.  * in a big window that's still in use by someone else, then there's 
  233.  * nothing to do.  On the other hand, if this mapping was handled 
  234.  * with a big window, AND if we were the final user of that mapping, 
  235.  * then destroy the mapping.
  236.  */
  237. void
  238. hub_piomap_free(hub_piomap_t hub_piomap)
  239. {
  240. devfs_handle_t hubv;
  241. hubinfo_t hubinfo;
  242. nasid_t nasid;
  243. unsigned long s;
  244. /* 
  245.  * Small windows are permanently mapped to corresponding widgets,
  246.  * so there're no resources to free.
  247.  */
  248. if (!(hub_piomap->hpio_flags & HUB_PIOMAP_IS_BIGWINDOW))
  249. return;
  250. ASSERT(hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID);
  251. ASSERT(hub_piomap->hpio_holdcnt > 0);
  252. hubv = hub_piomap->hpio_hub;
  253. hubinfo_get(hubv, &hubinfo);
  254. nasid = hubinfo->h_nasid;
  255. s = mutex_spinlock(&hubinfo->h_bwlock);
  256. /*
  257.  * If this is the last hold on this mapping, free it.
  258.  */
  259. if (--hub_piomap->hpio_holdcnt == 0) {
  260. IIO_ITTE_DISABLE(nasid, hub_piomap->hpio_bigwin_num );
  261. if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED) {
  262. hub_piomap->hpio_flags &= ~(HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED);
  263. hubinfo->h_num_big_window_fixed--;
  264. ASSERT(hubinfo->h_num_big_window_fixed >= 0);
  265. } else
  266. hub_piomap->hpio_flags &= ~HUB_PIOMAP_IS_VALID;
  267. (void)sv_signal(&hubinfo->h_bwwait);
  268. }
  269. mutex_spinunlock(&hubinfo->h_bwlock, s);
  270. }
  271. /*
  272.  * Establish a mapping to a given xtalk address range using the resources
  273.  * allocated earlier.
  274.  */
  275. caddr_t
  276. hub_piomap_addr(hub_piomap_t hub_piomap, /* mapping resources */
  277. iopaddr_t xtalk_addr, /* map for this xtalk address */
  278. size_t byte_count) /* map this many bytes */
  279. {
  280. /* Verify that range can be mapped using the specified piomap */
  281. if (xtalk_addr < hub_piomap->hpio_xtalk_info.xp_xtalk_addr)
  282. return(0);
  283. if (xtalk_addr + byte_count > 
  284. ( hub_piomap->hpio_xtalk_info.xp_xtalk_addr + 
  285. hub_piomap->hpio_xtalk_info.xp_mapsz))
  286. return(0);
  287. if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID)
  288. return(hub_piomap->hpio_xtalk_info.xp_kvaddr + 
  289. (xtalk_addr % hub_piomap->hpio_xtalk_info.xp_mapsz));
  290. else
  291. return(0);
  292. }
  293. /*
  294.  * Driver indicates that it's done with PIO's from an earlier piomap_addr.
  295.  */
  296. /* ARGSUSED */
  297. void
  298. hub_piomap_done(hub_piomap_t hub_piomap) /* done with these mapping resources */
  299. {
  300. /* Nothing to do */
  301. }
  302. /*
  303.  * For translations that require no mapping resources, supply a kernel virtual
  304.  * address that maps to the specified xtalk address range.
  305.  */
  306. /* ARGSUSED */
  307. caddr_t
  308. hub_piotrans_addr( devfs_handle_t dev, /* translate to this device */
  309. device_desc_t dev_desc, /* device descriptor */
  310. iopaddr_t xtalk_addr, /* Crosstalk address */
  311. size_t byte_count, /* map this many bytes */
  312. unsigned flags) /* (currently unused) */
  313. {
  314. xwidget_info_t widget_info = xwidget_info_get(dev);
  315. xwidgetnum_t widget = xwidget_info_id_get(widget_info);
  316. devfs_handle_t hubv = xwidget_info_master_get(widget_info);
  317. hub_piomap_t hub_piomap;
  318. hubinfo_t hubinfo;
  319. hubinfo_get(hubv, &hubinfo);
  320. if (xtalk_addr + byte_count <= SWIN_SIZE) {
  321. hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
  322. return(hub_piomap_addr(hub_piomap, xtalk_addr, byte_count));
  323. } else
  324. return(0);
  325. }
  326. /* DMA MANAGEMENT */
  327. /* Mapping from crosstalk space to system physical space */
  328. /* 
  329.  * There's not really very much to do here, since crosstalk maps
  330.  * directly to system physical space.  It's quite possible that this
  331.  * DMA layer will be bypassed in performance kernels.
  332.  */
  333. /* ARGSUSED */
  334. static void
  335. hub_dma_init(devfs_handle_t hubv)
  336. {
  337. }
  338. /*
  339.  * Allocate resources needed to set up DMA mappings up to a specified size
  340.  * on a specified adapter.
  341.  * 
  342.  * We don't actually use the adapter ID for anything.  It's just the adapter
  343.  * that the lower level driver plans to use for DMA.
  344.  */
  345. /* ARGSUSED */
  346. hub_dmamap_t
  347. hub_dmamap_alloc( devfs_handle_t dev, /* set up mappings for this device */
  348. device_desc_t dev_desc, /* device descriptor */
  349. size_t byte_count_max,  /* max size of a mapping */
  350. unsigned flags) /* defined in dma.h */
  351. {
  352. hub_dmamap_t dmamap;
  353. xwidget_info_t widget_info = xwidget_info_get(dev);
  354. xwidgetnum_t widget = xwidget_info_id_get(widget_info);
  355. devfs_handle_t hubv = xwidget_info_master_get(widget_info);
  356. dmamap = kern_malloc(sizeof(struct hub_dmamap_s));
  357. dmamap->hdma_xtalk_info.xd_dev = dev;
  358. dmamap->hdma_xtalk_info.xd_target = widget;
  359. dmamap->hdma_hub = hubv;
  360. dmamap->hdma_flags = HUB_DMAMAP_IS_VALID;
  361.   if (flags & XTALK_FIXED)
  362. dmamap->hdma_flags |= HUB_DMAMAP_IS_FIXED;
  363. return(dmamap);
  364. }
  365. /*
  366.  * Destroy a DMA mapping from crosstalk space to system address space.
  367.  * There is no actual mapping hardware to destroy, but we at least mark
  368.  * the dmamap INVALID and free the space that it took.
  369.  */
  370. void
  371. hub_dmamap_free(hub_dmamap_t hub_dmamap)
  372. {
  373. hub_dmamap->hdma_flags &= ~HUB_DMAMAP_IS_VALID;
  374. kern_free(hub_dmamap);
  375. }
  376. /*
  377.  * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc.
  378.  * Return an appropriate crosstalk address range that maps to the specified physical 
  379.  * address range.
  380.  */
  381. /* ARGSUSED */
  382. extern iopaddr_t
  383. hub_dmamap_addr( hub_dmamap_t dmamap, /* use these mapping resources */
  384. paddr_t paddr, /* map for this address */
  385. size_t byte_count) /* map this many bytes */
  386. {
  387. devfs_handle_t vhdl;
  388. ASSERT(dmamap->hdma_flags & HUB_DMAMAP_IS_VALID);
  389. if (dmamap->hdma_flags & HUB_DMAMAP_USED) {
  390.     /* If the map is FIXED, re-use is OK. */
  391.     if (!(dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
  392. vhdl = dmamap->hdma_xtalk_info.xd_dev;
  393. #if defined(SUPPORT_PRINTING_V_FORMAT)
  394. PRINT_WARNING("%v: hub_dmamap_addr re-uses dmamap.n",vhdl);
  395. #else
  396. PRINT_WARNING("0x%x: hub_dmamap_addr re-uses dmamap.n", vhdl);
  397. #endif
  398.     }
  399. } else {
  400. dmamap->hdma_flags |= HUB_DMAMAP_USED;
  401. }
  402. /* There isn't actually any DMA mapping hardware on the hub. */
  403. return(paddr);
  404. }
  405. /*
  406.  * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc.
  407.  * Return an appropriate crosstalk address list that maps to the specified physical 
  408.  * address list.
  409.  */
  410. /* ARGSUSED */
  411. alenlist_t
  412. hub_dmamap_list(hub_dmamap_t hub_dmamap, /* use these mapping resources */
  413. alenlist_t palenlist, /* map this area of memory */
  414. unsigned flags)
  415. {
  416. devfs_handle_t vhdl;
  417. ASSERT(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_VALID);
  418. if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) {
  419.     /* If the map is FIXED, re-use is OK. */
  420.     if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
  421. vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
  422. #if defined(SUPPORT_PRINTING_V_FORMAT)
  423. PRINT_WARNING("%v: hub_dmamap_list re-uses dmamapn",vhdl);
  424. #else
  425. PRINT_WARNING("0x%x: hub_dmamap_list re-uses dmamapn", vhdl);
  426. #endif
  427.     }
  428. } else {
  429. hub_dmamap->hdma_flags |= HUB_DMAMAP_USED;
  430. }
  431. /* There isn't actually any DMA mapping hardware on the hub.  */
  432. return(palenlist);
  433. }
  434. /*
  435.  * Driver indicates that it has completed whatever DMA it may have started
  436.  * after an earlier dmamap_addr or dmamap_list call.
  437.  */
  438. void
  439. hub_dmamap_done(hub_dmamap_t hub_dmamap) /* done with these mapping resources */
  440. {
  441. devfs_handle_t vhdl;
  442. if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) {
  443. hub_dmamap->hdma_flags &= ~HUB_DMAMAP_USED;
  444. } else {
  445.     /* If the map is FIXED, re-done is OK. */
  446.     if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
  447. vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
  448. #if defined(SUPPORT_PRINTING_V_FORMAT)
  449. PRINT_WARNING("%v: hub_dmamap_done already done with dmamapn",vhdl);
  450. #else
  451. PRINT_WARNING("0x%x: hub_dmamap_done already done with dmamapn", vhdl);
  452. #endif
  453.     }
  454. }
  455. }
  456. /*
  457.  * Translate a single system physical address into a crosstalk address.
  458.  */
  459. /* ARGSUSED */
  460. iopaddr_t
  461. hub_dmatrans_addr( devfs_handle_t dev, /* translate for this device */
  462. device_desc_t dev_desc, /* device descriptor */
  463. paddr_t paddr, /* system physical address */
  464. size_t byte_count, /* length */
  465. unsigned flags) /* defined in dma.h */
  466. {
  467. /* no translation needed */
  468. return(paddr);
  469. }
  470. /*
  471.  * Translate a list of IP27 addresses and lengths into a list of crosstalk 
  472.  * addresses and lengths.  No actual hardware mapping takes place; the hub 
  473.  * has no DMA mapping registers -- crosstalk addresses map directly.
  474.  */
  475. /* ARGSUSED */
  476. alenlist_t
  477. hub_dmatrans_list( devfs_handle_t dev, /* translate for this device */
  478. device_desc_t dev_desc, /* device descriptor */
  479. alenlist_t palenlist, /* system address/length list */
  480. unsigned flags) /* defined in dma.h */
  481. {
  482. /* no translation needed */
  483. return(palenlist);
  484. }
  485. /*ARGSUSED*/
  486. void
  487. hub_dmamap_drain( hub_dmamap_t map)
  488. {
  489.     /* XXX- flush caches, if cache coherency WAR is needed */
  490. }
  491. /*ARGSUSED*/
  492. void
  493. hub_dmaaddr_drain( devfs_handle_t vhdl,
  494. paddr_t addr,
  495. size_t bytes)
  496. {
  497.     /* XXX- flush caches, if cache coherency WAR is needed */
  498. }
  499. /*ARGSUSED*/
  500. void
  501. hub_dmalist_drain( devfs_handle_t vhdl,
  502. alenlist_t list)
  503. {
  504.     /* XXX- flush caches, if cache coherency WAR is needed */
  505. }
  506. /* INTERRUPT MANAGEMENT */
  507. /* ARGSUSED */
  508. static void
  509. hub_intr_init(devfs_handle_t hubv)
  510. {
  511. }
  512. /*
  513.  * hub_device_desc_update
  514.  * Update the passed in device descriptor with the actual the
  515.  *  target cpu number and interrupt priority level.
  516.  * NOTE : These might be the same as the ones passed in thru
  517.  * the descriptor.
  518.  */
  519. static void
  520. hub_device_desc_update(device_desc_t  dev_desc, 
  521.        ilvl_t  intr_swlevel,
  522.        cpuid_t cpu)
  523. {
  524. char cpuname[40];
  525. /* Store the interrupt priority level in the device descriptor */
  526. device_desc_intr_swlevel_set(dev_desc, intr_swlevel);
  527. /* Convert the cpuid to the vertex handle in the hwgraph and
  528.  * save it in the device descriptor.
  529.  */
  530. sprintf(cpuname,"/hw/cpunum/%ld",cpu);
  531. device_desc_intr_target_set(dev_desc, 
  532.     hwgraph_path_to_dev(cpuname));
  533. }
  534. int allocate_my_bit = INTRCONNECT_ANYBIT;
  535. /*
  536.  * Allocate resources required for an interrupt as specified in dev_desc.
  537.  * Returns a hub interrupt handle on success, or 0 on failure.
  538.  */
  539. static hub_intr_t
  540. do_hub_intr_alloc(devfs_handle_t dev, /* which crosstalk device */
  541.   device_desc_t dev_desc, /* device descriptor */
  542.   devfs_handle_t owner_dev, /* owner of this interrupt, if known */
  543.   int uncond_nothread) /* unconditionally non-threaded */
  544. {
  545. cpuid_t cpu = (cpuid_t)0; /* cpu to receive interrupt */
  546.         int cpupicked = 0;
  547. int bit; /* interrupt vector */
  548. /*REFERENCED*/
  549. int intr_resflags = 0;
  550. hub_intr_t intr_hdl;
  551. cnodeid_t nodeid; /* node to receive interrupt */
  552. /*REFERENCED*/
  553. nasid_t nasid; /* nasid to receive interrupt */
  554. struct xtalk_intr_s *xtalk_info;
  555. iopaddr_t xtalk_addr; /* xtalk addr on hub to set intr */
  556. xwidget_info_t xwidget_info; /* standard crosstalk widget info handle */
  557. char *intr_name = NULL;
  558. ilvl_t intr_swlevel;
  559. extern int default_intr_pri;
  560. #ifdef CONFIG_IA64_SGI_SN1 
  561. extern void synergy_intr_alloc(int, int);
  562. #endif
  563. /*
  564.  * If caller didn't explicily specify a device descriptor, see if there's
  565.  * a default descriptor associated with the device.
  566.  */
  567. if (!dev_desc) 
  568. dev_desc = device_desc_default_get(dev);
  569. if (dev_desc) {
  570. intr_name = device_desc_intr_name_get(dev_desc);
  571. intr_swlevel = device_desc_intr_swlevel_get(dev_desc);
  572. if (dev_desc->flags & D_INTR_ISERR) {
  573. intr_resflags = II_ERRORINT;
  574. } else if (!uncond_nothread && !(dev_desc->flags & D_INTR_NOTHREAD)) {
  575. intr_resflags = II_THREADED;
  576. } else {
  577. /* Neither an error nor a thread. */
  578. intr_resflags = 0;
  579. }
  580. } else {
  581. intr_swlevel = default_intr_pri;
  582. if (!uncond_nothread)
  583. intr_resflags = II_THREADED;
  584. }
  585. /* XXX - Need to determine if the interrupt should be threaded. */
  586. /* If the cpu has not been picked already then choose a candidate 
  587.  * interrupt target and reserve the interrupt bit 
  588.  */
  589. #if defined(NEW_INTERRUPTS)
  590. if (!cpupicked) {
  591. cpu = intr_heuristic(dev,dev_desc,allocate_my_bit,
  592.      intr_resflags,owner_dev,
  593.      intr_name,&bit);
  594. }
  595. #endif
  596. /* At this point we SHOULD have a valid cpu */
  597. if (cpu == CPU_NONE) {
  598. #if defined(SUPPORT_PRINTING_V_FORMAT)
  599. PRINT_WARNING("%v hub_intr_alloc could not allocate interruptn",
  600. owner_dev);
  601. #else
  602. PRINT_WARNING("0x%x hub_intr_alloc could not allocate interruptn",
  603. owner_dev);
  604. #endif
  605. return(0);
  606. }
  607. /* If the cpu has been picked already (due to the bridge data 
  608.  * corruption bug) then try to reserve an interrupt bit .
  609.  */
  610. #if defined(NEW_INTERRUPTS)
  611. if (cpupicked) {
  612. bit = intr_reserve_level(cpu, allocate_my_bit, 
  613.  intr_resflags, 
  614.  owner_dev, intr_name);
  615. if (bit < 0) {
  616. #if defined(SUPPORT_PRINTING_V_FORMAT)
  617. PRINT_WARNING("Could not reserve an interrupt bit for cpu "
  618. " %d and dev %vn",
  619. cpu,owner_dev);
  620. #else
  621. PRINT_WARNING("Could not reserve an interrupt bit for cpu "
  622. " %d and dev 0x%xn",
  623. cpu, owner_dev);
  624. #endif
  625. return(0);
  626. }
  627. }
  628. #endif /* NEW_INTERRUPTS */
  629. nodeid = cpuid_to_cnodeid(cpu);
  630. nasid = cpuid_to_nasid(cpu);
  631. xtalk_addr = HUBREG_AS_XTALKADDR(nasid, PIREG(PI_INT_PEND_MOD, cpuid_to_subnode(cpu)));
  632. /*
  633.  * Allocate an interrupt handle, and fill it in.  There are two
  634.  * pieces to an interrupt handle: the piece needed by generic
  635.  * xtalk code which is used by crosstalk device drivers, and
  636.  * the piece needed by low-level IP27 hardware code.
  637.  */
  638. intr_hdl = kmem_alloc_node(sizeof(struct hub_intr_s), KM_NOSLEEP, nodeid);
  639. ASSERT_ALWAYS(intr_hdl);
  640. /* 
  641.  * Fill in xtalk information for generic xtalk interfaces that
  642.  * operate on xtalk_intr_hdl's.
  643.  */
  644. xtalk_info = &intr_hdl->i_xtalk_info;
  645. xtalk_info->xi_dev = dev;
  646. xtalk_info->xi_vector = bit;
  647. xtalk_info->xi_addr = xtalk_addr;
  648. /*
  649.  * Regardless of which CPU we ultimately interrupt, a given crosstalk
  650.  * widget always handles interrupts (and PIO and DMA) through its 
  651.  * designated "master" crosstalk provider.
  652.  */
  653. xwidget_info = xwidget_info_get(dev);
  654. if (xwidget_info)
  655. xtalk_info->xi_target = xwidget_info_masterid_get(xwidget_info);
  656. /* Fill in low level hub information for hub_* interrupt interface */
  657. intr_hdl->i_swlevel = intr_swlevel;
  658. intr_hdl->i_cpuid = cpu;
  659. intr_hdl->i_bit = bit;
  660. intr_hdl->i_flags = HUB_INTR_IS_ALLOCED;
  661. /* Store the actual interrupt priority level & interrupt target
  662.  * cpu back in the device descriptor.
  663.  */
  664. hub_device_desc_update(dev_desc, intr_swlevel, cpu);
  665. #ifdef CONFIG_IA64_SGI_SN1
  666. synergy_intr_alloc((int)bit, (int)cpu);
  667. #endif
  668. return(intr_hdl);
  669. }
  670. /*
  671.  * Allocate resources required for an interrupt as specified in dev_desc.
  672.  * Returns a hub interrupt handle on success, or 0 on failure.
  673.  */
  674. hub_intr_t
  675. hub_intr_alloc( devfs_handle_t dev, /* which crosstalk device */
  676. device_desc_t dev_desc, /* device descriptor */
  677. devfs_handle_t owner_dev) /* owner of this interrupt, if known */
  678. {
  679. return(do_hub_intr_alloc(dev, dev_desc, owner_dev, 0));
  680. }
  681. /*
  682.  * Allocate resources required for an interrupt as specified in dev_desc.
  683.  * Uncondtionally request non-threaded, regardless of what the device
  684.  * descriptor might say.
  685.  * Returns a hub interrupt handle on success, or 0 on failure.
  686.  */
  687. hub_intr_t
  688. hub_intr_alloc_nothd(devfs_handle_t dev, /* which crosstalk device */
  689. device_desc_t dev_desc, /* device descriptor */
  690. devfs_handle_t owner_dev) /* owner of this interrupt, if known */
  691. {
  692. return(do_hub_intr_alloc(dev, dev_desc, owner_dev, 1));
  693. }
  694. /*
  695.  * Free resources consumed by intr_alloc.
  696.  */
  697. void
  698. hub_intr_free(hub_intr_t intr_hdl)
  699. {
  700. cpuid_t cpu = intr_hdl->i_cpuid;
  701. int bit = intr_hdl->i_bit;
  702. xtalk_intr_t xtalk_info;
  703. if (intr_hdl->i_flags & HUB_INTR_IS_CONNECTED) {
  704. /* Setting the following fields in the xtalk interrupt info
  705.    * clears the interrupt target register in the xtalk user
  706.    */
  707. xtalk_info = &intr_hdl->i_xtalk_info;
  708. xtalk_info->xi_dev = NODEV;
  709. xtalk_info->xi_vector = 0;
  710. xtalk_info->xi_addr = 0;
  711. hub_intr_disconnect(intr_hdl);
  712. }
  713. if (intr_hdl->i_flags & HUB_INTR_IS_ALLOCED)
  714. kfree(intr_hdl);
  715. #if defined(NEW_INTERRUPTS)
  716. intr_unreserve_level(cpu, bit);
  717. #endif
  718. }
  719. /*
  720.  * Associate resources allocated with a previous hub_intr_alloc call with the
  721.  * described handler, arg, name, etc.
  722.  */
  723. /*ARGSUSED*/
  724. int
  725. hub_intr_connect( hub_intr_t intr_hdl, /* xtalk intr resource handle */
  726. intr_func_t intr_func, /* xtalk intr handler */
  727. void *intr_arg, /* arg to intr handler */
  728. xtalk_intr_setfunc_t setfunc, /* func to set intr hw */
  729. void *setfunc_arg, /* arg to setfunc */
  730. void *thread) /* intr thread to use */
  731. {
  732. int rv;
  733. cpuid_t cpu = intr_hdl->i_cpuid;
  734. int bit = intr_hdl->i_bit;
  735. #ifdef CONFIG_IA64_SGI_SN1
  736. extern int synergy_intr_connect(int, int);
  737. #endif
  738. ASSERT(intr_hdl->i_flags & HUB_INTR_IS_ALLOCED);
  739. #if defined(NEW_INTERRUPTS)
  740. rv = intr_connect_level(cpu, bit, intr_hdl->i_swlevel, 
  741. intr_func, intr_arg, NULL);
  742. if (rv < 0)
  743. return(rv);
  744. #endif
  745. intr_hdl->i_xtalk_info.xi_setfunc = setfunc;
  746. intr_hdl->i_xtalk_info.xi_sfarg = setfunc_arg;
  747. if (setfunc) (*setfunc)((xtalk_intr_t)intr_hdl);
  748. intr_hdl->i_flags |= HUB_INTR_IS_CONNECTED;
  749. #ifdef CONFIG_IA64_SGI_SN1
  750. return(synergy_intr_connect((int)bit, (int)cpu));
  751. #endif
  752. }
  753. /*
  754.  * Disassociate handler with the specified interrupt.
  755.  */
  756. void
  757. hub_intr_disconnect(hub_intr_t intr_hdl)
  758. {
  759. /*REFERENCED*/
  760. int rv;
  761. cpuid_t cpu = intr_hdl->i_cpuid;
  762. int bit = intr_hdl->i_bit;
  763. xtalk_intr_setfunc_t setfunc;
  764. setfunc = intr_hdl->i_xtalk_info.xi_setfunc;
  765. /* TBD: send disconnected interrupts somewhere harmless */
  766. if (setfunc) (*setfunc)((xtalk_intr_t)intr_hdl);
  767. #if defined(NEW_INTERRUPTS)
  768. rv = intr_disconnect_level(cpu, bit);
  769. ASSERT(rv == 0);
  770. #endif
  771. intr_hdl->i_flags &= ~HUB_INTR_IS_CONNECTED;
  772. }
  773. /*
  774.  * Return a hwgraph vertex that represents the CPU currently
  775.  * targeted by an interrupt.
  776.  */
  777. devfs_handle_t
  778. hub_intr_cpu_get(hub_intr_t intr_hdl)
  779. {
  780. cpuid_t cpuid = intr_hdl->i_cpuid;
  781. ASSERT(cpuid != CPU_NONE);
  782. return(cpuid_to_vertex(cpuid));
  783. }
  784. /* CONFIGURATION MANAGEMENT */
  785. /*
  786.  * Perform initializations that allow this hub to start crosstalk support.
  787.  */
  788. void
  789. hub_provider_startup(devfs_handle_t hubv)
  790. {
  791. hub_pio_init(hubv);
  792. hub_dma_init(hubv);
  793. hub_intr_init(hubv);
  794. }
  795. /*
  796.  * Shutdown crosstalk support from a hub.
  797.  */
  798. void
  799. hub_provider_shutdown(devfs_handle_t hub)
  800. {
  801. /* TBD */
  802. xtalk_provider_unregister(hub);
  803. }
  804. /*
  805.  * Check that an address is in teh real small window widget 0 space
  806.  * or else in the big window we're using to emulate small window 0
  807.  * in the kernel.
  808.  */
  809. int
  810. hub_check_is_widget0(void *addr)
  811. {
  812. nasid_t nasid = NASID_GET(addr);
  813. if (((__psunsigned_t)addr >= RAW_NODE_SWIN_BASE(nasid, 0)) &&
  814.     ((__psunsigned_t)addr < RAW_NODE_SWIN_BASE(nasid, 1)))
  815. return 1;
  816. return 0;
  817. }
  818. /*
  819.  * Check that two addresses use the same widget
  820.  */
  821. int
  822. hub_check_window_equiv(void *addra, void *addrb)
  823. {
  824. if (hub_check_is_widget0(addra) && hub_check_is_widget0(addrb))
  825. return 1;
  826. /* XXX - Assume this is really a small window address */
  827. if (WIDGETID_GET((__psunsigned_t)addra) ==
  828.     WIDGETID_GET((__psunsigned_t)addrb))
  829. return 1;
  830. return 0;
  831. }
  832. /*
  833.  * Determine whether two PCI addresses actually refer to the same device.
  834.  * This only works if both addresses are in small windows.  It's used to
  835.  * determine whether prom addresses refer to particular PCI devices.
  836.  */
  837. /*
  838.  * XXX - This won't work as written if we ever have more than two nodes
  839.  * on a crossbow.  In that case, we'll need an array or partners.
  840.  */
  841. int
  842. hub_check_pci_equiv(void *addra, void *addrb)
  843. {
  844. nasid_t nasida, nasidb;
  845. /*
  846.  * This is for a permanent workaround that causes us to use a
  847.  * big window in place of small window 0.
  848.  */
  849. if (!hub_check_window_equiv(addra, addrb))
  850. return 0;
  851. /* If the offsets aren't the same, forget it. */
  852. if (SWIN_WIDGETADDR((__psunsigned_t)addra) !=
  853.     (SWIN_WIDGETADDR((__psunsigned_t)addrb)))
  854. return 0;
  855. /* Now, check the nasids */
  856. nasida = NASID_GET(addra);
  857. nasidb = NASID_GET(addrb);
  858. ASSERT(NASID_TO_COMPACT_NODEID(nasida) != INVALID_NASID);
  859. ASSERT(NASID_TO_COMPACT_NODEID(nasidb) != INVALID_NASID);
  860. /*
  861.  * Either the NASIDs must be the same or they must be crossbow
  862.  * partners (on the same crossbow).
  863.  */
  864. return (check_nasid_equiv(nasida, nasidb));
  865. }
  866. /*
  867.  * hub_setup_prb(nasid, prbnum, credits, conveyor)
  868.  *
  869.  *  Put a PRB into fire-and-forget mode if conveyor isn't set.  Otehrwise,
  870.  *  put it into conveyor belt mode with the specified number of credits.
  871.  */
  872. void
  873. hub_setup_prb(nasid_t nasid, int prbnum, int credits, int conveyor)
  874. {
  875. iprb_t prb;
  876. int prb_offset;
  877. #ifdef LATER
  878. extern int force_fire_and_forget;
  879. extern volatile int ignore_conveyor_override;
  880. if (force_fire_and_forget && !ignore_conveyor_override)
  881.     if (conveyor == HUB_PIO_CONVEYOR)
  882. conveyor = HUB_PIO_FIRE_N_FORGET;
  883. #endif
  884. /*
  885.  * Get the current register value.
  886.  */
  887. prb_offset = IIO_IOPRB(prbnum);
  888. prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);
  889. /*
  890.  * Clear out some fields.
  891.  */
  892. prb.iprb_ovflow = 1;
  893. prb.iprb_bnakctr = 0;
  894. prb.iprb_anakctr = 0;
  895. /*
  896.  * Enable or disable fire-and-forget mode.
  897.  */
  898. prb.iprb_ff = ((conveyor == HUB_PIO_CONVEYOR) ? 0 : 1);
  899. /*
  900.  * Set the appropriate number of PIO cresits for the widget.
  901.  */
  902. prb.iprb_xtalkctr = credits;
  903. /*
  904.  * Store the new value to the register.
  905.  */
  906. REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
  907. }
  908. /*
  909.  * hub_set_piomode()
  910.  *
  911.  *  Put the hub into either "PIO conveyor belt" mode or "fire-and-forget"
  912.  *  mode.  To do this, we have to make absolutely sure that no PIOs
  913.  * are in progress so we turn off access to all widgets for the duration
  914.  * of the function.
  915.  * 
  916.  * XXX - This code should really check what kind of widget we're talking
  917.  * to.  Bridges can only handle three requests, but XG will do more.
  918.  * How many can crossbow handle to widget 0?  We're assuming 1.
  919.  *
  920.  * XXX - There is a bug in the crossbow that link reset PIOs do not
  921.  * return write responses.  The easiest solution to this problem is to
  922.  * leave widget 0 (xbow) in fire-and-forget mode at all times.  This
  923.  * only affects pio's to xbow registers, which should be rare.
  924.  */
  925. void
  926. hub_set_piomode(nasid_t nasid, int conveyor)
  927. {
  928. hubreg_t ii_iowa;
  929. int direct_connect;
  930. hubii_wcr_t ii_wcr;
  931. int prbnum;
  932. int cons_lock = 0;
  933. ASSERT(NASID_TO_COMPACT_NODEID(nasid) != INVALID_CNODEID);
  934. if (nasid == get_console_nasid()) {
  935. PUTBUF_LOCK(s);
  936. cons_lock = 1;
  937. }
  938. ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
  939. REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);
  940. ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
  941. direct_connect = ii_wcr.iwcr_dir_con;
  942. if (direct_connect) {
  943. /* 
  944.  * Assume a bridge here.
  945.  */
  946. hub_setup_prb(nasid, 0, 3, conveyor);
  947. } else {
  948. /* 
  949.  * Assume a crossbow here.
  950.  */
  951. hub_setup_prb(nasid, 0, 1, conveyor);
  952. }
  953. for (prbnum = HUB_WIDGET_ID_MIN; prbnum <= HUB_WIDGET_ID_MAX; prbnum++) {
  954. /*
  955.  * XXX - Here's where we should take the widget type into
  956.  * when account assigning credits.
  957.  */
  958. /* Always set the PRBs in fire-and-forget mode */
  959. hub_setup_prb(nasid, prbnum, 3, conveyor);
  960. }
  961. REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
  962. if (cons_lock)
  963.     PUTBUF_UNLOCK(s);
  964. }
  965. /* Interface to allow special drivers to set hub specific
  966.  * device flags.
  967.  * Return 0 on failure , 1 on success
  968.  */
  969. int
  970. hub_widget_flags_set(nasid_t nasid,
  971.      xwidgetnum_t widget_num,
  972.      hub_widget_flags_t flags)
  973. {
  974. ASSERT((flags & HUB_WIDGET_FLAGS) == flags);
  975. if (flags & HUB_PIO_CONVEYOR) {
  976. hub_setup_prb(nasid,widget_num,
  977.       3,HUB_PIO_CONVEYOR); /* set the PRB in conveyor 
  978.     * belt mode with 3 credits
  979.     */
  980. } else if (flags & HUB_PIO_FIRE_N_FORGET) {
  981. hub_setup_prb(nasid,widget_num,
  982.       3,HUB_PIO_FIRE_N_FORGET); /* set the PRB in fire
  983.  *  and forget mode 
  984.  */
  985. }
  986. return 1;
  987. }
  988. /* Interface to allow special drivers to set hub specific
  989.  * device flags.
  990.  * Return 0 on failure , 1 on success
  991.  */
  992. int
  993. hub_device_flags_set(devfs_handle_t widget_vhdl,
  994.      hub_widget_flags_t flags)
  995. {
  996. xwidget_info_t widget_info = xwidget_info_get(widget_vhdl);
  997. xwidgetnum_t widget_num  = xwidget_info_id_get(widget_info);
  998. devfs_handle_t hub_vhdl    = xwidget_info_master_get(widget_info);
  999. hubinfo_t hub_info = 0;
  1000. nasid_t nasid;
  1001. unsigned long s;
  1002. int rv;
  1003. /* Use the nasid from the hub info hanging off the hub vertex
  1004.  * and widget number from the widget vertex
  1005.  */
  1006. hubinfo_get(hub_vhdl, &hub_info);
  1007. /* Being over cautious by grabbing a lock */
  1008. s  = mutex_spinlock(&hub_info->h_bwlock);
  1009. nasid  = hub_info->h_nasid;
  1010. rv  = hub_widget_flags_set(nasid,widget_num,flags);
  1011. mutex_spinunlock(&hub_info->h_bwlock, s);
  1012. return rv;
  1013. }
  1014. #if ((defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)) && defined(BRINGUP))
  1015. /* BRINGUP:  This ought to be useful for IP27 too but, for now,
  1016.  * make it SN1 only because `ii_ixtt_u_t' is not in IP27/hubio.h
  1017.  * (or anywhere else :-).
  1018.  */
  1019. int
  1020. hubii_ixtt_set(devfs_handle_t widget_vhdl, ii_ixtt_u_t *ixtt)
  1021. {
  1022. xwidget_info_t widget_info = xwidget_info_get(widget_vhdl);
  1023. devfs_handle_t hub_vhdl    = xwidget_info_master_get(widget_info);
  1024. hubinfo_t hub_info = 0;
  1025. nasid_t nasid;
  1026. unsigned long s;
  1027. /* Use the nasid from the hub info hanging off the hub vertex
  1028.  * and widget number from the widget vertex
  1029.  */
  1030. hubinfo_get(hub_vhdl, &hub_info);
  1031. /* Being over cautious by grabbing a lock */
  1032. s  = mutex_spinlock(&hub_info->h_bwlock);
  1033. nasid  = hub_info->h_nasid;
  1034. REMOTE_HUB_S(nasid, IIO_IXTT, ixtt->ii_ixtt_regval);
  1035. mutex_spinunlock(&hub_info->h_bwlock, s);
  1036. return 0;
  1037. }
  1038. int
  1039. hubii_ixtt_get(devfs_handle_t widget_vhdl, ii_ixtt_u_t *ixtt)
  1040. {
  1041. xwidget_info_t widget_info = xwidget_info_get(widget_vhdl);
  1042. devfs_handle_t hub_vhdl    = xwidget_info_master_get(widget_info);
  1043. hubinfo_t hub_info = 0;
  1044. nasid_t nasid;
  1045. unsigned long s;
  1046. /* Use the nasid from the hub info hanging off the hub vertex
  1047.  * and widget number from the widget vertex
  1048.  */
  1049. hubinfo_get(hub_vhdl, &hub_info);
  1050. /* Being over cautious by grabbing a lock */
  1051. s  = mutex_spinlock(&hub_info->h_bwlock);
  1052. nasid  = hub_info->h_nasid;
  1053. ixtt->ii_ixtt_regval = REMOTE_HUB_L(nasid, IIO_IXTT);
  1054. mutex_spinunlock(&hub_info->h_bwlock, s);
  1055. return 0;
  1056. }
  1057. #endif /* CONFIG_IA64_SGI_SN1 */
  1058. /*
  1059.  * hub_device_inquiry
  1060.  * Find out the xtalk widget related information stored in this 
  1061.  * hub's II.
  1062.  */
  1063. void
  1064. hub_device_inquiry(devfs_handle_t xbus_vhdl, xwidgetnum_t widget)
  1065. {
  1066. devfs_handle_t xconn, hub_vhdl;
  1067. char widget_name[8];
  1068. hubreg_t ii_iidem,ii_iiwa, ii_iowa;
  1069. hubinfo_t hubinfo;
  1070. nasid_t nasid;
  1071. int d;
  1072. sprintf(widget_name, "%d", widget);
  1073. if (hwgraph_traverse(xbus_vhdl, widget_name, &xconn)
  1074.     != GRAPH_SUCCESS)
  1075. return;
  1076. hub_vhdl = device_master_get(xconn);
  1077. if (hub_vhdl == GRAPH_VERTEX_NONE)
  1078. return;
  1079. hubinfo_get(hub_vhdl, &hubinfo);
  1080. if (!hubinfo)
  1081. return;
  1082. nasid = hubinfo->h_nasid;
  1083. ii_iidem = REMOTE_HUB_L(nasid, IIO_IIDEM);
  1084. ii_iiwa  = REMOTE_HUB_L(nasid, IIO_IIWA);
  1085. ii_iowa  = REMOTE_HUB_L(nasid, IIO_IOWA);
  1086. #if defined(SUPPORT_PRINTING_V_FORMAT)
  1087. printk("Inquiry Info for %vn", xconn);
  1088. #else
  1089. printk("Inquiry Info for 0x%xn", xconn);
  1090. #endif
  1091. printk("tDevices shutdown [ ");
  1092. for (d = 0 ; d <= 7 ; d++)
  1093. if (!(ii_iidem & (IIO_IIDEM_WIDGETDEV_MASK(widget,d))))
  1094. printk(" %d", d);
  1095. printk("]n");
  1096. printk("tInbound access ? %sn",
  1097. ii_iiwa & IIO_IIWA_WIDGET(widget) ? "yes" : "no");
  1098. printk("tOutbound access ? %sn",
  1099. ii_iowa & IIO_IOWA_WIDGET(widget) ? "yes" : "no");
  1100. }
  1101. /*
  1102.  * A pointer to this structure hangs off of every hub hwgraph vertex.
  1103.  * The generic xtalk layer may indirect through it to get to this specific
  1104.  * crosstalk bus provider.
  1105.  */
  1106. xtalk_provider_t hub_provider = {
  1107. (xtalk_piomap_alloc_f *) hub_piomap_alloc,
  1108. (xtalk_piomap_free_f *) hub_piomap_free,
  1109. (xtalk_piomap_addr_f *) hub_piomap_addr,
  1110. (xtalk_piomap_done_f *) hub_piomap_done,
  1111. (xtalk_piotrans_addr_f *) hub_piotrans_addr,
  1112. (xtalk_dmamap_alloc_f *) hub_dmamap_alloc,
  1113. (xtalk_dmamap_free_f *) hub_dmamap_free,
  1114. (xtalk_dmamap_addr_f *) hub_dmamap_addr,
  1115. (xtalk_dmamap_list_f *) hub_dmamap_list,
  1116. (xtalk_dmamap_done_f *) hub_dmamap_done,
  1117. (xtalk_dmatrans_addr_f *) hub_dmatrans_addr,
  1118. (xtalk_dmatrans_list_f *) hub_dmatrans_list,
  1119. (xtalk_dmamap_drain_f *) hub_dmamap_drain,
  1120. (xtalk_dmaaddr_drain_f *) hub_dmaaddr_drain,
  1121. (xtalk_dmalist_drain_f *) hub_dmalist_drain,
  1122. (xtalk_intr_alloc_f *) hub_intr_alloc,
  1123. (xtalk_intr_alloc_f *) hub_intr_alloc_nothd,
  1124. (xtalk_intr_free_f *) hub_intr_free,
  1125. (xtalk_intr_connect_f *) hub_intr_connect,
  1126. (xtalk_intr_disconnect_f *) hub_intr_disconnect,
  1127. (xtalk_intr_cpu_get_f *) hub_intr_cpu_get,
  1128. (xtalk_provider_startup_f *) hub_provider_startup,
  1129. (xtalk_provider_shutdown_f *) hub_provider_shutdown,
  1130. };