Home | History | Annotate | Line # | Download | only in pci
pci_1000.c revision 1.8
      1 /* $NetBSD: pci_1000.c,v 1.8 2000/06/04 19:14:20 cgd Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is based on pci_kn20aa.c, written by Chris G. Demetriou at
      8  * Carnegie-Mellon University. Platform support for Mikasa and Mikasa/Pinnacle
      9  * (Pinkasa) by Ross Harvey with copyright assignment by permission of Avalon
     10  * Computer Systems, Inc.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. All advertising materials mentioning features or use of this software
     21  *    must display the following acknowledgement:
     22  *	This product includes software developed by the NetBSD
     23  *	Foundation, Inc. and its contributors.
     24  * 4. Neither the name of The NetBSD Foundation nor the names of its
     25  *    contributors may be used to endorse or promote products derived
     26  *    from this software without specific prior written permission.
     27  *
     28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     38  * POSSIBILITY OF SUCH DAMAGE.
     39  */
     40 
     41 /*
     42  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
     43  * All rights reserved.
     44  *
     45  * Author: Chris G. Demetriou
     46  *
     47  * Permission to use, copy, modify and distribute this software and
     48  * its documentation is hereby granted, provided that both the copyright
     49  * notice and this permission notice appear in all copies of the
     50  * software, derivative works or modified versions, and any portions
     51  * thereof, and that both notices appear in supporting documentation.
     52  *
     53  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     54  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     55  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     56  *
     57  * Carnegie Mellon requests users of this software to return to
     58  *
     59  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     60  *  School of Computer Science
     61  *  Carnegie Mellon University
     62  *  Pittsburgh PA 15213-3890
     63  *
     64  * any improvements or extensions that they make and grant Carnegie the
     65  * rights to redistribute these changes.
     66  */
     67 
     68 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
     69 
     70 __KERNEL_RCSID(0, "$NetBSD: pci_1000.c,v 1.8 2000/06/04 19:14:20 cgd Exp $");
     71 
     72 #include <sys/types.h>
     73 #include <sys/param.h>
     74 #include <sys/time.h>
     75 #include <sys/systm.h>
     76 #include <sys/errno.h>
     77 #include <sys/malloc.h>
     78 #include <sys/device.h>
     79 #include <sys/syslog.h>
     80 
     81 #include <vm/vm.h>
     82 
     83 #include <machine/autoconf.h>
     84 
     85 #include <dev/pci/pcireg.h>
     86 #include <dev/pci/pcivar.h>
     87 
     88 #include <alpha/pci/pci_1000.h>
     89 
     90 #include <machine/intrcnt.h>
     91 
     92 #include "sio.h"
     93 #if NSIO > 0 || NPCEB > 0
     94 #include <alpha/pci/siovar.h>
     95 #endif
     96 
     97 static bus_space_tag_t another_mystery_icu_iot;
     98 static bus_space_handle_t another_mystery_icu_ioh;
     99 
    100 int	dec_1000_intr_map __P((void *, pcitag_t, int, int, pci_intr_handle_t *));
    101 const char *dec_1000_intr_string __P((void *, pci_intr_handle_t));
    102 const struct evcnt *dec_1000_intr_evcnt __P((void *, pci_intr_handle_t));
    103 void	*dec_1000_intr_establish __P((void *, pci_intr_handle_t,
    104 	    int, int (*func)(void *), void *));
    105 void	dec_1000_intr_disestablish __P((void *, void *));
    106 
    107 #define	PCI_STRAY_MAX	  5
    108 
    109 struct alpha_shared_intr *dec_1000_pci_intr;
    110 
    111 static void dec_1000_iointr __P((void *framep, unsigned long vec));
    112 static void dec_1000_enable_intr __P((int irq));
    113 static void dec_1000_disable_intr __P((int irq));
    114 static void pci_1000_imi __P((void));
    115 static pci_chipset_tag_t pc_tag;
    116 
    117 void
    118 pci_1000_pickintr(core, iot, memt, pc)
    119 	void *core;
    120 	bus_space_tag_t iot, memt;
    121 	pci_chipset_tag_t pc;
    122 {
    123 	int i;
    124 
    125 	another_mystery_icu_iot = iot;
    126 
    127 	pc_tag = pc;
    128 	if (bus_space_map(iot, 0x536, 2, 0, &another_mystery_icu_ioh))
    129 		panic("pci_1000_pickintr");
    130         pc->pc_intr_v = core;
    131         pc->pc_intr_map = dec_1000_intr_map;
    132         pc->pc_intr_string = dec_1000_intr_string;
    133 	pc->pc_intr_evcnt = dec_1000_intr_evcnt;
    134         pc->pc_intr_establish = dec_1000_intr_establish;
    135         pc->pc_intr_disestablish = dec_1000_intr_disestablish;
    136 
    137 	pc->pc_pciide_compat_intr_establish = NULL;
    138 
    139 	dec_1000_pci_intr = alpha_shared_intr_alloc(INTRCNT_DEC_1000_IRQ_LEN);
    140 	for (i = 0; i < INTRCNT_DEC_1000_IRQ_LEN; i++)
    141 		alpha_shared_intr_set_maxstrays(dec_1000_pci_intr, i,
    142 		    PCI_STRAY_MAX);
    143 
    144 	pci_1000_imi();
    145 #if NSIO > 0 || NPCEB > 0
    146 	sio_intr_setup(pc, iot);
    147 #endif
    148 	set_iointr(dec_1000_iointr);
    149 }
    150 
    151 int
    152 dec_1000_intr_map(ccv, bustag, buspin, line, ihp)
    153         void *ccv;
    154         pcitag_t bustag;
    155         int buspin, line;
    156         pci_intr_handle_t *ihp;
    157 {
    158 	int	device;
    159 
    160 	if (buspin == 0)	/* No IRQ used. */
    161 		return 1;
    162 	if (!(1 <= buspin && buspin <= 4))
    163 		goto bad;
    164 
    165 	alpha_pci_decompose_tag(pc_tag, bustag, NULL, &device, NULL);
    166 
    167 	switch(device) {
    168 	case 6:
    169 		if(buspin != 1)
    170 			break;
    171 		*ihp = 0xc;		/* integrated ncr scsi */
    172 		return 0;
    173 	case 11:
    174 	case 12:
    175 	case 13:
    176 		*ihp = (device - 11) * 4 + buspin - 1;
    177 		return 0;
    178 	}
    179 
    180 bad:	printf("dec_1000_intr_map: can't map dev %d pin %d\n", device, buspin);
    181 	return 1;
    182 }
    183 
    184 const char *
    185 dec_1000_intr_string(ccv, ih)
    186 	void *ccv;
    187 	pci_intr_handle_t ih;
    188 {
    189 	static const char irqmsg_fmt[] = "dec_1000 irq %ld";
    190         static char irqstr[sizeof irqmsg_fmt];
    191 
    192         if (ih >= INTRCNT_DEC_1000_IRQ_LEN)
    193                 panic("dec_1000_intr_string: bogus dec_1000 IRQ 0x%lx\n", ih);
    194 
    195         snprintf(irqstr, sizeof irqstr, irqmsg_fmt, ih);
    196         return (irqstr);
    197 }
    198 
    199 const struct evcnt *
    200 dec_1000_intr_evcnt(ccv, ih)
    201 	void *ccv;
    202 	pci_intr_handle_t ih;
    203 {
    204 
    205 	/* XXX for now, no evcnt parent reported */
    206 	return (NULL);
    207 }
    208 
    209 void *
    210 dec_1000_intr_establish(ccv, ih, level, func, arg)
    211         void *ccv, *arg;
    212         pci_intr_handle_t ih;
    213         int level;
    214         int (*func) __P((void *));
    215 {
    216 	void *cookie;
    217 
    218         if (ih >= INTRCNT_DEC_1000_IRQ_LEN)
    219                 panic("dec_1000_intr_establish: IRQ too high, 0x%lx\n", ih);
    220 
    221 	cookie = alpha_shared_intr_establish(dec_1000_pci_intr, ih, IST_LEVEL,
    222 	    level, func, arg, "dec_1000 irq");
    223 
    224 	if (cookie != NULL &&
    225 	    alpha_shared_intr_isactive(dec_1000_pci_intr, ih))
    226 		dec_1000_enable_intr(ih);
    227 	return (cookie);
    228 }
    229 
    230 void
    231 dec_1000_intr_disestablish(ccv, cookie)
    232         void *ccv, *cookie;
    233 {
    234 	struct alpha_shared_intrhand *ih = cookie;
    235 	unsigned int irq = ih->ih_num;
    236 	int s;
    237 
    238 	s = splhigh();
    239 
    240 	alpha_shared_intr_disestablish(dec_1000_pci_intr, cookie,
    241 	    "dec_1000 irq");
    242 	if (alpha_shared_intr_isactive(dec_1000_pci_intr, irq) == 0) {
    243 		dec_1000_disable_intr(irq);
    244 		alpha_shared_intr_set_dfltsharetype(dec_1000_pci_intr, irq,
    245 		    IST_NONE);
    246 	}
    247 
    248 	splx(s);
    249 }
    250 
    251 static void
    252 dec_1000_iointr(framep, vec)
    253 	void *framep;
    254 	unsigned long vec;
    255 {
    256 	int irq;
    257 
    258 	if (vec >= 0x900) {
    259 		if (vec >= 0x900 + (INTRCNT_DEC_1000_IRQ_LEN << 4))
    260 			panic("dec_1000_iointr: vec 0x%lx out of range\n", vec);
    261 		irq = (vec - 0x900) >> 4;
    262 
    263 		intrcnt[INTRCNT_DEC_1000_IRQ + irq]++;
    264 
    265 		if (!alpha_shared_intr_dispatch(dec_1000_pci_intr, irq)) {
    266 			alpha_shared_intr_stray(dec_1000_pci_intr, irq,
    267 			    "dec_1000 irq");
    268 			if (ALPHA_SHARED_INTR_DISABLE(dec_1000_pci_intr, irq))
    269 				dec_1000_disable_intr(irq);
    270 		}
    271 		return;
    272 	}
    273 #if NSIO > 0 || NPCEB > 0
    274 	if (vec >= 0x800) {
    275 		sio_iointr(framep, vec);
    276 		return;
    277 	}
    278 #endif
    279 	panic("dec_1000_iointr: weird vec 0x%lx\n", vec);
    280 }
    281 
    282 /*
    283  * Read and write the mystery ICU IMR registers
    284  */
    285 
    286 #define	IR() bus_space_read_2(another_mystery_icu_iot,		\
    287 				another_mystery_icu_ioh, 0)
    288 
    289 #define	IW(v) bus_space_write_2(another_mystery_icu_iot,	\
    290 				another_mystery_icu_ioh, 0, (v))
    291 
    292 /*
    293  * Enable and disable interrupts at the ICU level
    294  */
    295 
    296 static void
    297 dec_1000_enable_intr(irq)
    298 	int irq;
    299 {
    300 	IW(IR() | 1 << irq);
    301 }
    302 
    303 static void
    304 dec_1000_disable_intr(irq)
    305 	int irq;
    306 {
    307 	IW(IR() & ~(1 << irq));
    308 }
    309 /*
    310  * Initialize mystery ICU
    311  */
    312 static void
    313 pci_1000_imi()
    314 {
    315 	IW(0);					/* XXX ?? */
    316 }
    317