Annotation of sys/arch/armish/dev/iq80321_pci.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: iq80321_pci.c,v 1.9 2007/05/10 17:59:24 deraadt Exp $ */
! 2: /* $NetBSD: iq80321_pci.c,v 1.5 2005/12/11 12:17:09 christos Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * Written by Jason R. Thorpe for Wasabi Systems, Inc.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: * 3. All advertising materials mentioning features or use of this software
! 19: * must display the following acknowledgement:
! 20: * This product includes software developed for the NetBSD Project by
! 21: * Wasabi Systems, Inc.
! 22: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
! 23: * or promote products derived from this software without specific prior
! 24: * written permission.
! 25: *
! 26: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
! 30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 36: * POSSIBILITY OF SUCH DAMAGE.
! 37: */
! 38:
! 39: /*
! 40: * IQ80321 PCI interrupt support.
! 41: */
! 42:
! 43: #include <sys/param.h>
! 44: #include <sys/systm.h>
! 45: #include <sys/device.h>
! 46:
! 47: #include <machine/bus.h>
! 48:
! 49: #include <armish/dev/iq80321reg.h>
! 50: #include <armish/dev/iq80321var.h>
! 51:
! 52: #include <arm/xscale/i80321reg.h>
! 53: #include <arm/xscale/i80321var.h>
! 54:
! 55: #include <dev/pci/pcidevs.h>
! 56: #include <dev/pci/ppbreg.h>
! 57:
! 58: int iq80321_pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
! 59: const char *iq80321_pci_intr_string(void *, pci_intr_handle_t);
! 60: void *iq80321_pci_intr_establish(void *, pci_intr_handle_t,
! 61: int, int (*func)(void *), void *, char *);
! 62: void iq80321_pci_intr_disestablish(void *, void *);
! 63:
! 64: struct irq_map {
! 65: uint8_t dev;
! 66: uint8_t intrpin;
! 67: uint8_t irq;
! 68: };
! 69:
! 70:
! 71: struct pci_id_list {
! 72: uint8_t bus;
! 73: uint8_t dev;
! 74: pci_vendor_id_t vend;
! 75: pci_product_id_t prod;
! 76: };
! 77:
! 78: struct board_id {
! 79: char *name;
! 80: struct irq_map *irq_map;
! 81: struct pci_id_list list[];
! 82: };
! 83:
! 84: struct irq_map *iq80321_irq_map;
! 85:
! 86: struct irq_map iq80321_thecus_irq_map[] = {
! 87: { 1, 1, ICU_INT_XINT(0) }, /* thecus re0 27 */
! 88: { 2, 1, ICU_INT_XINT(3) }, /* thecus re1 30 */
! 89: { 3, 1, ICU_INT_XINT(2) }, /* thecus sata 29 */
! 90: { 4, 1, ICU_INT_XINT(0) }, /* thecus uhci0 27 ??? */
! 91: { 4, 2, ICU_INT_XINT(0) }, /* thecus uhci1 27 */
! 92: { 4, 3, ICU_INT_XINT(2) }, /* thecus ehci0 29 */
! 93: { 5, 1, ICU_INT_XINT(3) }, /* thecus minipci slot */
! 94: { 0, 0, 255}
! 95: };
! 96:
! 97: struct irq_map iq80321_hdlg_irq_map[] = {
! 98: { 1, 1, ICU_INT_XINT(0) }, /* em0 27 */
! 99: { 2, 1, ICU_INT_XINT(1) }, /* wdc0 28 */
! 100: { 3, 1, ICU_INT_XINT(2) }, /* ochi0 29 */
! 101: { 3, 2, ICU_INT_XINT(2) }, /* ochi0 29 */
! 102: { 3, 3, ICU_INT_XINT(2) }, /* echi0 29 */
! 103: { 0, 0, 255}
! 104: };
! 105: struct irq_map certance_irq_map[] = {
! 106: { 0, 1, ICU_INT_XINT(0) }, /* em0 27 */
! 107: { 0, 2, ICU_INT_XINT(0) }, /* em0 27 */
! 108: { 1, 1, ICU_INT_XINT(1) }, /* sata 28 */
! 109: #if 0
! 110: { 2, 1, ICU_INT_XINT(0) }, /* scsi 29 */
! 111: #endif
! 112: { 2, 2, ICU_INT_XINT(3) }, /* scsi 30 */
! 113: { 0, 0, 255}
! 114: };
! 115: struct board_id thecus = {
! 116: "Thecus Nx100",
! 117: iq80321_thecus_irq_map,
! 118: {
! 119: { 0, 1, PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169 },
! 120: /* fill in the rest of the devices */
! 121: { 0, 0, 0, 0 }
! 122: }
! 123: };
! 124: struct board_id iodata = {
! 125: "I/O Data HDL-G",
! 126: iq80321_hdlg_irq_map,
! 127: {
! 128: { 0, 1, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82541GI },
! 129: /* fill in the rest of the devices */
! 130: { 0, 0, 0, 0 }
! 131: }
! 132: };
! 133: struct board_id certance = {
! 134: "Certance CP3100",
! 135: certance_irq_map,
! 136: {
! 137: { 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546EB_COPPER },
! 138: { 0, 1, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_31244 },
! 139: { 0, 2, PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_1010_2 },
! 140: /* fill in the rest of the devices */
! 141: { 0, 0, 0, 0 }
! 142: }
! 143: };
! 144:
! 145: struct board_id *systems[] = {
! 146: &thecus,
! 147: &iodata,
! 148: &certance,
! 149: NULL
! 150: };
! 151:
! 152: void
! 153: iq80321_pci_init(pci_chipset_tag_t pc, void *cookie)
! 154: {
! 155: pc->pc_intr_v = cookie; /* the i80321 softc */
! 156: pc->pc_intr_map = iq80321_pci_intr_map;
! 157: pc->pc_intr_string = iq80321_pci_intr_string;
! 158: pc->pc_intr_establish = iq80321_pci_intr_establish;
! 159: pc->pc_intr_disestablish = iq80321_pci_intr_disestablish;
! 160:
! 161: }
! 162: void
! 163: iq80321_pci_init2(pci_chipset_tag_t pc, void *cookie)
! 164: {
! 165: pcitag_t tag;
! 166: int i, j;
! 167: struct board_id *sys;
! 168: u_int32_t reg;
! 169:
! 170:
! 171: for (i = 0; systems[i] != NULL; i++) {
! 172: sys = systems[i];
! 173: for (j = 0; sys->list[j].vend != 0; j++) {
! 174: tag = pci_make_tag(pc, sys->list[j].bus,
! 175: sys->list[j].dev, 0);
! 176: reg = pci_conf_read(pc, tag, 0 /* ID */);
! 177: #ifdef PROBE_NEW_BOARD
! 178: printf("read %x expected %x\n", reg,
! 179: (sys->list[j].vend | sys->list[j].prod << 16));
! 180: #endif
! 181: if ((sys->list[j].vend | sys->list[j].prod << 16) !=
! 182: reg){
! 183: sys = NULL;
! 184: break;
! 185: }
! 186: }
! 187: if (sys != NULL)
! 188: break;
! 189: }
! 190: if (sys == NULL) {
! 191: printf("board id failed\n");
! 192: #ifdef PROBE_NEW_BOARD
! 193: for (i = 0; i < 16; i++) {
! 194: tag = pci_make_tag(pc, 0, i, 0);
! 195: printf("bus 0, dev %d: %x\n", i,
! 196: pci_conf_read(pc, tag, 0 /* ID */));
! 197: }
! 198: #endif
! 199: } else
! 200: printf(": %s", sys->name);
! 201: iq80321_irq_map = sys->irq_map;
! 202:
! 203: /* XXX */
! 204: if (sys == &thecus) {
! 205: /*
! 206: * thecus com irq appears to not be attached, override
! 207: * it's irq here, it is tied to the tick timer, irq9
! 208: * - yes this is a hack.
! 209: */
! 210: extern int com_irq_override;
! 211: com_irq_override = 28;
! 212: }
! 213: }
! 214:
! 215: int
! 216: iq80321_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
! 217: {
! 218: struct i80321_softc *sc = pa->pa_pc->pc_intr_v;
! 219: pci_chipset_tag_t pc = pa->pa_pc;
! 220: pcitag_t tag = pa->pa_intrtag;
! 221: int i;
! 222:
! 223: int b, d, f;
! 224: uint32_t busno;
! 225: uint32_t intr;
! 226:
! 227: busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
! 228: busno = PCIXSR_BUSNO(busno);
! 229: if (busno == 0xff)
! 230: busno = 0;
! 231:
! 232: pci_decompose_tag(pc, tag, &b, &d, &f);
! 233:
! 234: /* No mappings for devices not on our bus. */
! 235: if (b != busno)
! 236: goto no_mapping;
! 237:
! 238: for (i = 0; iq80321_irq_map[i].irq != 255; i++) {
! 239: if (d == iq80321_irq_map[i].dev &&
! 240: pa->pa_intrpin == iq80321_irq_map[i].intrpin) {
! 241: *ihp = iq80321_irq_map[i].irq;
! 242: intr = pci_conf_read(pa->pa_pc, pa->pa_intrtag,
! 243: PCI_INTERRUPT_REG);
! 244: intr = (intr & ~0xff) | iq80321_irq_map[i].irq;
! 245: pci_conf_write(pa->pa_pc, pa->pa_intrtag,
! 246: PCI_INTERRUPT_REG, intr);
! 247: return (0);
! 248: }
! 249: }
! 250:
! 251: no_mapping:
! 252: intr = pci_conf_read(pa->pa_pc, pa->pa_intrtag,
! 253: PCI_INTERRUPT_REG);
! 254:
! 255: printf("iq80321_pci_intr_map: no mapping for %d/%d/%d (%d, %d, %d)\n",
! 256: pa->pa_bus, pa->pa_device, pa->pa_function, d, pa->pa_intrpin, intr);
! 257: return (1);
! 258: }
! 259:
! 260: const char *
! 261: iq80321_pci_intr_string(void *v, pci_intr_handle_t ih)
! 262: {
! 263: static char irqname[32];
! 264:
! 265: snprintf(irqname, sizeof irqname, "irq %d", ih);
! 266: return (irqname);
! 267: }
! 268:
! 269: void *
! 270: iq80321_pci_intr_establish(void *v, pci_intr_handle_t ih, int ipl,
! 271: int (*func)(void *), void *arg, char *name)
! 272: {
! 273:
! 274: return (i80321_intr_establish(ih, ipl, func, arg, name));
! 275: }
! 276:
! 277: void
! 278: iq80321_pci_intr_disestablish(void *v, void *cookie)
! 279: {
! 280:
! 281: i80321_intr_disestablish(cookie);
! 282: }
CVSweb