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