necpb.c revision 1.2
1/*	$NetBSD: necpb.c,v 1.2 2000/06/17 07:25:57 soda Exp $	*/
2
3/*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *	This product includes software developed by the NetBSD
22 *	Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 *    contributors may be used to endorse or promote products derived
25 *    from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40/*
41 * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
42 * Copyright (c) 1994 Charles M. Hannum.  All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 *    notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 *    notice, this list of conditions and the following disclaimer in the
51 *    documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 *    must display the following acknowledgement:
54 *	This product includes software developed by Charles M. Hannum.
55 * 4. The name of the author may not be used to endorse or promote products
56 *    derived from this software without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
67 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 */
69
70#include <sys/types.h>
71#include <sys/param.h>
72#include <sys/time.h>
73#include <sys/systm.h>
74#include <sys/errno.h>
75#include <sys/device.h>
76#include <sys/malloc.h>
77#include <sys/extent.h>
78
79#include <vm/vm.h>
80#include <vm/vm_kern.h>
81
82#define _ARC_BUS_DMA_PRIVATE
83#include <machine/bus.h>
84
85#include <machine/pio.h>
86
87#include <machine/autoconf.h>
88#include <machine/cpu.h>
89
90#include <dev/pci/pcivar.h>
91#include <dev/pci/pcireg.h>
92
93#include <arc/pica/rd94.h>
94#include <arc/pci/necpbvar.h>
95
96int	necpbmatch __P((struct device *, struct cfdata *, void *));
97void	necpbattach __P((struct device *, struct device *, void *));
98
99static	int	necpbprint __P((void *, const char *));
100
101void		necpb_attach_hook __P((struct device *, struct device *,
102		    struct pcibus_attach_args *));
103int		necpb_bus_maxdevs __P((pci_chipset_tag_t, int));
104pcitag_t	necpb_make_tag __P((pci_chipset_tag_t, int, int, int));
105void		necpb_decompose_tag __P((pci_chipset_tag_t, pcitag_t, int *,
106		    int *, int *));
107pcireg_t	necpb_conf_read __P((pci_chipset_tag_t, pcitag_t, int));
108void		necpb_conf_write __P((pci_chipset_tag_t, pcitag_t, int,
109		    pcireg_t));
110int		necpb_intr_map __P((pci_chipset_tag_t, pcitag_t, int, int,
111		    pci_intr_handle_t *));
112const char *	necpb_intr_string __P((pci_chipset_tag_t, pci_intr_handle_t));
113void *		necpb_intr_establish __P((pci_chipset_tag_t, pci_intr_handle_t,
114		    int, int (*func)(void *), void *));
115void		necpb_intr_disestablish __P((pci_chipset_tag_t, void *));
116
117int		necpb_intr(unsigned, struct clockframe *);
118
119
120struct cfattach necpb_ca = {
121	sizeof(struct necpb_softc), necpbmatch, necpbattach,
122};
123
124extern struct cfdriver necpb_cd;
125
126static struct necpb_intrhand	*necpb_inttbl[4];
127
128/* There can be only one. */
129int necpbfound;
130struct necpb_config necpb_configuration;
131static long necpb_mem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(10) / sizeof(long)];
132static long necpb_io_ex_storage[EXTENT_FIXED_STORAGE_SIZE(10) / sizeof(long)];
133
134int
135necpbmatch(parent, match, aux)
136	struct device *parent;
137	struct cfdata *match;
138	void *aux;
139{
140	struct confargs *ca = aux;
141
142	if (strcmp(ca->ca_name, necpb_cd.cd_name) != 0)
143		return (0);
144
145	if (necpbfound)
146		return (0);
147
148	return (1);
149}
150
151/*
152 * Set up the chipset's function pointers.
153 */
154void
155necpb_init(ncp)
156	struct necpb_config *ncp;
157{
158	pcitag_t tag;
159	pcireg_t csr;
160
161	if (ncp->nc_initialized)
162		return;
163
164	arc_large_bus_space_init(&ncp->nc_memt, "necpcimem",
165	    RD94_P_PCI_MEM, 0, RD94_S_PCI_MEM);
166	arc_bus_space_init_extent(&ncp->nc_memt, (caddr_t)necpb_mem_ex_storage,
167	    sizeof(necpb_mem_ex_storage));
168
169	arc_bus_space_init(&ncp->nc_iot, "necpciio",
170	    RD94_P_PCI_IO, RD94_V_PCI_IO, 0, RD94_S_PCI_IO);
171	arc_bus_space_init_extent(&ncp->nc_iot, (caddr_t)necpb_io_ex_storage,
172	    sizeof(necpb_io_ex_storage));
173
174	jazz_bus_dma_tag_init(&ncp->nc_dmat);
175
176	ncp->nc_pc.pc_attach_hook = necpb_attach_hook;
177	ncp->nc_pc.pc_bus_maxdevs = necpb_bus_maxdevs;
178	ncp->nc_pc.pc_make_tag = necpb_make_tag;
179	ncp->nc_pc.pc_conf_read = necpb_conf_read;
180	ncp->nc_pc.pc_conf_write = necpb_conf_write;
181	ncp->nc_pc.pc_intr_map = necpb_intr_map;
182	ncp->nc_pc.pc_intr_string = necpb_intr_string;
183	ncp->nc_pc.pc_intr_establish = necpb_intr_establish;
184	ncp->nc_pc.pc_intr_disestablish = necpb_intr_disestablish;
185
186	/* XXX: enable all mem/io/busmaster */
187	tag = necpb_make_tag(&ncp->nc_pc, 0, 3, 0);
188	csr = necpb_conf_read(&ncp->nc_pc, tag, PCI_COMMAND_STATUS_REG);
189	csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
190	    PCI_COMMAND_MASTER_ENABLE;
191	necpb_conf_write(&ncp->nc_pc, tag, PCI_COMMAND_STATUS_REG, csr);
192
193	tag = necpb_make_tag(&ncp->nc_pc, 0, 4, 0);
194	csr = necpb_conf_read(&ncp->nc_pc, tag, PCI_COMMAND_STATUS_REG);
195	csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
196	    PCI_COMMAND_MASTER_ENABLE;
197	necpb_conf_write(&ncp->nc_pc, tag, PCI_COMMAND_STATUS_REG, csr);
198
199	tag = necpb_make_tag(&ncp->nc_pc, 0, 5, 0);
200	csr = necpb_conf_read(&ncp->nc_pc, tag, PCI_COMMAND_STATUS_REG);
201	csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
202	    PCI_COMMAND_MASTER_ENABLE;
203	necpb_conf_write(&ncp->nc_pc, tag, PCI_COMMAND_STATUS_REG, csr);
204
205	ncp->nc_initialized = 1;
206}
207
208void
209necpbattach(parent, self, aux)
210	struct device *parent, *self;
211	void *aux;
212{
213	struct necpb_softc *sc = (struct necpb_softc *)self;
214	struct pcibus_attach_args pba;
215	int i;
216
217	necpbfound = 1;
218
219	printf("\n");
220
221	sc->sc_ncp = &necpb_configuration;
222	necpb_init(sc->sc_ncp);
223
224	out32(RD94_SYS_PCI_INTMASK, 0xf);
225
226	for (i = 0; i < 4; i++)
227		necpb_inttbl[i] = NULL;
228
229	set_intr(MIPS_INT_MASK_2, necpb_intr, 3);
230
231	pba.pba_busname = "pci";
232	pba.pba_iot = &sc->sc_ncp->nc_iot;
233	pba.pba_memt = &sc->sc_ncp->nc_memt;
234	pba.pba_dmat = &sc->sc_ncp->nc_dmat;
235	pba.pba_pc = &sc->sc_ncp->nc_pc;
236	pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
237	pba.pba_bus = 0;
238
239	config_found(self, &pba, necpbprint);
240}
241
242static int
243necpbprint(aux, pnp)
244	void *aux;
245	const char *pnp;
246{
247	struct pcibus_attach_args *pba = aux;
248
249	if (pnp)
250		printf("%s at %s", pba->pba_busname, pnp);
251	printf(" bus %d", pba->pba_bus);
252	return (UNCONF);
253}
254
255void
256necpb_attach_hook(parent, self, pba)
257	struct device *parent, *self;
258	struct pcibus_attach_args *pba;
259{
260}
261
262int
263necpb_bus_maxdevs(pc, busno)
264	pci_chipset_tag_t pc;
265	int busno;
266{
267	return (32);
268}
269
270pcitag_t
271necpb_make_tag(pc, bus, device, function)
272	pci_chipset_tag_t pc;
273	int bus, device, function;
274{
275	pcitag_t tag;
276
277	if (bus >= 256 || device >= 32 || function >= 8)
278		panic("necpb_make_tag: bad request");
279
280	tag = 0x80000000 | (bus << 16) | (device << 11) | (function << 8);
281	return (tag);
282}
283
284void
285necpb_decompose_tag(pc, tag, bp, dp, fp)
286	pci_chipset_tag_t pc;
287	pcitag_t tag;
288	int *bp, *dp, *fp;
289{
290	if (bp != NULL)
291		*bp = (tag >> 16) & 0xff;
292	if (dp != NULL)
293		*dp = (tag >> 11) & 0x1f;
294	if (fp != NULL)
295		*fp = (tag >> 8) & 0x07;
296}
297
298pcireg_t
299necpb_conf_read(pc, tag, reg)
300	pci_chipset_tag_t pc;
301	pcitag_t tag;
302	int reg;
303{
304	pcireg_t data;
305	int s;
306
307	s = splhigh();
308	out32(RD94_SYS_PCI_CONFADDR, tag | reg);
309	data = in32(RD94_SYS_PCI_CONFDATA);
310	out32(RD94_SYS_PCI_CONFADDR, 0);
311	splx(s);
312
313	return (data);
314}
315
316void
317necpb_conf_write(pc, tag, reg, data)
318	pci_chipset_tag_t pc;
319	pcitag_t tag;
320	int reg;
321	pcireg_t data;
322{
323	int s;
324
325	s = splhigh();
326	out32(RD94_SYS_PCI_CONFADDR, tag | reg);
327	out32(RD94_SYS_PCI_CONFDATA, data);
328	out32(RD94_SYS_PCI_CONFADDR, 0);
329	splx(s);
330}
331
332int
333necpb_intr_map(pc, intrtag, pin, line, ihp)
334	pci_chipset_tag_t pc;
335	pcitag_t intrtag;
336	int pin, line;
337	pci_intr_handle_t *ihp;
338{
339	int bus, dev;
340
341	if (pin == 0) {
342		/* No IRQ used. */
343		*ihp = -1;
344		return (1);
345	}
346
347	if (pin > 4) {
348		printf("necpb_intr_map: bad interrupt pin %d\n", pin);
349		*ihp = -1;
350		return (1);
351	}
352
353	necpb_decompose_tag(pc, intrtag, &bus, &dev, NULL);
354	if (bus != 0) {
355		*ihp = -1;
356		return (1);
357	}
358
359	switch (dev) {
360	case 3:
361		*ihp = (pin+2) % 4;
362		break;
363	case 4:
364		*ihp = (pin+1) % 4;
365		break;
366	case 5:
367		*ihp = (pin) % 4;
368		break;
369	default:
370		*ihp = -1;
371		return (1);
372	}
373
374	return (0);
375}
376
377const char *
378necpb_intr_string(pc, ih)
379	pci_chipset_tag_t pc;
380	pci_intr_handle_t ih;
381{
382	static char str[8];
383
384	if (ih >= 4)
385		panic("necpb_intr_string: bogus handle %d", ih);
386	sprintf(str, "int %c", 'A' + (int)ih);
387	return (str);
388}
389
390void *
391necpb_intr_establish(pc, ih, level, func, arg)
392	pci_chipset_tag_t pc;
393	pci_intr_handle_t ih;
394	int level, (*func) __P((void *));
395	void *arg;
396{
397	struct necpb_intrhand *n, *p;
398	u_int32_t	mask;
399
400	if (ih >= 4)
401		panic("necpb_intr_establish: bogus handle");
402
403	n = malloc(sizeof(struct necpb_intrhand), M_DEVBUF, M_NOWAIT);
404	if (n == NULL)
405		panic("necpb_intr_establish: can't malloc interrupt handle");
406
407	n->ih_func = func;
408	n->ih_arg = arg;
409	n->ih_next = NULL;
410	n->ih_intn = ih;
411
412	if (necpb_inttbl[ih] == NULL) {
413		necpb_inttbl[ih] = n;
414		mask = in32(RD94_SYS_PCI_INTMASK);
415		mask |= 1 << ih;
416		out32(RD94_SYS_PCI_INTMASK, mask);
417	} else {
418		p = necpb_inttbl[ih];
419		while (p->ih_next != NULL)
420			p = p->ih_next;
421		p->ih_next = n;
422	}
423
424	return n;
425}
426
427void
428necpb_intr_disestablish(pc, cookie)
429	pci_chipset_tag_t pc;
430	void *cookie;
431{
432	struct necpb_intrhand *n, *p, *q;
433	u_int32_t	mask;
434
435	n = cookie;
436
437	q = NULL;
438	p = necpb_inttbl[n->ih_intn];
439	while (p != n) {
440		if (p == NULL)
441			panic("necpb_intr_disestablish: broken intr table");
442		q = p;
443		p = p->ih_next;
444	}
445
446	if (q == NULL) {
447		necpb_inttbl[n->ih_intn] = n->ih_next;
448		if (n->ih_next == NULL) {
449			mask = in32(RD94_SYS_PCI_INTMASK);
450			mask &= ~(1 << n->ih_intn);
451			out32(RD94_SYS_PCI_INTMASK, mask);
452		}
453	} else
454		q->ih_next = n->ih_next;
455
456	free(n, M_DEVBUF);
457}
458
459/*
460 *   Handle PCI/EISA interrupt.
461 */
462int
463necpb_intr(mask, cf)
464	unsigned mask;
465	struct clockframe *cf;
466{
467	u_int32_t vector, stat;
468	struct necpb_intrhand *p;
469	int a;
470
471	vector = in32(RD94_SYS_INTSTAT2) & 0xffff;
472
473	if (vector == 0x4000) {
474		stat = in32(RD94_SYS_PCI_INTSTAT);
475		stat &= in32(RD94_SYS_PCI_INTMASK);
476		for (a=0; a<4; a++) {
477			if (stat & (1 << a)) {
478#if 0
479				printf("pint %d\n", a);
480#endif
481				p = necpb_inttbl[a];
482				while (p != NULL) {
483					(*p->ih_func)(p->ih_arg);
484					p = p->ih_next;
485				}
486			}
487		}
488	} else if (vector == 0x8000) {
489		printf("eisa_nmi\n");
490	} else {
491		printf("eint %d\n", vector & 0xff);
492#if 0
493		eisa_intr(vector & 0xff);
494#endif
495	}
496
497	return (~0);
498}
499