ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / sn / io / sn2 / pciio.c
1 /*
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
4  * for more details.
5  *
6  * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
7  */
8
9 #include <asm/sn/pci/pci_bus_cvlink.h>
10 #include <asm/sn/simulator.h>
11
12 char                    pciio_info_fingerprint[] = "pciio_info";
13
14 /* =====================================================================
15  *    PCI Generic Bus Provider
16  * Implement PCI provider operations.  The pciio* layer provides a
17  * platform-independent interface for PCI devices.  This layer
18  * switches among the possible implementations of a PCI adapter.
19  */
20
21 /* =====================================================================
22  *    Provider Function Location
23  *
24  *      If there is more than one possible provider for
25  *      this platform, we need to examine the master
26  *      vertex of the current vertex for a provider
27  *      function structure, and indirect through the
28  *      appropriately named member.
29  */
30
31 pciio_provider_t *
32 pciio_to_provider_fns(vertex_hdl_t dev)
33 {
34     pciio_info_t            card_info;
35     pciio_provider_t       *provider_fns;
36
37     /*
38      * We're called with two types of vertices, one is
39      * the bridge vertex (ends with "pci") and the other is the
40      * pci slot vertex (ends with "pci/[0-8]").  For the first type
41      * we need to get the provider from the PFUNCS label.  For
42      * the second we get it from fastinfo/c_pops.
43      */
44     provider_fns = pciio_provider_fns_get(dev);
45     if (provider_fns == NULL) {
46         card_info = pciio_info_get(dev);
47         if (card_info != NULL) {
48                 provider_fns = pciio_info_pops_get(card_info);
49         }
50     }
51
52     if (provider_fns == NULL) {
53         char devname[MAXDEVNAME];
54         panic("%s: provider_fns == NULL", vertex_to_name(dev, devname, MAXDEVNAME));
55     }
56     return provider_fns;
57
58 }
59
60 #define DEV_FUNC(dev,func)      pciio_to_provider_fns(dev)->func
61 #define CAST_PIOMAP(x)          ((pciio_piomap_t)(x))
62 #define CAST_DMAMAP(x)          ((pciio_dmamap_t)(x))
63 #define CAST_INTR(x)            ((pciio_intr_t)(x))
64
65 /*
66  * Many functions are not passed their vertex
67  * information directly; rather, they must
68  * dive through a resource map. These macros
69  * are available to coordinate this detail.
70  */
71 #define PIOMAP_FUNC(map,func)           DEV_FUNC((map)->pp_dev,func)
72 #define DMAMAP_FUNC(map,func)           DEV_FUNC((map)->pd_dev,func)
73 #define INTR_FUNC(intr_hdl,func)        DEV_FUNC((intr_hdl)->pi_dev,func)
74
75 /* =====================================================================
76  *          PIO MANAGEMENT
77  *
78  *      For mapping system virtual address space to
79  *      pciio space on a specified card
80  */
81
82 pciio_piomap_t
83 pciio_piomap_alloc(vertex_hdl_t dev,    /* set up mapping for this device */
84                    device_desc_t dev_desc,      /* device descriptor */
85                    pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */
86                    iopaddr_t addr,      /* lowest address (or offset in window) */
87                    size_t byte_count,   /* size of region containing our mappings */
88                    size_t byte_count_max,       /* maximum size of a mapping */
89                    unsigned flags)
90 {                                       /* defined in sys/pio.h */
91     return (pciio_piomap_t) DEV_FUNC(dev, piomap_alloc)
92         (dev, dev_desc, space, addr, byte_count, byte_count_max, flags);
93 }
94
95 void
96 pciio_piomap_free(pciio_piomap_t pciio_piomap)
97 {
98     PIOMAP_FUNC(pciio_piomap, piomap_free)
99         (CAST_PIOMAP(pciio_piomap));
100 }
101
102 caddr_t
103 pciio_piomap_addr(pciio_piomap_t pciio_piomap,  /* mapping resources */
104                   iopaddr_t pciio_addr, /* map for this pciio address */
105                   size_t byte_count)
106 {                                       /* map this many bytes */
107     pciio_piomap->pp_kvaddr = PIOMAP_FUNC(pciio_piomap, piomap_addr)
108         (CAST_PIOMAP(pciio_piomap), pciio_addr, byte_count);
109
110     return pciio_piomap->pp_kvaddr;
111 }
112
113 void
114 pciio_piomap_done(pciio_piomap_t pciio_piomap)
115 {
116     PIOMAP_FUNC(pciio_piomap, piomap_done)
117         (CAST_PIOMAP(pciio_piomap));
118 }
119
120 caddr_t
121 pciio_piotrans_addr(vertex_hdl_t dev,   /* translate for this device */
122                     device_desc_t dev_desc,     /* device descriptor */
123                     pciio_space_t space,        /* CFG, MEM, IO, or a device-decoded window */
124                     iopaddr_t addr,     /* starting address (or offset in window) */
125                     size_t byte_count,  /* map this many bytes */
126                     unsigned flags)
127 {                                       /* (currently unused) */
128     return DEV_FUNC(dev, piotrans_addr)
129         (dev, dev_desc, space, addr, byte_count, flags);
130 }
131
132 caddr_t
133 pciio_pio_addr(vertex_hdl_t dev,        /* translate for this device */
134                device_desc_t dev_desc,  /* device descriptor */
135                pciio_space_t space,     /* CFG, MEM, IO, or a device-decoded window */
136                iopaddr_t addr,          /* starting address (or offset in window) */
137                size_t byte_count,       /* map this many bytes */
138                pciio_piomap_t *mapp,    /* where to return the map pointer */
139                unsigned flags)
140 {                                       /* PIO flags */
141     pciio_piomap_t          map = 0;
142     int                     errfree = 0;
143     caddr_t                 res;
144
145     if (mapp) {
146         map = *mapp;                    /* possible pre-allocated map */
147         *mapp = 0;                      /* record "no map used" */
148     }
149
150     res = pciio_piotrans_addr
151         (dev, dev_desc, space, addr, byte_count, flags);
152     if (res)
153         return res;                     /* pciio_piotrans worked */
154
155     if (!map) {
156         map = pciio_piomap_alloc
157             (dev, dev_desc, space, addr, byte_count, byte_count, flags);
158         if (!map)
159             return res;                 /* pciio_piomap_alloc failed */
160         errfree = 1;
161     }
162
163     res = pciio_piomap_addr
164         (map, addr, byte_count);
165     if (!res) {
166         if (errfree)
167             pciio_piomap_free(map);
168         return res;                     /* pciio_piomap_addr failed */
169     }
170     if (mapp)
171         *mapp = map;                    /* pass back map used */
172
173     return res;                         /* pciio_piomap_addr succeeded */
174 }
175
176 iopaddr_t
177 pciio_piospace_alloc(vertex_hdl_t dev,  /* Device requiring space */
178                      device_desc_t dev_desc,    /* Device descriptor */
179                      pciio_space_t space,       /* MEM32/MEM64/IO */
180                      size_t byte_count, /* Size of mapping */
181                      size_t align)
182 {                                       /* Alignment needed */
183     if (align < PAGE_SIZE)
184         align = PAGE_SIZE;
185     return DEV_FUNC(dev, piospace_alloc)
186         (dev, dev_desc, space, byte_count, align);
187 }
188
189 void
190 pciio_piospace_free(vertex_hdl_t dev,   /* Device freeing space */
191                     pciio_space_t space,        /* Type of space        */
192                     iopaddr_t pciaddr,  /* starting address */
193                     size_t byte_count)
194 {                                       /* Range of address   */
195     DEV_FUNC(dev, piospace_free)
196         (dev, space, pciaddr, byte_count);
197 }
198
199 /* =====================================================================
200  *          DMA MANAGEMENT
201  *
202  *      For mapping from pci space to system
203  *      physical space.
204  */
205
206 pciio_dmamap_t
207 pciio_dmamap_alloc(vertex_hdl_t dev,    /* set up mappings for this device */
208                    device_desc_t dev_desc,      /* device descriptor */
209                    size_t byte_count_max,       /* max size of a mapping */
210                    unsigned flags)
211 {                                       /* defined in dma.h */
212     return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
213         (dev, dev_desc, byte_count_max, flags);
214 }
215
216 void
217 pciio_dmamap_free(pciio_dmamap_t pciio_dmamap)
218 {
219     DMAMAP_FUNC(pciio_dmamap, dmamap_free)
220         (CAST_DMAMAP(pciio_dmamap));
221 }
222
223 iopaddr_t
224 pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,  /* use these mapping resources */
225                   paddr_t paddr,        /* map for this address */
226                   size_t byte_count)
227 {                                       /* map this many bytes */
228     return DMAMAP_FUNC(pciio_dmamap, dmamap_addr)
229         (CAST_DMAMAP(pciio_dmamap), paddr, byte_count);
230 }
231
232 void
233 pciio_dmamap_done(pciio_dmamap_t pciio_dmamap)
234 {
235     DMAMAP_FUNC(pciio_dmamap, dmamap_done)
236         (CAST_DMAMAP(pciio_dmamap));
237 }
238
239 iopaddr_t
240 pciio_dmatrans_addr(vertex_hdl_t dev,   /* translate for this device */
241                     device_desc_t dev_desc,     /* device descriptor */
242                     paddr_t paddr,      /* system physical address */
243                     size_t byte_count,  /* length */
244                     unsigned flags)
245 {                                       /* defined in dma.h */
246     return DEV_FUNC(dev, dmatrans_addr)
247         (dev, dev_desc, paddr, byte_count, flags);
248 }
249
250 iopaddr_t
251 pciio_dma_addr(vertex_hdl_t dev,        /* translate for this device */
252                device_desc_t dev_desc,  /* device descriptor */
253                paddr_t paddr,           /* system physical address */
254                size_t byte_count,       /* length */
255                pciio_dmamap_t *mapp,    /* map to use, then map we used */
256                unsigned flags)
257 {                                       /* PIO flags */
258     pciio_dmamap_t          map = 0;
259     int                     errfree = 0;
260     iopaddr_t               res;
261
262     if (mapp) {
263         map = *mapp;                    /* possible pre-allocated map */
264         *mapp = 0;                      /* record "no map used" */
265     }
266
267     res = pciio_dmatrans_addr
268         (dev, dev_desc, paddr, byte_count, flags);
269     if (res)
270         return res;                     /* pciio_dmatrans worked */
271
272     if (!map) {
273         map = pciio_dmamap_alloc
274             (dev, dev_desc, byte_count, flags);
275         if (!map)
276             return res;                 /* pciio_dmamap_alloc failed */
277         errfree = 1;
278     }
279
280     res = pciio_dmamap_addr
281         (map, paddr, byte_count);
282     if (!res) {
283         if (errfree)
284             pciio_dmamap_free(map);
285         return res;                     /* pciio_dmamap_addr failed */
286     }
287     if (mapp)
288         *mapp = map;                    /* pass back map used */
289
290     return res;                         /* pciio_dmamap_addr succeeded */
291 }
292
293 void
294 pciio_dmamap_drain(pciio_dmamap_t map)
295 {
296     DMAMAP_FUNC(map, dmamap_drain)
297         (CAST_DMAMAP(map));
298 }
299
300 void
301 pciio_dmaaddr_drain(vertex_hdl_t dev, paddr_t addr, size_t size)
302 {
303     DEV_FUNC(dev, dmaaddr_drain)
304         (dev, addr, size);
305 }
306
307 /* =====================================================================
308  *          INTERRUPT MANAGEMENT
309  *
310  *      Allow crosstalk devices to establish interrupts
311  */
312
313 /*
314  * Allocate resources required for an interrupt as specified in intr_desc.
315  * Return resource handle in intr_hdl.
316  */
317 pciio_intr_t
318 pciio_intr_alloc(vertex_hdl_t dev,      /* which Crosstalk device */
319                  device_desc_t dev_desc,        /* device descriptor */
320                  pciio_intr_line_t lines,       /* INTR line(s) to attach */
321                  vertex_hdl_t owner_dev)
322 {                                       /* owner of this interrupt */
323     return (pciio_intr_t) DEV_FUNC(dev, intr_alloc)
324         (dev, dev_desc, lines, owner_dev);
325 }
326
327 /*
328  * Free resources consumed by intr_alloc.
329  */
330 void
331 pciio_intr_free(pciio_intr_t intr_hdl)
332 {
333     INTR_FUNC(intr_hdl, intr_free)
334         (CAST_INTR(intr_hdl));
335 }
336
337 /*
338  * Associate resources allocated with a previous pciio_intr_alloc call with the
339  * described handler, arg, name, etc.
340  *
341  * Returns 0 on success, returns <0 on failure.
342  */
343 int
344 pciio_intr_connect(pciio_intr_t intr_hdl,
345                 intr_func_t intr_func, intr_arg_t intr_arg)     /* pciio intr resource handle */
346 {
347     return INTR_FUNC(intr_hdl, intr_connect)
348         (CAST_INTR(intr_hdl), intr_func, intr_arg);
349 }
350
351 /*
352  * Disassociate handler with the specified interrupt.
353  */
354 void
355 pciio_intr_disconnect(pciio_intr_t intr_hdl)
356 {
357     INTR_FUNC(intr_hdl, intr_disconnect)
358         (CAST_INTR(intr_hdl));
359 }
360
361 /*
362  * Return a hwgraph vertex that represents the CPU currently
363  * targeted by an interrupt.
364  */
365 vertex_hdl_t
366 pciio_intr_cpu_get(pciio_intr_t intr_hdl)
367 {
368     return INTR_FUNC(intr_hdl, intr_cpu_get)
369         (CAST_INTR(intr_hdl));
370 }
371
372 void
373 pciio_slot_func_to_name(char                   *name,
374                         pciio_slot_t            slot,
375                         pciio_function_t        func)
376 {
377     /*
378      * standard connection points:
379      *
380      * PCIIO_SLOT_NONE: .../pci/direct
381      * PCIIO_FUNC_NONE: .../pci/<SLOT>                  ie. .../pci/3
382      * multifunction:   .../pci/<SLOT><FUNC>            ie. .../pci/3c
383      */
384
385     if (slot == PCIIO_SLOT_NONE)
386         sprintf(name, EDGE_LBL_DIRECT);
387     else if (func == PCIIO_FUNC_NONE)
388         sprintf(name, "%d", slot);
389     else
390         sprintf(name, "%d%c", slot, 'a'+func);
391 }
392
393 /*
394  * pciio_cardinfo_get
395  *
396  * Get the pciio info structure corresponding to the
397  * specified PCI "slot" (we like it when the same index
398  * number is used for the PCI IDSEL, the REQ/GNT pair,
399  * and the interrupt line being used for INTA. We like
400  * it so much we call it the slot number).
401  */
402 static pciio_info_t
403 pciio_cardinfo_get(
404                       vertex_hdl_t pciio_vhdl,
405                       pciio_slot_t pci_slot)
406 {
407     char                    namebuf[16];
408     pciio_info_t            info = 0;
409     vertex_hdl_t            conn;
410
411     pciio_slot_func_to_name(namebuf, pci_slot, PCIIO_FUNC_NONE);
412     if (GRAPH_SUCCESS ==
413         hwgraph_traverse(pciio_vhdl, namebuf, &conn)) {
414         info = pciio_info_chk(conn);
415         hwgraph_vertex_unref(conn);
416     }
417
418     return info;
419 }
420
421
422 /*
423  * pciio_error_handler:
424  * dispatch an error to the appropriate
425  * pciio connection point, or process
426  * it as a generic pci error.
427  * Yes, the first parameter is the
428  * provider vertex at the middle of
429  * the bus; we get to the pciio connect
430  * point using the ioerror widgetdev field.
431  *
432  * This function is called by the
433  * specific PCI provider, after it has figured
434  * out where on the PCI bus (including which slot,
435  * if it can tell) the error came from.
436  */
437 /*ARGSUSED */
438 int
439 pciio_error_handler(
440                        vertex_hdl_t pciio_vhdl,
441                        int error_code,
442                        ioerror_mode_t mode,
443                        ioerror_t *ioerror)
444 {
445     pciio_info_t            pciio_info;
446     vertex_hdl_t            pconn_vhdl;
447     pciio_slot_t            slot;
448
449     int                     retval;
450
451 #if DEBUG && ERROR_DEBUG
452     printk("%v: pciio_error_handler\n", pciio_vhdl);
453 #endif
454
455     IOERR_PRINTF(printk(KERN_NOTICE "%v: PCI Bus Error: Error code: %d Error mode: %d\n",
456                          pciio_vhdl, error_code, mode));
457
458     /* If there is an error handler sitting on
459      * the "no-slot" connection point, give it
460      * first crack at the error. NOTE: it is
461      * quite possible that this function may
462      * do further refining of the ioerror.
463      */
464     pciio_info = pciio_cardinfo_get(pciio_vhdl, PCIIO_SLOT_NONE);
465     if (pciio_info && pciio_info->c_efunc) {
466         pconn_vhdl = pciio_info_dev_get(pciio_info);
467
468         retval = pciio_info->c_efunc
469             (pciio_info->c_einfo, error_code, mode, ioerror);
470         if (retval != IOERROR_UNHANDLED)
471             return retval;
472     }
473
474     /* Is the error associated with a particular slot?
475      */
476     if (IOERROR_FIELDVALID(ioerror, widgetdev)) {
477         short widgetdev;
478         /*
479          * NOTE : 
480          * widgetdev is a 4byte value encoded as slot in the higher order
481          * 2 bytes and function in the lower order 2 bytes.
482          */
483         IOERROR_GETVALUE(widgetdev, ioerror, widgetdev);
484         slot = pciio_widgetdev_slot_get(widgetdev);
485
486         /* If this slot has an error handler,
487          * deliver the error to it.
488          */
489         pciio_info = pciio_cardinfo_get(pciio_vhdl, slot);
490         if (pciio_info != NULL) {
491             if (pciio_info->c_efunc != NULL) {
492
493                 pconn_vhdl = pciio_info_dev_get(pciio_info);
494
495                 retval = pciio_info->c_efunc
496                     (pciio_info->c_einfo, error_code, mode, ioerror);
497                 if (retval != IOERROR_UNHANDLED)
498                     return retval;
499             }
500         }
501     }
502
503     return (mode == MODE_DEVPROBE)
504         ? IOERROR_HANDLED       /* probes are OK */
505         : IOERROR_UNHANDLED;    /* otherwise, foo! */
506 }
507
508 /* =====================================================================
509  *          CONFIGURATION MANAGEMENT
510  */
511
512 /*
513  * Startup a crosstalk provider
514  */
515 void
516 pciio_provider_startup(vertex_hdl_t pciio_provider)
517 {
518     DEV_FUNC(pciio_provider, provider_startup)
519         (pciio_provider);
520 }
521
522 /*
523  * Shutdown a crosstalk provider
524  */
525 void
526 pciio_provider_shutdown(vertex_hdl_t pciio_provider)
527 {
528     DEV_FUNC(pciio_provider, provider_shutdown)
529         (pciio_provider);
530 }
531
532 /*
533  * Read value of configuration register
534  */
535 uint64_t
536 pciio_config_get(vertex_hdl_t   dev,
537                  unsigned       reg,
538                  unsigned       size)
539 {
540     uint64_t    value = 0;
541     unsigned    shift = 0;
542
543     /* handle accesses that cross words here,
544      * since that's common code between all
545      * possible providers.
546      */
547     while (size > 0) {
548         unsigned        biw = 4 - (reg&3);
549         if (biw > size)
550             biw = size;
551
552         value |= DEV_FUNC(dev, config_get)
553             (dev, reg, biw) << shift;
554
555         shift += 8*biw;
556         reg += biw;
557         size -= biw;
558     }
559     return value;
560 }
561
562 /*
563  * Change value of configuration register
564  */
565 void
566 pciio_config_set(vertex_hdl_t   dev,
567                  unsigned       reg,
568                  unsigned       size,
569                  uint64_t       value)
570 {
571     /* handle accesses that cross words here,
572      * since that's common code between all
573      * possible providers.
574      */
575     while (size > 0) {
576         unsigned        biw = 4 - (reg&3);
577         if (biw > size)
578             biw = size;
579             
580         DEV_FUNC(dev, config_set)
581             (dev, reg, biw, value);
582         reg += biw;
583         size -= biw;
584         value >>= biw * 8;
585     }
586 }
587
588 /* =====================================================================
589  *          GENERIC PCI SUPPORT FUNCTIONS
590  */
591
592 /*
593  * Issue a hardware reset to a card.
594  */
595 int
596 pciio_reset(vertex_hdl_t dev)
597 {
598     return DEV_FUNC(dev, reset) (dev);
599 }
600
601 /****** Generic pci slot information interfaces ******/
602
603 pciio_info_t
604 pciio_info_chk(vertex_hdl_t pciio)
605 {
606     arbitrary_info_t        ainfo = 0;
607
608     hwgraph_info_get_LBL(pciio, INFO_LBL_PCIIO, &ainfo);
609     return (pciio_info_t) ainfo;
610 }
611
612 pciio_info_t
613 pciio_info_get(vertex_hdl_t pciio)
614 {
615     pciio_info_t            pciio_info;
616
617     pciio_info = (pciio_info_t) hwgraph_fastinfo_get(pciio);
618
619     if ((pciio_info != NULL) &&
620         (pciio_info->c_fingerprint != pciio_info_fingerprint)
621         && (pciio_info->c_fingerprint != NULL)) {
622
623         return((pciio_info_t)-1); /* Should panic .. */
624     }
625
626     return pciio_info;
627 }
628
629 void
630 pciio_info_set(vertex_hdl_t pciio, pciio_info_t pciio_info)
631 {
632     if (pciio_info != NULL)
633         pciio_info->c_fingerprint = pciio_info_fingerprint;
634     hwgraph_fastinfo_set(pciio, (arbitrary_info_t) pciio_info);
635
636     /* Also, mark this vertex as a PCI slot
637      * and use the pciio_info, so pciio_info_chk
638      * can work (and be fairly efficient).
639      */
640     hwgraph_info_add_LBL(pciio, INFO_LBL_PCIIO,
641                          (arbitrary_info_t) pciio_info);
642 }
643
644 vertex_hdl_t
645 pciio_info_dev_get(pciio_info_t pciio_info)
646 {
647     return (pciio_info->c_vertex);
648 }
649
650 /*ARGSUSED*/
651 pciio_bus_t
652 pciio_info_bus_get(pciio_info_t pciio_info)
653 {
654     return (pciio_info->c_bus);
655 }
656
657 pciio_slot_t
658 pciio_info_slot_get(pciio_info_t pciio_info)
659 {
660     return (pciio_info->c_slot);
661 }
662
663 pciio_function_t
664 pciio_info_function_get(pciio_info_t pciio_info)
665 {
666     return (pciio_info->c_func);
667 }
668
669 pciio_vendor_id_t
670 pciio_info_vendor_id_get(pciio_info_t pciio_info)
671 {
672     return (pciio_info->c_vendor);
673 }
674
675 pciio_device_id_t
676 pciio_info_device_id_get(pciio_info_t pciio_info)
677 {
678     return (pciio_info->c_device);
679 }
680
681 vertex_hdl_t
682 pciio_info_master_get(pciio_info_t pciio_info)
683 {
684     return (pciio_info->c_master);
685 }
686
687 arbitrary_info_t
688 pciio_info_mfast_get(pciio_info_t pciio_info)
689 {
690     return (pciio_info->c_mfast);
691 }
692
693 pciio_provider_t       *
694 pciio_info_pops_get(pciio_info_t pciio_info)
695 {
696     return (pciio_info->c_pops);
697 }
698
699 /* =====================================================================
700  *          GENERIC PCI INITIALIZATION FUNCTIONS
701  */
702
703 /*
704  *    pciioattach: called for each vertex in the graph
705  *      that is a PCI provider.
706  */
707 /*ARGSUSED */
708 int
709 pciio_attach(vertex_hdl_t pciio)
710 {
711 #if DEBUG && ATTACH_DEBUG
712     char devname[MAXDEVNAME];
713     printk("%s: pciio_attach\n", vertex_to_name(pciio, devname, MAXDEVNAME));
714 #endif
715     return 0;
716 }
717
718 /*
719  * Associate a set of pciio_provider functions with a vertex.
720  */
721 void
722 pciio_provider_register(vertex_hdl_t provider, pciio_provider_t *pciio_fns)
723 {
724     hwgraph_info_add_LBL(provider, INFO_LBL_PFUNCS, (arbitrary_info_t) pciio_fns);
725 }
726
727 /*
728  * Disassociate a set of pciio_provider functions with a vertex.
729  */
730 void
731 pciio_provider_unregister(vertex_hdl_t provider)
732 {
733     arbitrary_info_t        ainfo;
734
735     hwgraph_info_remove_LBL(provider, INFO_LBL_PFUNCS, (long *) &ainfo);
736 }
737
738 /*
739  * Obtain a pointer to the pciio_provider functions for a specified Crosstalk
740  * provider.
741  */
742 pciio_provider_t       *
743 pciio_provider_fns_get(vertex_hdl_t provider)
744 {
745     arbitrary_info_t        ainfo = 0;
746
747     (void) hwgraph_info_get_LBL(provider, INFO_LBL_PFUNCS, &ainfo);
748     return (pciio_provider_t *) ainfo;
749 }
750
751 pciio_info_t
752 pciio_device_info_new(
753                 pciio_info_t pciio_info,
754                 vertex_hdl_t master,
755                 pciio_slot_t slot,
756                 pciio_function_t func,
757                 pciio_vendor_id_t vendor_id,
758                 pciio_device_id_t device_id)
759 {
760     if (!pciio_info) {
761         pciio_info = kmalloc(sizeof (*(pciio_info)), GFP_KERNEL);
762         if ( pciio_info )
763                 memset(pciio_info, 0, sizeof (*(pciio_info)));
764         else {
765                 printk(KERN_WARNING "pciio_device_info_new(): Unable to "
766                         "allocate memory\n");
767                 return NULL;
768         }
769     }
770     pciio_info->c_slot = slot;
771     pciio_info->c_func = func;
772     pciio_info->c_vendor = vendor_id;
773     pciio_info->c_device = device_id;
774     pciio_info->c_master = master;
775     pciio_info->c_mfast = hwgraph_fastinfo_get(master);
776     pciio_info->c_pops = pciio_provider_fns_get(master);
777     pciio_info->c_efunc = 0;
778     pciio_info->c_einfo = 0;
779
780     return pciio_info;
781 }
782
783 void
784 pciio_device_info_free(pciio_info_t pciio_info)
785 {
786     /* NOTE : pciio_info is a structure within the pcibr_info
787      *        and not a pointer to memory allocated on the heap !!
788      */
789     memset((char *)pciio_info, 0, sizeof(pciio_info));
790 }
791
792 vertex_hdl_t
793 pciio_device_info_register(
794                 vertex_hdl_t connectpt,         /* vertex at center of bus */
795                 pciio_info_t pciio_info)        /* details about the connectpt */
796 {
797     char                name[32];
798     vertex_hdl_t        pconn;
799     int device_master_set(vertex_hdl_t, vertex_hdl_t);
800
801     pciio_slot_func_to_name(name,
802                             pciio_info->c_slot,
803                             pciio_info->c_func);
804
805     if (GRAPH_SUCCESS !=
806         hwgraph_path_add(connectpt, name, &pconn))
807         return pconn;
808
809     pciio_info->c_vertex = pconn;
810     pciio_info_set(pconn, pciio_info);
811
812     /*
813      * create link to our pci provider
814      */
815
816     device_master_set(pconn, pciio_info->c_master);
817     return pconn;
818 }
819
820 void
821 pciio_device_info_unregister(vertex_hdl_t connectpt,
822                              pciio_info_t pciio_info)
823 {
824     char                name[32];
825     vertex_hdl_t        pconn = NULL;
826
827     if (!pciio_info)
828         return;
829
830     pciio_slot_func_to_name(name,
831                             pciio_info->c_slot,
832                             pciio_info->c_func);
833
834     pciio_info_set(pconn,0);
835
836     hwgraph_vertex_unref(pconn);
837     hwgraph_vertex_destroy(pconn);
838 }
839
840 /*ARGSUSED */
841 int
842 pciio_device_attach(vertex_hdl_t pconn,
843                     int          drv_flags)
844 {
845     pciio_info_t            pciio_info;
846     pciio_vendor_id_t       vendor_id;
847     pciio_device_id_t       device_id;
848
849
850     pciio_info = pciio_info_get(pconn);
851
852     vendor_id = pciio_info->c_vendor;
853     device_id = pciio_info->c_device;
854
855     /* we don't start attaching things until
856      * all the driver init routines (including
857      * pciio_init) have been called; so we
858      * can assume here that we have a registry.
859      */
860
861     return(cdl_add_connpt(vendor_id, device_id, pconn, drv_flags));
862 }
863
864 int
865 pciio_device_detach(vertex_hdl_t pconn,
866                     int          drv_flags)
867 {
868     return(0);
869 }
870
871 /*
872  * Allocate space from the specified PCI window mapping resource.  On
873  * success record information about the allocation in the supplied window
874  * allocation cookie (if non-NULL) and return the address of the allocated
875  * window.  On failure return NULL.
876  *
877  * The "size" parameter is usually from a PCI device's Base Address Register
878  * (BAR) decoder.  As such, the allocation must be aligned to be a multiple of
879  * that.  The "align" parameter acts as a ``minimum alignment'' allocation
880  * constraint.  The alignment contraint reflects system or device addressing
881  * restrictions such as the inability to share higher level ``windows''
882  * between devices, etc.  The returned PCI address allocation will be a
883  * multiple of the alignment constraint both in alignment and size.  Thus, the
884  * returned PCI address block is aligned to the maximum of the requested size
885  * and alignment.
886  */
887 iopaddr_t
888 pciio_device_win_alloc(struct resource *root_resource,
889                        pciio_win_alloc_t win_alloc,
890                        size_t start, size_t size, size_t align)
891 {
892
893         struct resource *new_res;
894         int status;
895
896         new_res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL);
897         if (!new_res)
898                 return 0;
899
900         if (start > 0) {
901                 status = allocate_resource( root_resource, new_res,
902                         size, start /* Min start addr. */,
903                         (start + size) - 1, 1,
904                         NULL, NULL);
905         } else {
906                 if (size > align)
907                         align = size;
908                 status = allocate_resource( root_resource, new_res,
909                                     size, align /* Min start addr. */,
910                                     root_resource->end, align,
911                                     NULL, NULL);
912         }
913
914         if (status) {
915                 kfree(new_res);
916                 return((iopaddr_t) NULL);
917         }
918
919         /*
920          * If a window allocation cookie has been supplied, use it to keep
921          * track of all the allocated space assigned to this window.
922          */
923         if (win_alloc) {
924                 win_alloc->wa_resource = new_res;
925                 win_alloc->wa_base = new_res->start;
926                 win_alloc->wa_pages = size;
927         }
928
929         return new_res->start;
930 }
931
932 /*
933  * Free the specified window allocation back into the PCI window mapping
934  * resource.  As noted above, we keep page addresses offset by 1 ...
935  */
936 void
937 pciio_device_win_free(pciio_win_alloc_t win_alloc)
938 {
939         int status;
940
941         if (win_alloc->wa_resource) {
942                 status = release_resource(win_alloc->wa_resource);
943                 if (!status)
944                         kfree(win_alloc->wa_resource);
945                 else
946                         BUG();
947         }
948 }
949
950 /*
951  * pciio_error_register:
952  * arrange for a function to be called with
953  * a specified first parameter plus other
954  * information when an error is encountered
955  * and traced to the pci slot corresponding
956  * to the connection point pconn.
957  *
958  * may also be called with a null function
959  * pointer to "unregister" the error handler.
960  *
961  * NOTE: subsequent calls silently overwrite
962  * previous data for this vertex. We assume that
963  * cooperating drivers, well, cooperate ...
964  */
965 void
966 pciio_error_register(vertex_hdl_t pconn,
967                      error_handler_f *efunc,
968                      error_handler_arg_t einfo)
969 {
970     pciio_info_t            pciio_info;
971
972     pciio_info = pciio_info_get(pconn);
973     ASSERT(pciio_info != NULL);
974     pciio_info->c_efunc = efunc;
975     pciio_info->c_einfo = einfo;
976 }
977
978 /*
979  * Check if any device has been found in this slot, and return
980  * true or false
981  * vhdl is the vertex for the slot
982  */
983 int
984 pciio_slot_inuse(vertex_hdl_t pconn_vhdl)
985 {
986     pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);
987
988     ASSERT(pciio_info);
989     ASSERT(pciio_info->c_vertex == pconn_vhdl);
990     if (pciio_info->c_vendor) {
991         /*
992          * Non-zero value for vendor indicate
993          * a board being found in this slot.
994          */
995         return 1;
996     }
997     return 0;
998 }
999
1000 int
1001 pciio_info_type1_get(pciio_info_t pci_info)
1002 {
1003         return (pci_info->c_type1);
1004 }