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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: io.c,v 1.2 2001/06/26 14:02:43 pfg Exp $
  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-2002 Silicon Graphics, Inc.  All Rights Reserved.
  8.  */
  9. #include <linux/types.h>
  10. #include <linux/slab.h>
  11. #include <asm/sn/types.h>
  12. #include <asm/sn/sgi.h>
  13. #include <asm/sn/driver.h>
  14. #include <asm/sn/iograph.h>
  15. #include <asm/param.h>
  16. #include <asm/sn/pio.h>
  17. #include <asm/sn/xtalk/xwidget.h>
  18. #include <asm/sn/io.h>
  19. #include <asm/sn/sn_private.h>
  20. #include <asm/sn/addrs.h>
  21. #include <asm/sn/invent.h>
  22. #include <asm/sn/hcl.h>
  23. #include <asm/sn/hcl_util.h>
  24. #include <asm/sn/intr.h>
  25. #include <asm/sn/xtalk/xtalkaddrs.h>
  26. #include <asm/sn/klconfig.h>
  27. #include <asm/sn/sn_cpuid.h>
  28. extern xtalk_provider_t hub_provider;
  29. extern void hub_intr_init(devfs_handle_t hubv);
  30. /*      
  31.  * hub_device_desc_update               
  32.  *      Update the passed in device descriptor with the actual the
  33.  *      target cpu number and interrupt priority level.
  34.  *      NOTE : These might be the same as the ones passed in thru
  35.  *      the descriptor.
  36.  */     
  37. void
  38. hub_device_desc_update(device_desc_t    dev_desc,
  39.                        ilvl_t           intr_swlevel, 
  40.                        cpuid_t          cpu)
  41. {       
  42. }
  43. /*
  44.  * Perform any initializations needed to support hub-based I/O.
  45.  * Called once during startup.
  46.  */
  47. void
  48. hubio_init(void)
  49. {
  50. #ifdef LATER
  51. /* This isn't needed unless we port the entire sio driver ... */
  52.         extern void early_brl1_port_init( void );
  53. early_brl1_port_init();
  54. #endif
  55. }
  56. /* 
  57.  * Implementation of hub iobus operations.
  58.  *
  59.  * Hub provides a crosstalk "iobus" on IP27 systems.  These routines
  60.  * provide a platform-specific implementation of xtalk used by all xtalk 
  61.  * cards on IP27 systems.
  62.  *
  63.  * Called from corresponding xtalk_* routines.
  64.  */
  65. /* PIO MANAGEMENT */
  66. /* For mapping system virtual address space to xtalk space on a specified widget */
  67. /*
  68.  * Setup pio structures needed for a particular hub.
  69.  */
  70. void
  71. hub_pio_init(devfs_handle_t hubv)
  72. {
  73. xwidgetnum_t widget;
  74. hubinfo_t hubinfo;
  75. nasid_t nasid;
  76. int bigwin;
  77. hub_piomap_t hub_piomap;
  78. hubinfo_get(hubv, &hubinfo);
  79. nasid = hubinfo->h_nasid;
  80. /* Initialize small window piomaps for this hub */
  81. for (widget=0; widget <= HUB_WIDGET_ID_MAX; widget++) {
  82. hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
  83. hub_piomap->hpio_xtalk_info.xp_target = widget;
  84. hub_piomap->hpio_xtalk_info.xp_xtalk_addr = 0;
  85. hub_piomap->hpio_xtalk_info.xp_mapsz = SWIN_SIZE;
  86. hub_piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)NODE_SWIN_BASE(nasid, widget);
  87. hub_piomap->hpio_hub = hubv;
  88. hub_piomap->hpio_flags = HUB_PIOMAP_IS_VALID;
  89. }
  90. /* Initialize big window piomaps for this hub */
  91. for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
  92. hub_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin);
  93. hub_piomap->hpio_xtalk_info.xp_mapsz = BWIN_SIZE;
  94. hub_piomap->hpio_hub = hubv;
  95. hub_piomap->hpio_holdcnt = 0;
  96. hub_piomap->hpio_flags = HUB_PIOMAP_IS_BIGWINDOW;
  97. IIO_ITTE_DISABLE(nasid, bigwin);
  98. }
  99. hub_set_piomode(nasid, HUB_PIO_CONVEYOR);
  100. mutex_spinlock_init(&hubinfo->h_bwlock);
  101. /*
  102.  * If this lock can be acquired from interrupts or bh's, add SV_INTS or SV_BHS,
  103.  * respectively, to the flags here.
  104.  */
  105. sv_init(&hubinfo->h_bwwait, &hubinfo->h_bwlock, SV_ORDER_FIFO | SV_MON_SPIN); 
  106. }
  107. /* 
  108.  * Create a caddr_t-to-xtalk_addr mapping.
  109.  *
  110.  * Use a small window if possible (that's the usual case), but
  111.  * manage big windows if needed.  Big window mappings can be
  112.  * either FIXED or UNFIXED -- we keep at least 1 big window available
  113.  * for UNFIXED mappings.
  114.  *
  115.  * Returns an opaque pointer-sized type which can be passed to
  116.  * other hub_pio_* routines on success, or NULL if the request
  117.  * cannot be satisfied.
  118.  */
  119. /* ARGSUSED */
  120. hub_piomap_t
  121. hub_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */
  122. device_desc_t dev_desc, /* device descriptor */
  123. iopaddr_t xtalk_addr, /* map for this xtalk_addr range */
  124. size_t byte_count,
  125. size_t byte_count_max,  /* maximum size of a mapping */
  126. unsigned flags) /* defined in sys/pio.h */
  127. {
  128. xwidget_info_t widget_info = xwidget_info_get(dev);
  129. xwidgetnum_t widget = xwidget_info_id_get(widget_info);
  130. devfs_handle_t hubv = xwidget_info_master_get(widget_info);
  131. hubinfo_t hubinfo;
  132. hub_piomap_t bw_piomap;
  133. int bigwin, free_bw_index;
  134. nasid_t nasid;
  135. volatile hubreg_t junk;
  136. unsigned long s;
  137. /* sanity check */
  138. if (byte_count_max > byte_count)
  139. return(NULL);
  140. hubinfo_get(hubv, &hubinfo);
  141. /* If xtalk_addr range is mapped by a small window, we don't have 
  142.  * to do much 
  143.  */
  144. if (xtalk_addr + byte_count <= SWIN_SIZE)
  145. return(hubinfo_swin_piomap_get(hubinfo, (int)widget));
  146. /* We need to use a big window mapping.  */
  147. /*
  148.  * TBD: Allow requests that would consume multiple big windows --
  149.  * split the request up and use multiple mapping entries.
  150.  * For now, reject requests that span big windows.
  151.  */
  152. if ((xtalk_addr % BWIN_SIZE) + byte_count > BWIN_SIZE)
  153. return(NULL);
  154. /* Round xtalk address down for big window alignement */
  155. xtalk_addr = xtalk_addr & ~(BWIN_SIZE-1);
  156. /*
  157.  * Check to see if an existing big window mapping will suffice.
  158.  */
  159. tryagain:
  160. free_bw_index = -1;
  161. s = mutex_spinlock(&hubinfo->h_bwlock);
  162. for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
  163. bw_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin);
  164. /* If mapping is not valid, skip it */
  165. if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_VALID)) {
  166. free_bw_index = bigwin;
  167. continue;
  168. }
  169. /* 
  170.  * If mapping is UNFIXED, skip it.  We don't allow sharing
  171.  * of UNFIXED mappings, because this would allow starvation.
  172.  */
  173. if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED))
  174. continue;
  175. if ( xtalk_addr == bw_piomap->hpio_xtalk_info.xp_xtalk_addr &&
  176.      widget == bw_piomap->hpio_xtalk_info.xp_target) {
  177. bw_piomap->hpio_holdcnt++;
  178. mutex_spinunlock(&hubinfo->h_bwlock, s);
  179. return(bw_piomap);
  180. }
  181. }
  182. /*
  183.  * None of the existing big window mappings will work for us --
  184.  * we need to establish a new mapping.
  185.  */
  186. /* Insure that we don't consume all big windows with FIXED mappings */
  187. if (flags & PIOMAP_FIXED) {
  188. if (hubinfo->h_num_big_window_fixed < HUB_NUM_BIG_WINDOW-1) {
  189. ASSERT(free_bw_index >= 0);
  190. hubinfo->h_num_big_window_fixed++;
  191. } else {
  192. bw_piomap = NULL;
  193. goto done;
  194. }
  195. } else /* PIOMAP_UNFIXED */ {
  196. if (free_bw_index < 0) {
  197. if (flags & PIOMAP_NOSLEEP) {
  198. bw_piomap = NULL;
  199. goto done;
  200. }
  201. sv_wait(&hubinfo->h_bwwait, 0, 0);
  202. goto tryagain;
  203. }
  204. }
  205. /* OK!  Allocate big window free_bw_index for this mapping. */
  206.   /* 
  207.  * The code below does a PIO write to setup an ITTE entry.
  208.  * We need to prevent other CPUs from seeing our updated memory 
  209.  * shadow of the ITTE (in the piomap) until the ITTE entry is 
  210.  * actually set up; otherwise, another CPU might attempt a PIO 
  211.  * prematurely.  
  212.  *
  213.  * Also, the only way we can know that an entry has been received 
  214.  * by the hub and can be used by future PIO reads/writes is by 
  215.  * reading back the ITTE entry after writing it.
  216.  *
  217.  * For these two reasons, we PIO read back the ITTE entry after
  218.  * we write it.
  219.  */
  220. nasid = hubinfo->h_nasid;
  221. IIO_ITTE_PUT(nasid, free_bw_index, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
  222. junk = HUB_L(IIO_ITTE_GET(nasid, free_bw_index));
  223. bw_piomap = hubinfo_bwin_piomap_get(hubinfo, free_bw_index);
  224. bw_piomap->hpio_xtalk_info.xp_dev = dev;
  225. bw_piomap->hpio_xtalk_info.xp_target = widget;
  226. bw_piomap->hpio_xtalk_info.xp_xtalk_addr = xtalk_addr;
  227. bw_piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)NODE_BWIN_BASE(nasid, free_bw_index);
  228. bw_piomap->hpio_holdcnt++;
  229. bw_piomap->hpio_bigwin_num = free_bw_index;
  230. if (flags & PIOMAP_FIXED)
  231. bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED;
  232. else
  233. bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID;
  234. done:
  235. mutex_spinunlock(&hubinfo->h_bwlock, s);
  236. return(bw_piomap);
  237. }
  238. /*
  239.  * hub_piomap_free destroys a caddr_t-to-xtalk pio mapping and frees
  240.  * any associated mapping resources.  
  241.  *
  242.  * If this * piomap was handled with a small window, or if it was handled
  243.  * in a big window that's still in use by someone else, then there's 
  244.  * nothing to do.  On the other hand, if this mapping was handled 
  245.  * with a big window, AND if we were the final user of that mapping, 
  246.  * then destroy the mapping.
  247.  */
  248. void
  249. hub_piomap_free(hub_piomap_t hub_piomap)
  250. {
  251. devfs_handle_t hubv;
  252. hubinfo_t hubinfo;
  253. nasid_t nasid;
  254. unsigned long s;
  255. /* 
  256.  * Small windows are permanently mapped to corresponding widgets,
  257.  * so there're no resources to free.
  258.  */
  259. if (!(hub_piomap->hpio_flags & HUB_PIOMAP_IS_BIGWINDOW))
  260. return;
  261. ASSERT(hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID);
  262. ASSERT(hub_piomap->hpio_holdcnt > 0);
  263. hubv = hub_piomap->hpio_hub;
  264. hubinfo_get(hubv, &hubinfo);
  265. nasid = hubinfo->h_nasid;
  266. s = mutex_spinlock(&hubinfo->h_bwlock);
  267. /*
  268.  * If this is the last hold on this mapping, free it.
  269.  */
  270. if (--hub_piomap->hpio_holdcnt == 0) {
  271. IIO_ITTE_DISABLE(nasid, hub_piomap->hpio_bigwin_num );
  272. if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED) {
  273. hub_piomap->hpio_flags &= ~(HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED);
  274. hubinfo->h_num_big_window_fixed--;
  275. ASSERT(hubinfo->h_num_big_window_fixed >= 0);
  276. } else
  277. hub_piomap->hpio_flags &= ~HUB_PIOMAP_IS_VALID;
  278. (void)sv_signal(&hubinfo->h_bwwait);
  279. }
  280. mutex_spinunlock(&hubinfo->h_bwlock, s);
  281. }
  282. /*
  283.  * Establish a mapping to a given xtalk address range using the resources
  284.  * allocated earlier.
  285.  */
  286. caddr_t
  287. hub_piomap_addr(hub_piomap_t hub_piomap, /* mapping resources */
  288. iopaddr_t xtalk_addr, /* map for this xtalk address */
  289. size_t byte_count) /* map this many bytes */
  290. {
  291. /* Verify that range can be mapped using the specified piomap */
  292. if (xtalk_addr < hub_piomap->hpio_xtalk_info.xp_xtalk_addr)
  293. return(0);
  294. if (xtalk_addr + byte_count > 
  295. ( hub_piomap->hpio_xtalk_info.xp_xtalk_addr + 
  296. hub_piomap->hpio_xtalk_info.xp_mapsz))
  297. return(0);
  298. if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID)
  299. return(hub_piomap->hpio_xtalk_info.xp_kvaddr + 
  300. (xtalk_addr % hub_piomap->hpio_xtalk_info.xp_mapsz));
  301. else
  302. return(0);
  303. }
  304. /*
  305.  * Driver indicates that it's done with PIO's from an earlier piomap_addr.
  306.  */
  307. /* ARGSUSED */
  308. void
  309. hub_piomap_done(hub_piomap_t hub_piomap) /* done with these mapping resources */
  310. {
  311. /* Nothing to do */
  312. }
  313. /*
  314.  * For translations that require no mapping resources, supply a kernel virtual
  315.  * address that maps to the specified xtalk address range.
  316.  */
  317. /* ARGSUSED */
  318. caddr_t
  319. hub_piotrans_addr( devfs_handle_t dev, /* translate to this device */
  320. device_desc_t dev_desc, /* device descriptor */
  321. iopaddr_t xtalk_addr, /* Crosstalk address */
  322. size_t byte_count, /* map this many bytes */
  323. unsigned flags) /* (currently unused) */
  324. {
  325. xwidget_info_t widget_info = xwidget_info_get(dev);
  326. xwidgetnum_t widget = xwidget_info_id_get(widget_info);
  327. devfs_handle_t hubv = xwidget_info_master_get(widget_info);
  328. hub_piomap_t hub_piomap;
  329. hubinfo_t hubinfo;
  330. hubinfo_get(hubv, &hubinfo);
  331. if (xtalk_addr + byte_count <= SWIN_SIZE) {
  332. hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
  333. return(hub_piomap_addr(hub_piomap, xtalk_addr, byte_count));
  334. } else
  335. return(0);
  336. }
  337. /* DMA MANAGEMENT */
  338. /* Mapping from crosstalk space to system physical space */
  339. /* 
  340.  * There's not really very much to do here, since crosstalk maps
  341.  * directly to system physical space.  It's quite possible that this
  342.  * DMA layer will be bypassed in performance kernels.
  343.  */
  344. /* ARGSUSED */
  345. void
  346. hub_dma_init(devfs_handle_t hubv)
  347. {
  348. }
  349. /*
  350.  * Allocate resources needed to set up DMA mappings up to a specified size
  351.  * on a specified adapter.
  352.  * 
  353.  * We don't actually use the adapter ID for anything.  It's just the adapter
  354.  * that the lower level driver plans to use for DMA.
  355.  */
  356. /* ARGSUSED */
  357. hub_dmamap_t
  358. hub_dmamap_alloc( devfs_handle_t dev, /* set up mappings for this device */
  359. device_desc_t dev_desc, /* device descriptor */
  360. size_t byte_count_max,  /* max size of a mapping */
  361. unsigned flags) /* defined in dma.h */
  362. {
  363. hub_dmamap_t dmamap;
  364. xwidget_info_t widget_info = xwidget_info_get(dev);
  365. xwidgetnum_t widget = xwidget_info_id_get(widget_info);
  366. devfs_handle_t hubv = xwidget_info_master_get(widget_info);
  367. dmamap = kmalloc(sizeof(struct hub_dmamap_s), GFP_ATOMIC);
  368. dmamap->hdma_xtalk_info.xd_dev = dev;
  369. dmamap->hdma_xtalk_info.xd_target = widget;
  370. dmamap->hdma_hub = hubv;
  371. dmamap->hdma_flags = HUB_DMAMAP_IS_VALID;
  372.   if (flags & XTALK_FIXED)
  373. dmamap->hdma_flags |= HUB_DMAMAP_IS_FIXED;
  374. return(dmamap);
  375. }
  376. /*
  377.  * Destroy a DMA mapping from crosstalk space to system address space.
  378.  * There is no actual mapping hardware to destroy, but we at least mark
  379.  * the dmamap INVALID and free the space that it took.
  380.  */
  381. void
  382. hub_dmamap_free(hub_dmamap_t hub_dmamap)
  383. {
  384. hub_dmamap->hdma_flags &= ~HUB_DMAMAP_IS_VALID;
  385. kern_free(hub_dmamap);
  386. }
  387. /*
  388.  * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc.
  389.  * Return an appropriate crosstalk address range that maps to the specified physical 
  390.  * address range.
  391.  */
  392. /* ARGSUSED */
  393. extern iopaddr_t
  394. hub_dmamap_addr( hub_dmamap_t dmamap, /* use these mapping resources */
  395. paddr_t paddr, /* map for this address */
  396. size_t byte_count) /* map this many bytes */
  397. {
  398. devfs_handle_t vhdl;
  399. ASSERT(dmamap->hdma_flags & HUB_DMAMAP_IS_VALID);
  400. if (dmamap->hdma_flags & HUB_DMAMAP_USED) {
  401.     /* If the map is FIXED, re-use is OK. */
  402.     if (!(dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
  403. vhdl = dmamap->hdma_xtalk_info.xd_dev;
  404. #if defined(SUPPORT_PRINTING_V_FORMAT)
  405. printk(KERN_WARNING  "%v: hub_dmamap_addr re-uses dmamap.n",vhdl);
  406. #else
  407. printk(KERN_WARNING  "%p: hub_dmamap_addr re-uses dmamap.n", (void *)vhdl);
  408. #endif
  409.     }
  410. } else {
  411. dmamap->hdma_flags |= HUB_DMAMAP_USED;
  412. }
  413. /* There isn't actually any DMA mapping hardware on the hub. */
  414. return(paddr);
  415. }
  416. /*
  417.  * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc.
  418.  * Return an appropriate crosstalk address list that maps to the specified physical 
  419.  * address list.
  420.  */
  421. /* ARGSUSED */
  422. alenlist_t
  423. hub_dmamap_list(hub_dmamap_t hub_dmamap, /* use these mapping resources */
  424. alenlist_t palenlist, /* map this area of memory */
  425. unsigned flags)
  426. {
  427. devfs_handle_t vhdl;
  428. ASSERT(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_VALID);
  429. if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) {
  430.     /* If the map is FIXED, re-use is OK. */
  431.     if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
  432. vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
  433. #if defined(SUPPORT_PRINTING_V_FORMAT)
  434. printk(KERN_WARNING  "%v: hub_dmamap_list re-uses dmamapn",vhdl);
  435. #else
  436. printk(KERN_WARNING  "%p: hub_dmamap_list re-uses dmamapn", (void *)vhdl);
  437. #endif
  438.     }
  439. } else {
  440. hub_dmamap->hdma_flags |= HUB_DMAMAP_USED;
  441. }
  442. /* There isn't actually any DMA mapping hardware on the hub.  */
  443. return(palenlist);
  444. }
  445. /*
  446.  * Driver indicates that it has completed whatever DMA it may have started
  447.  * after an earlier dmamap_addr or dmamap_list call.
  448.  */
  449. void
  450. hub_dmamap_done(hub_dmamap_t hub_dmamap) /* done with these mapping resources */
  451. {
  452. devfs_handle_t vhdl;
  453. if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) {
  454. hub_dmamap->hdma_flags &= ~HUB_DMAMAP_USED;
  455. } else {
  456.     /* If the map is FIXED, re-done is OK. */
  457.     if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
  458. vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
  459. #if defined(SUPPORT_PRINTING_V_FORMAT)
  460. printk(KERN_WARNING  "%v: hub_dmamap_done already done with dmamapn",vhdl);
  461. #else
  462. printk(KERN_WARNING  "%p: hub_dmamap_done already done with dmamapn", (void *)vhdl);
  463. #endif
  464.     }
  465. }
  466. }
  467. /*
  468.  * Translate a single system physical address into a crosstalk address.
  469.  */
  470. /* ARGSUSED */
  471. iopaddr_t
  472. hub_dmatrans_addr( devfs_handle_t dev, /* translate for this device */
  473. device_desc_t dev_desc, /* device descriptor */
  474. paddr_t paddr, /* system physical address */
  475. size_t byte_count, /* length */
  476. unsigned flags) /* defined in dma.h */
  477. {
  478. /* no translation needed */
  479. return(paddr);
  480. }
  481. /*
  482.  * Translate a list of IP27 addresses and lengths into a list of crosstalk 
  483.  * addresses and lengths.  No actual hardware mapping takes place; the hub 
  484.  * has no DMA mapping registers -- crosstalk addresses map directly.
  485.  */
  486. /* ARGSUSED */
  487. alenlist_t
  488. hub_dmatrans_list( devfs_handle_t dev, /* translate for this device */
  489. device_desc_t dev_desc, /* device descriptor */
  490. alenlist_t palenlist, /* system address/length list */
  491. unsigned flags) /* defined in dma.h */
  492. {
  493. /* no translation needed */
  494. return(palenlist);
  495. }
  496. /*ARGSUSED*/
  497. void
  498. hub_dmamap_drain( hub_dmamap_t map)
  499. {
  500.     /* XXX- flush caches, if cache coherency WAR is needed */
  501. }
  502. /*ARGSUSED*/
  503. void
  504. hub_dmaaddr_drain( devfs_handle_t vhdl,
  505. paddr_t addr,
  506. size_t bytes)
  507. {
  508.     /* XXX- flush caches, if cache coherency WAR is needed */
  509. }
  510. /*ARGSUSED*/
  511. void
  512. hub_dmalist_drain( devfs_handle_t vhdl,
  513. alenlist_t list)
  514. {
  515.     /* XXX- flush caches, if cache coherency WAR is needed */
  516. }
  517. /* CONFIGURATION MANAGEMENT */
  518. /*
  519.  * Perform initializations that allow this hub to start crosstalk support.
  520.  */
  521. void
  522. hub_provider_startup(devfs_handle_t hubv)
  523. {
  524. extern void hub_dma_init(devfs_handle_t hubv);
  525. extern void hub_pio_init(devfs_handle_t hubv);
  526. hub_pio_init(hubv);
  527. hub_dma_init(hubv);
  528. hub_intr_init(hubv);
  529. }
  530. /*
  531.  * Shutdown crosstalk support from a hub.
  532.  */
  533. void
  534. hub_provider_shutdown(devfs_handle_t hub)
  535. {
  536. /* TBD */
  537. xtalk_provider_unregister(hub);
  538. }
  539. /*
  540.  * Check that an address is in teh real small window widget 0 space
  541.  * or else in the big window we're using to emulate small window 0
  542.  * in the kernel.
  543.  */
  544. int
  545. hub_check_is_widget0(void *addr)
  546. {
  547. nasid_t nasid = NASID_GET(addr);
  548. if (((__psunsigned_t)addr >= RAW_NODE_SWIN_BASE(nasid, 0)) &&
  549.     ((__psunsigned_t)addr < RAW_NODE_SWIN_BASE(nasid, 1)))
  550. return 1;
  551. return 0;
  552. }
  553. /*
  554.  * Check that two addresses use the same widget
  555.  */
  556. int
  557. hub_check_window_equiv(void *addra, void *addrb)
  558. {
  559. if (hub_check_is_widget0(addra) && hub_check_is_widget0(addrb))
  560. return 1;
  561. /* XXX - Assume this is really a small window address */
  562. if (WIDGETID_GET((__psunsigned_t)addra) ==
  563.     WIDGETID_GET((__psunsigned_t)addrb))
  564. return 1;
  565. return 0;
  566. }
  567. /*
  568.  * Determine whether two PCI addresses actually refer to the same device.
  569.  * This only works if both addresses are in small windows.  It's used to
  570.  * determine whether prom addresses refer to particular PCI devices.
  571.  */
  572. /*
  573.  * XXX - This won't work as written if we ever have more than two nodes
  574.  * on a crossbow.  In that case, we'll need an array or partners.
  575.  */
  576. int
  577. hub_check_pci_equiv(void *addra, void *addrb)
  578. {
  579. nasid_t nasida, nasidb;
  580. /*
  581.  * This is for a permanent workaround that causes us to use a
  582.  * big window in place of small window 0.
  583.  */
  584. if (!hub_check_window_equiv(addra, addrb))
  585. return 0;
  586. /* If the offsets aren't the same, forget it. */
  587. if (SWIN_WIDGETADDR((__psunsigned_t)addra) !=
  588.     (SWIN_WIDGETADDR((__psunsigned_t)addrb)))
  589. return 0;
  590. /* Now, check the nasids */
  591. nasida = NASID_GET(addra);
  592. nasidb = NASID_GET(addrb);
  593. ASSERT(NASID_TO_COMPACT_NODEID(nasida) != INVALID_NASID);
  594. ASSERT(NASID_TO_COMPACT_NODEID(nasidb) != INVALID_NASID);
  595. /*
  596.  * Either the NASIDs must be the same or they must be crossbow
  597.  * partners (on the same crossbow).
  598.  */
  599. return (check_nasid_equiv(nasida, nasidb));
  600. }
  601. /*
  602.  * hub_setup_prb(nasid, prbnum, credits, conveyor)
  603.  *
  604.  *  Put a PRB into fire-and-forget mode if conveyor isn't set.  Otehrwise,
  605.  *  put it into conveyor belt mode with the specified number of credits.
  606.  */
  607. void
  608. hub_setup_prb(nasid_t nasid, int prbnum, int credits, int conveyor)
  609. {
  610. iprb_t prb;
  611. int prb_offset;
  612. #ifdef LATER
  613. extern int force_fire_and_forget;
  614. extern volatile int ignore_conveyor_override;
  615. if (force_fire_and_forget && !ignore_conveyor_override)
  616.     if (conveyor == HUB_PIO_CONVEYOR)
  617. conveyor = HUB_PIO_FIRE_N_FORGET;
  618. #endif
  619. /*
  620.  * Get the current register value.
  621.  */
  622. prb_offset = IIO_IOPRB(prbnum);
  623. prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);
  624. /*
  625.  * Clear out some fields.
  626.  */
  627. prb.iprb_ovflow = 1;
  628. prb.iprb_bnakctr = 0;
  629. prb.iprb_anakctr = 0;
  630. /*
  631.  * Enable or disable fire-and-forget mode.
  632.  */
  633. prb.iprb_ff = ((conveyor == HUB_PIO_CONVEYOR) ? 0 : 1);
  634. /*
  635.  * Set the appropriate number of PIO cresits for the widget.
  636.  */
  637. prb.iprb_xtalkctr = credits;
  638. /*
  639.  * Store the new value to the register.
  640.  */
  641. REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
  642. }
  643. /*
  644.  * hub_set_piomode()
  645.  *
  646.  *  Put the hub into either "PIO conveyor belt" mode or "fire-and-forget"
  647.  *  mode.  To do this, we have to make absolutely sure that no PIOs
  648.  * are in progress so we turn off access to all widgets for the duration
  649.  * of the function.
  650.  * 
  651.  * XXX - This code should really check what kind of widget we're talking
  652.  * to.  Bridges can only handle three requests, but XG will do more.
  653.  * How many can crossbow handle to widget 0?  We're assuming 1.
  654.  *
  655.  * XXX - There is a bug in the crossbow that link reset PIOs do not
  656.  * return write responses.  The easiest solution to this problem is to
  657.  * leave widget 0 (xbow) in fire-and-forget mode at all times.  This
  658.  * only affects pio's to xbow registers, which should be rare.
  659.  */
  660. void
  661. hub_set_piomode(nasid_t nasid, int conveyor)
  662. {
  663. hubreg_t ii_iowa;
  664. int direct_connect;
  665. hubii_wcr_t ii_wcr;
  666. int prbnum;
  667. int cons_lock = 0;
  668. ASSERT(NASID_TO_COMPACT_NODEID(nasid) != INVALID_CNODEID);
  669. if (nasid == get_console_nasid()) {
  670. PUTBUF_LOCK(s);
  671. cons_lock = 1;
  672. }
  673. ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
  674. REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);
  675. ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
  676. direct_connect = ii_wcr.iwcr_dir_con;
  677. if (direct_connect) {
  678. /* 
  679.  * Assume a bridge here.
  680.  */
  681. hub_setup_prb(nasid, 0, 3, conveyor);
  682. } else {
  683. /* 
  684.  * Assume a crossbow here.
  685.  */
  686. hub_setup_prb(nasid, 0, 1, conveyor);
  687. }
  688. for (prbnum = HUB_WIDGET_ID_MIN; prbnum <= HUB_WIDGET_ID_MAX; prbnum++) {
  689. /*
  690.  * XXX - Here's where we should take the widget type into
  691.  * when account assigning credits.
  692.  */
  693. /* Always set the PRBs in fire-and-forget mode */
  694. hub_setup_prb(nasid, prbnum, 3, conveyor);
  695. }
  696. REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
  697. if (cons_lock)
  698.     PUTBUF_UNLOCK(s);
  699. }
  700. /* Interface to allow special drivers to set hub specific
  701.  * device flags.
  702.  * Return 0 on failure , 1 on success
  703.  */
  704. int
  705. hub_widget_flags_set(nasid_t nasid,
  706.      xwidgetnum_t widget_num,
  707.      hub_widget_flags_t flags)
  708. {
  709. ASSERT((flags & HUB_WIDGET_FLAGS) == flags);
  710. if (flags & HUB_PIO_CONVEYOR) {
  711. hub_setup_prb(nasid,widget_num,
  712.       3,HUB_PIO_CONVEYOR); /* set the PRB in conveyor 
  713.     * belt mode with 3 credits
  714.     */
  715. } else if (flags & HUB_PIO_FIRE_N_FORGET) {
  716. hub_setup_prb(nasid,widget_num,
  717.       3,HUB_PIO_FIRE_N_FORGET); /* set the PRB in fire
  718.  *  and forget mode 
  719.  */
  720. }
  721. return 1;
  722. }
  723. /* Interface to allow special drivers to set hub specific
  724.  * device flags.
  725.  * Return 0 on failure , 1 on success
  726.  */
  727. int
  728. hub_device_flags_set(devfs_handle_t widget_vhdl,
  729.      hub_widget_flags_t flags)
  730. {
  731. xwidget_info_t widget_info = xwidget_info_get(widget_vhdl);
  732. xwidgetnum_t widget_num  = xwidget_info_id_get(widget_info);
  733. devfs_handle_t hub_vhdl    = xwidget_info_master_get(widget_info);
  734. hubinfo_t hub_info = 0;
  735. nasid_t nasid;
  736. unsigned long s;
  737. int rv;
  738. /* Use the nasid from the hub info hanging off the hub vertex
  739.  * and widget number from the widget vertex
  740.  */
  741. hubinfo_get(hub_vhdl, &hub_info);
  742. /* Being over cautious by grabbing a lock */
  743. s  = mutex_spinlock(&hub_info->h_bwlock);
  744. nasid  = hub_info->h_nasid;
  745. rv  = hub_widget_flags_set(nasid,widget_num,flags);
  746. mutex_spinunlock(&hub_info->h_bwlock, s);
  747. return rv;
  748. }
  749. /*
  750.  * hub_device_inquiry
  751.  * Find out the xtalk widget related information stored in this 
  752.  * hub's II.
  753.  */
  754. void
  755. hub_device_inquiry(devfs_handle_t xbus_vhdl, xwidgetnum_t widget)
  756. {
  757. devfs_handle_t xconn, hub_vhdl;
  758. char widget_name[8];
  759. hubreg_t ii_iidem,ii_iiwa, ii_iowa;
  760. hubinfo_t hubinfo;
  761. nasid_t nasid;
  762. int d;
  763. sprintf(widget_name, "%d", widget);
  764. if (hwgraph_traverse(xbus_vhdl, widget_name, &xconn)
  765.     != GRAPH_SUCCESS)
  766. return;
  767. hub_vhdl = device_master_get(xconn);
  768. if (hub_vhdl == GRAPH_VERTEX_NONE)
  769. return;
  770. hubinfo_get(hub_vhdl, &hubinfo);
  771. if (!hubinfo)
  772. return;
  773. nasid = hubinfo->h_nasid;
  774. ii_iidem = REMOTE_HUB_L(nasid, IIO_IIDEM);
  775. ii_iiwa  = REMOTE_HUB_L(nasid, IIO_IIWA);
  776. ii_iowa  = REMOTE_HUB_L(nasid, IIO_IOWA);
  777. #if defined(SUPPORT_PRINTING_V_FORMAT)
  778. printk("Inquiry Info for %vn", xconn);
  779. #else
  780. printk("Inquiry Info for %pn", (void *)xconn);
  781. #endif
  782. printk("tDevices shutdown [ ");
  783. for (d = 0 ; d <= 7 ; d++)
  784. if (!(ii_iidem & (IIO_IIDEM_WIDGETDEV_MASK(widget,d))))
  785. printk(" %d", d);
  786. printk("]n");
  787. printk("tInbound access ? %sn",
  788. ii_iiwa & IIO_IIWA_WIDGET(widget) ? "yes" : "no");
  789. printk("tOutbound access ? %sn",
  790. ii_iowa & IIO_IOWA_WIDGET(widget) ? "yes" : "no");
  791. }
  792. /*
  793.  * A pointer to this structure hangs off of every hub hwgraph vertex.
  794.  * The generic xtalk layer may indirect through it to get to this specific
  795.  * crosstalk bus provider.
  796.  */
  797. xtalk_provider_t hub_provider = {
  798. (xtalk_piomap_alloc_f *) hub_piomap_alloc,
  799. (xtalk_piomap_free_f *) hub_piomap_free,
  800. (xtalk_piomap_addr_f *) hub_piomap_addr,
  801. (xtalk_piomap_done_f *) hub_piomap_done,
  802. (xtalk_piotrans_addr_f *) hub_piotrans_addr,
  803. (xtalk_dmamap_alloc_f *) hub_dmamap_alloc,
  804. (xtalk_dmamap_free_f *) hub_dmamap_free,
  805. (xtalk_dmamap_addr_f *) hub_dmamap_addr,
  806. (xtalk_dmamap_list_f *) hub_dmamap_list,
  807. (xtalk_dmamap_done_f *) hub_dmamap_done,
  808. (xtalk_dmatrans_addr_f *) hub_dmatrans_addr,
  809. (xtalk_dmatrans_list_f *) hub_dmatrans_list,
  810. (xtalk_dmamap_drain_f *) hub_dmamap_drain,
  811. (xtalk_dmaaddr_drain_f *) hub_dmaaddr_drain,
  812. (xtalk_dmalist_drain_f *) hub_dmalist_drain,
  813. (xtalk_intr_alloc_f *) hub_intr_alloc,
  814. (xtalk_intr_alloc_f *) hub_intr_alloc_nothd,
  815. (xtalk_intr_free_f *) hub_intr_free,
  816. (xtalk_intr_connect_f *) hub_intr_connect,
  817. (xtalk_intr_disconnect_f *) hub_intr_disconnect,
  818. (xtalk_intr_cpu_get_f *) hub_intr_cpu_get,
  819. (xtalk_provider_startup_f *) hub_provider_startup,
  820. (xtalk_provider_shutdown_f *) hub_provider_shutdown,
  821. };