]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/sys/alpha/mcbus/mcpcia.c
Clone Kip's Xen on stable/6 tree so that I can work on improving FreeBSD/amd64
[FreeBSD/FreeBSD.git] / 6 / sys / alpha / mcbus / mcpcia.c
1 /*-
2  * Copyright (c) 2000 Matthew Jacob
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #define __RMAN_RESOURCE_VISIBLE
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/lock.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/mutex.h>
38 #include <sys/bus.h>
39 #include <sys/cons.h>
40 #include <machine/bus.h>
41 #include <machine/md_var.h>
42 #include <sys/proc.h>
43 #include <sys/rman.h>
44 #include <sys/interrupt.h>
45
46 #include <machine/swiz.h>
47 #include <machine/intr.h>
48 #include <machine/intrcnt.h>
49 #include <machine/resource.h>
50 #include <machine/sgmap.h>
51 #include <machine/prom.h>
52 #include <vm/vm.h>
53 #include <vm/vm_page.h>
54  
55
56 #include <alpha/mcbus/mcbusreg.h>
57 #include <alpha/mcbus/mcbusvar.h>
58
59 #include <alpha/mcbus/mcpciareg.h>
60 #include <alpha/mcbus/mcpciavar.h>
61 #include <alpha/pci/pcibus.h>
62 #include <dev/pci/pcireg.h>
63 #include <dev/pci/pcivar.h>
64
65 #include "alphapci_if.h"
66 #include "pcib_if.h"
67
68 static devclass_t       mcpcia_devclass;
69
70 /* We're only allowing for one MCBUS right now */
71 static device_t         mcpcias[MCPCIA_PER_MCBUS];
72
73 #define KV(pa)          ((void *)ALPHA_PHYS_TO_K0SEG(pa))
74
75 struct mcpcia_softc {
76         struct mcpcia_softc *next;
77         device_t        dev;            /* backpointer */
78         u_int64_t       sysbase;        /* shorthand */
79         vm_offset_t     dmem_base;      /* dense memory */
80         vm_offset_t     smem_base;      /* sparse memory */
81         vm_offset_t     io_base;        /* sparse i/o */
82         int             mcpcia_inst;    /* our mcpcia instance # */
83         struct swiz_space io_space;     /* accessor for ports */
84         struct swiz_space mem_space;    /* accessor for memory */
85         struct rman     io_rman;        /* resource manager for ports */
86         struct rman     mem_rman;       /* resource manager for memory */
87 };
88 static struct mcpcia_softc *mcpcia_eisa = NULL;
89 extern void dec_kn300_cons_init(void);
90
91 static driver_intr_t mcpcia_intr;
92 static void mcpcia_enable_intr(struct mcpcia_softc *, int);
93 static void mcpcia_disable_intr(struct mcpcia_softc *, int);
94
95 /*
96  * SGMAP window for ISA: 8M at 8M
97  */
98 #define MCPCIA_ISA_SG_MAPPED_BASE       (8*1024*1024)
99 #define MCPCIA_ISA_SG_MAPPED_SIZE       (8*1024*1024)
100
101 /*
102  * Direct-mapped window: 2G at 2G
103  */
104 #define MCPCIA_DIRECT_MAPPED_BASE       (2UL*1024UL*1024UL*1024UL)
105 #define MCPCIA_DIRECT_MAPPED_SIZE       (2UL*1024UL*1024UL*1024UL)
106
107 /*
108  * SGMAP window for PCI: 1G at 1G
109  */
110 #define MCPCIA_PCI_SG_MAPPED_BASE       (1UL*1024UL*1024UL*1024UL)
111 #define MCPCIA_PCI_SG_MAPPED_SIZE       (1UL*1024UL*1024UL*1024UL)
112
113 #define MCPCIA_SGTLB_INVALIDATE(sc)                                     \
114 do {                                                                    \
115         alpha_mb();                                                     \
116         REGVAL(MCPCIA_SG_TBIA(sc)) = 0xdeadbeef;                        \
117         alpha_mb();                                                     \
118 } while (0)
119
120 static void mcpcia_dma_init(struct mcpcia_softc *);
121 static void mcpcia_sgmap_map(void *, bus_addr_t, vm_offset_t);
122
123 #define MCPCIA_SOFTC(dev)       (struct mcpcia_softc *) device_get_softc(dev)
124
125 static struct mcpcia_softc *mcpcia_root;
126
127 /*
128  * Early console support requires us to partially probe the bus to
129  * find the ISA bus resources.
130  */
131 void
132 mcpcia_init(int gid, int mid)
133 {
134         static struct swiz_space io_space;
135         static struct swiz_space mem_space;
136         u_int64_t sysbase;
137         vm_offset_t regs, io_base, smem_base;
138
139         sysbase = MCBUS_IOSPACE |
140                 (((u_int64_t) gid) << MCBUS_GID_SHIFT) |
141                 (((u_int64_t) mid) << MCBUS_MID_SHIFT);
142
143         if (EISA_PRESENT(REGVAL(sysbase
144                                 | MCPCIA_PCI_BRIDGE
145                                 | _MCPCIA_PCI_REV))) {
146                 /*
147                  * Define temporary spaces for bootstrap i/o.
148                  */
149                 regs      = (vm_offset_t) KV(sysbase);
150                 io_base   = regs + MCPCIA_PCI_IOSPACE;
151                 smem_base = regs + MCPCIA_PCI_SPARSE;
152
153                 swiz_init_space(&io_space, io_base);
154                 swiz_init_space(&mem_space, smem_base);
155
156                 busspace_isa_io = (struct alpha_busspace *) &io_space;
157                 busspace_isa_mem = (struct alpha_busspace *) &mem_space;
158         }
159 }
160
161 static int
162 mcpcia_probe(device_t dev)
163 {
164         device_t child;
165         int unit;
166         struct mcpcia_softc *xc, *sc = MCPCIA_SOFTC(dev);
167
168         unit = device_get_unit(dev);
169         if (mcpcias[unit]) {
170                 printf("%s: already attached\n", device_get_nameunit(dev));
171                 return EEXIST;
172         }
173         sc->mcpcia_inst = unit;
174         if ((xc = mcpcia_root) == NULL) {
175                 mcpcia_root = sc;
176         } else {
177                 while (xc->next)
178                         xc = xc->next;
179                 xc->next = sc;
180         }
181         sc->dev = mcpcias[unit] = dev;
182         /* PROBE ? */
183         device_set_desc(dev, "MCPCIA PCI Adapter");
184         if (unit == 0) {
185                 pci_init_resources();
186         }
187         child = device_add_child(dev, "pci", -1);
188         device_set_ivars(child, &sc->mcpcia_inst);
189         return (0);
190 }
191
192 static int
193 mcpcia_attach(device_t dev)
194 {
195         struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
196         device_t p = device_get_parent(dev);
197         vm_offset_t regs;
198         u_int32_t ctl;
199         int mid, gid, rval;
200         void *intr;
201
202         mid = mcbus_get_mid(dev);
203         gid = mcbus_get_gid(dev);
204
205         sc->sysbase = MCBUS_IOSPACE |
206             (((u_int64_t) gid) << MCBUS_GID_SHIFT) | \
207             (((u_int64_t) mid) << MCBUS_MID_SHIFT);
208         regs            = (vm_offset_t) KV(sc->sysbase);
209         sc->dmem_base   = regs + MCPCIA_PCI_DENSE;
210         sc->smem_base   = regs + MCPCIA_PCI_SPARSE;
211         sc->io_base     = regs + MCPCIA_PCI_IOSPACE;
212
213         swiz_init_space(&sc->io_space, sc->io_base);
214         swiz_init_space(&sc->mem_space, sc->smem_base);
215
216         sc->io_rman.rm_start = 0;
217         sc->io_rman.rm_end = ~0u;
218         sc->io_rman.rm_type = RMAN_ARRAY;
219         sc->io_rman.rm_descr = "I/O ports";
220         if (rman_init(&sc->io_rman)
221             || rman_manage_region(&sc->io_rman, 0x0, (1L << 32)))
222                 panic("mcpcia_attach: io_rman");
223
224         sc->mem_rman.rm_start = 0;
225         sc->mem_rman.rm_end = ~0u;
226         sc->mem_rman.rm_type = RMAN_ARRAY;
227         sc->mem_rman.rm_descr = "I/O memory";
228         if (rman_init(&sc->mem_rman)
229             || rman_manage_region(&sc->mem_rman, 0x0, (1L << 32)))
230                 panic("mcpcia_attach: mem_rman");
231
232         /*
233          * Disable interrupts and clear errors prior to probing
234          */
235         REGVAL(MCPCIA_INT_MASK0(sc)) = 0;
236         REGVAL(MCPCIA_INT_MASK1(sc)) = 0;
237         REGVAL(MCPCIA_CAP_ERR(sc)) = 0xFFFFFFFF;
238         alpha_mb();
239
240         /*
241          * Say who we are
242          */
243         ctl = REGVAL(MCPCIA_PCI_REV(sc));
244         printf("%s: Horse Revision %d, %s Handed Saddle Revision %d,"
245             " CAP Revision %d\n", device_get_nameunit(dev), HORSE_REV(ctl),
246             (SADDLE_TYPE(ctl) & 1)? "Right": "Left", SADDLE_REV(ctl),
247             CAP_REV(ctl));
248
249         /*
250          * See if we're the fella with the EISA bus...
251          */
252
253         if (EISA_PRESENT(REGVAL(MCPCIA_PCI_REV(sc)))) {
254                 mcpcia_eisa = sc;
255         }
256
257         /*
258          * Set up DMA stuff here.
259          */
260
261         mcpcia_dma_init(sc);
262
263         /*
264          * Register our interrupt service requirements with our parent.
265          */
266         rval =
267             BUS_SETUP_INTR(p, dev, NULL, INTR_TYPE_MISC, mcpcia_intr, 0, &intr);
268         if (rval == 0) {
269                 if (sc == mcpcia_eisa) {
270                         busspace_isa_io = (struct alpha_busspace *)
271                                 &sc->io_space;
272                         busspace_isa_mem = (struct alpha_busspace *)
273                                 &sc->mem_space;
274                         /*
275                          * Enable EISA interrupts.
276                          */
277                         mcpcia_enable_intr(sc, 16);
278                 }
279                 bus_generic_attach(dev);
280         }
281         return (rval);
282 }
283
284 static void
285 mcpcia_enable_intr(struct mcpcia_softc *sc, int irq)
286 {
287
288         REGVAL(MCPCIA_INT_MASK0(sc)) |= (1 << irq);
289         alpha_mb();
290 }
291
292 static void
293 mcpcia_disable_intr(struct mcpcia_softc *sc, int irq)
294 {
295
296         /*
297          * We need to write to INT_REQ as well as INT_MASK0 in case we
298          * are trying to mask an interrupt which is already
299          * asserted. Writing a 1 bit to INT_REQ clears the
300          * corresponding bit in the register.
301          */
302         REGVAL(MCPCIA_INT_MASK0(sc)) &= ~(1 << irq);
303         REGVAL(MCPCIA_INT_REQ(sc)) = (1 << irq);
304         alpha_mb();
305 }
306
307 static void
308 mcpcia_disable_intr_vec(uintptr_t vector)
309 {
310         int mid, irq;
311         struct mcpcia_softc *sc = mcpcia_root;
312
313         if (vector < MCPCIA_VEC_PCI) {
314                 printf("EISA disable (0x%lx)\n", vector);
315                 return;
316         }
317
318         if (vector == MCPCIA_VEC_NCR) {
319                 mid = 5;
320                 irq = 16;
321         } else {
322                 int tmp, slot;
323                 tmp = vector - MCPCIA_VEC_PCI;
324                 mid = (tmp / MCPCIA_VECWIDTH_PER_MCPCIA) + 4;
325                 tmp &= (MCPCIA_VECWIDTH_PER_MCPCIA - 1);
326                 slot = tmp / MCPCIA_VECWIDTH_PER_SLOT;
327                 if (slot < 2 || slot > 5) {
328                         printf("Bad slot (%d) for vector %lx\n", slot, vector);
329                         return;
330                 }
331                 tmp -= (2 * MCPCIA_VECWIDTH_PER_SLOT);
332                 irq = (tmp >> MCPCIA_VECWIDTH_PER_INTPIN) & 0xf;
333         }
334 /*      printf("D<%03x>=%d,%d\n", vector, mid, irq); */
335         while (sc) {
336                 if (mcbus_get_mid(sc->dev) == mid) {
337                         break;
338                 }
339                 sc = sc->next;
340         }
341         if (sc == NULL) {
342                 panic("couldn't find MCPCIA softc for vector 0x%lx", vector);
343         }
344         mtx_lock_spin(&icu_lock);
345         mcpcia_disable_intr(sc, irq);
346         mtx_unlock_spin(&icu_lock);
347 }
348
349 static void
350 mcpcia_enable_intr_vec(uintptr_t vector)
351 {
352         int mid, irq;
353         struct mcpcia_softc *sc = mcpcia_root;
354
355         if (vector < MCPCIA_VEC_PCI) {
356                 printf("EISA ensable (0x%lx)\n", vector);
357                 return;
358         }
359
360         if (vector == MCPCIA_VEC_NCR) {
361                 mid = 5;
362                 irq = 16;
363         } else {
364                 int tmp, slot;
365                 tmp = vector - MCPCIA_VEC_PCI;
366                 mid = (tmp / MCPCIA_VECWIDTH_PER_MCPCIA) + 4;
367                 tmp &= (MCPCIA_VECWIDTH_PER_MCPCIA - 1);
368                 slot = tmp / MCPCIA_VECWIDTH_PER_SLOT;
369                 if (slot < 2 || slot > 5) {
370                         printf("Bad slot (%d) for vector %lx\n", slot, vector);
371                         return;
372                 }
373                 tmp -= (2 * MCPCIA_VECWIDTH_PER_SLOT);
374                 irq = (tmp >> MCPCIA_VECWIDTH_PER_INTPIN) & 0xf;
375         }
376 /*      printf("E<%03x>=%d,%d\n", vector, mid, irq); */
377         while (sc) {
378                 if (mcbus_get_mid(sc->dev) == mid) {
379                         break;
380                 }
381                 sc = sc->next;
382         }
383         if (sc == NULL) {
384                 panic("couldn't find MCPCIA softc for vector 0x%lx", vector);
385         }
386         mtx_lock_spin(&icu_lock);
387         mcpcia_enable_intr(sc, irq);
388         mtx_unlock_spin(&icu_lock);
389 }
390
391 static int
392 mcpcia_pci_route_interrupt(device_t bus, device_t dev, int pin)
393 {
394         int irq, slot, mid;
395
396         /*
397          * Validate requested pin number.
398          */
399         if ((pin < 1) || (pin > 4)) {
400                 printf("mcpcia_pci_route_interrupt: bad interrupt pin %d\n",
401                     pin);
402                 return(255);
403         }
404
405         slot = pci_get_slot(dev);
406         mid = mcbus_get_mid(bus);
407
408 #if 0
409         printf("mcpcia_pci_route_interrupt: called for slot=%d, pin=%d, mid=%d\n", slot, pin, mid);
410 #endif
411
412         if (mid == 5 && slot == 1) {
413                 irq = 16;       /* MID 5, slot 1, is the internal NCR 53c810 */
414         } else if (slot >= 2 && slot <= 5) {
415                 irq = ((slot - 2) * 4) + (pin - 1);
416         } else {
417                 printf("mcpcia_pci_route_interrupt: weird device number %d\n",
418                     slot);
419                 return (255);
420         }
421
422         return(irq);
423 }
424
425 static int
426 mcpcia_setup_intr(device_t dev, device_t child, struct resource *ir, int flags,
427        driver_intr_t *intr, void *arg, void **cp)
428 {
429         struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
430         int mid, birq, irq, error, h;
431         
432         irq = ir->r_start;
433         mid = mcbus_get_mid(dev);
434
435         error = rman_activate_resource(ir);
436         if (error)
437                 return error;
438
439         /*
440          * We now construct a vector as the hardware would, unless
441          * this is the internal NCR 53c810 interrupt.
442          */
443         if (irq == 16) {
444                 h = MCPCIA_VEC_NCR;
445         } else {
446                 h = MCPCIA_VEC_PCI +
447                     ((mid - MCPCIA_PCI_MIDMIN) * MCPCIA_VECWIDTH_PER_MCPCIA) +
448                     irq * MCPCIA_VECWIDTH_PER_INTPIN +
449                     2 * MCPCIA_VECWIDTH_PER_SLOT;
450         }
451         birq = irq + INTRCNT_KN300_IRQ;
452         error = alpha_setup_intr(device_get_nameunit(child), h,
453             intr, arg, flags, cp, &intrcnt[birq],
454             mcpcia_disable_intr_vec, mcpcia_enable_intr_vec);
455         if (error)
456                 return error;
457         mtx_lock_spin(&icu_lock);
458         mcpcia_enable_intr(sc, irq);
459         mtx_unlock_spin(&icu_lock);
460         device_printf(child, "interrupting at IRQ 0x%x (vec 0x%x)\n",
461             irq , h);
462         return (0);
463 }
464
465 static int
466 mcpcia_teardown_intr(device_t dev, device_t child, struct resource *i, void *c)
467 {
468         struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
469
470         mtx_lock_spin(&icu_lock);
471         mcpcia_disable_intr(sc, i->r_start);
472         mtx_unlock_spin(&icu_lock);
473         alpha_teardown_intr(c);
474         return (rman_deactivate_resource(i));
475 }
476
477 static int
478 mcpcia_read_ivar(device_t dev, device_t child, int which, u_long *result)
479 {
480         switch (which) {
481         case  PCIB_IVAR_BUS:
482                 *result = 0;
483                 return 0;
484         }
485         return ENOENT;
486 }
487
488 static void *
489 mcpcia_cvt_dense(device_t dev, vm_offset_t addr)
490 {
491         struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
492
493         addr &= 0xffffffffUL;
494         return (void *) KV(addr | sc->dmem_base);
495         
496 }
497
498 static struct alpha_busspace *
499 mcpcia_get_bustag(device_t dev, int type)
500 {
501         struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
502
503         switch (type) {
504         case SYS_RES_IOPORT:
505                 return (struct alpha_busspace *) &sc->io_space;
506
507         case SYS_RES_MEMORY:
508                 return (struct alpha_busspace *) &sc->mem_space;
509         }
510
511         return 0;
512 }
513
514 static struct rman *
515 mcpcia_get_rman(device_t dev, int type)
516 {
517         struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
518
519         switch (type) {
520         case SYS_RES_IOPORT:
521                 return &sc->io_rman;
522
523         case SYS_RES_MEMORY:
524                 return &sc->mem_rman;
525         }
526
527         return 0;
528 }
529
530 static int
531 mcpcia_maxslots(device_t dev)
532 {
533         return (MCPCIA_MAXDEV);
534 }
535
536 static u_int32_t
537 mcpcia_read_config(device_t dev, int bus, int slot, int func,
538                    int off, int sz)
539 {
540         struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
541         u_int32_t *dp, data, rvp;
542         u_int64_t paddr;
543
544         if ((off == PCIR_INTLINE) && (sz == 1)) {
545                 /* SRM left bad value; let intr_route fill them in later */
546                 return ~0;
547         }
548
549         rvp = data = ~0;
550
551         /*
552          * There's nothing in slot 0 on a primary bus.
553          */
554         if (bus == 0 && (slot < 1 || slot >= MCPCIA_MAXDEV))
555                 return (data);
556
557         paddr = bus << 21;
558         paddr |= slot << 16;
559         paddr |= func << 13;
560         paddr |= ((sz - 1) << 3);
561         paddr |= ((unsigned long) ((off >> 2) << 7));
562         paddr |= MCPCIA_PCI_CONF;
563         paddr |= sc->sysbase;
564         dp = (u_int32_t *)KV(paddr);
565
566 #if     0
567 printf("CFGREAD MID %d %d.%d.%d sz %d off %d -> paddr 0x%x",
568 mcbus_get_mid(dev), bus , slot, func, sz, off, paddr);
569 #endif
570         if (badaddr(dp, sizeof (*dp)) == 0) {
571                 data = *dp;
572         }
573         if (data != ~0) {
574                 if (sz == 1) {
575                         rvp = SPARSE_BYTE_EXTRACT(off, data);
576                 } else if (sz == 2) {
577                         rvp = SPARSE_WORD_EXTRACT(off, data);
578                 } else {
579                         rvp = data;
580                 }
581         } else {
582                 rvp = data;
583         }
584
585 #if     0
586 printf(" data 0x%x -> 0x%x\n", data, rvp);
587 #endif
588         return (rvp);
589 }
590
591 static void
592 mcpcia_write_config(device_t dev, int bus, int slot, int func,
593                     int off, u_int32_t data, int sz)
594 {
595         struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
596         u_int32_t *dp;
597         u_int64_t paddr;
598
599         /*
600          * There's nothing in slot 0 on a primary bus.
601          */
602         if (bus != 0 && (slot < 1 || slot >= MCPCIA_MAXDEV))
603                 return;
604
605         paddr = bus << 21;
606         paddr |= slot << 16;
607         paddr |= func << 13;
608         paddr |= ((sz - 1) << 3);
609         paddr |= ((unsigned long) ((off >> 2) << 7));
610         paddr |= MCPCIA_PCI_CONF;
611         paddr |= sc->sysbase;
612         dp = (u_int32_t *)KV(paddr);
613
614         if (badaddr(dp, sizeof (*dp)) == 0) {
615                 u_int32_t new_data;
616                 if (sz == 1) {
617                         new_data = SPARSE_BYTE_INSERT(off, data);
618                 } else if (sz == 2) {
619                         new_data = SPARSE_WORD_INSERT(off, data);
620                 } else  {
621                         new_data = data;
622                 }
623
624 #if     0
625 printf("CFGWRITE MID%d %d.%d.%d sz %d off %d paddr %lx, data %x new_data %x\n",
626 mcbus_get_mid(dev), bus , slot, func, sz, off, paddr, data, new_data);
627 #endif
628
629                 *dp = new_data;
630         }
631 }
632
633 static void
634 mcpcia_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa)
635 {
636         u_int64_t *sgtable = arg;
637         int index = alpha_btop(ba - MCPCIA_ISA_SG_MAPPED_BASE);
638
639         if (pa) {
640                 if (pa > (1L<<32))
641                         panic("mcpcia_sgmap_map: can't map address 0x%lx", pa);
642                 sgtable[index] = ((pa >> 13) << 1) | 1;
643         } else {
644                 sgtable[index] = 0;
645         }
646         alpha_mb();
647         MCPCIA_SGTLB_INVALIDATE(mcpcia_eisa);
648 }
649
650 static void
651 mcpcia_dma_init(struct mcpcia_softc *sc)
652 {
653
654         /*
655          * Disable all windows first.
656          */
657
658         REGVAL(MCPCIA_W0_BASE(sc)) = 0;
659         REGVAL(MCPCIA_W1_BASE(sc)) = 0;
660         REGVAL(MCPCIA_W2_BASE(sc)) = 0;
661         REGVAL(MCPCIA_W3_BASE(sc)) = 0;
662         REGVAL(MCPCIA_T0_BASE(sc)) = 0;
663         REGVAL(MCPCIA_T1_BASE(sc)) = 0;
664         REGVAL(MCPCIA_T2_BASE(sc)) = 0;
665         REGVAL(MCPCIA_T3_BASE(sc)) = 0;
666         alpha_mb();
667
668         /*
669          * Set up window 0 as an 8MB SGMAP-mapped window starting at 8MB.
670          * Do this only for the EISA carrying MCPCIA. Partly because
671          * there's only one chipset sgmap thingie.
672          */
673
674         if (sc == mcpcia_eisa) {
675                 void *sgtable;
676                 REGVAL(MCPCIA_W0_MASK(sc)) = MCPCIA_WMASK_8M;
677
678                 sgtable = contigmalloc(8192, M_DEVBUF,
679                     M_NOWAIT, 0, 1L<<34, 32<<10, 1L<<34);
680
681                 if (sgtable == NULL) {
682                         panic("mcpcia_dma_init: cannot allocate sgmap");
683                         /* NOTREACHED */
684                 }
685                 REGVAL(MCPCIA_T0_BASE(sc)) =
686                     pmap_kextract((vm_offset_t)sgtable) >> MCPCIA_TBASEX_SHIFT;
687
688                 alpha_mb();
689                 REGVAL(MCPCIA_W0_BASE(sc)) = MCPCIA_WBASE_EN |
690                     MCPCIA_WBASE_SG | MCPCIA_ISA_SG_MAPPED_BASE;
691                 alpha_mb();
692                 MCPCIA_SGTLB_INVALIDATE(sc);
693                 chipset.sgmap = sgmap_map_create(MCPCIA_ISA_SG_MAPPED_BASE,
694                     MCPCIA_ISA_SG_MAPPED_BASE + MCPCIA_ISA_SG_MAPPED_SIZE - 1,
695                     mcpcia_sgmap_map, sgtable);
696         }
697
698         /*
699          * Set up window 1 as a 2 GB Direct-mapped window starting at 2GB.
700          */
701
702         REGVAL(MCPCIA_W1_MASK(sc)) = MCPCIA_WMASK_2G;
703         REGVAL(MCPCIA_T1_BASE(sc)) = 0;
704         alpha_mb();
705         REGVAL(MCPCIA_W1_BASE(sc)) =
706                 MCPCIA_DIRECT_MAPPED_BASE | MCPCIA_WBASE_EN;
707         alpha_mb();
708
709         /*
710          * When we get around to redoing the 'chipset' stuff to have more
711          * than one sgmap handler...
712          */
713
714 #if     0
715         /*
716          * Set up window 2 as a 1G SGMAP-mapped window starting at 1G.
717          */
718
719         REGVAL(MCPCIA_W2_MASK(sc)) = MCPCIA_WMASK_1G;
720         REGVAL(MCPCIA_T2_BASE(sc)) =
721                 ccp->cc_pci_sgmap.aps_ptpa >> MCPCIA_TBASEX_SHIFT;
722         alpha_mb();
723         REGVAL(MCPCIA_W2_BASE(sc)) =
724                 MCPCIA_WBASE_EN | MCPCIA_WBASE_SG | MCPCIA_PCI_SG_MAPPED_BASE;
725         alpha_mb();
726 #endif
727
728         /* XXX XXX BEGIN XXX XXX */
729         {                                                       /* XXX */
730                 alpha_XXX_dmamap_or = MCPCIA_DIRECT_MAPPED_BASE;/* XXX */
731         }                                                       /* XXX */
732         /* XXX XXX END XXX XXX */
733 }
734
735 /*
736  */
737
738 static void
739 mcpcia_intr(void *arg)
740 {
741         unsigned long vec = (unsigned long) arg;
742
743         /*
744          * Check for I2C interrupts.  These are technically within
745          * the PCI vector range, but no PCI device should ever map
746          * to them.
747          */
748         if (vec == MCPCIA_I2C_CVEC) {
749                 printf("i2c: controller interrupt\n");
750                 return;
751         }
752         if (vec == MCPCIA_I2C_BVEC) {
753                 printf("i2c: bus interrupt\n");
754                 return;
755         }
756
757         alpha_dispatch_intr(NULL, vec);
758 }
759
760 static device_method_t mcpcia_methods[] = {
761         /* Device interface */
762         DEVMETHOD(device_probe,                 mcpcia_probe),
763         DEVMETHOD(device_attach,                mcpcia_attach),
764
765         /* Bus interface */
766         DEVMETHOD(bus_print_child,              bus_generic_print_child),
767         DEVMETHOD(bus_read_ivar,                mcpcia_read_ivar),
768         DEVMETHOD(bus_setup_intr,               mcpcia_setup_intr),
769         DEVMETHOD(bus_teardown_intr,            mcpcia_teardown_intr),
770         DEVMETHOD(bus_alloc_resource,           alpha_pci_alloc_resource),
771         DEVMETHOD(bus_release_resource,         pci_release_resource),
772         DEVMETHOD(bus_activate_resource,        pci_activate_resource),
773         DEVMETHOD(bus_deactivate_resource,      pci_deactivate_resource),
774
775         /* alphapci interface */
776         DEVMETHOD(alphapci_cvt_dense,           mcpcia_cvt_dense),
777         DEVMETHOD(alphapci_get_bustag,          mcpcia_get_bustag),
778         DEVMETHOD(alphapci_get_rman,            mcpcia_get_rman),
779
780         /* pcib interface */
781         DEVMETHOD(pcib_maxslots,                mcpcia_maxslots),
782         DEVMETHOD(pcib_read_config,             mcpcia_read_config),
783         DEVMETHOD(pcib_write_config,            mcpcia_write_config),
784         DEVMETHOD(pcib_route_interrupt,         mcpcia_pci_route_interrupt),
785
786         { 0, 0 }
787 };
788
789 static driver_t mcpcia_driver = {
790         "pcib", mcpcia_methods, sizeof (struct mcpcia_softc)
791 };
792
793 DRIVER_MODULE(pcib, mcbus, mcpcia_driver, mcpcia_devclass, 0, 0);