Annotation of sys/arch/alpha/pci/pci_6600.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pci_6600.c,v 1.16 2007/05/02 21:50:14 martin Exp $ */
! 2: /* $NetBSD: pci_6600.c,v 1.5 2000/06/06 00:50:15 thorpej Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1999 by Ross Harvey. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Ross Harvey.
! 18: * 4. The name of Ross Harvey may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY ROSS HARVEY ``AS IS'' AND ANY EXPRESS
! 22: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 23: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURP0SE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL ROSS HARVEY BE LIABLE FOR ANY
! 25: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: *
! 33: */
! 34:
! 35: #include <sys/param.h>
! 36: #include <sys/systm.h>
! 37: #include <sys/kernel.h>
! 38: #include <sys/device.h>
! 39: #include <sys/malloc.h>
! 40:
! 41: #include <uvm/uvm.h>
! 42:
! 43: #include <machine/autoconf.h>
! 44: #define _ALPHA_BUS_DMA_PRIVATE
! 45: #include <machine/bus.h>
! 46: #include <machine/rpb.h>
! 47:
! 48: #include <dev/pci/pcireg.h>
! 49: #include <dev/pci/pcivar.h>
! 50: #include <dev/pci/pciidereg.h>
! 51: #include <dev/pci/pciidevar.h>
! 52:
! 53: #include <alpha/pci/tsreg.h>
! 54: #include <alpha/pci/tsvar.h>
! 55: #include <alpha/pci/pci_6600.h>
! 56:
! 57: #define pci_6600() { Generate ctags(1) key. }
! 58:
! 59: #include "sio.h"
! 60: #if NSIO
! 61: #include <alpha/pci/siovar.h>
! 62: #endif
! 63:
! 64: #define PCI_NIRQ 64
! 65: #define PCI_STRAY_MAX 5
! 66:
! 67: /*
! 68: * Some Tsunami models have a PCI device (the USB controller) with interrupts
! 69: * tied to ISA IRQ lines. The IRQ is encoded as:
! 70: *
! 71: * line = 0xe0 | isa_irq;
! 72: */
! 73: #define DEC_6600_LINE_IS_ISA(line) ((line) >= 0xe0 && (line) <= 0xef)
! 74: #define DEC_6600_LINE_ISA_IRQ(line) ((line) & 0x0f)
! 75:
! 76: static char *irqtype = "6600 irq";
! 77: static struct tsp_config *sioprimary;
! 78:
! 79: void dec_6600_intr_disestablish(void *, void *);
! 80: void *dec_6600_intr_establish(void *, pci_intr_handle_t, int,
! 81: int (*func)(void *), void *, char *);
! 82: const char *dec_6600_intr_string(void *, pci_intr_handle_t);
! 83: int dec_6600_intr_line(void *, pci_intr_handle_t);
! 84: int dec_6600_intr_map(void *, pcitag_t, int, int, pci_intr_handle_t *);
! 85: void *dec_6600_pciide_compat_intr_establish(void *, struct device *,
! 86: struct pci_attach_args *, int, int (*)(void *), void *);
! 87: void dec_6600_pciide_compat_intr_disestablish(void *, void *);
! 88:
! 89: struct alpha_shared_intr *dec_6600_pci_intr;
! 90:
! 91: void dec_6600_iointr(void *arg, unsigned long vec);
! 92: extern void dec_6600_intr_enable(int irq);
! 93: extern void dec_6600_intr_disable(int irq);
! 94:
! 95: void
! 96: pci_6600_pickintr(pcp)
! 97: struct tsp_config *pcp;
! 98: {
! 99: bus_space_tag_t iot = &pcp->pc_iot;
! 100: pci_chipset_tag_t pc = &pcp->pc_pc;
! 101: #if 0
! 102: char *cp;
! 103: #endif
! 104: int i;
! 105:
! 106: pc->pc_intr_v = pcp;
! 107: pc->pc_intr_map = dec_6600_intr_map;
! 108: pc->pc_intr_string = dec_6600_intr_string;
! 109: pc->pc_intr_line = dec_6600_intr_line;
! 110: pc->pc_intr_establish = dec_6600_intr_establish;
! 111: pc->pc_intr_disestablish = dec_6600_intr_disestablish;
! 112: pc->pc_pciide_compat_intr_establish = NULL;
! 113:
! 114: /*
! 115: * System-wide and Pchip-0-only logic...
! 116: */
! 117: if (dec_6600_pci_intr == NULL) {
! 118: sioprimary = pcp;
! 119: pc->pc_pciide_compat_intr_establish =
! 120: dec_6600_pciide_compat_intr_establish;
! 121: dec_6600_pci_intr = alpha_shared_intr_alloc(PCI_NIRQ);
! 122: for (i = 0; i < PCI_NIRQ; i++) {
! 123: alpha_shared_intr_set_maxstrays(dec_6600_pci_intr, i,
! 124: PCI_STRAY_MAX);
! 125: alpha_shared_intr_set_private(dec_6600_pci_intr, i,
! 126: sioprimary);
! 127: }
! 128: #if NSIO
! 129: sio_intr_setup(pc, iot);
! 130: dec_6600_intr_enable(55); /* irq line for sio */
! 131: #endif
! 132: }
! 133: }
! 134:
! 135: int
! 136: dec_6600_intr_map(acv, bustag, buspin, line, ihp)
! 137: void *acv;
! 138: pcitag_t bustag;
! 139: int buspin, line;
! 140: pci_intr_handle_t *ihp;
! 141: {
! 142: struct tsp_config *pcp = acv;
! 143: pci_chipset_tag_t pc = &pcp->pc_pc;
! 144: int bus, device, function;
! 145:
! 146: if (buspin == 0) {
! 147: /* No IRQ used. */
! 148: return 1;
! 149: }
! 150: if (buspin > 4) {
! 151: printf("intr_map: bad interrupt pin %d\n", buspin);
! 152: return 1;
! 153: }
! 154:
! 155: pci_decompose_tag(pc, bustag, &bus, &device, &function);
! 156:
! 157: /*
! 158: * The console places the interrupt mapping in the "line" value.
! 159: * A value of (char)-1 indicates there is no mapping.
! 160: */
! 161: if (line == 0xff) {
! 162: printf("dec_6600_intr_map: no mapping for %d/%d/%d\n",
! 163: bus, device, function);
! 164: return (1);
! 165: }
! 166:
! 167: #if NSIO == 0
! 168: if (DEC_6600_LINE_IS_ISA(line)) {
! 169: printf("dec_6600_intr_map: ISA IRQ %d for %d/%d/%d\n",
! 170: DEC_6600_LINE_ISA_IRQ(line), bus, device, function);
! 171: return (1);
! 172: }
! 173: #endif
! 174:
! 175: if (DEC_6600_LINE_IS_ISA(line) == 0 && line >= PCI_NIRQ)
! 176: panic("dec_6600_intr_map: dec 6600 irq too large (%d)",
! 177: line);
! 178:
! 179: *ihp = line;
! 180: return (0);
! 181: }
! 182:
! 183: const char *
! 184: dec_6600_intr_string(acv, ih)
! 185: void *acv;
! 186: pci_intr_handle_t ih;
! 187: {
! 188:
! 189: static const char irqfmt[] = "dec 6600 irq %ld";
! 190: static char irqstr[sizeof irqfmt];
! 191:
! 192: #if NSIO
! 193: if (DEC_6600_LINE_IS_ISA(ih))
! 194: return (sio_intr_string(NULL /*XXX*/,
! 195: DEC_6600_LINE_ISA_IRQ(ih)));
! 196: #endif
! 197:
! 198: snprintf(irqstr, sizeof irqstr, irqfmt, ih);
! 199: return (irqstr);
! 200: }
! 201:
! 202: int
! 203: dec_6600_intr_line(acv, ih)
! 204: void *acv;
! 205: pci_intr_handle_t ih;
! 206: {
! 207:
! 208: #if NSIO
! 209: if (DEC_6600_LINE_IS_ISA(ih))
! 210: return (sio_intr_line(NULL /*XXX*/,
! 211: DEC_6600_LINE_ISA_IRQ(ih)));
! 212: #endif
! 213:
! 214: return (ih);
! 215: }
! 216:
! 217: void *
! 218: dec_6600_intr_establish(acv, ih, level, func, arg, name)
! 219: void *acv, *arg;
! 220: pci_intr_handle_t ih;
! 221: int level;
! 222: int (*func)(void *);
! 223: char *name;
! 224: {
! 225: void *cookie;
! 226:
! 227: #if NSIO
! 228: if (DEC_6600_LINE_IS_ISA(ih))
! 229: return (sio_intr_establish(NULL /*XXX*/,
! 230: DEC_6600_LINE_ISA_IRQ(ih), IST_LEVEL, level, func, arg,
! 231: name));
! 232: #endif
! 233:
! 234: if (ih >= PCI_NIRQ)
! 235: panic("dec_6600_intr_establish: bogus dec 6600 IRQ 0x%lx",
! 236: ih);
! 237:
! 238: cookie = alpha_shared_intr_establish(dec_6600_pci_intr, ih, IST_LEVEL,
! 239: level, func, arg, name);
! 240:
! 241: if (cookie != NULL &&
! 242: alpha_shared_intr_firstactive(dec_6600_pci_intr, ih)) {
! 243: scb_set(0x900 + SCB_IDXTOVEC(ih), dec_6600_iointr, NULL);
! 244: dec_6600_intr_enable(ih);
! 245: }
! 246: return (cookie);
! 247: }
! 248:
! 249: void
! 250: dec_6600_intr_disestablish(acv, cookie)
! 251: void *acv, *cookie;
! 252: {
! 253: struct alpha_shared_intrhand *ih = cookie;
! 254: unsigned int irq = ih->ih_num;
! 255: int s;
! 256:
! 257: #if NSIO
! 258: /*
! 259: * We have to determine if this is an ISA IRQ or not! We do this
! 260: * by checking to see if the intrhand points back to an intrhead
! 261: * that points to the sioprimary TSP. If not, it's an ISA IRQ.
! 262: * Pretty disgusting, eh?
! 263: */
! 264: if (ih->ih_intrhead->intr_private != sioprimary) {
! 265: sio_intr_disestablish(NULL /*XXX*/, cookie);
! 266: return;
! 267: }
! 268: #endif
! 269:
! 270: s = splhigh();
! 271:
! 272: alpha_shared_intr_disestablish(dec_6600_pci_intr, cookie, irqtype);
! 273: if (alpha_shared_intr_isactive(dec_6600_pci_intr, irq) == 0) {
! 274: dec_6600_intr_disable(irq);
! 275: alpha_shared_intr_set_dfltsharetype(dec_6600_pci_intr, irq,
! 276: IST_NONE);
! 277: scb_free(0x900 + SCB_IDXTOVEC(irq));
! 278: }
! 279:
! 280: splx(s);
! 281: }
! 282:
! 283: void
! 284: dec_6600_iointr(arg, vec)
! 285: void *arg;
! 286: unsigned long vec;
! 287: {
! 288: int irq;
! 289:
! 290: irq = SCB_VECTOIDX(vec - 0x900);
! 291:
! 292: if (irq >= PCI_NIRQ)
! 293: panic("iointr: irq %d is too high", irq);
! 294:
! 295: if (!alpha_shared_intr_dispatch(dec_6600_pci_intr, irq)) {
! 296: alpha_shared_intr_stray(dec_6600_pci_intr, irq,
! 297: irqtype);
! 298: if (ALPHA_SHARED_INTR_DISABLE(dec_6600_pci_intr, irq))
! 299: dec_6600_intr_disable(irq);
! 300: } else
! 301: alpha_shared_intr_reset_strays(dec_6600_pci_intr, irq);
! 302: }
! 303:
! 304: void
! 305: dec_6600_intr_enable(irq)
! 306: int irq;
! 307: {
! 308: alpha_mb();
! 309: STQP(TS_C_DIM0) |= 1UL << irq;
! 310: alpha_mb();
! 311: }
! 312:
! 313: void
! 314: dec_6600_intr_disable(irq)
! 315: int irq;
! 316: {
! 317: alpha_mb();
! 318: STQP(TS_C_DIM0) &= ~(1UL << irq);
! 319: alpha_mb();
! 320: }
! 321:
! 322: void *
! 323: dec_6600_pciide_compat_intr_establish(v, dev, pa, chan, func, arg)
! 324: void *v;
! 325: struct device *dev;
! 326: struct pci_attach_args *pa;
! 327: int chan;
! 328: int (*func)(void *);
! 329: void *arg;
! 330: {
! 331: pci_chipset_tag_t pc = pa->pa_pc;
! 332: void *cookie = NULL;
! 333: int bus, irq;
! 334:
! 335: pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL);
! 336:
! 337: /*
! 338: * If this isn't PCI bus #0 on the TSP that holds the PCI-ISA
! 339: * bridge, all bets are off.
! 340: */
! 341: if (bus != 0 || pc->pc_intr_v != sioprimary)
! 342: return (NULL);
! 343:
! 344: irq = PCIIDE_COMPAT_IRQ(chan);
! 345: #if NSIO
! 346: cookie = sio_intr_establish(NULL /*XXX*/, irq, IST_EDGE, IPL_BIO,
! 347: func, arg, dev->dv_xname);
! 348:
! 349: if (cookie == NULL)
! 350: return (NULL);
! 351: #endif
! 352: return (cookie);
! 353: }
! 354:
! 355: void
! 356: dec_6600_pciide_compat_intr_disestablish(v, cookie)
! 357: void *v;
! 358: void *cookie;
! 359: {
! 360: sio_intr_disestablish(NULL, cookie);
! 361: }
CVSweb