1 /* $NetBSD: pci_2100_a50.c,v 1.37 2010/12/15 01:27:19 matt Exp $ */ 2 3 /* 4 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Author: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 31 32 __KERNEL_RCSID(0, "$NetBSD: pci_2100_a50.c,v 1.37 2010/12/15 01:27:19 matt Exp $"); 33 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/time.h> 37 #include <sys/systm.h> 38 #include <sys/errno.h> 39 #include <sys/device.h> 40 41 #include <machine/autoconf.h> 42 #include <machine/bus.h> 43 #include <machine/intr.h> 44 45 #include <dev/isa/isavar.h> 46 #include <dev/pci/pcireg.h> 47 #include <dev/pci/pcivar.h> 48 49 #include <alpha/pci/apecsvar.h> 50 51 #include <alpha/pci/pci_2100_a50.h> 52 #include <alpha/pci/siovar.h> 53 #include <alpha/pci/sioreg.h> 54 55 #include "sio.h" 56 57 int dec_2100_a50_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 58 const char *dec_2100_a50_intr_string(void *, pci_intr_handle_t); 59 const struct evcnt *dec_2100_a50_intr_evcnt(void *, pci_intr_handle_t); 60 void *dec_2100_a50_intr_establish(void *, pci_intr_handle_t, 61 int, int (*func)(void *), void *); 62 void dec_2100_a50_intr_disestablish(void *, void *); 63 64 #define APECS_SIO_DEVICE 7 /* XXX */ 65 66 void 67 pci_2100_a50_pickintr(struct apecs_config *acp) 68 { 69 bus_space_tag_t iot = &acp->ac_iot; 70 pci_chipset_tag_t pc = &acp->ac_pc; 71 pcireg_t sioclass; 72 int sioII; 73 74 /* XXX MAGIC NUMBER */ 75 sioclass = pci_conf_read(pc, pci_make_tag(pc, 0, 7, 0), PCI_CLASS_REG); 76 sioII = (sioclass & 0xff) >= 3; 77 78 if (!sioII) 79 printf("WARNING: SIO NOT SIO II... NO BETS...\n"); 80 81 pc->pc_intr_v = acp; 82 pc->pc_intr_map = dec_2100_a50_intr_map; 83 pc->pc_intr_string = dec_2100_a50_intr_string; 84 pc->pc_intr_evcnt = dec_2100_a50_intr_evcnt; 85 pc->pc_intr_establish = dec_2100_a50_intr_establish; 86 pc->pc_intr_disestablish = dec_2100_a50_intr_disestablish; 87 88 /* Not supported on 2100 A50. */ 89 pc->pc_pciide_compat_intr_establish = NULL; 90 91 #if NSIO 92 sio_intr_setup(pc, iot); 93 #else 94 panic("pci_2100_a50_pickintr: no I/O interrupt handler (no sio)"); 95 #endif 96 } 97 98 int 99 dec_2100_a50_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 100 { 101 pcitag_t bustag = pa->pa_intrtag; 102 int buspin = pa->pa_intrpin; 103 pci_chipset_tag_t pc = pa->pa_pc; 104 int device, pirq; 105 pcireg_t pirqreg; 106 u_int8_t pirqline; 107 108 #ifndef DIAGNOSTIC 109 pirq = 0; /* XXX gcc -Wuninitialized */ 110 #endif 111 112 if (buspin == 0) { 113 /* No IRQ used. */ 114 return 1; 115 } 116 if (buspin > 4) { 117 printf("dec_2100_a50_intr_map: bad interrupt pin %d\n", 118 buspin); 119 return 1; 120 } 121 122 pci_decompose_tag(pc, bustag, NULL, &device, NULL); 123 124 switch (device) { 125 case 6: /* NCR SCSI */ 126 pirq = 3; 127 break; 128 129 case 11: /* slot 1 */ 130 case 14: /* slot 3 */ 131 switch (buspin) { 132 case PCI_INTERRUPT_PIN_A: 133 case PCI_INTERRUPT_PIN_D: 134 pirq = 0; 135 break; 136 case PCI_INTERRUPT_PIN_B: 137 pirq = 2; 138 break; 139 case PCI_INTERRUPT_PIN_C: 140 pirq = 1; 141 break; 142 #ifdef DIAGNOSTIC 143 default: /* XXX gcc -Wuninitialized */ 144 panic("dec_2100_a50_intr_map bogus PCI pin %d", 145 buspin); 146 #endif 147 }; 148 break; 149 150 case 12: /* slot 2 */ 151 switch (buspin) { 152 case PCI_INTERRUPT_PIN_A: 153 case PCI_INTERRUPT_PIN_D: 154 pirq = 1; 155 break; 156 case PCI_INTERRUPT_PIN_B: 157 pirq = 0; 158 break; 159 case PCI_INTERRUPT_PIN_C: 160 pirq = 2; 161 break; 162 #ifdef DIAGNOSTIC 163 default: /* XXX gcc -Wuninitialized */ 164 panic("dec_2100_a50_intr_map bogus PCI pin %d", 165 buspin); 166 #endif 167 }; 168 break; 169 170 case 13: /* slot 3 */ 171 switch (buspin) { 172 case PCI_INTERRUPT_PIN_A: 173 case PCI_INTERRUPT_PIN_D: 174 pirq = 2; 175 break; 176 case PCI_INTERRUPT_PIN_B: 177 pirq = 1; 178 break; 179 case PCI_INTERRUPT_PIN_C: 180 pirq = 0; 181 break; 182 #ifdef DIAGNOSTIC 183 default: /* XXX gcc -Wuninitialized */ 184 panic("dec_2100_a50_intr_map bogus PCI pin %d", 185 buspin); 186 #endif 187 }; 188 break; 189 190 default: 191 printf("dec_2100_a50_intr_map: weird device number %d\n", 192 device); 193 return 1; 194 } 195 196 pirqreg = pci_conf_read(pc, pci_make_tag(pc, 0, APECS_SIO_DEVICE, 0), 197 SIO_PCIREG_PIRQ_RTCTRL); 198 #if 0 199 printf("pci_2100_a50_intr_map: device %d pin %c: pirq %d, reg = %x\n", 200 device, '@' + buspin, pirq, pirqreg); 201 #endif 202 pirqline = (pirqreg >> (pirq * 8)) & 0xff; 203 if ((pirqline & 0x80) != 0) 204 return 1; 205 pirqline &= 0xf; 206 207 #if 0 208 printf("pci_2100_a50_intr_map: device %d pin %c: mapped to line %d\n", 209 device, '@' + buspin, pirqline); 210 #endif 211 212 *ihp = pirqline; 213 return (0); 214 } 215 216 const char * 217 dec_2100_a50_intr_string(void *acv, pci_intr_handle_t ih) 218 { 219 #if 0 220 struct apecs_config *acp = acv; 221 #endif 222 223 return sio_intr_string(NULL /*XXX*/, ih); 224 } 225 226 const struct evcnt * 227 dec_2100_a50_intr_evcnt(void *acv, pci_intr_handle_t ih) 228 { 229 #if 0 230 struct apecs_config *acp = acv; 231 #endif 232 233 return sio_intr_evcnt(NULL /*XXX*/, ih); 234 } 235 236 void * 237 dec_2100_a50_intr_establish(void *acv, pci_intr_handle_t ih, int level, int (*func)(void *), void *arg) 238 { 239 #if 0 240 struct apecs_config *acp = acv; 241 #endif 242 243 return sio_intr_establish(NULL /*XXX*/, ih, IST_LEVEL, level, func, 244 arg); 245 } 246 247 void 248 dec_2100_a50_intr_disestablish(void *acv, void *cookie) 249 { 250 #if 0 251 struct apecs_config *acp = acv; 252 #endif 253 254 sio_intr_disestablish(NULL /*XXX*/, cookie); 255 } 256