xref: /openbsd-src/sys/arch/alpha/pci/mcpcia_pci.c (revision 4a39ccd02c887d988c1a5398dd2142879056da5f)
1*4a39ccd0Sderaadt /* $OpenBSD: mcpcia_pci.c,v 1.3 2012/12/05 23:20:10 deraadt Exp $ */
22f4de8e4Srobert /* $NetBSD: mcpcia_pci.c,v 1.5 2007/03/04 05:59:11 christos Exp $ */
32f4de8e4Srobert 
42f4de8e4Srobert /*
52f4de8e4Srobert  * Copyright (c) 1998 by Matthew Jacob
62f4de8e4Srobert  * NASA AMES Research Center.
72f4de8e4Srobert  * All rights reserved.
82f4de8e4Srobert  *
92f4de8e4Srobert  * Redistribution and use in source and binary forms, with or without
102f4de8e4Srobert  * modification, are permitted provided that the following conditions
112f4de8e4Srobert  * are met:
122f4de8e4Srobert  * 1. Redistributions of source code must retain the above copyright
132f4de8e4Srobert  *    notice immediately at the beginning of the file, without modification,
142f4de8e4Srobert  *    this list of conditions, and the following disclaimer.
152f4de8e4Srobert  * 2. Redistributions in binary form must reproduce the above copyright
162f4de8e4Srobert  *    notice, this list of conditions and the following disclaimer in the
172f4de8e4Srobert  *    documentation and/or other materials provided with the distribution.
182f4de8e4Srobert  * 3. The name of the author may not be used to endorse or promote products
192f4de8e4Srobert  *    derived from this software without specific prior written permission.
202f4de8e4Srobert  *
212f4de8e4Srobert  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
222f4de8e4Srobert  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
232f4de8e4Srobert  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
242f4de8e4Srobert  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
252f4de8e4Srobert  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
262f4de8e4Srobert  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
272f4de8e4Srobert  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
282f4de8e4Srobert  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
292f4de8e4Srobert  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
302f4de8e4Srobert  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
312f4de8e4Srobert  * SUCH DAMAGE.
322f4de8e4Srobert  */
332f4de8e4Srobert 
342f4de8e4Srobert #include <sys/param.h>
352f4de8e4Srobert #include <sys/systm.h>
362f4de8e4Srobert #include <sys/kernel.h>
372f4de8e4Srobert #include <sys/device.h>
382f4de8e4Srobert 
392f4de8e4Srobert #include <uvm/uvm_extern.h>
402f4de8e4Srobert 
412f4de8e4Srobert #include <dev/pci/pcireg.h>
422f4de8e4Srobert #include <dev/pci/pcivar.h>
432f4de8e4Srobert #include <alpha/pci/mcpciareg.h>
442f4de8e4Srobert #include <alpha/pci/mcpciavar.h>
452f4de8e4Srobert 
462f4de8e4Srobert #define	KV(_addr)	((void *)ALPHA_PHYS_TO_K0SEG((_addr)))
472f4de8e4Srobert 
48b1926db3Smiod void	mcpcia_attach_hook(struct device *, struct device *,
492f4de8e4Srobert 	    struct pcibus_attach_args *);
50b1926db3Smiod int	mcpcia_bus_maxdevs(void *, int);
51b1926db3Smiod pcitag_t mcpcia_make_tag(void *, int, int, int);
52b1926db3Smiod void	mcpcia_decompose_tag(void *, pcitag_t, int *, int *, int *);
53b1926db3Smiod int	mcpcia_conf_size(void *, pcitag_t);
54b1926db3Smiod pcireg_t mcpcia_conf_read(void *, pcitag_t, int);
55b1926db3Smiod void	mcpcia_conf_write(void *, pcitag_t, int, pcireg_t);
562f4de8e4Srobert 
572f4de8e4Srobert void
mcpcia_pci_init(pc,v)582f4de8e4Srobert mcpcia_pci_init(pc, v)
592f4de8e4Srobert 	pci_chipset_tag_t pc;
602f4de8e4Srobert 	void *v;
612f4de8e4Srobert {
622f4de8e4Srobert 	pc->pc_conf_v = v;
632f4de8e4Srobert 	pc->pc_attach_hook = mcpcia_attach_hook;
642f4de8e4Srobert 	pc->pc_bus_maxdevs = mcpcia_bus_maxdevs;
652f4de8e4Srobert 	pc->pc_make_tag = mcpcia_make_tag;
662f4de8e4Srobert 	pc->pc_decompose_tag = mcpcia_decompose_tag;
67b1926db3Smiod 	pc->pc_conf_size = mcpcia_conf_size;
682f4de8e4Srobert 	pc->pc_conf_read = mcpcia_conf_read;
692f4de8e4Srobert 	pc->pc_conf_write = mcpcia_conf_write;
702f4de8e4Srobert }
712f4de8e4Srobert 
72b1926db3Smiod void
mcpcia_attach_hook(parent,self,pba)732f4de8e4Srobert mcpcia_attach_hook(parent, self, pba)
742f4de8e4Srobert 	struct device *parent, *self;
752f4de8e4Srobert 	struct pcibus_attach_args *pba;
762f4de8e4Srobert {
772f4de8e4Srobert }
782f4de8e4Srobert 
79b1926db3Smiod int
mcpcia_bus_maxdevs(cpv,busno)802f4de8e4Srobert mcpcia_bus_maxdevs(cpv, busno)
812f4de8e4Srobert 	void *cpv;
822f4de8e4Srobert 	int busno;
832f4de8e4Srobert {
842f4de8e4Srobert 	return (MCPCIA_MAXDEV);
852f4de8e4Srobert }
862f4de8e4Srobert 
87b1926db3Smiod pcitag_t
mcpcia_make_tag(cpv,b,d,f)882f4de8e4Srobert mcpcia_make_tag(cpv, b, d, f)
892f4de8e4Srobert 	void *cpv;
902f4de8e4Srobert 	int b, d, f;
912f4de8e4Srobert {
922f4de8e4Srobert 	pcitag_t tag;
932f4de8e4Srobert 	tag = (b << 21) | (d << 16) | (f << 13);
942f4de8e4Srobert 	return (tag);
952f4de8e4Srobert }
962f4de8e4Srobert 
97b1926db3Smiod void
mcpcia_decompose_tag(cpv,tag,bp,dp,fp)982f4de8e4Srobert mcpcia_decompose_tag(cpv, tag, bp, dp, fp)
992f4de8e4Srobert 	void *cpv;
1002f4de8e4Srobert 	pcitag_t tag;
1012f4de8e4Srobert 	int *bp, *dp, *fp;
1022f4de8e4Srobert {
1032f4de8e4Srobert 	if (bp != NULL)
1042f4de8e4Srobert 		*bp = (tag >> 21) & 0xff;
1052f4de8e4Srobert 	if (dp != NULL)
1062f4de8e4Srobert 		*dp = (tag >> 16) & 0x1f;
1072f4de8e4Srobert 	if (fp != NULL)
1082f4de8e4Srobert 		*fp = (tag >> 13) & 0x7;
1092f4de8e4Srobert }
1102f4de8e4Srobert 
111b1926db3Smiod int
mcpcia_conf_size(void * cpv,pcitag_t tag)112b1926db3Smiod mcpcia_conf_size(void *cpv, pcitag_t tag)
113b1926db3Smiod {
114b1926db3Smiod 	return PCI_CONFIG_SPACE_SIZE;
115b1926db3Smiod }
116b1926db3Smiod 
117b1926db3Smiod pcireg_t
mcpcia_conf_read(cpv,tag,offset)1182f4de8e4Srobert mcpcia_conf_read(cpv, tag, offset)
1192f4de8e4Srobert 	void *cpv;
1202f4de8e4Srobert 	pcitag_t tag;
1212f4de8e4Srobert 	int offset;
1222f4de8e4Srobert {
1232f4de8e4Srobert 	struct mcpcia_config *ccp = cpv;
1242f4de8e4Srobert 	pcireg_t *dp, data = (pcireg_t) -1;
1252f4de8e4Srobert 	unsigned long paddr;
1262f4de8e4Srobert 
1272f4de8e4Srobert 	/*
1282f4de8e4Srobert 	 * There's nothing in slot 0 on a primary bus- don't even try.
1292f4de8e4Srobert 	 */
1302f4de8e4Srobert 	if ((tag >> 21) == 0 && ((u_int32_t) tag & 0x1f0000) == 0)
1312f4de8e4Srobert 		return (data);
1322f4de8e4Srobert 
1332f4de8e4Srobert 	if (ccp == NULL) {
1342f4de8e4Srobert 		panic("NULL ccp in mcpcia_conf_read");
1352f4de8e4Srobert 	}
1362f4de8e4Srobert 	paddr =	(unsigned long) tag;
1372f4de8e4Srobert 	paddr |= (3LL << 3);	/* 32 Bit PCI byte enables */
1382f4de8e4Srobert 	paddr |= ((unsigned long) ((offset >> 2) << 7));
1392f4de8e4Srobert 	paddr |= MCPCIA_PCI_CONF;
1402f4de8e4Srobert 	paddr |= ccp->cc_sysbase;
1412f4de8e4Srobert 	dp = (pcireg_t *)KV(paddr);
1422f4de8e4Srobert 	if (badaddr(dp, sizeof (*dp)) == 0) {
1432f4de8e4Srobert 		data = *dp;
1442f4de8e4Srobert 	}
1452f4de8e4Srobert 	return (data);
1462f4de8e4Srobert }
1472f4de8e4Srobert 
148b1926db3Smiod void
mcpcia_conf_write(cpv,tag,offset,data)1492f4de8e4Srobert mcpcia_conf_write(cpv, tag, offset, data)
1502f4de8e4Srobert 	void *cpv;
1512f4de8e4Srobert 	pcitag_t tag;
1522f4de8e4Srobert 	int offset;
1532f4de8e4Srobert 	pcireg_t data;
1542f4de8e4Srobert {
1552f4de8e4Srobert 	struct mcpcia_config *ccp = cpv;
1562f4de8e4Srobert 	pcireg_t *dp;
1572f4de8e4Srobert 	unsigned long paddr;
1582f4de8e4Srobert 
1592f4de8e4Srobert 	/*
1602f4de8e4Srobert 	 * There's nothing in slot 0 on a primary bus- don't even try.
1612f4de8e4Srobert 	 */
1622f4de8e4Srobert 	if ((tag >> 21) == 0 && ((u_int32_t) tag & 0x1f0000) == 0)
1632f4de8e4Srobert 		return;
1642f4de8e4Srobert 
1652f4de8e4Srobert 	if (ccp == NULL) {
1662f4de8e4Srobert 		panic("NULL ccp in mcpcia_conf_write");
1672f4de8e4Srobert 	}
1682f4de8e4Srobert 	paddr =	(unsigned long) tag;
1692f4de8e4Srobert 	paddr |= (3LL << 3);	/* 32 Bit PCI byte enables */
1702f4de8e4Srobert 	paddr |= ((unsigned long) ((offset >> 2) << 7));
1712f4de8e4Srobert 	paddr |= MCPCIA_PCI_CONF;
1722f4de8e4Srobert 	paddr |= ccp->cc_sysbase;
1732f4de8e4Srobert 
1742f4de8e4Srobert 	dp = (pcireg_t *)KV(paddr);
1752f4de8e4Srobert 	*dp = data;
1762f4de8e4Srobert }
177