Home | History | Annotate | Line # | Download | only in i386
      1 /*	$NetBSD: rbus_machdep.c,v 1.27 2017/08/15 09:25:00 maxv Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1999
      5  *     HAYAKAWA Koichi.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: rbus_machdep.c,v 1.27 2017/08/15 09:25:00 maxv Exp $");
     30 
     31 #include "opt_pcibios.h"
     32 #include "opt_pcifixup.h"
     33 
     34 #include <sys/param.h>
     35 #include <sys/systm.h>
     36 #include <sys/extent.h>
     37 
     38 #include <sys/sysctl.h>
     39 
     40 #include <sys/bus.h>
     41 #include <dev/cardbus/rbus.h>
     42 
     43 #include <sys/device.h>
     44 #include <dev/isa/isareg.h>
     45 #include <dev/isa/isavar.h>
     46 
     47 #include <dev/pci/pcivar.h>
     48 #if defined(PCI_ADDR_FIXUP)
     49 #include <arch/x86/pci/pci_addr_fixup.h>
     50 #endif
     51 
     52 #ifndef RBUS_IO_BASE
     53 #define	RBUS_IO_BASE	0x4000
     54 #endif
     55 #ifndef RBUS_IO_SIZE
     56 #define	RBUS_IO_SIZE	0x2000
     57 #endif
     58 
     59 #ifndef RBUS_MIN_START
     60 #define RBUS_MIN_START 0x40000000	/* 1GB */
     61 #else
     62 /*
     63  * Note that kernel config forced RBUS_MIN_START.
     64  */
     65 #define RBUS_MIN_START_FORCED
     66 #endif
     67 bus_addr_t rbus_min_start = RBUS_MIN_START;
     68 
     69 /*
     70  * Dynamically set the start address for rbus.  This must be called
     71  * before rbus is initialized.  The start address should be determined
     72  * by the amount of installed memory.  Generally 1 GB has been found
     73  * to be a good value, but it fails on some Thinkpads (e.g. 2645-4AU),
     74  * for which 0.5 GB is a good value.  It also fails on (at least)
     75  * Thinkpads with 2GB of RAM, for which 2 GB is a good value.
     76  *
     77  * Thus, a general strategy of setting rbus_min_start to the amount of
     78  * memory seems in order.  However, the actually amount of memory is
     79  * generally slightly more than the amount found, e.g. 1014MB vs 1024,
     80  * or 2046 vs 2048.
     81  */
     82 void
     83 rbus_min_start_hint(psize_t ram)
     84 {
     85 #ifdef RBUS_MIN_START_FORCED
     86 	aprint_debug("rbus: rbus_min_start from config at %#0" PRIxPADDR "\n",
     87 	    rbus_min_start);
     88 #else
     89 	if (ram <= 192*1024*1024UL) {
     90 		/*
     91 		 * <= 192 MB, so try 0.5 GB.  This will work on
     92 		 * Thinkpad 600E (2645-4AU), which fails at 1GB, and
     93 		 * on some other older machines that may have trouble
     94 		 * with addresses needing more than 20 bits.
     95 		 */
     96 		rbus_min_start = 512 * 1024 * 1024UL;
     97 	}
     98 
     99 	if (ram >= 1024*1024*1024UL) {
    100 		/*
    101 		 * > 1GB, so try 2 GB.
    102 		 */
    103 		rbus_min_start =  2 * 1024 * 1024 * 1024UL;
    104 	}
    105 
    106 	/* XXX Not tested in > 2 GB case. */
    107 	if (ram > 2 * 1024*1024*1024UL) {
    108 		/*
    109 		 * > 2 GB, so try 3 GB.
    110 		 */
    111 		rbus_min_start =  3 * 1024 * 1024 * 1024UL;
    112 	}
    113 
    114 	aprint_debug("rbus: rbus_min_start set to %#0" PRIxPADDR "\n",
    115 	    rbus_min_start);
    116 #endif
    117 }
    118 
    119 
    120 /*
    121  * rbus_tag_t rbus_fakeparent_mem(struct pci_attach_args *pa)
    122  *
    123  *   This function makes an rbus tag for memory space.  This rbus tag
    124  *   shares the all memory region of ex_iomem.
    125  */
    126 rbus_tag_t
    127 rbus_pccbb_parent_mem(struct pci_attach_args *pa)
    128 {
    129 	bus_addr_t start;
    130 	bus_size_t size;
    131 	extern struct extent *iomem_ex;
    132 	struct extent *ex = iomem_ex;
    133 
    134 #if defined(PCI_ADDR_FIXUP)
    135 	if (pciaddr.extent_mem != NULL)
    136 		ex = pciaddr.extent_mem;
    137 #endif
    138 
    139 	start = ex->ex_start;
    140 
    141 	/*
    142 	 * XXX: unfortunately, iomem_ex cannot be used for the dynamic
    143 	 * bus_space allocation.  There are some hidden memory (or
    144 	 * some obstacles which are not recognised by the kernel) in
    145 	 * the region governed by iomem_ex.  So I decide to use only
    146 	 * very high address region.
    147 	 *
    148 	 * If pcibios_addr_fixup() succeeded, the PCI device is using an area
    149 	 * which is not recognised by the kernel as already reserved.
    150 	 */
    151 
    152 	if (start < rbus_min_start)
    153 		start = rbus_min_start;
    154 
    155 	size = ex->ex_end - start;
    156 
    157 	return rbus_new_root_share(pa->pa_memt, ex, start, size, 0);
    158 }
    159 
    160 
    161 /*
    162  * rbus_tag_t rbus_pccbb_parent_io(struct pci_attach_args *pa)
    163  */
    164 rbus_tag_t
    165 rbus_pccbb_parent_io(struct pci_attach_args *pa)
    166 {
    167 	bus_addr_t start;
    168 	bus_size_t size;
    169 	rbus_tag_t ret;
    170 	extern struct extent *ioport_ex;
    171 	struct extent *ex = ioport_ex;
    172 
    173 #if defined(PCI_ADDR_FIXUP)
    174 	if (pciaddr.extent_port != NULL)
    175 		ex = pciaddr.extent_port;
    176 #endif
    177 
    178 	start = RBUS_IO_BASE;
    179 	size  = RBUS_IO_SIZE;
    180 
    181 	ret = rbus_new_root_share(pa->pa_iot, ex, start, size, 0);
    182 	if (ret == NULL)
    183 		panic("failed to alloc I/O space");
    184 
    185 	return ret;
    186 }
    187