File: /usr/src/linux/arch/ia64/sn/io/xtalk.c

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     
11     #include <linux/types.h>
12     #include <linux/slab.h>
13     #include <asm/sn/sgi.h>
14     #include <asm/sn/iobus.h>
15     #include <asm/sn/iograph.h>
16     #include <asm/sn/invent.h>
17     #include <asm/sn/hcl.h>
18     #include <asm/sn/labelcl.h>
19     #include <asm/sn/hcl_util.h>
20     
21     #include <asm/sn/xtalk/xtalk.h>
22     #include <asm/sn/xtalk/xswitch.h>
23     #include <asm/sn/xtalk/xwidget.h>
24     
25     #include <asm/sn/xtalk/xtalk_private.h>
26     
27     /*
28      * Implement crosstalk provider operations.  The xtalk* layer provides a
29      * platform-independent interface for crosstalk devices.  This layer
30      * switches among the possible implementations of a crosstalk adapter.
31      *
32      * On platforms with only one possible xtalk provider, macros can be
33      * set up at the top that cause the table lookups and indirections to
34      * completely disappear.
35      */
36     
37     #define	NEW(ptr)	(ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
38     #define	DEL(ptr)	(kfree(ptr))
39     
40     char                    widget_info_fingerprint[] = "widget_info";
41     
42     cdl_p                   xtalk_registry = NULL;
43     
44     #include <asm/sn/agent.h>
45     #define	DEV_FUNC(dev,func)	hub_##func
46     #define	CAST_PIOMAP(x)		((hub_piomap_t)(x))
47     #define	CAST_DMAMAP(x)		((hub_dmamap_t)(x))
48     #define	CAST_INTR(x)		((hub_intr_t)(x))
49     
50     /* =====================================================================
51      *            Function Table of Contents
52      */
53     xtalk_piomap_t          xtalk_piomap_alloc(devfs_handle_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned);
54     void                    xtalk_piomap_free(xtalk_piomap_t);
55     caddr_t                 xtalk_piomap_addr(xtalk_piomap_t, iopaddr_t, size_t);
56     void                    xtalk_piomap_done(xtalk_piomap_t);
57     caddr_t                 xtalk_piotrans_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, unsigned);
58     caddr_t                 xtalk_pio_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned);
59     void                    xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *);
60     caddr_t                 xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
61     static caddr_t          null_xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
62     xtalk_dmamap_t          xtalk_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned);
63     void                    xtalk_dmamap_free(xtalk_dmamap_t);
64     iopaddr_t               xtalk_dmamap_addr(xtalk_dmamap_t, paddr_t, size_t);
65     alenlist_t              xtalk_dmamap_list(xtalk_dmamap_t, alenlist_t, unsigned);
66     void                    xtalk_dmamap_done(xtalk_dmamap_t);
67     iopaddr_t               xtalk_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned);
68     alenlist_t              xtalk_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned);
69     void			xtalk_dmamap_drain(xtalk_dmamap_t);
70     void			xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t);
71     void			xtalk_dmalist_drain(devfs_handle_t, alenlist_t);
72     xtalk_intr_t            xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t);
73     xtalk_intr_t            xtalk_intr_alloc_nothd(devfs_handle_t, device_desc_t, devfs_handle_t);
74     void                    xtalk_intr_free(xtalk_intr_t);
75     int                     xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *, void *);
76     void                    xtalk_intr_disconnect(xtalk_intr_t);
77     devfs_handle_t            xtalk_intr_cpu_get(xtalk_intr_t);
78     int                     xtalk_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *);
79     int                     xtalk_error_devenable(devfs_handle_t, int, int);
80     void                    xtalk_provider_startup(devfs_handle_t);
81     void                    xtalk_provider_shutdown(devfs_handle_t);
82     devfs_handle_t            xtalk_intr_dev_get(xtalk_intr_t);
83     xwidgetnum_t            xtalk_intr_target_get(xtalk_intr_t);
84     xtalk_intr_vector_t     xtalk_intr_vector_get(xtalk_intr_t);
85     iopaddr_t               xtalk_intr_addr_get(struct xtalk_intr_s *);
86     void                   *xtalk_intr_sfarg_get(xtalk_intr_t);
87     devfs_handle_t            xtalk_pio_dev_get(xtalk_piomap_t);
88     xwidgetnum_t            xtalk_pio_target_get(xtalk_piomap_t);
89     iopaddr_t               xtalk_pio_xtalk_addr_get(xtalk_piomap_t);
90     ulong                   xtalk_pio_mapsz_get(xtalk_piomap_t);
91     caddr_t                 xtalk_pio_kvaddr_get(xtalk_piomap_t);
92     devfs_handle_t            xtalk_dma_dev_get(xtalk_dmamap_t);
93     xwidgetnum_t            xtalk_dma_target_get(xtalk_dmamap_t);
94     xwidget_info_t          xwidget_info_chk(devfs_handle_t);
95     xwidget_info_t          xwidget_info_get(devfs_handle_t);
96     void                    xwidget_info_set(devfs_handle_t, xwidget_info_t);
97     devfs_handle_t            xwidget_info_dev_get(xwidget_info_t);
98     xwidgetnum_t            xwidget_info_id_get(xwidget_info_t);
99     devfs_handle_t            xwidget_info_master_get(xwidget_info_t);
100     xwidgetnum_t            xwidget_info_masterid_get(xwidget_info_t);
101     xwidget_part_num_t      xwidget_info_part_num_get(xwidget_info_t);
102     xwidget_mfg_num_t       xwidget_info_mfg_num_get(xwidget_info_t);
103     char 			*xwidget_info_name_get(xwidget_info_t);
104     void                    xtalk_init(void);
105     void                    xtalk_provider_register(devfs_handle_t, xtalk_provider_t *);
106     void                    xtalk_provider_unregister(devfs_handle_t);
107     xtalk_provider_t       *xtalk_provider_fns_get(devfs_handle_t);
108     int                     xwidget_driver_register(xwidget_part_num_t, 
109     						xwidget_mfg_num_t, 
110     						char *, unsigned);
111     void                    xwidget_driver_unregister(char *);
112     int                     xwidget_register(xwidget_hwid_t, devfs_handle_t, 
113     					 xwidgetnum_t, devfs_handle_t, 
114     					 xwidgetnum_t, async_attach_t);
115     int			xwidget_unregister(devfs_handle_t);
116     void                    xwidget_error_register(devfs_handle_t, error_handler_f *,
117     					       error_handler_arg_t);
118     void                    xwidget_reset(devfs_handle_t);
119     char			*xwidget_name_get(devfs_handle_t);
120     #if !defined(DEV_FUNC)
121     /*
122      * There is more than one possible provider
123      * for this platform. We need to examine the
124      * master vertex of the current vertex for
125      * a provider function structure, and indirect
126      * through the appropriately named member.
127      */
128     #define	DEV_FUNC(dev,func)	xwidget_to_provider_fns(dev)->func
129     #define	CAST_PIOMAP(x)		((xtalk_piomap_t)(x))
130     #define	CAST_DMAMAP(x)		((xtalk_dmamap_t)(x))
131     #define	CAST_INTR(x)		((xtalk_intr_t)(x))
132     
133     static xtalk_provider_t *
134     xwidget_to_provider_fns(devfs_handle_t xconn)
135     {
136         xwidget_info_t          widget_info;
137         xtalk_provider_t       *provider_fns;
138     
139         widget_info = xwidget_info_get(xconn);
140         ASSERT(widget_info != NULL);
141     
142         provider_fns = xwidget_info_pops_get(widget_info);
143         ASSERT(provider_fns != NULL);
144     
145         return (provider_fns);
146     }
147     #endif
148     
149     /*
150      * Many functions are not passed their vertex
151      * information directly; rather, they must
152      * dive through a resource map. These macros
153      * are available to coordinate this detail.
154      */
155     #define	PIOMAP_FUNC(map,func)	DEV_FUNC(map->xp_dev,func)
156     #define	DMAMAP_FUNC(map,func)	DEV_FUNC(map->xd_dev,func)
157     #define	INTR_FUNC(intr,func)	DEV_FUNC(intr_hdl->xi_dev,func)
158     
159     /* =====================================================================
160      *                    PIO MANAGEMENT
161      *
162      *      For mapping system virtual address space to
163      *      xtalk space on a specified widget
164      */
165     
166     xtalk_piomap_t
167     xtalk_piomap_alloc(devfs_handle_t dev,	/* set up mapping for this device */
168     		   device_desc_t dev_desc,	/* device descriptor */
169     		   iopaddr_t xtalk_addr,	/* map for this xtalk_addr range */
170     		   size_t byte_count,
171     		   size_t byte_count_max,	/* maximum size of a mapping */
172     		   unsigned flags)
173     {				/* defined in sys/pio.h */
174         return (xtalk_piomap_t) DEV_FUNC(dev, piomap_alloc)
175     	(dev, dev_desc, xtalk_addr, byte_count, byte_count_max, flags);
176     }
177     
178     
179     void
180     xtalk_piomap_free(xtalk_piomap_t xtalk_piomap)
181     {
182         PIOMAP_FUNC(xtalk_piomap, piomap_free)
183     	(CAST_PIOMAP(xtalk_piomap));
184     }
185     
186     
187     caddr_t
188     xtalk_piomap_addr(xtalk_piomap_t xtalk_piomap,	/* mapping resources */
189     		  iopaddr_t xtalk_addr,		/* map for this xtalk address */
190     		  size_t byte_count)
191     {				/* map this many bytes */
192         return PIOMAP_FUNC(xtalk_piomap, piomap_addr)
193     	(CAST_PIOMAP(xtalk_piomap), xtalk_addr, byte_count);
194     }
195     
196     
197     void
198     xtalk_piomap_done(xtalk_piomap_t xtalk_piomap)
199     {
200         PIOMAP_FUNC(xtalk_piomap, piomap_done)
201     	(CAST_PIOMAP(xtalk_piomap));
202     }
203     
204     
205     caddr_t
206     xtalk_piotrans_addr(devfs_handle_t dev,	/* translate for this device */
207     		    device_desc_t dev_desc,	/* device descriptor */
208     		    iopaddr_t xtalk_addr,	/* Crosstalk address */
209     		    size_t byte_count,	/* map this many bytes */
210     		    unsigned flags)
211     {				/* (currently unused) */
212         return DEV_FUNC(dev, piotrans_addr)
213     	(dev, dev_desc, xtalk_addr, byte_count, flags);
214     }
215     
216     caddr_t
217     xtalk_pio_addr(devfs_handle_t dev,	/* translate for this device */
218     	       device_desc_t dev_desc,	/* device descriptor */
219     	       iopaddr_t addr,		/* starting address (or offset in window) */
220     	       size_t byte_count,	/* map this many bytes */
221     	       xtalk_piomap_t *mapp,	/* where to return the map pointer */
222     	       unsigned flags)
223     {					/* PIO flags */
224         xtalk_piomap_t          map = 0;
225         caddr_t                 res;
226     
227         if (mapp)
228     	*mapp = 0;			/* record "no map used" */
229     
230         res = xtalk_piotrans_addr
231     	(dev, dev_desc, addr, byte_count, flags);
232         if (res)
233     	return res;			/* xtalk_piotrans worked */
234     
235         map = xtalk_piomap_alloc
236     	(dev, dev_desc, addr, byte_count, byte_count, flags);
237         if (!map)
238     	return res;			/* xtalk_piomap_alloc failed */
239     
240         res = xtalk_piomap_addr
241     	(map, addr, byte_count);
242         if (!res) {
243     	xtalk_piomap_free(map);
244     	return res;			/* xtalk_piomap_addr failed */
245         }
246         if (mapp)
247     	*mapp = map;			/* pass back map used */
248     
249         return res;				/* xtalk_piomap_addr succeeded */
250     }
251     
252     /* =====================================================================
253      *            EARLY PIOTRANS SUPPORT
254      *
255      *      There are places where drivers (mgras, for instance)
256      *      need to get PIO translations before the infrastructure
257      *      is extended to them (setting up textports, for
258      *      instance). These drivers should call
259      *      xtalk_early_piotrans_addr with their xtalk ID
260      *      information, a sequence number (so we can use the second
261      *      mgras for instance), and the usual piotrans parameters.
262      *
263      *      Machine specific code should provide an implementation
264      *      of early_piotrans_addr, and present a pointer to this
265      *      function to xtalk_set_early_piotrans_addr so it can be
266      *      used by clients without the clients having to know what
267      *      platform or what xtalk provider is in use.
268      */
269     
270     static xtalk_early_piotrans_addr_f null_xtalk_early_piotrans_addr;
271     
272     xtalk_early_piotrans_addr_f *impl_early_piotrans_addr = null_xtalk_early_piotrans_addr;
273     
274     /* xtalk_set_early_piotrans_addr:
275      * specify the early_piotrans_addr implementation function.
276      */
277     void
278     xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *impl)
279     {
280         impl_early_piotrans_addr = impl;
281     }
282     
283     /* xtalk_early_piotrans_addr:
284      * figure out a PIO address for the "nth" crosstalk widget that
285      * matches the specified part and mfgr number. Returns NULL if
286      * there is no such widget, or if the requested mapping can not
287      * be constructed.
288      * Limitations on which crosstalk slots (and busses) are
289      * checked, and definitions of the ordering of the search across
290      * the crosstalk slots, are defined by the platform.
291      */
292     caddr_t
293     xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
294     			  xwidget_mfg_num_t mfg_num,
295     			  int which,
296     			  iopaddr_t xtalk_addr,
297     			  size_t byte_count,
298     			  unsigned flags)
299     {
300         return impl_early_piotrans_addr
301     	(part_num, mfg_num, which, xtalk_addr, byte_count, flags);
302     }
303     
304     /* null_xtalk_early_piotrans_addr:
305      * used as the early_piotrans_addr implementation until and
306      * unless a real implementation is provided. In DEBUG kernels,
307      * we want to know who is calling before the implementation is
308      * registered; in non-DEBUG kernels, return NULL representing
309      * lack of mapping support.
310      */
311     /*ARGSUSED */
312     static caddr_t
313     null_xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
314     			       xwidget_mfg_num_t mfg_num,
315     			       int which,
316     			       iopaddr_t xtalk_addr,
317     			       size_t byte_count,
318     			       unsigned flags)
319     {
320     #if DEBUG
321         PRINT_PANIC("null_xtalk_early_piotrans_addr");
322     #endif
323         return NULL;
324     }
325     
326     /* =====================================================================
327      *                    DMA MANAGEMENT
328      *
329      *      For mapping from crosstalk space to system
330      *      physical space.
331      */
332     
333     xtalk_dmamap_t
334     xtalk_dmamap_alloc(devfs_handle_t dev,	/* set up mappings for this device */
335     		   device_desc_t dev_desc,	/* device descriptor */
336     		   size_t byte_count_max,	/* max size of a mapping */
337     		   unsigned flags)
338     {				/* defined in dma.h */
339         return (xtalk_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
340     	(dev, dev_desc, byte_count_max, flags);
341     }
342     
343     
344     void
345     xtalk_dmamap_free(xtalk_dmamap_t xtalk_dmamap)
346     {
347         DMAMAP_FUNC(xtalk_dmamap, dmamap_free)
348     	(CAST_DMAMAP(xtalk_dmamap));
349     }
350     
351     
352     iopaddr_t
353     xtalk_dmamap_addr(xtalk_dmamap_t xtalk_dmamap,	/* use these mapping resources */
354     		  paddr_t paddr,	/* map for this address */
355     		  size_t byte_count)
356     {				/* map this many bytes */
357         return DMAMAP_FUNC(xtalk_dmamap, dmamap_addr)
358     	(CAST_DMAMAP(xtalk_dmamap), paddr, byte_count);
359     }
360     
361     
362     alenlist_t
363     xtalk_dmamap_list(xtalk_dmamap_t xtalk_dmamap,	/* use these mapping resources */
364     		  alenlist_t alenlist,	/* map this Address/Length List */
365     		  unsigned flags)
366     {
367         return DMAMAP_FUNC(xtalk_dmamap, dmamap_list)
368     	(CAST_DMAMAP(xtalk_dmamap), alenlist, flags);
369     }
370     
371     
372     void
373     xtalk_dmamap_done(xtalk_dmamap_t xtalk_dmamap)
374     {
375         DMAMAP_FUNC(xtalk_dmamap, dmamap_done)
376     	(CAST_DMAMAP(xtalk_dmamap));
377     }
378     
379     
380     iopaddr_t
381     xtalk_dmatrans_addr(devfs_handle_t dev,	/* translate for this device */
382     		    device_desc_t dev_desc,	/* device descriptor */
383     		    paddr_t paddr,	/* system physical address */
384     		    size_t byte_count,	/* length */
385     		    unsigned flags)
386     {				/* defined in dma.h */
387         return DEV_FUNC(dev, dmatrans_addr)
388     	(dev, dev_desc, paddr, byte_count, flags);
389     }
390     
391     
392     alenlist_t
393     xtalk_dmatrans_list(devfs_handle_t dev,	/* translate for this device */
394     		    device_desc_t dev_desc,	/* device descriptor */
395     		    alenlist_t palenlist,	/* system address/length list */
396     		    unsigned flags)
397     {				/* defined in dma.h */
398         return DEV_FUNC(dev, dmatrans_list)
399     	(dev, dev_desc, palenlist, flags);
400     }
401     
402     void
403     xtalk_dmamap_drain(xtalk_dmamap_t map)
404     {
405         DMAMAP_FUNC(map, dmamap_drain)
406     	(CAST_DMAMAP(map));
407     }
408     
409     void
410     xtalk_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size)
411     {
412         DEV_FUNC(dev, dmaaddr_drain)
413     	(dev, addr, size);
414     }
415     
416     void
417     xtalk_dmalist_drain(devfs_handle_t dev, alenlist_t list)
418     {
419         DEV_FUNC(dev, dmalist_drain)
420     	(dev, list);
421     }
422     
423     /* =====================================================================
424      *                    INTERRUPT MANAGEMENT
425      *
426      *      Allow crosstalk devices to establish interrupts
427      */
428     
429     /*
430      * Allocate resources required for an interrupt as specified in intr_desc.
431      * Return resource handle in intr_hdl.
432      */
433     xtalk_intr_t
434     xtalk_intr_alloc(devfs_handle_t dev,	/* which Crosstalk device */
435     		 device_desc_t dev_desc,	/* device descriptor */
436     		 devfs_handle_t owner_dev)
437     {				/* owner of this interrupt */
438         return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc)
439     	(dev, dev_desc, owner_dev);
440     }
441     
442     /*
443      * Allocate resources required for an interrupt as specified in dev_desc.
444      * Unconditionally setup resources to be non-threaded.
445      * Return resource handle in intr_hdl.
446      */
447     xtalk_intr_t
448     xtalk_intr_alloc_nothd(devfs_handle_t dev,	/* which Crosstalk device */
449     		 	device_desc_t dev_desc,	/* device descriptor */
450     		 	devfs_handle_t owner_dev)	/* owner of this interrupt */
451     {
452         return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc_nothd)
453     	(dev, dev_desc, owner_dev);
454     }
455     
456     /*
457      * Free resources consumed by intr_alloc.
458      */
459     void
460     xtalk_intr_free(xtalk_intr_t intr_hdl)
461     {
462         INTR_FUNC(intr_hdl, intr_free)
463     	(CAST_INTR(intr_hdl));
464     }
465     
466     
467     /*
468      * Associate resources allocated with a previous xtalk_intr_alloc call with the
469      * described handler, arg, name, etc.
470      *
471      * Returns 0 on success, returns <0 on failure.
472      */
473     int
474     xtalk_intr_connect(xtalk_intr_t intr_hdl,	/* xtalk intr resource handle */
475     		   intr_func_t intr_func,	/* xtalk intr handler */
476     		   intr_arg_t intr_arg,		/* arg to intr handler */
477     		   xtalk_intr_setfunc_t setfunc,	/* func to set intr hw */
478     		   void *setfunc_arg,	/* arg to setfunc */
479     		   void *thread)
480     {				/* intr thread to use */
481         return INTR_FUNC(intr_hdl, intr_connect)
482     	(CAST_INTR(intr_hdl), intr_func, intr_arg, setfunc, setfunc_arg, thread);
483     }
484     
485     
486     /*
487      * Disassociate handler with the specified interrupt.
488      */
489     void
490     xtalk_intr_disconnect(xtalk_intr_t intr_hdl)
491     {
492         INTR_FUNC(intr_hdl, intr_disconnect)
493     	(CAST_INTR(intr_hdl));
494     }
495     
496     
497     /*
498      * Return a hwgraph vertex that represents the CPU currently
499      * targeted by an interrupt.
500      */
501     devfs_handle_t
502     xtalk_intr_cpu_get(xtalk_intr_t intr_hdl)
503     {
504         return INTR_FUNC(intr_hdl, intr_cpu_get)
505     	(CAST_INTR(intr_hdl));
506     }
507     
508     
509     /*
510      * =====================================================================
511      *                      ERROR MANAGEMENT
512      */
513     
514     /*
515      * xtalk_error_handler:
516      * pass this error on to the handler registered
517      * at the specified xtalk connecdtion point,
518      * or complain about it here if there is no handler.
519      *
520      * This routine plays two roles during error delivery
521      * to most widgets: first, the external agent (heart,
522      * hub, or whatever) calls in with the error and the
523      * connect point representing the crosstalk switch,
524      * or whatever crosstalk device is directly connected
525      * to the agent.
526      *
527      * If there is a switch, it will generally look at the
528      * widget number stashed in the ioerror structure; and,
529      * if the error came from some widget other than the
530      * switch, it will call back into xtalk_error_handler
531      * with the connection point of the offending port.
532      */
533     int
534     xtalk_error_handler(
535     		       devfs_handle_t xconn,
536     		       int error_code,
537     		       ioerror_mode_t mode,
538     		       ioerror_t *ioerror)
539     {
540         xwidget_info_t          xwidget_info;
541     
542     #if DEBUG && ERROR_DEBUG
543     #ifdef SUPPORT_PRINTING_V_FORMAT
544         printk("%v: xtalk_error_handler\n", xconn);
545     #else
546         printk("%x: xtalk_error_handler\n", xconn);
547     #endif
548     #endif
549     
550         xwidget_info = xwidget_info_get(xconn);
551         /* Make sure that xwidget_info is a valid pointer before derefencing it.
552          * We could come in here during very early initialization. 
553          */
554         if (xwidget_info && xwidget_info->w_efunc)
555     	return xwidget_info->w_efunc
556     	    (xwidget_info->w_einfo,
557     	     error_code, mode, ioerror);
558         /*
559          * no error handler registered for
560          * the offending port. it's not clear
561          * what needs to be done, but reporting
562          * it would be a good thing, unless it
563          * is a mode that requires nothing.
564          */
565         if ((mode == MODE_DEVPROBE) || (mode == MODE_DEVUSERERROR) ||
566     	(mode == MODE_DEVREENABLE))
567     	return IOERROR_HANDLED;
568     
569     #ifdef	LATER
570     #ifdef SUPPORT_PRINTING_V_FORMAT
571         PRINT_WARNING("Xbow at %v encountered Fatal error", xconn);
572     #else
573         PRINT_WARNING("Xbow at %x encountered Fatal error", xconn);
574     #endif
575     #endif	/* LATER */
576         ioerror_dump("xtalk", error_code, mode, ioerror);
577     
578         return IOERROR_UNHANDLED;
579     }
580     
581     int
582     xtalk_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code)
583     {
584         return DEV_FUNC(xconn_vhdl, error_devenable) (xconn_vhdl, devnum, error_code);
585     }
586     
587     
588     /* =====================================================================
589      *                    CONFIGURATION MANAGEMENT
590      */
591     
592     /*
593      * Startup a crosstalk provider
594      */
595     void
596     xtalk_provider_startup(devfs_handle_t xtalk_provider)
597     {
598         DEV_FUNC(xtalk_provider, provider_startup)
599     	(xtalk_provider);
600     }
601     
602     
603     /*
604      * Shutdown a crosstalk provider
605      */
606     void
607     xtalk_provider_shutdown(devfs_handle_t xtalk_provider)
608     {
609         DEV_FUNC(xtalk_provider, provider_shutdown)
610     	(xtalk_provider);
611     }
612     
613     /* 
614      * Enable a device on a xtalk widget 
615      */
616     void
617     xtalk_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum)
618     {
619         DEV_FUNC(xconn_vhdl, widgetdev_enable) (xconn_vhdl, devnum);
620     }
621     
622     /* 
623      * Shutdown a device on a xtalk widget 
624      */
625     void
626     xtalk_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum)
627     {
628         DEV_FUNC(xconn_vhdl, widgetdev_shutdown) (xconn_vhdl, devnum);
629     }
630     
631     int
632     xtalk_dma_enabled(devfs_handle_t xconn_vhdl)
633     {
634         return DEV_FUNC(xconn_vhdl, dma_enabled) (xconn_vhdl);
635     }
636     /*
637      * Generic crosstalk functions, for use with all crosstalk providers
638      * and all crosstalk devices.
639      */
640     
641     /****** Generic crosstalk interrupt interfaces ******/
642     devfs_handle_t
643     xtalk_intr_dev_get(xtalk_intr_t xtalk_intr)
644     {
645         return (xtalk_intr->xi_dev);
646     }
647     
648     xwidgetnum_t
649     xtalk_intr_target_get(xtalk_intr_t xtalk_intr)
650     {
651         return (xtalk_intr->xi_target);
652     }
653     
654     xtalk_intr_vector_t
655     xtalk_intr_vector_get(xtalk_intr_t xtalk_intr)
656     {
657         return (xtalk_intr->xi_vector);
658     }
659     
660     iopaddr_t
661     xtalk_intr_addr_get(struct xtalk_intr_s *xtalk_intr)
662     {
663         return (xtalk_intr->xi_addr);
664     }
665     
666     void                   *
667     xtalk_intr_sfarg_get(xtalk_intr_t xtalk_intr)
668     {
669         return (xtalk_intr->xi_sfarg);
670     }
671     
672     /****** Generic crosstalk pio interfaces ******/
673     devfs_handle_t
674     xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap)
675     {
676         return (xtalk_piomap->xp_dev);
677     }
678     
679     xwidgetnum_t
680     xtalk_pio_target_get(xtalk_piomap_t xtalk_piomap)
681     {
682         return (xtalk_piomap->xp_target);
683     }
684     
685     iopaddr_t
686     xtalk_pio_xtalk_addr_get(xtalk_piomap_t xtalk_piomap)
687     {
688         return (xtalk_piomap->xp_xtalk_addr);
689     }
690     
691     ulong
692     xtalk_pio_mapsz_get(xtalk_piomap_t xtalk_piomap)
693     {
694         return (xtalk_piomap->xp_mapsz);
695     }
696     
697     caddr_t
698     xtalk_pio_kvaddr_get(xtalk_piomap_t xtalk_piomap)
699     {
700         return (xtalk_piomap->xp_kvaddr);
701     }
702     
703     
704     /****** Generic crosstalk dma interfaces ******/
705     devfs_handle_t
706     xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap)
707     {
708         return (xtalk_dmamap->xd_dev);
709     }
710     
711     xwidgetnum_t
712     xtalk_dma_target_get(xtalk_dmamap_t xtalk_dmamap)
713     {
714         return (xtalk_dmamap->xd_target);
715     }
716     
717     
718     /****** Generic crosstalk widget information interfaces ******/
719     
720     /* xwidget_info_chk:
721      * check to see if this vertex is a widget;
722      * if so, return its widget_info (if any).
723      * if not, return NULL.
724      */
725     xwidget_info_t
726     xwidget_info_chk(devfs_handle_t xwidget)
727     {
728         arbitrary_info_t        ainfo = 0;
729     
730         hwgraph_info_get_LBL(xwidget, INFO_LBL_XWIDGET, &ainfo);
731         return (xwidget_info_t) ainfo;
732     }
733     
734     
735     xwidget_info_t
736     xwidget_info_get(devfs_handle_t xwidget)
737     {
738         xwidget_info_t          widget_info;
739     
740         widget_info = (xwidget_info_t)
741     	hwgraph_fastinfo_get(xwidget);
742     
743     #ifdef	LATER
744         if ((widget_info != NULL) &&
745     	(widget_info->w_fingerprint != widget_info_fingerprint))
746     #ifdef SUPPORT_PRINTING_V_FORMAT
747     	PRINT_PANIC("%v bad xwidget_info", xwidget);
748     #else
749     	PRINT_PANIC("%x bad xwidget_info", xwidget);
750     #endif
751     #endif	/* LATER */
752     
753         return (widget_info);
754     }
755     
756     void
757     xwidget_info_set(devfs_handle_t xwidget, xwidget_info_t widget_info)
758     {
759         if (widget_info != NULL)
760     	widget_info->w_fingerprint = widget_info_fingerprint;
761     
762         hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) widget_info);
763     
764         /* Also, mark this vertex as an xwidget,
765          * and use the widget_info, so xwidget_info_chk
766          * can work (and be fairly efficient).
767          */
768         hwgraph_info_add_LBL(xwidget, INFO_LBL_XWIDGET,
769     			 (arbitrary_info_t) widget_info);
770     }
771     
772     devfs_handle_t
773     xwidget_info_dev_get(xwidget_info_t xwidget_info)
774     {
775         if (xwidget_info == NULL)
776     	panic("null xwidget_info");
777         return (xwidget_info->w_vertex);
778     }
779     
780     xwidgetnum_t
781     xwidget_info_id_get(xwidget_info_t xwidget_info)
782     {
783         if (xwidget_info == NULL)
784     	panic("null xwidget_info");
785         return (xwidget_info->w_id);
786     }
787     
788     
789     devfs_handle_t
790     xwidget_info_master_get(xwidget_info_t xwidget_info)
791     {
792         if (xwidget_info == NULL)
793     	panic("null xwidget_info");
794         return (xwidget_info->w_master);
795     }
796     
797     xwidgetnum_t
798     xwidget_info_masterid_get(xwidget_info_t xwidget_info)
799     {
800         if (xwidget_info == NULL)
801     	panic("null xwidget_info");
802         return (xwidget_info->w_masterid);
803     }
804     
805     xwidget_part_num_t
806     xwidget_info_part_num_get(xwidget_info_t xwidget_info)
807     {
808         if (xwidget_info == NULL)
809     	panic("null xwidget_info");
810         return (xwidget_info->w_hwid.part_num);
811     }
812     
813     xwidget_mfg_num_t
814     xwidget_info_mfg_num_get(xwidget_info_t xwidget_info)
815     {
816         if (xwidget_info == NULL)
817     	panic("null xwidget_info");
818         return (xwidget_info->w_hwid.mfg_num);
819     }
820     /* Extract the widget name from the widget information
821      * for the xtalk widget.
822      */
823     char *
824     xwidget_info_name_get(xwidget_info_t xwidget_info)
825     {
826         if (xwidget_info == NULL)
827     	panic("null xwidget info");
828         return(xwidget_info->w_name);
829     }
830     /****** Generic crosstalk initialization interfaces ******/
831     
832     /*
833      * One-time initialization needed for systems that support crosstalk.
834      */
835     void
836     xtalk_init(void)
837     {
838         cdl_p                   cp;
839     
840     #if DEBUG && ATTACH_DEBUG
841         printf("xtalk_init\n");
842     #endif
843         /* Allocate the registry.
844          * We might already have one.
845          * If we don't, go get one.
846          * MPness: someone might have
847          * set one up for us while we
848          * were not looking; use an atomic
849          * compare-and-swap to commit to
850          * using the new registry if and
851          * only if nobody else did first.
852          * If someone did get there first,
853          * toss the one we allocated back
854          * into the pool.
855          */
856         if (xtalk_registry == NULL) {
857     	cp = cdl_new(EDGE_LBL_XIO, "part", "mfgr");
858     	if (!compare_and_swap_ptr((void **) &xtalk_registry, NULL, (void *) cp)) {
859     	    cdl_del(cp);
860     	}
861         }
862         ASSERT(xtalk_registry != NULL);
863     }
864     
865     /*
866      * Associate a set of xtalk_provider functions with a vertex.
867      */
868     void
869     xtalk_provider_register(devfs_handle_t provider, xtalk_provider_t *xtalk_fns)
870     {
871         hwgraph_fastinfo_set(provider, (arbitrary_info_t) xtalk_fns);
872     }
873     
874     /*
875      * Disassociate a set of xtalk_provider functions with a vertex.
876      */
877     void
878     xtalk_provider_unregister(devfs_handle_t provider)
879     {
880         hwgraph_fastinfo_set(provider, (arbitrary_info_t)NULL);
881     }
882     
883     /*
884      * Obtain a pointer to the xtalk_provider functions for a specified Crosstalk
885      * provider.
886      */
887     xtalk_provider_t       *
888     xtalk_provider_fns_get(devfs_handle_t provider)
889     {
890         return ((xtalk_provider_t *) hwgraph_fastinfo_get(provider));
891     }
892     
893     /*
894      * Announce a driver for a particular crosstalk part.
895      * Returns 0 on success or -1 on failure.  Failure occurs if the
896      * specified hardware already has a driver.
897      */
898     /*ARGSUSED4 */
899     int
900     xwidget_driver_register(xwidget_part_num_t part_num,
901     			xwidget_mfg_num_t mfg_num,
902     			char *driver_prefix,
903     			unsigned flags)
904     {
905         /* a driver's init routine could call
906          * xwidget_driver_register before the
907          * system calls xtalk_init; so, we
908          * make the call here.
909          */
910         if (xtalk_registry == NULL)
911     	xtalk_init();
912     
913         return cdl_add_driver(xtalk_registry,
914     			  part_num, mfg_num,
915     			  driver_prefix, flags, NULL);
916     }
917     
918     /*
919      * Inform xtalk infrastructure that a driver is no longer available for
920      * handling any widgets.
921      */
922     void
923     xwidget_driver_unregister(char *driver_prefix)
924     {
925         /* before a driver calls unregister,
926          * it must have called registger; so we
927          * can assume we have a registry here.
928          */
929         ASSERT(xtalk_registry != NULL);
930     
931         cdl_del_driver(xtalk_registry, driver_prefix, NULL);
932     }
933     
934     /*
935      * Call some function with each vertex that
936      * might be one of this driver's attach points.
937      */
938     void
939     xtalk_iterate(char *driver_prefix,
940     	      xtalk_iter_f *func)
941     {
942         ASSERT(xtalk_registry != NULL);
943     
944         cdl_iterate(xtalk_registry, driver_prefix, (cdl_iter_f *)func);
945     }
946     
947     /*
948      * xwidget_register:
949      *	Register a xtalk device (xwidget) by doing the following.
950      *      -allocate and initialize xwidget_info data
951      *      -allocate a hwgraph vertex with name based on widget number (id)
952      *      -look up the widget's initialization function and call it,
953      *      or remember the vertex for later initialization.
954      *
955      */
956     int
957     xwidget_register(xwidget_hwid_t hwid,		/* widget's hardware ID */
958     		 devfs_handle_t 	widget,		/* widget to initialize */
959     		 xwidgetnum_t 	id,		/* widget's target id (0..f) */
960     		 devfs_handle_t 	master,		/* widget's master vertex */
961     		 xwidgetnum_t 	targetid,	/* master's target id (9/a) */
962     		 async_attach_t aa)
963     {			
964         xwidget_info_t          widget_info;
965         char		    *s,devnm[MAXDEVNAME];
966     
967         /* Allocate widget_info and associate it with widget vertex */
968         NEW(widget_info);
969     
970         /* Initialize widget_info */
971         widget_info->w_vertex = widget;
972         widget_info->w_id = id;
973         widget_info->w_master = master;
974         widget_info->w_masterid = targetid;
975         widget_info->w_hwid = *hwid;	/* structure copy */
976         widget_info->w_efunc = 0;
977         widget_info->w_einfo = 0;
978         /*
979          * get the name of this xwidget vertex and keep the info.
980          * This is needed during errors and interrupts, but as
981          * long as we have it, we can use it elsewhere.
982          */
983         s = dev_to_name(widget,devnm,MAXDEVNAME);
984         widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
985         strcpy(widget_info->w_name,s);
986         
987         xwidget_info_set(widget, widget_info);
988     
989         device_master_set(widget, master);
990     
991         /* All the driver init routines (including
992          * xtalk_init) are called before we get into
993          * attaching devices, so we can assume we
994          * have a registry here.
995          */
996         ASSERT(xtalk_registry != NULL);
997     
998         /* 
999          * Add pointer to async attach info -- tear down will be done when
1000          * the particular descendant is done with the info.
1001          */
1002         if (aa)
1003     	    async_attach_add_info(widget, aa);
1004     
1005         return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
1006                               widget, 0);
1007     }
1008     
1009     /*
1010      * xwidget_unregister :
1011      *	Unregister the xtalk device and detach all its hwgraph namespace.
1012      */
1013     int
1014     xwidget_unregister(devfs_handle_t widget)
1015     {
1016         xwidget_info_t	widget_info;
1017         xwidget_hwid_t	hwid;
1018     
1019         /* Make sure that we have valid widget information initialized */
1020         if (!(widget_info = xwidget_info_get(widget)))
1021     	return(1);
1022     
1023         /* Remove the inventory information associated
1024          * with the widget.
1025          */
1026         hwgraph_inventory_remove(widget, -1, -1, -1, -1, -1);
1027         
1028         hwid = &(widget_info->w_hwid);
1029     
1030         cdl_del_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
1031                        widget, 0);
1032     
1033         /* Clean out the xwidget information */
1034         (void)kfree(widget_info->w_name);
1035         BZERO((void *)widget_info, sizeof(widget_info));
1036         DEL(widget_info);
1037         
1038         return(0);
1039     }
1040     
1041     void
1042     xwidget_error_register(devfs_handle_t xwidget,
1043     		       error_handler_f *efunc,
1044     		       error_handler_arg_t einfo)
1045     {
1046         xwidget_info_t          xwidget_info;
1047     
1048         xwidget_info = xwidget_info_get(xwidget);
1049         ASSERT(xwidget_info != NULL);
1050         xwidget_info->w_efunc = efunc;
1051         xwidget_info->w_einfo = einfo;
1052     }
1053     
1054     /*
1055      * Issue a link reset to a widget.
1056      */
1057     void
1058     xwidget_reset(devfs_handle_t xwidget)
1059     {
1060         xswitch_reset_link(xwidget);
1061     
1062     }
1063     
1064     
1065     void
1066     xwidget_gfx_reset(devfs_handle_t xwidget)
1067     {
1068         xwidget_info_t info;
1069     
1070         xswitch_reset_link(xwidget);
1071         info = xwidget_info_get(xwidget);
1072     #ifdef LATER
1073         ASSERT_ALWAYS(info != NULL);
1074     #endif
1075     
1076         /*
1077          * Enable this for other architectures once we add widget_reset to the
1078          * xtalk provider interface.
1079          */
1080         DEV_FUNC(xtalk_provider, widget_reset)
1081     	(xwidget_info_master_get(info), xwidget_info_id_get(info));
1082     }
1083     
1084     #define ANON_XWIDGET_NAME	"No Name"	/* Default Widget Name */
1085     
1086     /* Get the canonical hwgraph  name of xtalk widget */
1087     char *
1088     xwidget_name_get(devfs_handle_t xwidget_vhdl)
1089     {
1090     	xwidget_info_t  info;
1091     
1092     	/* If we have a bogus widget handle then return
1093     	 * a default anonymous widget name.
1094     	 */
1095     	if (xwidget_vhdl == GRAPH_VERTEX_NONE)
1096     	    return(ANON_XWIDGET_NAME);
1097     	/* Read the widget name stored in the widget info
1098     	 * for the widget setup during widget initialization.
1099     	 */
1100     	info = xwidget_info_get(xwidget_vhdl);
1101     	ASSERT(info != NULL);
1102     	return(xwidget_info_name_get(info));
1103     }
1104     
1105     /*
1106      * xtalk_device_shutdown
1107      *	Disable  the specified xtalk widget and clean out all the software
1108      *	state associated with it.
1109      */
1110     int
1111     xtalk_device_shutdown(devfs_handle_t xbus_vhdl, xwidgetnum_t widget)
1112     {
1113     	devfs_handle_t	widget_vhdl;
1114     	char		edge_name[8];
1115     
1116     	sprintf(edge_name, "%d", widget);
1117     	if (hwgraph_traverse(xbus_vhdl, edge_name, &widget_vhdl) 
1118     	    != GRAPH_SUCCESS)
1119     		return(1);
1120     
1121     	xwidget_unregister(widget_vhdl);
1122     	
1123     	return(0);
1124     }
1125     /*
1126      * xtalk_device_inquiry
1127      *	Find out hardware information about the xtalk widget.
1128      */
1129     int
1130     xtalk_device_inquiry(devfs_handle_t xbus_vhdl, xwidgetnum_t widget)
1131     {
1132     
1133     	extern void hub_device_inquiry(devfs_handle_t, xwidgetnum_t);
1134     	hub_device_inquiry(xbus_vhdl, widget);
1135     	return(0);
1136     }
1137