1 /*
2  *  Copyright (C) 2003-2009  Anders Gavare.  All rights reserved.
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions are met:
6  *
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. The name of the author may not be used to endorse or promote products
13  *     derived from this software without specific prior written permission.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  *  SUCH DAMAGE.
26  *
27  *
28  *  COMMENT: Motorola MPC105 "Eagle" host bridge
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "bus_isa.h"
36 #include "bus_pci.h"
37 #include "cpu.h"
38 #include "device.h"
39 #include "interrupt.h"
40 #include "machine.h"
41 #include "memory.h"
42 #include "misc.h"
43 
44 
45 struct eagle_data {
46 	struct interrupt irq;
47 
48 	struct pci_data	*pci_data;
49 };
50 
51 
DEVICE_ACCESS(eagle)52 DEVICE_ACCESS(eagle)
53 {
54 	struct eagle_data *d = (struct eagle_data *) extra;
55 	uint64_t idata = 0, odata = 0;
56 	int bus, dev, func, reg;
57 
58 	if (writeflag == MEM_WRITE)
59 		idata = memory_readmax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN);
60 
61 	/*
62 	 *  Pass accesses to ISA ports 0xcf8 and 0xcfc onto bus_pci_*:
63 	 */
64 
65 	switch (relative_addr) {
66 
67 	case 0:	/*  Address:  */
68 		bus_pci_decompose_1(idata, &bus, &dev, &func, &reg);
69 		bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, reg);
70 		break;
71 
72 	case 4:	/*  Data:  */
73 		bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ?
74 		    &odata : &idata, len, writeflag);
75 		break;
76 	}
77 
78 	if (writeflag == MEM_READ)
79 		memory_writemax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN, odata);
80 
81 	return 1;
82 }
83 
84 
DEVINIT(eagle)85 DEVINIT(eagle)
86 {
87 	struct eagle_data *d;
88 	uint64_t pci_io_offset, pci_mem_offset;
89 	uint64_t isa_portbase = 0, isa_membase = 0;
90 	uint64_t pci_portbase = 0, pci_membase = 0;
91 	char pci_irq_base[300];
92 	char isa_irq_base[300];
93 
94 	CHECK_ALLOCATION(d = (struct eagle_data *) malloc(sizeof(struct eagle_data)));
95 	memset(d, 0, sizeof(struct eagle_data));
96 
97 	/*  The interrupt path to the CPU at which we are connected:  */
98 	INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
99 
100 	/*
101 	 *  According to http://www.beatjapan.org/mirror/www.be.com/
102 	 *  aboutbe/benewsletter/Issue27.html#Cookbook :
103 	 *
104 	 *  "HARDWARE MEMORY MAP
105 	 *   The MPC105 defines the physical memory map of the system as
106 	 *   follows:
107 	 *
108 	 *   Start        Size         Description
109 	 *
110 	 *   0x00000000   0x40000000   Physical RAM
111 	 *   0x40000000   0x40000000   Other system memory
112 	 *                             (motherboard glue regs)
113 	 *   0x80000000   0x00800000   ISA I/O
114 	 *   0x81000000   0x3E800000   PCI I/O
115 	 *   0xBFFFFFF0   0x00000010   PCI/ISA interrupt acknowledge
116 	 *   0xC0000000   0x3F000000   PCI memory
117 	 *   0xFF000000   0x01000000   ROM/flash
118 	 */
119 
120 	/*  TODO: Make these work like the BE web page stated...  */
121 	pci_io_offset  = 0x80000000ULL;
122 	pci_mem_offset = 0xc0000000ULL;
123 	pci_portbase   = 0x00000000ULL;
124 	pci_membase    = 0x00000000ULL;
125 	isa_portbase   = 0x80000000ULL;
126 	isa_membase    = 0xc0000000ULL;
127 
128 	switch (devinit->machine->machine_type) {
129 	/* case MACHINE_BEBOX:
130 		snprintf(pci_irq_base, sizeof(pci_irq_base), "%s.bebox",
131 		    devinit->interrupt_path);
132 		snprintf(isa_irq_base, sizeof(isa_irq_base), "%s.bebox.5",
133 		    devinit->interrupt_path);
134 		break; */
135 	default:
136 		snprintf(pci_irq_base, sizeof(pci_irq_base), "%s",
137 		    devinit->interrupt_path);
138 		snprintf(isa_irq_base, sizeof(isa_irq_base), "%s",
139 		    devinit->interrupt_path);
140 	}
141 
142 	/*  Create a PCI bus:  */
143 	d->pci_data = bus_pci_init(devinit->machine, devinit->interrupt_path,
144 	    pci_io_offset, pci_mem_offset,
145 	    pci_portbase, pci_membase, pci_irq_base,
146 	    isa_portbase, isa_membase, isa_irq_base);
147 
148 	/*  Add the PCI glue for the controller itself:  */
149 	bus_pci_add(devinit->machine, d->pci_data,
150 	    devinit->machine->memory, 0, 0, 0, "eagle");
151 
152 	/*  ADDR and DATA configuration ports in ISA space:  */
153 	memory_device_register(devinit->machine->memory, "eagle",
154 	    isa_portbase + BUS_PCI_ADDR, 8, dev_eagle_access, d,
155 	    DM_DEFAULT, NULL);
156 
157 	switch (devinit->machine->machine_type) {
158 
159 	/* case MACHINE_BEBOX:
160 		bus_isa_init(devinit->machine, isa_irq_base,
161 		    BUS_ISA_IDE0 | BUS_ISA_VGA, isa_portbase, isa_membase);
162 		bus_pci_add(devinit->machine, d->pci_data,
163 		    devinit->machine->memory, 0, 11, 0, "i82378zb");
164 		break; */
165 
166 	case MACHINE_PREP:
167 		bus_pci_add(devinit->machine, d->pci_data,
168 		    devinit->machine->memory, 0, 11, 0, "ibm_isa");
169 		break;
170 
171 	case MACHINE_MVMEPPC:
172 		bus_isa_init(devinit->machine, isa_irq_base,
173 		    BUS_ISA_LPTBASE_3BC, isa_portbase, isa_membase);
174 
175 		switch (devinit->machine->machine_subtype) {
176 		case MACHINE_MVMEPPC_1600:
177 			bus_pci_add(devinit->machine, d->pci_data,
178 			    devinit->machine->memory, 0, 11, 0, "i82378zb");
179 			break;
180 		default:fatal("unimplemented machine subtype for "
181 			    "eagle/mvmeppc\n");
182 			exit(1);
183 		}
184 		break;
185 
186 	default:fatal("unimplemented machine type for eagle\n");
187 		exit(1);
188 	}
189 
190 	devinit->return_ptr = d->pci_data;
191 
192 	return 1;
193 }
194 
195