Home | History | Annotate | Line # | Download | only in pci
pci_hades.c revision 1.14.18.1
      1  1.14.18.1  christos /*	$NetBSD: pci_hades.c,v 1.14.18.1 2019/06/10 22:05:58 christos Exp $	*/
      2        1.1       leo 
      3        1.1       leo /*
      4        1.1       leo  * Copyright (c) 1996 Leo Weppelman.  All rights reserved.
      5        1.1       leo  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
      6        1.1       leo  * Copyright (c) 1994 Charles M. Hannum.  All rights reserved.
      7        1.1       leo  *
      8        1.1       leo  * Redistribution and use in source and binary forms, with or without
      9        1.1       leo  * modification, are permitted provided that the following conditions
     10        1.1       leo  * are met:
     11        1.1       leo  * 1. Redistributions of source code must retain the above copyright
     12        1.1       leo  *    notice, this list of conditions and the following disclaimer.
     13        1.1       leo  * 2. Redistributions in binary form must reproduce the above copyright
     14        1.1       leo  *    notice, this list of conditions and the following disclaimer in the
     15        1.1       leo  *    documentation and/or other materials provided with the distribution.
     16        1.1       leo  * 3. All advertising materials mentioning features or use of this software
     17        1.1       leo  *    must display the following acknowledgement:
     18        1.1       leo  *	This product includes software developed by Charles M. Hannum.
     19        1.1       leo  * 4. The name of the author may not be used to endorse or promote products
     20        1.1       leo  *    derived from this software without specific prior written permission.
     21        1.1       leo  *
     22        1.1       leo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23        1.1       leo  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24        1.1       leo  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25        1.1       leo  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26        1.1       leo  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27        1.1       leo  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28        1.1       leo  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29        1.1       leo  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30        1.1       leo  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31        1.1       leo  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32        1.1       leo  */
     33        1.5     lukem 
     34        1.5     lukem #include <sys/cdefs.h>
     35  1.14.18.1  christos __KERNEL_RCSID(0, "$NetBSD: pci_hades.c,v 1.14.18.1 2019/06/10 22:05:58 christos Exp $");
     36        1.1       leo 
     37        1.1       leo #include <sys/types.h>
     38        1.1       leo #include <sys/param.h>
     39        1.1       leo #include <sys/systm.h>
     40        1.1       leo #include <sys/device.h>
     41        1.1       leo 
     42        1.4   thorpej #include <uvm/uvm_extern.h>
     43        1.4   thorpej 
     44       1.12    dyoung #include <sys/bus.h>
     45        1.1       leo 
     46        1.1       leo #include <dev/pci/pcivar.h>
     47        1.1       leo #include <dev/pci/pcireg.h>
     48        1.1       leo 
     49        1.1       leo #include <machine/cpu.h>
     50        1.1       leo #include <machine/iomap.h>
     51        1.1       leo #include <machine/mfp.h>
     52        1.7       dsl #include <sys/bswap.h>
     53        1.1       leo 
     54        1.1       leo #include <atari/atari/device.h>
     55        1.1       leo #include <atari/pci/pci_vga.h>
     56        1.2       leo #include <atari/dev/grf_etreg.h>
     57        1.1       leo 
     58        1.1       leo int
     59       1.10       dsl pci_bus_maxdevs(pci_chipset_tag_t pc, int busno)
     60        1.1       leo {
     61  1.14.18.1  christos 
     62  1.14.18.1  christos 	return 4;
     63        1.1       leo }
     64        1.1       leo 
     65        1.9       dsl static int pci_config_offset(pcitag_t);
     66        1.1       leo 
     67        1.1       leo /*
     68        1.4   thorpej  * Atari_init.c maps the config areas PAGE_SIZE bytes apart....
     69        1.1       leo  */
     70  1.14.18.1  christos static int
     71  1.14.18.1  christos pci_config_offset(pcitag_t tag)
     72        1.1       leo {
     73  1.14.18.1  christos 	int device;
     74        1.1       leo 
     75        1.1       leo 	device = (tag >> 11) & 0x1f;
     76  1.14.18.1  christos 
     77  1.14.18.1  christos 	return device * PAGE_SIZE;
     78        1.1       leo }
     79        1.1       leo 
     80        1.1       leo pcireg_t
     81       1.10       dsl pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
     82        1.1       leo {
     83  1.14.18.1  christos 	uint32_t data;
     84        1.1       leo 
     85  1.14.18.1  christos 	if ((uint32_t)reg >= PCI_CONF_SIZE)
     86  1.14.18.1  christos 		return 0xffffffff;
     87       1.14   msaitoh 
     88  1.14.18.1  christos 	data = *(uint32_t *)(pci_conf_addr + pci_config_offset(tag) + reg);
     89  1.14.18.1  christos 	return bswap32(data);
     90        1.1       leo }
     91        1.1       leo 
     92        1.1       leo void
     93       1.10       dsl pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
     94        1.1       leo {
     95       1.14   msaitoh 
     96  1.14.18.1  christos 	if ((uint32_t)reg >= PCI_CONF_SIZE)
     97       1.14   msaitoh 		return;
     98       1.14   msaitoh 
     99  1.14.18.1  christos 	*((uint32_t *)(pci_conf_addr + pci_config_offset(tag) + reg))
    100  1.14.18.1  christos 	    = bswap32(data);
    101        1.1       leo }
    102        1.1       leo 
    103        1.1       leo /*
    104        1.1       leo  * The interrupt stuff is rather ugly. On the Hades, all interrupt lines
    105        1.1       leo  * for a slot are wired together and connected to IO 0,1,2 or 5 (slots:
    106        1.1       leo  * (0-3) on the TT-MFP. The Pci-config code initializes the irq. number
    107        1.1       leo  * to the slot position.
    108        1.1       leo  */
    109        1.1       leo static pci_intr_info_t iinfo[4] = { { -1 }, { -1 }, { -1 }, { -1 } };
    110        1.1       leo 
    111  1.14.18.1  christos static int iifun(int, int);
    112        1.1       leo 
    113        1.1       leo static int
    114       1.10       dsl iifun(int slot, int sr)
    115        1.1       leo {
    116        1.1       leo 	pci_intr_info_t *iinfo_p;
    117  1.14.18.1  christos 	int s;
    118        1.1       leo 
    119        1.1       leo 	iinfo_p = &iinfo[slot];
    120        1.1       leo 
    121        1.1       leo 	/*
    122        1.1       leo 	 * Disable the interrupts
    123        1.1       leo 	 */
    124        1.1       leo 	MFP2->mf_imrb  &= ~iinfo_p->imask;
    125        1.1       leo 
    126        1.1       leo 	if ((sr & PSL_IPL) >= (iinfo_p->ipl & PSL_IPL)) {
    127        1.1       leo 		/*
    128        1.1       leo 		 * We're running at a too high priority now.
    129        1.1       leo 		 */
    130        1.1       leo 		add_sicallback((si_farg)iifun, (void*)slot, 0);
    131  1.14.18.1  christos 	} else {
    132        1.1       leo 		s = splx(iinfo_p->ipl);
    133  1.14.18.1  christos 		(void)(iinfo_p->ifunc)(iinfo_p->iarg);
    134        1.1       leo 		splx(s);
    135        1.1       leo 
    136        1.1       leo 		/*
    137        1.1       leo 		 * Re-enable interrupts after handling
    138        1.1       leo 		 */
    139        1.1       leo 		MFP2->mf_imrb |= iinfo_p->imask;
    140        1.1       leo 	}
    141        1.1       leo 	return 1;
    142        1.1       leo }
    143        1.1       leo 
    144        1.8        ad int
    145        1.8        ad pci_intr_setattr(pci_chipset_tag_t pc, pci_intr_handle_t *ih,
    146  1.14.18.1  christos     int attr, uint64_t data)
    147        1.8        ad {
    148        1.8        ad 
    149        1.8        ad 	switch (attr) {
    150        1.8        ad 	case PCI_INTR_MPSAFE:
    151        1.8        ad 		return 0;
    152        1.8        ad 	default:
    153        1.8        ad 		return ENODEV;
    154        1.8        ad 	}
    155        1.8        ad }
    156        1.8        ad 
    157        1.1       leo void *
    158  1.14.18.1  christos pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
    159  1.14.18.1  christos     int (*ih_fun)(void *), void *ih_arg)
    160        1.1       leo {
    161        1.1       leo 	pci_intr_info_t *iinfo_p;
    162        1.1       leo 	struct intrhand	*ihand;
    163  1.14.18.1  christos 	int slot;
    164        1.1       leo 
    165        1.1       leo 	slot    = ih;
    166        1.1       leo 	iinfo_p = &iinfo[slot];
    167        1.1       leo 
    168        1.1       leo 	if (iinfo_p->ipl > 0)
    169  1.14.18.1  christos 		panic("pci_intr_establish: interrupt was already established");
    170        1.1       leo 
    171        1.1       leo 	ihand = intr_establish((slot == 3) ? 23 : 16 + slot, USER_VEC, 0,
    172  1.14.18.1  christos 	    (hw_ifun_t)iifun, (void *)slot);
    173        1.1       leo 	if (ihand != NULL) {
    174        1.1       leo 		iinfo_p->ipl   = level;
    175        1.1       leo 		iinfo_p->imask = (slot == 3) ? 0x80 : (0x01 << slot);
    176        1.1       leo 		iinfo_p->ifunc = ih_fun;
    177        1.1       leo 		iinfo_p->iarg  = ih_arg;
    178        1.1       leo 		iinfo_p->ihand = ihand;
    179        1.1       leo 
    180        1.1       leo 		/*
    181        1.1       leo 		 * Enable (unmask) the interrupt
    182        1.1       leo 		 */
    183        1.1       leo 		MFP2->mf_imrb |= iinfo_p->imask;
    184        1.1       leo 		MFP2->mf_ierb |= iinfo_p->imask;
    185  1.14.18.1  christos 		return iinfo_p;
    186        1.1       leo 	}
    187        1.1       leo 	return NULL;
    188        1.1       leo }
    189        1.1       leo 
    190        1.1       leo void
    191       1.10       dsl pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
    192        1.1       leo {
    193        1.1       leo 	pci_intr_info_t *iinfo_p = (pci_intr_info_t *)cookie;
    194        1.1       leo 
    195        1.1       leo 	if (iinfo->ipl < 0)
    196  1.14.18.1  christos 		panic("pci_intr_disestablish: interrupt was not established");
    197        1.1       leo 
    198        1.1       leo 	MFP2->mf_imrb &= ~iinfo->imask;
    199        1.1       leo 	MFP2->mf_ierb &= ~iinfo->imask;
    200  1.14.18.1  christos 	(void)intr_disestablish(iinfo_p->ihand);
    201        1.1       leo 	iinfo_p->ipl = -1;
    202        1.2       leo }
    203        1.2       leo 
    204        1.2       leo /*
    205        1.2       leo  * XXX: Why are we repeating this everywhere! (Leo)
    206        1.2       leo  */
    207        1.2       leo #define PCI_LINMEMBASE  0x0e000000
    208        1.2       leo 
    209  1.14.18.1  christos static const uint8_t crt_tab[] = {
    210        1.2       leo 	0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
    211        1.2       leo 	0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
    212        1.2       leo 	0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
    213        1.2       leo 	0xff };
    214        1.2       leo 
    215  1.14.18.1  christos static const uint8_t seq_tab[] = {
    216  1.14.18.1  christos 	0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00
    217  1.14.18.1  christos };
    218  1.14.18.1  christos 
    219  1.14.18.1  christos static const uint8_t attr_tab[] = {
    220  1.14.18.1  christos 	0x0c, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x00, 0x00
    221  1.14.18.1  christos };
    222  1.14.18.1  christos 
    223  1.14.18.1  christos static const uint8_t gdc_tab[] = {
    224  1.14.18.1  christos 	0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff
    225  1.14.18.1  christos };
    226        1.2       leo 
    227        1.2       leo void
    228  1.14.18.1  christos ati_vga_init(pci_chipset_tag_t pc, pcitag_t tag, int id, volatile uint8_t *ba,
    229  1.14.18.1  christos     uint8_t *fb)
    230        1.2       leo {
    231  1.14.18.1  christos 	uint32_t csr;
    232  1.14.18.1  christos 	int i;
    233        1.2       leo 
    234        1.2       leo 	/* Turn on the card */
    235        1.2       leo 	pci_conf_write(pc, tag, PCI_MAPREG_START, PCI_LINMEMBASE);
    236        1.2       leo 	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
    237        1.2       leo 	csr |= (PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE);
    238        1.2       leo 	csr |= PCI_COMMAND_MASTER_ENABLE;
    239        1.2       leo 	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
    240        1.2       leo 
    241        1.2       leo 	/*
    242        1.2       leo 	 * Make sure we're allowed to write all crt-registers and reload them.
    243        1.2       leo 	 */
    244        1.2       leo 	WCrt(ba, CRT_ID_END_VER_RETR, (RCrt(ba, CRT_ID_END_VER_RETR) & 0x7f));
    245        1.2       leo 
    246        1.2       leo 	for (i = 0; i < 0x18; i++)
    247        1.2       leo 		WCrt(ba, i, crt_tab[i]);
    248        1.2       leo 	for (i = 0; i < 8; i++)
    249        1.2       leo 		WSeq(ba, i, seq_tab[i]);
    250        1.2       leo 	for (i = 0; i < 9; i++)
    251        1.2       leo 		WGfx(ba, i, gdc_tab[i]);
    252        1.2       leo 	for (i = 0x10; i < 0x18; i++)
    253        1.2       leo 		WAttr(ba, i, attr_tab[i - 0x10]);
    254        1.2       leo 	WAttr(ba, 0x20, 0);
    255        1.1       leo }
    256