Commit | Line | Data |
---|---|---|
aea481da DE |
1 | /* Copyright (C) 1998, Cygnus Solutions */ |
2 | ||
3 | #include "pke.h" | |
4 | #include <stdlib.h> | |
5 | ||
6 | ||
7 | /* Imported functions */ | |
8 | ||
9 | void device_error (device *me, char* message); /* device.c */ | |
10 | ||
11 | ||
12 | /* Internal function declarations */ | |
13 | ||
14 | static int pke_io_read_buffer(device*, void*, int, address_word, | |
15 | unsigned, sim_cpu*, sim_cia); | |
16 | static int pke_io_write_buffer(device*, const void*, int, address_word, | |
17 | unsigned, sim_cpu*, sim_cia); | |
18 | static void pke_issue(struct pke_device*); | |
19 | ||
20 | ||
21 | /* Static data */ | |
22 | ||
23 | struct pke_device pke0_device = | |
24 | { | |
25 | { "pke0", &pke_io_read_buffer, &pke_io_write_buffer }, /* device */ | |
26 | 0, 0, /* ID, flags */ | |
27 | PKE0_REGISTER_WINDOW_START, PKE0_FIFO_START, /* memory-mapping addresses */ | |
28 | {}, /* regs */ | |
29 | NULL, 0, 0, NULL, /* FIFO */ | |
30 | 0 /* pc */ | |
31 | }; | |
32 | ||
33 | ||
34 | struct pke_device pke1_device = | |
35 | { | |
36 | { "pke1", &pke_io_read_buffer, &pke_io_write_buffer }, /* device */ | |
37 | 1, 0, /* ID, flags */ | |
38 | PKE1_REGISTER_WINDOW_START, PKE1_FIFO_START, /* memory-mapping addresses */ | |
39 | {}, /* regs */ | |
40 | NULL, 0, 0, NULL, /* FIFO */ | |
41 | 0 /* pc */ | |
42 | }; | |
43 | ||
44 | ||
45 | ||
46 | /* External functions */ | |
47 | ||
48 | ||
49 | /* Attach PKE0 addresses to main memory */ | |
50 | ||
51 | void | |
52 | pke0_attach(SIM_DESC sd) | |
53 | { | |
54 | sim_core_attach (sd, | |
55 | NULL, | |
56 | 0 /*level*/, | |
57 | access_read_write, | |
58 | 0 /*space ???*/, | |
59 | pke0_device.register_memory_addr, | |
60 | PKE_REGISTER_WINDOW_SIZE /*nr_bytes*/, | |
61 | 0 /*modulo*/, | |
62 | (device*) &pke0_device, | |
63 | NULL /*buffer*/); | |
64 | ||
65 | sim_core_attach (sd, | |
66 | NULL, | |
67 | 0 /*level*/, | |
68 | access_read_write, | |
69 | 0 /*space ???*/, | |
70 | pke0_device.fifo_memory_addr, | |
71 | sizeof(quadword) /*nr_bytes*/, | |
72 | 0 /*modulo*/, | |
73 | (device*) &pke1_device, | |
74 | NULL /*buffer*/); | |
75 | } | |
76 | ||
77 | ||
78 | /* Attach PKE1 addresses to main memory */ | |
79 | ||
80 | void | |
81 | pke1_attach(SIM_DESC sd) | |
82 | { | |
83 | sim_core_attach (sd, | |
84 | NULL, | |
85 | 0 /*level*/, | |
86 | access_read_write, | |
87 | 0 /*space ???*/, | |
88 | pke1_device.register_memory_addr, | |
89 | PKE_REGISTER_WINDOW_SIZE /*nr_bytes*/, | |
90 | 0 /*modulo*/, | |
91 | (device*) &pke1_device, | |
92 | NULL /*buffer*/); | |
93 | ||
94 | sim_core_attach (sd, | |
95 | NULL, | |
96 | 0 /*level*/, | |
97 | access_read_write, | |
98 | 0 /*space ???*/, | |
99 | pke1_device.fifo_memory_addr, | |
100 | sizeof(quadword) /*nr_bytes*/, | |
101 | 0 /*modulo*/, | |
102 | (device*) &pke1_device, | |
103 | NULL /*buffer*/); | |
104 | } | |
105 | ||
106 | ||
107 | /* Issue a PKE0 instruction if possible */ | |
108 | ||
109 | void | |
110 | pke0_issue() | |
111 | { | |
112 | pke_issue(& pke0_device); | |
113 | } | |
114 | ||
115 | ||
116 | /* Issue a PKE1 instruction if possible */ | |
117 | ||
118 | void | |
119 | pke1_issue() | |
120 | { | |
121 | pke_issue(& pke0_device); | |
122 | } | |
123 | ||
124 | ||
125 | ||
126 | /* Internal functions */ | |
127 | ||
128 | ||
129 | /* Handle a PKE read; return no. of bytes read */ | |
130 | ||
131 | int | |
132 | pke_io_read_buffer(device *me_, | |
133 | void *dest, | |
134 | int space, | |
135 | address_word addr, | |
136 | unsigned nr_bytes, | |
137 | sim_cpu *processor, | |
138 | sim_cia cia) | |
139 | { | |
140 | /* downcast to gather embedding pke_device struct */ | |
141 | struct pke_device* me = (struct pke_device*) me_; | |
142 | ||
143 | /* enforce that an access does not span more than one quadword */ | |
144 | address_word low = ADDR_TRUNC_QW(addr); | |
145 | address_word high = ADDR_TRUNC_QW(addr + nr_bytes - 1); | |
146 | if(low != high) | |
147 | return 0; | |
148 | ||
149 | /* classify address & handle */ | |
150 | if(addr >= me->register_memory_addr && | |
151 | addr < me->register_memory_addr + PKE_REGISTER_WINDOW_SIZE) | |
152 | { | |
153 | /* register bank */ | |
154 | int reg_num = ADDR_TRUNC_QW(addr - me->register_memory_addr) >> 4; | |
155 | int readable = 1; | |
156 | ||
157 | /* ensure readibility of register: all okay except PKE1-only ones read on PKE0 */ | |
158 | switch(reg_num) | |
159 | { | |
160 | case PKE_REG_BASE: | |
161 | case PKE_REG_OFST: | |
162 | case PKE_REG_TOPS: | |
163 | case PKE_REG_TOP: | |
164 | case PKE_REG_DBF: | |
165 | if(me->pke_number == 0) /* PKE0 cannot access these registers */ | |
166 | readable = 0; | |
167 | } | |
168 | ||
169 | /* perform read & return */ | |
170 | if(readable) | |
171 | { | |
172 | /* find byte-offset inside register bank */ | |
173 | int reg_byte = ADDR_OFFSET_QW(addr); | |
174 | void* src = ((unsigned_1*) (& me->regs[reg_num])) + reg_byte; | |
175 | /* copy the bits */ | |
176 | memcpy(dest, src, nr_bytes); | |
177 | /* okay */ | |
178 | return nr_bytes; | |
179 | } | |
180 | else | |
181 | { | |
182 | /* error */ | |
183 | return 0; | |
184 | } | |
185 | ||
186 | /* NOTREACHED */ | |
187 | } | |
188 | else if(addr >= me->fifo_memory_addr && | |
189 | addr < me->fifo_memory_addr + sizeof(quadword)) | |
190 | { | |
191 | /* FIFO */ | |
192 | ||
193 | /* XXX: FIFO is not readable. */ | |
194 | return 0; | |
195 | } | |
196 | ||
197 | /* NOTREACHED */ | |
198 | } | |
199 | ||
200 | ||
201 | /* Handle a PKE read; return no. of bytes written */ | |
202 | ||
203 | int | |
204 | pke_io_write_buffer(device *me_, | |
205 | const void *src, | |
206 | int space, | |
207 | address_word addr, | |
208 | unsigned nr_bytes, | |
209 | sim_cpu *processor, | |
210 | sim_cia cia) | |
211 | { | |
212 | /* downcast to gather embedding pke_device struct */ | |
213 | struct pke_device* me = (struct pke_device*) me_; | |
214 | ||
215 | /* enforce that an access does not span more than one quadword */ | |
216 | address_word low = ADDR_TRUNC_QW(addr); | |
217 | address_word high = ADDR_TRUNC_QW(addr + nr_bytes - 1); | |
218 | if(low != high) | |
219 | return 0; | |
220 | ||
221 | /* classify address & handle */ | |
222 | if(addr >= me->register_memory_addr && | |
223 | addr < me->register_memory_addr + PKE_REGISTER_WINDOW_SIZE) | |
224 | { | |
225 | /* register bank */ | |
226 | int reg_num = ADDR_TRUNC_QW(addr - me->register_memory_addr) >> 4; | |
227 | int writeable = 1; | |
228 | ||
229 | /* ensure readibility of register: all okay except PKE1-only ones read on PKE0 */ | |
230 | switch(reg_num) | |
231 | { | |
232 | case PKE_REG_BASE: | |
233 | case PKE_REG_OFST: | |
234 | case PKE_REG_TOPS: | |
235 | case PKE_REG_TOP: | |
236 | case PKE_REG_DBF: | |
237 | if(me->pke_number == 0) /* PKE0 cannot access these registers */ | |
238 | writeable = 0; | |
239 | } | |
240 | ||
241 | /* perform write & return */ | |
242 | if(writeable) | |
243 | { | |
244 | /* find byte-offset inside register bank */ | |
245 | int reg_byte = ADDR_OFFSET_QW(addr); | |
246 | void* dest = ((unsigned_1*) (& me->regs[reg_num])) + reg_byte; | |
247 | /* copy the bits */ | |
248 | memcpy(dest, src, nr_bytes); | |
249 | return nr_bytes; | |
250 | } | |
251 | else | |
252 | { | |
253 | /* error */ | |
254 | return 0; | |
255 | } | |
256 | ||
257 | /* NOTREACHED */ | |
258 | } | |
259 | else if(addr >= me->fifo_memory_addr && | |
260 | addr < me->fifo_memory_addr + sizeof(quadword)) | |
261 | { | |
262 | /* FIFO */ | |
263 | ||
264 | /* assert transfer size == 128 bits */ | |
265 | if(nr_bytes != sizeof(quadword)) | |
266 | return 0; | |
267 | ||
268 | /* ensure FIFO has enough elements */ | |
269 | if(me->fifo_num_elements == me->fifo_buffer_size) | |
270 | { | |
271 | /* time to grow */ | |
272 | int new_fifo_buffer_size = me->fifo_buffer_size + 20; | |
273 | void* ptr = realloc((void*) me->fifo, new_fifo_buffer_size*sizeof(quadword)); | |
274 | ||
275 | if(ptr == NULL) | |
276 | { | |
277 | /* oops, cannot enlarge FIFO any more */ | |
278 | device_error(me_, "Cannot enlarge FIFO buffer\n"); | |
279 | return 0; | |
280 | } | |
281 | ||
282 | me->fifo_buffer_size = new_fifo_buffer_size; | |
283 | } | |
284 | ||
285 | /* add new quadword at end of FIFO */ | |
286 | memcpy(& me->fifo[++me->fifo_num_elements], src, nr_bytes); | |
287 | ||
288 | /* okay */ | |
289 | return nr_bytes; | |
290 | } | |
291 | ||
292 | /* NOTREACHED */ | |
293 | } | |
294 | ||
295 | ||
296 | ||
297 | /* Issue & swallow one PKE opcode if possible */ | |
298 | ||
299 | void | |
300 | pke_issue(struct pke_device* me) | |
301 | { | |
302 | ||
303 | ||
304 | } | |
305 | ||
306 |