2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
9 #include <linux/types.h>
10 #include <linux/slab.h>
11 #include <linux/sched.h>
12 #include <asm/sn/types.h>
13 #include <asm/sn/sgi.h>
14 #include <asm/sn/driver.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/hcl.h>
22 #include <asm/sn/hcl_util.h>
23 #include <asm/sn/intr.h>
24 #include <asm/sn/xtalk/xtalkaddrs.h>
25 #include <asm/sn/klconfig.h>
26 #include <asm/sn/sn_cpuid.h>
28 extern xtalk_provider_t hub_provider;
30 static int force_fire_and_forget = 1;
31 static int ignore_conveyor_override;
35 * Implementation of hub iobus operations.
37 * Hub provides a crosstalk "iobus" on IP27 systems. These routines
38 * provide a platform-specific implementation of xtalk used by all xtalk
39 * cards on IP27 systems.
41 * Called from corresponding xtalk_* routines.
46 /* For mapping system virtual address space to xtalk space on a specified widget */
49 * Setup pio structures needed for a particular hub.
52 hub_pio_init(vertex_hdl_t hubv)
58 hub_piomap_t hub_piomap;
60 hubinfo_get(hubv, &hubinfo);
61 nasid = hubinfo->h_nasid;
63 /* Initialize small window piomaps for this hub */
64 for (widget=0; widget <= HUB_WIDGET_ID_MAX; widget++) {
65 hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
66 hub_piomap->hpio_xtalk_info.xp_target = widget;
67 hub_piomap->hpio_xtalk_info.xp_xtalk_addr = 0;
68 hub_piomap->hpio_xtalk_info.xp_mapsz = SWIN_SIZE;
69 hub_piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)NODE_SWIN_BASE(nasid, widget);
70 hub_piomap->hpio_hub = hubv;
71 hub_piomap->hpio_flags = HUB_PIOMAP_IS_VALID;
74 /* Initialize big window piomaps for this hub */
75 for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
76 hub_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin);
77 hub_piomap->hpio_xtalk_info.xp_mapsz = BWIN_SIZE;
78 hub_piomap->hpio_hub = hubv;
79 hub_piomap->hpio_holdcnt = 0;
80 hub_piomap->hpio_flags = HUB_PIOMAP_IS_BIGWINDOW;
81 IIO_ITTE_DISABLE(nasid, bigwin);
83 hub_set_piomode(nasid, HUB_PIO_CONVEYOR);
85 spin_lock_init(&hubinfo->h_bwlock);
86 init_waitqueue_head(&hubinfo->h_bwwait);
90 * Create a caddr_t-to-xtalk_addr mapping.
92 * Use a small window if possible (that's the usual case), but
93 * manage big windows if needed. Big window mappings can be
94 * either FIXED or UNFIXED -- we keep at least 1 big window available
95 * for UNFIXED mappings.
97 * Returns an opaque pointer-sized type which can be passed to
98 * other hub_pio_* routines on success, or NULL if the request
99 * cannot be satisfied.
103 hub_piomap_alloc(vertex_hdl_t dev, /* set up mapping for this device */
104 device_desc_t dev_desc, /* device descriptor */
105 iopaddr_t xtalk_addr, /* map for this xtalk_addr range */
107 size_t byte_count_max, /* maximum size of a mapping */
108 unsigned flags) /* defined in sys/pio.h */
110 xwidget_info_t widget_info = xwidget_info_get(dev);
111 xwidgetnum_t widget = xwidget_info_id_get(widget_info);
112 vertex_hdl_t hubv = xwidget_info_master_get(widget_info);
114 hub_piomap_t bw_piomap;
115 int bigwin, free_bw_index;
117 volatile hubreg_t junk;
119 #ifdef PIOMAP_UNC_ACC_SPACE
124 if (byte_count_max > byte_count)
127 hubinfo_get(hubv, &hubinfo);
129 /* If xtalk_addr range is mapped by a small window, we don't have
132 if (xtalk_addr + byte_count <= SWIN_SIZE) {
135 piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
136 #ifdef PIOMAP_UNC_ACC_SPACE
137 if (flags & PIOMAP_UNC_ACC) {
138 addr = (uint64_t)piomap->hpio_xtalk_info.xp_kvaddr;
139 addr |= PIOMAP_UNC_ACC_SPACE;
140 piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)addr;
146 /* We need to use a big window mapping. */
149 * TBD: Allow requests that would consume multiple big windows --
150 * split the request up and use multiple mapping entries.
151 * For now, reject requests that span big windows.
153 if ((xtalk_addr % BWIN_SIZE) + byte_count > BWIN_SIZE)
157 /* Round xtalk address down for big window alignement */
158 xtalk_addr = xtalk_addr & ~(BWIN_SIZE-1);
161 * Check to see if an existing big window mapping will suffice.
165 spin_lock(&hubinfo->h_bwlock);
166 for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
167 bw_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin);
169 /* If mapping is not valid, skip it */
170 if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_VALID)) {
171 free_bw_index = bigwin;
176 * If mapping is UNFIXED, skip it. We don't allow sharing
177 * of UNFIXED mappings, because this would allow starvation.
179 if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED))
182 if ( xtalk_addr == bw_piomap->hpio_xtalk_info.xp_xtalk_addr &&
183 widget == bw_piomap->hpio_xtalk_info.xp_target) {
184 bw_piomap->hpio_holdcnt++;
185 spin_unlock(&hubinfo->h_bwlock);
191 * None of the existing big window mappings will work for us --
192 * we need to establish a new mapping.
195 /* Insure that we don't consume all big windows with FIXED mappings */
196 if (flags & PIOMAP_FIXED) {
197 if (hubinfo->h_num_big_window_fixed < HUB_NUM_BIG_WINDOW-1) {
198 ASSERT(free_bw_index >= 0);
199 hubinfo->h_num_big_window_fixed++;
204 } else /* PIOMAP_UNFIXED */ {
205 if (free_bw_index < 0) {
206 if (flags & PIOMAP_NOSLEEP) {
210 DECLARE_WAITQUEUE(wait, current);
212 spin_unlock(&hubinfo->h_bwlock);
213 set_current_state(TASK_UNINTERRUPTIBLE);
214 add_wait_queue_exclusive(&hubinfo->h_bwwait, &wait);
216 remove_wait_queue(&hubinfo->h_bwwait, &wait);
223 /* OK! Allocate big window free_bw_index for this mapping. */
225 * The code below does a PIO write to setup an ITTE entry.
226 * We need to prevent other CPUs from seeing our updated memory
227 * shadow of the ITTE (in the piomap) until the ITTE entry is
228 * actually set up; otherwise, another CPU might attempt a PIO
231 * Also, the only way we can know that an entry has been received
232 * by the hub and can be used by future PIO reads/writes is by
233 * reading back the ITTE entry after writing it.
235 * For these two reasons, we PIO read back the ITTE entry after
239 nasid = hubinfo->h_nasid;
240 IIO_ITTE_PUT(nasid, free_bw_index, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
241 junk = HUB_L(IIO_ITTE_GET(nasid, free_bw_index));
243 bw_piomap = hubinfo_bwin_piomap_get(hubinfo, free_bw_index);
244 bw_piomap->hpio_xtalk_info.xp_dev = dev;
245 bw_piomap->hpio_xtalk_info.xp_target = widget;
246 bw_piomap->hpio_xtalk_info.xp_xtalk_addr = xtalk_addr;
247 kvaddr = (caddr_t)NODE_BWIN_BASE(nasid, free_bw_index);
248 #ifdef PIOMAP_UNC_ACC_SPACE
249 if (flags & PIOMAP_UNC_ACC) {
250 addr = (uint64_t)kvaddr;
251 addr |= PIOMAP_UNC_ACC_SPACE;
252 kvaddr = (caddr_t)addr;
255 bw_piomap->hpio_xtalk_info.xp_kvaddr = kvaddr;
256 bw_piomap->hpio_holdcnt++;
257 bw_piomap->hpio_bigwin_num = free_bw_index;
259 if (flags & PIOMAP_FIXED)
260 bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED;
262 bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID;
265 spin_unlock(&hubinfo->h_bwlock);
270 * hub_piomap_free destroys a caddr_t-to-xtalk pio mapping and frees
271 * any associated mapping resources.
273 * If this * piomap was handled with a small window, or if it was handled
274 * in a big window that's still in use by someone else, then there's
275 * nothing to do. On the other hand, if this mapping was handled
276 * with a big window, AND if we were the final user of that mapping,
277 * then destroy the mapping.
280 hub_piomap_free(hub_piomap_t hub_piomap)
287 * Small windows are permanently mapped to corresponding widgets,
288 * so there're no resources to free.
290 if (!(hub_piomap->hpio_flags & HUB_PIOMAP_IS_BIGWINDOW))
293 ASSERT(hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID);
294 ASSERT(hub_piomap->hpio_holdcnt > 0);
296 hubv = hub_piomap->hpio_hub;
297 hubinfo_get(hubv, &hubinfo);
298 nasid = hubinfo->h_nasid;
300 spin_lock(&hubinfo->h_bwlock);
303 * If this is the last hold on this mapping, free it.
305 if (--hub_piomap->hpio_holdcnt == 0) {
306 IIO_ITTE_DISABLE(nasid, hub_piomap->hpio_bigwin_num );
308 if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED) {
309 hub_piomap->hpio_flags &= ~(HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED);
310 hubinfo->h_num_big_window_fixed--;
311 ASSERT(hubinfo->h_num_big_window_fixed >= 0);
313 hub_piomap->hpio_flags &= ~HUB_PIOMAP_IS_VALID;
315 wake_up(&hubinfo->h_bwwait);
318 spin_unlock(&hubinfo->h_bwlock);
322 * Establish a mapping to a given xtalk address range using the resources
326 hub_piomap_addr(hub_piomap_t hub_piomap, /* mapping resources */
327 iopaddr_t xtalk_addr, /* map for this xtalk address */
328 size_t byte_count) /* map this many bytes */
330 /* Verify that range can be mapped using the specified piomap */
331 if (xtalk_addr < hub_piomap->hpio_xtalk_info.xp_xtalk_addr)
334 if (xtalk_addr + byte_count >
335 ( hub_piomap->hpio_xtalk_info.xp_xtalk_addr +
336 hub_piomap->hpio_xtalk_info.xp_mapsz))
339 if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID)
340 return hub_piomap->hpio_xtalk_info.xp_kvaddr +
341 (xtalk_addr % hub_piomap->hpio_xtalk_info.xp_mapsz);
348 * Driver indicates that it's done with PIO's from an earlier piomap_addr.
352 hub_piomap_done(hub_piomap_t hub_piomap) /* done with these mapping resources */
359 * For translations that require no mapping resources, supply a kernel virtual
360 * address that maps to the specified xtalk address range.
364 hub_piotrans_addr( vertex_hdl_t dev, /* translate to this device */
365 device_desc_t dev_desc, /* device descriptor */
366 iopaddr_t xtalk_addr, /* Crosstalk address */
367 size_t byte_count, /* map this many bytes */
368 unsigned flags) /* (currently unused) */
370 xwidget_info_t widget_info = xwidget_info_get(dev);
371 xwidgetnum_t widget = xwidget_info_id_get(widget_info);
372 vertex_hdl_t hubv = xwidget_info_master_get(widget_info);
373 hub_piomap_t hub_piomap;
377 hubinfo_get(hubv, &hubinfo);
379 if (xtalk_addr + byte_count <= SWIN_SIZE) {
380 hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
381 addr = hub_piomap_addr(hub_piomap, xtalk_addr, byte_count);
382 #ifdef PIOMAP_UNC_ACC_SPACE
383 if (flags & PIOMAP_UNC_ACC) {
385 iaddr = (uint64_t)addr;
386 iaddr |= PIOMAP_UNC_ACC_SPACE;
387 addr = (caddr_t)iaddr;
397 /* Mapping from crosstalk space to system physical space */
401 * Allocate resources needed to set up DMA mappings up to a specified size
402 * on a specified adapter.
404 * We don't actually use the adapter ID for anything. It's just the adapter
405 * that the lower level driver plans to use for DMA.
409 hub_dmamap_alloc( vertex_hdl_t dev, /* set up mappings for this device */
410 device_desc_t dev_desc, /* device descriptor */
411 size_t byte_count_max, /* max size of a mapping */
412 unsigned flags) /* defined in dma.h */
415 xwidget_info_t widget_info = xwidget_info_get(dev);
416 xwidgetnum_t widget = xwidget_info_id_get(widget_info);
417 vertex_hdl_t hubv = xwidget_info_master_get(widget_info);
419 dmamap = kmalloc(sizeof(struct hub_dmamap_s), GFP_ATOMIC);
420 dmamap->hdma_xtalk_info.xd_dev = dev;
421 dmamap->hdma_xtalk_info.xd_target = widget;
422 dmamap->hdma_hub = hubv;
423 dmamap->hdma_flags = HUB_DMAMAP_IS_VALID;
424 if (flags & XTALK_FIXED)
425 dmamap->hdma_flags |= HUB_DMAMAP_IS_FIXED;
431 * Destroy a DMA mapping from crosstalk space to system address space.
432 * There is no actual mapping hardware to destroy, but we at least mark
433 * the dmamap INVALID and free the space that it took.
436 hub_dmamap_free(hub_dmamap_t hub_dmamap)
438 hub_dmamap->hdma_flags &= ~HUB_DMAMAP_IS_VALID;
443 * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc.
444 * Return an appropriate crosstalk address range that maps to the specified physical
449 hub_dmamap_addr( hub_dmamap_t dmamap, /* use these mapping resources */
450 paddr_t paddr, /* map for this address */
451 size_t byte_count) /* map this many bytes */
455 ASSERT(dmamap->hdma_flags & HUB_DMAMAP_IS_VALID);
457 if (dmamap->hdma_flags & HUB_DMAMAP_USED) {
458 /* If the map is FIXED, re-use is OK. */
459 if (!(dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
460 char name[MAXDEVNAME];
461 vhdl = dmamap->hdma_xtalk_info.xd_dev;
462 printk(KERN_WARNING "%s: hub_dmamap_addr re-uses dmamap.\n", vertex_to_name(vhdl, name, MAXDEVNAME));
465 dmamap->hdma_flags |= HUB_DMAMAP_USED;
468 /* There isn't actually any DMA mapping hardware on the hub. */
469 return (PHYS_TO_DMA(paddr));
473 * Driver indicates that it has completed whatever DMA it may have started
474 * after an earlier dmamap_addr call.
477 hub_dmamap_done(hub_dmamap_t hub_dmamap) /* done with these mapping resources */
481 if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) {
482 hub_dmamap->hdma_flags &= ~HUB_DMAMAP_USED;
484 /* If the map is FIXED, re-done is OK. */
485 if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
486 char name[MAXDEVNAME];
487 vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
488 printk(KERN_WARNING "%s: hub_dmamap_done already done with dmamap\n", vertex_to_name(vhdl, name, MAXDEVNAME));
494 * Translate a single system physical address into a crosstalk address.
498 hub_dmatrans_addr( vertex_hdl_t dev, /* translate for this device */
499 device_desc_t dev_desc, /* device descriptor */
500 paddr_t paddr, /* system physical address */
501 size_t byte_count, /* length */
502 unsigned flags) /* defined in dma.h */
504 return (PHYS_TO_DMA(paddr));
509 hub_dmamap_drain( hub_dmamap_t map)
511 /* XXX- flush caches, if cache coherency WAR is needed */
516 hub_dmaaddr_drain( vertex_hdl_t vhdl,
520 /* XXX- flush caches, if cache coherency WAR is needed */
524 /* CONFIGURATION MANAGEMENT */
527 * Perform initializations that allow this hub to start crosstalk support.
530 hub_provider_startup(vertex_hdl_t hubv)
534 hubinfo_get(hubv, &hubinfo);
536 intr_init_vecblk(nasid_to_cnodeid(hubinfo->h_nasid));
540 * Shutdown crosstalk support from a hub.
543 hub_provider_shutdown(vertex_hdl_t hub)
546 xtalk_provider_unregister(hub);
550 * Check that an address is in the real small window widget 0 space
551 * or else in the big window we're using to emulate small window 0
555 hub_check_is_widget0(void *addr)
557 nasid_t nasid = NASID_GET(addr);
559 if (((unsigned long)addr >= RAW_NODE_SWIN_BASE(nasid, 0)) &&
560 ((unsigned long)addr < RAW_NODE_SWIN_BASE(nasid, 1)))
567 * Check that two addresses use the same widget
570 hub_check_window_equiv(void *addra, void *addrb)
572 if (hub_check_is_widget0(addra) && hub_check_is_widget0(addrb))
575 /* XXX - Assume this is really a small window address */
576 if (WIDGETID_GET((unsigned long)addra) ==
577 WIDGETID_GET((unsigned long)addrb))
585 * hub_setup_prb(nasid, prbnum, credits, conveyor)
587 * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise,
588 * put it into conveyor belt mode with the specified number of credits.
591 hub_setup_prb(nasid_t nasid, int prbnum, int credits, int conveyor)
596 if (force_fire_and_forget && !ignore_conveyor_override)
597 if (conveyor == HUB_PIO_CONVEYOR)
598 conveyor = HUB_PIO_FIRE_N_FORGET;
601 * Get the current register value.
603 prb_offset = IIO_IOPRB(prbnum);
604 prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);
607 * Clear out some fields.
610 prb.iprb_bnakctr = 0;
611 prb.iprb_anakctr = 0;
614 * Enable or disable fire-and-forget mode.
616 prb.iprb_ff = ((conveyor == HUB_PIO_CONVEYOR) ? 0 : 1);
619 * Set the appropriate number of PIO cresits for the widget.
621 prb.iprb_xtalkctr = credits;
624 * Store the new value to the register.
626 REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
632 * Put the hub into either "PIO conveyor belt" mode or "fire-and-forget"
633 * mode. To do this, we have to make absolutely sure that no PIOs
634 * are in progress so we turn off access to all widgets for the duration
637 * XXX - This code should really check what kind of widget we're talking
638 * to. Bridges can only handle three requests, but XG will do more.
639 * How many can crossbow handle to widget 0? We're assuming 1.
641 * XXX - There is a bug in the crossbow that link reset PIOs do not
642 * return write responses. The easiest solution to this problem is to
643 * leave widget 0 (xbow) in fire-and-forget mode at all times. This
644 * only affects pio's to xbow registers, which should be rare.
647 hub_set_piomode(nasid_t nasid, int conveyor)
654 ASSERT(nasid_to_cnodeid(nasid) != INVALID_CNODEID);
656 ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
657 REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);
659 ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
660 direct_connect = ii_wcr.iwcr_dir_con;
662 if (direct_connect) {
664 * Assume a bridge here.
666 hub_setup_prb(nasid, 0, 3, conveyor);
669 * Assume a crossbow here.
671 hub_setup_prb(nasid, 0, 1, conveyor);
674 for (prbnum = HUB_WIDGET_ID_MIN; prbnum <= HUB_WIDGET_ID_MAX; prbnum++) {
676 * XXX - Here's where we should take the widget type into
677 * when account assigning credits.
679 /* Always set the PRBs in fire-and-forget mode */
680 hub_setup_prb(nasid, prbnum, 3, conveyor);
683 REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
685 /* Interface to allow special drivers to set hub specific
687 * Return 0 on failure , 1 on success
690 hub_widget_flags_set(nasid_t nasid,
691 xwidgetnum_t widget_num,
692 hub_widget_flags_t flags)
695 ASSERT((flags & HUB_WIDGET_FLAGS) == flags);
697 if (flags & HUB_PIO_CONVEYOR) {
698 hub_setup_prb(nasid,widget_num,
699 3,HUB_PIO_CONVEYOR); /* set the PRB in conveyor
700 * belt mode with 3 credits
702 } else if (flags & HUB_PIO_FIRE_N_FORGET) {
703 hub_setup_prb(nasid,widget_num,
704 3,HUB_PIO_FIRE_N_FORGET); /* set the PRB in fire
713 * A pointer to this structure hangs off of every hub hwgraph vertex.
714 * The generic xtalk layer may indirect through it to get to this specific
715 * crosstalk bus provider.
717 xtalk_provider_t hub_provider = {
718 .piomap_alloc = (xtalk_piomap_alloc_f *) hub_piomap_alloc,
719 .piomap_free = (xtalk_piomap_free_f *) hub_piomap_free,
720 .piomap_addr = (xtalk_piomap_addr_f *) hub_piomap_addr,
721 .piomap_done = (xtalk_piomap_done_f *) hub_piomap_done,
722 .piotrans_addr = (xtalk_piotrans_addr_f *) hub_piotrans_addr,
724 .dmamap_alloc = (xtalk_dmamap_alloc_f *) hub_dmamap_alloc,
725 .dmamap_free = (xtalk_dmamap_free_f *) hub_dmamap_free,
726 .dmamap_addr = (xtalk_dmamap_addr_f *) hub_dmamap_addr,
727 .dmamap_done = (xtalk_dmamap_done_f *) hub_dmamap_done,
728 .dmatrans_addr = (xtalk_dmatrans_addr_f *) hub_dmatrans_addr,
729 .dmamap_drain = (xtalk_dmamap_drain_f *) hub_dmamap_drain,
730 .dmaaddr_drain = (xtalk_dmaaddr_drain_f *) hub_dmaaddr_drain,
732 .intr_alloc = (xtalk_intr_alloc_f *) hub_intr_alloc,
733 .intr_alloc_nothd = (xtalk_intr_alloc_f *) hub_intr_alloc_nothd,
734 .intr_free = (xtalk_intr_free_f *) hub_intr_free,
735 .intr_connect = (xtalk_intr_connect_f *) hub_intr_connect,
736 .intr_disconnect = (xtalk_intr_disconnect_f *) hub_intr_disconnect,
737 .provider_startup = (xtalk_provider_startup_f *) hub_provider_startup,
738 .provider_shutdown = (xtalk_provider_shutdown_f *) hub_provider_shutdown,