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