xref: /openbsd/sys/arch/alpha/pci/sio.c (revision 4887a701)
1*4887a701Sart /*	$OpenBSD: sio.c,v 1.18 2001/02/05 17:14:40 art Exp $	*/
23a630e3fSniklas /*	$NetBSD: sio.c,v 1.15 1996/12/05 01:39:36 cgd Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*
5417eba8cSderaadt  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
6df930be7Sderaadt  * All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * Author: Chris G. Demetriou
9df930be7Sderaadt  *
10df930be7Sderaadt  * Permission to use, copy, modify and distribute this software and
11df930be7Sderaadt  * its documentation is hereby granted, provided that both the copyright
12df930be7Sderaadt  * notice and this permission notice appear in all copies of the
13df930be7Sderaadt  * software, derivative works or modified versions, and any portions
14df930be7Sderaadt  * thereof, and that both notices appear in supporting documentation.
15df930be7Sderaadt  *
16df930be7Sderaadt  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17df930be7Sderaadt  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18df930be7Sderaadt  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19df930be7Sderaadt  *
20df930be7Sderaadt  * Carnegie Mellon requests users of this software to return to
21df930be7Sderaadt  *
22df930be7Sderaadt  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
23df930be7Sderaadt  *  School of Computer Science
24df930be7Sderaadt  *  Carnegie Mellon University
25df930be7Sderaadt  *  Pittsburgh PA 15213-3890
26df930be7Sderaadt  *
27df930be7Sderaadt  * any improvements or extensions that they make and grant Carnegie the
28df930be7Sderaadt  * rights to redistribute these changes.
29df930be7Sderaadt  */
30df930be7Sderaadt 
31df930be7Sderaadt #include <sys/param.h>
32df930be7Sderaadt #include <sys/systm.h>
33df930be7Sderaadt #include <sys/kernel.h>
34df930be7Sderaadt #include <sys/device.h>
35df930be7Sderaadt 
36417eba8cSderaadt #include <machine/intr.h>
37e464495eSniklas #include <machine/bus.h>
38417eba8cSderaadt 
3934fbf6deSderaadt #include <dev/isa/isavar.h>
4034fbf6deSderaadt #include <dev/eisa/eisavar.h>
4134fbf6deSderaadt 
42df930be7Sderaadt #include <dev/pci/pcireg.h>
43df930be7Sderaadt #include <dev/pci/pcivar.h>
44df930be7Sderaadt #include <dev/pci/pcidevs.h>
45df930be7Sderaadt 
4634fbf6deSderaadt #include <alpha/pci/siovar.h>
47df930be7Sderaadt 
483a630e3fSniklas struct sio_softc {
493a630e3fSniklas 	struct device	sc_dv;
503a630e3fSniklas 
513a630e3fSniklas 	bus_space_tag_t sc_iot, sc_memt;
523a630e3fSniklas 	int		sc_haseisa;
533a630e3fSniklas };
543a630e3fSniklas 
553a630e3fSniklas #ifdef __BROKEN_INDIRECT_CONFIG
56df930be7Sderaadt int	siomatch __P((struct device *, void *, void *));
573a630e3fSniklas #else
583a630e3fSniklas int	siomatch __P((struct device *, struct cfdata *, void *));
593a630e3fSniklas #endif
60df930be7Sderaadt void	sioattach __P((struct device *, struct device *, void *));
61df930be7Sderaadt 
62417eba8cSderaadt struct cfattach sio_ca = {
633a630e3fSniklas 	sizeof(struct sio_softc), siomatch, sioattach,
64417eba8cSderaadt };
65417eba8cSderaadt 
66417eba8cSderaadt struct cfdriver sio_cd = {
67417eba8cSderaadt 	NULL, "sio", DV_DULL,
68df930be7Sderaadt };
69df930be7Sderaadt 
703a630e3fSniklas #ifdef __BROKEN_INDIRECT_CONFIG
7134fbf6deSderaadt int	pcebmatch __P((struct device *, void *, void *));
723a630e3fSniklas #else
733a630e3fSniklas int	pcebmatch __P((struct device *, struct cfdata *, void *));
743a630e3fSniklas #endif
7534fbf6deSderaadt 
76417eba8cSderaadt struct cfattach pceb_ca = {
77835a491cSart 	sizeof(struct sio_softc), pcebmatch, sioattach,
7834fbf6deSderaadt };
7934fbf6deSderaadt 
80417eba8cSderaadt struct cfdriver pceb_cd = {
81417eba8cSderaadt 	NULL, "pceb", DV_DULL,
82417eba8cSderaadt };
83417eba8cSderaadt 
84417eba8cSderaadt union sio_attach_args {
85417eba8cSderaadt 	const char *sa_name;			/* XXX should be common */
86417eba8cSderaadt 	struct isabus_attach_args sa_iba;
87417eba8cSderaadt 	struct eisabus_attach_args sa_eba;
88417eba8cSderaadt };
89417eba8cSderaadt 
90833613b2Skstailey int	sioprint __P((void *, const char *pnp));
91417eba8cSderaadt void	sio_isa_attach_hook __P((struct device *, struct device *,
92417eba8cSderaadt 	    struct isabus_attach_args *));
93417eba8cSderaadt void	sio_eisa_attach_hook __P((struct device *, struct device *,
94417eba8cSderaadt 	    struct eisabus_attach_args *));
95417eba8cSderaadt int	sio_eisa_maxslots __P((void *));
96417eba8cSderaadt int	sio_eisa_intr_map __P((void *, u_int, eisa_intr_handle_t *));
9780b183b6Sderaadt void	siocfiddle __P((struct isabus_attach_args *iba));
98df930be7Sderaadt 
993a630e3fSniklas void	sio_bridge_callback __P((void *));
1003a630e3fSniklas 
101df930be7Sderaadt int
102df930be7Sderaadt siomatch(parent, match, aux)
103df930be7Sderaadt 	struct device *parent;
1043a630e3fSniklas #ifdef __BROKEN_INDIRECT_CONFIG
1053a630e3fSniklas 	void *match;
1063a630e3fSniklas #else
1073a630e3fSniklas 	struct cfdata *match;
1083a630e3fSniklas #endif
1093a630e3fSniklas 	void *aux;
110df930be7Sderaadt {
111417eba8cSderaadt 	struct pci_attach_args *pa = aux;
112df930be7Sderaadt 
1136a30a1c1Smillert 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CONTAQ &&
114e6dd45c8Smillert 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CONTAQ_82C693 &&
1156a30a1c1Smillert 	    pa->pa_function == 0)
11634fbf6deSderaadt 		return (1);
1176a30a1c1Smillert 
1186a30a1c1Smillert 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
1196a30a1c1Smillert 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_SIO)
1206a30a1c1Smillert 		return (1);
1216a30a1c1Smillert 
1226a30a1c1Smillert 	return (0);
12334fbf6deSderaadt }
12434fbf6deSderaadt 
12534fbf6deSderaadt int
12634fbf6deSderaadt pcebmatch(parent, match, aux)
12734fbf6deSderaadt 	struct device *parent;
1283a630e3fSniklas #ifdef __BROKEN_INDIRECT_CONFIG
1293a630e3fSniklas 	void *match;
1303a630e3fSniklas #else
1313a630e3fSniklas 	struct cfdata *match;
1323a630e3fSniklas #endif
1333a630e3fSniklas 	void *aux;
13434fbf6deSderaadt {
135417eba8cSderaadt 	struct pci_attach_args *pa = aux;
13634fbf6deSderaadt 
137*4887a701Sart 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
138*4887a701Sart 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB)
139df930be7Sderaadt 		return (1);
140*4887a701Sart 
141*4887a701Sart 	return (0);
142df930be7Sderaadt }
143df930be7Sderaadt 
144df930be7Sderaadt void
145df930be7Sderaadt sioattach(parent, self, aux)
146df930be7Sderaadt 	struct device *parent, *self;
147df930be7Sderaadt 	void *aux;
148df930be7Sderaadt {
1493a630e3fSniklas 	struct sio_softc *sc = (struct sio_softc *)self;
150417eba8cSderaadt 	struct pci_attach_args *pa = aux;
151df930be7Sderaadt 
15250c9667dSderaadt 	printf("\n");
15334fbf6deSderaadt 
1543a630e3fSniklas 	sc->sc_iot = pa->pa_iot;
1553a630e3fSniklas 	sc->sc_memt = pa->pa_memt;
1563a630e3fSniklas 	sc->sc_haseisa = (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PCEB);
157df930be7Sderaadt 
15834fbf6deSderaadt #ifdef EVCNT_COUNTERS
1593a630e3fSniklas 	evcnt_attach(&sc->sc_dv, "intr", &sio_intr_evcnt);
16034fbf6deSderaadt #endif
16134fbf6deSderaadt 
1623a630e3fSniklas 	set_pci_isa_bridge_callback(sio_bridge_callback, sc);
1633a630e3fSniklas }
1643a630e3fSniklas 
1653a630e3fSniklas void
1663a630e3fSniklas sio_bridge_callback(v)
1673a630e3fSniklas 	void *v;
1683a630e3fSniklas {
1693a630e3fSniklas 	struct sio_softc *sc = v;
1703a630e3fSniklas 	struct alpha_eisa_chipset ec;
1713a630e3fSniklas 	struct alpha_isa_chipset ic;
1723a630e3fSniklas 	union sio_attach_args sa;
1733a630e3fSniklas 
1743a630e3fSniklas 	if (sc->sc_haseisa) {
175417eba8cSderaadt 		ec.ec_v = NULL;
176417eba8cSderaadt 		ec.ec_attach_hook = sio_eisa_attach_hook;
177417eba8cSderaadt 		ec.ec_maxslots = sio_eisa_maxslots;
178417eba8cSderaadt 		ec.ec_intr_map = sio_eisa_intr_map;
179417eba8cSderaadt 		ec.ec_intr_string = sio_intr_string;
180417eba8cSderaadt 		ec.ec_intr_establish = sio_intr_establish;
181417eba8cSderaadt 		ec.ec_intr_disestablish = sio_intr_disestablish;
182417eba8cSderaadt 
183417eba8cSderaadt 		sa.sa_eba.eba_busname = "eisa";
1843a630e3fSniklas 		sa.sa_eba.eba_iot = sc->sc_iot;
1853a630e3fSniklas 		sa.sa_eba.eba_memt = sc->sc_memt;
186417eba8cSderaadt 		sa.sa_eba.eba_ec = &ec;
1873a630e3fSniklas 		config_found(&sc->sc_dv, &sa.sa_eba, sioprint);
188df930be7Sderaadt 	}
189df930be7Sderaadt 
190417eba8cSderaadt 	ic.ic_v = NULL;
191417eba8cSderaadt 	ic.ic_attach_hook = sio_isa_attach_hook;
192417eba8cSderaadt 	ic.ic_intr_establish = sio_intr_establish;
193417eba8cSderaadt 	ic.ic_intr_disestablish = sio_intr_disestablish;
194417eba8cSderaadt 
195417eba8cSderaadt 	sa.sa_iba.iba_busname = "isa";
1963a630e3fSniklas 	sa.sa_iba.iba_iot = sc->sc_iot;
1973a630e3fSniklas 	sa.sa_iba.iba_memt = sc->sc_memt;
198417eba8cSderaadt 	sa.sa_iba.iba_ic = &ic;
1993a630e3fSniklas 	config_found(&sc->sc_dv, &sa.sa_iba, sioprint);
200417eba8cSderaadt }
201417eba8cSderaadt 
202417eba8cSderaadt int
203df930be7Sderaadt sioprint(aux, pnp)
204df930be7Sderaadt 	void *aux;
205833613b2Skstailey 	const char *pnp;
206df930be7Sderaadt {
207417eba8cSderaadt         register union sio_attach_args *sa = aux;
208df930be7Sderaadt 
209df930be7Sderaadt         if (pnp)
210417eba8cSderaadt                 printf("%s at %s", sa->sa_name, pnp);
211df930be7Sderaadt         return (UNCONF);
212df930be7Sderaadt }
213417eba8cSderaadt 
214417eba8cSderaadt void
215417eba8cSderaadt sio_isa_attach_hook(parent, self, iba)
216417eba8cSderaadt 	struct device *parent, *self;
217417eba8cSderaadt 	struct isabus_attach_args *iba;
218417eba8cSderaadt {
21980b183b6Sderaadt 	siocfiddle(iba);
220417eba8cSderaadt }
221417eba8cSderaadt 
222417eba8cSderaadt void
223417eba8cSderaadt sio_eisa_attach_hook(parent, self, eba)
224417eba8cSderaadt 	struct device *parent, *self;
225417eba8cSderaadt 	struct eisabus_attach_args *eba;
226417eba8cSderaadt {
227417eba8cSderaadt 
228417eba8cSderaadt 	/* Nothing to do. */
229417eba8cSderaadt }
230417eba8cSderaadt 
231417eba8cSderaadt int
232417eba8cSderaadt sio_eisa_maxslots(v)
233417eba8cSderaadt 	void *v;
234417eba8cSderaadt {
235417eba8cSderaadt 
236417eba8cSderaadt 	return 16;		/* as good a number as any.  only 8, maybe? */
237417eba8cSderaadt }
238417eba8cSderaadt 
239417eba8cSderaadt int
240417eba8cSderaadt sio_eisa_intr_map(v, irq, ihp)
241417eba8cSderaadt 	void *v;
242417eba8cSderaadt 	u_int irq;
243417eba8cSderaadt 	eisa_intr_handle_t *ihp;
244417eba8cSderaadt {
245417eba8cSderaadt 
246417eba8cSderaadt #define	ICU_LEN		16	/* number of ISA IRQs (XXX) */
247417eba8cSderaadt 
248417eba8cSderaadt 	if (irq >= ICU_LEN) {
249417eba8cSderaadt 		printf("sio_eisa_intr_map: bad IRQ %d\n", irq);
250417eba8cSderaadt 		*ihp = -1;
251417eba8cSderaadt 		return 1;
252417eba8cSderaadt 	}
253417eba8cSderaadt 	if (irq == 2) {
254417eba8cSderaadt 		printf("sio_eisa_intr_map: changed IRQ 2 to IRQ 9\n");
255417eba8cSderaadt 		irq = 9;
256417eba8cSderaadt 	}
257417eba8cSderaadt 
258417eba8cSderaadt 	*ihp = irq;
259417eba8cSderaadt 	return 0;
260417eba8cSderaadt }
26180b183b6Sderaadt 
26280b183b6Sderaadt 
26380b183b6Sderaadt /*
26480b183b6Sderaadt  * Look for and gently fondle the 87312 Super I/O chip.
26580b183b6Sderaadt  */
26680b183b6Sderaadt 
26780b183b6Sderaadt #define SIOC_IDE_ENABLE	0x40
26880b183b6Sderaadt #define	SIOC_NPORTS	2
26980b183b6Sderaadt void
27080b183b6Sderaadt siocfiddle(iba)
27180b183b6Sderaadt 	struct isabus_attach_args *iba;
27280b183b6Sderaadt {
27380b183b6Sderaadt 	bus_space_tag_t iot = iba->iba_iot;
27480b183b6Sderaadt 	bus_space_handle_t ioh;
27580b183b6Sderaadt 	extern int cputype;
27680b183b6Sderaadt 	int addr;
27780b183b6Sderaadt 	u_int8_t reg0;
27880b183b6Sderaadt 
27980b183b6Sderaadt 	/* Decide based on machine type */
28080b183b6Sderaadt 	switch (cputype) {
28180b183b6Sderaadt 	case 11:			/* DEC AXPpci */
28280b183b6Sderaadt 	case 12:			/* DEC 2100 A50 */
28380b183b6Sderaadt 		addr = 0x26e;
28480b183b6Sderaadt 		break;
28580b183b6Sderaadt 	case 26:			/* DEC EB164 */
28680b183b6Sderaadt 		addr = 0x398;
28780b183b6Sderaadt 		break;
28880b183b6Sderaadt 	default:
28980b183b6Sderaadt 		return;
29080b183b6Sderaadt 	}
29180b183b6Sderaadt 
29280b183b6Sderaadt 	if (bus_space_map(iot, addr, SIOC_NPORTS, 0, &ioh))
29380b183b6Sderaadt 		return;
29480b183b6Sderaadt 
29580b183b6Sderaadt 	/* select and read register 0 */
29680b183b6Sderaadt 	bus_space_write_1(iot, ioh, 0, 0);
29780b183b6Sderaadt 	reg0 = bus_space_read_1(iot, ioh, 1);
29880b183b6Sderaadt 
29980b183b6Sderaadt 	/* write back with IDE enabled flag set, and do it twice!  */
30080b183b6Sderaadt 	bus_space_write_1(iot, ioh, 0, 0);
30180b183b6Sderaadt 	bus_space_write_1(iot, ioh, 1, reg0 | SIOC_IDE_ENABLE);
30280b183b6Sderaadt 	bus_space_write_1(iot, ioh, 1, reg0 | SIOC_IDE_ENABLE);
30380b183b6Sderaadt 
30480b183b6Sderaadt 	bus_space_unmap(iot, ioh, SIOC_NPORTS);
30580b183b6Sderaadt }
306