1 /* $Id: sun2-control.c,v 1.5 2009/08/30 14:42:15 fredette Exp $ */
2
3 /* machine/sun2/sun2-control.c - implementation of Sun 2 emulation control space: */
4
5 /*
6 * Copyright (c) 2003 Matt Fredette
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Matt Fredette.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include <tme/common.h>
37 _TME_RCSID("$Id: sun2-control.c,v 1.5 2009/08/30 14:42:15 fredette Exp $");
38
39 /* includes: */
40 #include "sun2-impl.h"
41
42 /* macros: */
43
44 /* the bus cycle handler for function code three space: */
45 int
_tme_sun2_control_cycle_handler(void * _sun2,struct tme_bus_cycle * cycle_init)46 _tme_sun2_control_cycle_handler(void *_sun2, struct tme_bus_cycle *cycle_init)
47 {
48 struct tme_sun2 *sun2;
49 struct tme_bus_cycle cycle_resp;
50 tme_bus_addr32_t reg, address, index;
51 tme_uint32_t pte;
52 int rc;
53
54 /* recover our sun2: */
55 sun2 = (struct tme_sun2 *) _sun2;
56
57 /* get the register and address and index: */
58 reg = cycle_init->tme_bus_cycle_address & (TME_SUN2_PAGE_SIZE - 1);
59 reg = TME_MIN(reg, TME_SUN2_CONTROL_JUNK);
60 address = cycle_init->tme_bus_cycle_address & ~(TME_SUN2_PAGE_SIZE - 1);
61 index = address >> TME_SUN2_PAGE_SIZE_LOG2;
62
63 /* this macro evaluates to TRUE whenever a register is maybe being
64 accessed: */
65 #define _TME_SUN2_REG_ACCESSED(icreg) \
66 ((TME_SUN2_CONTROL_ADDRESS(icreg) == 0) \
67 ? (reg < sizeof(sun2->icreg)) \
68 : TME_RANGES_OVERLAP(reg, \
69 reg \
70 + cycle_init->tme_bus_cycle_size - 1, \
71 !TME_SUN2_CONTROL_ADDRESS(icreg) + \
72 TME_SUN2_CONTROL_ADDRESS(icreg), \
73 TME_SUN2_CONTROL_ADDRESS(icreg) \
74 + sizeof(sun2->icreg) - 1))
75
76 /* whenever the page map register is accessed, we need to fill it
77 before running the cycle: */
78 if (_TME_SUN2_REG_ACCESSED(tme_sun2_pgmap_hi)
79 || _TME_SUN2_REG_ACCESSED(tme_sun2_pgmap_lo)) {
80
81 /* get the PTE from the MMU: */
82 rc = _tme_sun2_mmu_pte_get(sun2, address, &pte);
83 assert(rc == TME_OK);
84 sun2->tme_sun2_pgmap_hi = (pte >> 16);
85 sun2->tme_sun2_pgmap_lo = (pte & 0xffff);
86 }
87
88 /* whenever the segment map register is accessed, we need to fill it
89 before running the cycle: */
90 if (_TME_SUN2_REG_ACCESSED(tme_sun2_segmap)
91 && cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ) {
92 sun2->tme_sun2_segmap = tme_sun_mmu_segmap_get(sun2->tme_sun2_mmu, sun2->tme_sun2_context_user, address);
93 }
94
95 /* whenever the IDPROM register is accessed, we need to fill it
96 before running the cycle: */
97 if (_TME_SUN2_REG_ACCESSED(tme_sun2_idprom)
98 && index < sizeof(sun2->tme_sun2_idprom_contents)) {
99 sun2->tme_sun2_idprom = sun2->tme_sun2_idprom_contents[index];
100 }
101
102 /* run the cycle: */
103 TME_SUN2_CONTROL_BUS_CYCLE(sun2, reg, &cycle_resp);
104 cycle_resp.tme_bus_cycle_type = (cycle_init->tme_bus_cycle_type
105 ^ (TME_BUS_CYCLE_WRITE
106 | TME_BUS_CYCLE_READ));
107 cycle_resp.tme_bus_cycle_lane_routing = cycle_init->tme_bus_cycle_lane_routing;
108 tme_bus_cycle_xfer(cycle_init, &cycle_resp);
109
110 /* whenever the bus error register is read or written, it is
111 cleared: */
112 if (_TME_SUN2_REG_ACCESSED(tme_sun2_buserr)) {
113 sun2->tme_sun2_buserr = 0;
114 }
115
116 /* these registers only need action taken when they're written: */
117 if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
118
119 /* the page map has been written: */
120 if (_TME_SUN2_REG_ACCESSED(tme_sun2_pgmap_hi)
121 || _TME_SUN2_REG_ACCESSED(tme_sun2_pgmap_lo)) {
122 pte = sun2->tme_sun2_pgmap_hi;
123 pte = (pte << 16) | sun2->tme_sun2_pgmap_lo;
124 rc = _tme_sun2_mmu_pte_set(sun2, address, pte);
125 assert(rc == TME_OK);
126 }
127
128 /* the segment map has been written: */
129 if (_TME_SUN2_REG_ACCESSED(tme_sun2_segmap)) {
130 tme_sun_mmu_segmap_set(sun2->tme_sun2_mmu, sun2->tme_sun2_context_user, address, sun2->tme_sun2_segmap);
131 }
132
133 /* the system context register has been written: */
134 if (_TME_SUN2_REG_ACCESSED(tme_sun2_context_system)) {
135 _tme_sun2_mmu_context_system_set(sun2);
136 }
137
138 /* the system context register has been written: */
139 if (_TME_SUN2_REG_ACCESSED(tme_sun2_context_user)) {
140 _tme_sun2_mmu_context_user_set(sun2);
141 }
142
143 /* the diag register has been written: */
144 if (_TME_SUN2_REG_ACCESSED(tme_sun2_diag)) {
145 /* TBD */
146 }
147
148 /* the system enable register has been written: */
149 if (_TME_SUN2_REG_ACCESSED(tme_sun2_enable)) {
150 rc = _tme_sun2_ipl_check(sun2);
151 assert(rc == TME_OK);
152 /* in case TME_SUN2_ENA_NOTBOOT changed, make a pseudo-context
153 change: */
154 _tme_sun2_mmu_context_user_set(sun2);
155 }
156 }
157
158 return (TME_OK);
159 }
160
161 #if 1
162 #include <stdio.h>
163
164 /* this dumps out the sun2 state: */
165 void
tme_sun2_dump(struct tme_sun2 * sun2)166 tme_sun2_dump(struct tme_sun2 *sun2)
167 {
168
169 /* dump out the page map register: */
170 fprintf(stderr, "PGMAP = 0x%04x%04x\n",
171 sun2->tme_sun2_pgmap_hi,
172 sun2->tme_sun2_pgmap_lo);
173 fprintf(stderr, "SEGMAP = 0x%02x\n", sun2->tme_sun2_segmap);
174 fprintf(stderr, "\n");
175 fprintf(stderr, "SCONTEXT = 0x%02x\n", sun2->tme_sun2_context_system);
176 fprintf(stderr, " CONTEXT = 0x%02x\n", sun2->tme_sun2_context_user);
177 fprintf(stderr, "\n");
178 fprintf(stderr, "IDPROM = 0x%02x\n", sun2->tme_sun2_idprom);
179 fprintf(stderr, "DIAG = 0x%02x\n", sun2->tme_sun2_diag);
180 fprintf(stderr, "BUSERR = 0x%04x\n", sun2->tme_sun2_buserr);
181 fprintf(stderr, "ENABLE = 0x%04x\n", sun2->tme_sun2_enable);
182 }
183 #endif /* 1 */
184