|
|
1.1 root 1: /* $Id: sun2-bwtwo.c,v 1.2 2003/07/29 18:25:17 fredette Exp $ */
2:
3: /* machine/sun2/sun2-bwtwo.c - Sun2 bwtwo emulation implementation: */
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-bwtwo.c,v 1.2 2003/07/29 18:25:17 fredette Exp $");
38:
39: /* includes: */
40: #include <tme/machine/sun.h>
41: #include <tme/generic/bus-device.h>
42: #include <tme/generic/fb.h>
43:
44: /* macros: */
45:
46: /* screen dimensions: */
47: #define TME_SUN2BW2_LO_WIDTH (1152)
48: #define TME_SUN2BW2_LO_HEIGHT (900)
49: #define TME_SUN2BW2_HI_WIDTH (1024)
50: #define TME_SUN2BW2_HI_HEIGHT (1024)
51:
52: /* register offsets and sizes: */
53: #define TME_SUN2BW2_REG_MEM (0)
54: #define TME_SUN2BW2_SIZ_MEM (0x20000)
55: #define TME_SUN2BW2_REG_CSR_OBMEM (0x81800)
56: #define TME_SUN2BW2_REG_CSR_OBIO (0x20000)
57: #define TME_SUN2BW2_SIZ_CSR (0x00002)
58: #define TME_SUN2BW2_SIZ_CSR_PAGE (0x00800)
59:
60: /* the bits in the Control/Status register: */
61: #define TME_SUN2BW2_CSR_ENABLE_VIDEO (0x8000) /* enable video */
62: #define TME_SUN2BW2_CSR_ENABLE_COPY (0x4000) /* enable copy mode */
63: #define TME_SUN2BW2_CSR_ENABLE_INT (0x2000) /* interrupt enable */
64: #define TME_SUN2BW2_CSR_INT_ACTIVE (0x1000) /* interrupt is active */
65: #define TME_SUN2BW2_CSR_JUMPER_B (0x0800) /* jumper B */
66: #define TME_SUN2BW2_CSR_JUMPER_A (0x0400) /* jumper A */
67: #define TME_SUN2BW2_CSR_JUMPER_COLOR (0x0200) /* jumper color */
68: #define TME_SUN2BW2_CSR_JUMPER_HIRES (0x0100) /* jumper hires */
69: #define TME_SUN2BW2_CSR_COPYBASE_MASK (0x007E) /* copybase mask */
70:
71: #if 0
72: #define TME_SUN2BW2_DEBUG
73: #endif
74:
75: /* structures: */
76:
77: /* the card: */
78: struct tme_sun2bw2 {
79:
80: /* our simple bus device header: */
81: struct tme_bus_device tme_sun2bw2_device;
82: #define tme_sun2bw2_element tme_sun2bw2_device.tme_bus_device_element
83:
84: /* the mutex protecting the card: */
85: tme_mutex_t tme_sun2bw2_mutex;
86:
87: /* the rwlock protecting the card: */
88: tme_rwlock_t tme_sun2bw2_rwlock;
89:
90: /* the framebuffer connection: */
91: struct tme_fb_connection *tme_sun2bw2_fb_connection;
92:
93: /* if our interrupt line is currently asserted: */
94: int tme_sun2bw2_int_asserted;
95:
96: /* the (relative) bus address of our csr register: */
97: tme_bus_addr_t tme_sun2bw2_csr_address;
98:
99: /* the (relative) bus address of the first byte after displayed
100: framebuffer memory: */
101: tme_bus_addr_t tme_sun2bw2_end_address;
102:
103: /* the framebuffer memory: */
104: tme_uint8_t *tme_sun2bw2_fb_memory;
105:
106: /* any pad memory: */
107: tme_uint8_t *tme_sun2bw2_pad_memory;
108:
109: /* our csr: */
110: tme_uint16_t tme_sun2bw2_csr;
111: };
112:
113: /* globals: */
114:
115: static const struct tme_bus_subregion _tme_sun2bw2_subregion_csr_obmem = {
116: TME_SUN2BW2_REG_CSR_OBMEM,
117: TME_SUN2BW2_REG_CSR_OBMEM
118: + TME_SUN2BW2_SIZ_CSR_PAGE
119: - 1,
120: NULL };
121: static const struct tme_bus_subregion _tme_sun2bw2_subregion_csr_obio = {
122: TME_SUN2BW2_REG_CSR_OBIO,
123: TME_SUN2BW2_REG_CSR_OBIO
124: + TME_SUN2BW2_SIZ_CSR_PAGE
125: - 1,
126: NULL };
127:
128: #ifdef TME_SUN2BW2_DEBUG
129: static int
130: _tme_sun2bw2_update_debug(struct tme_fb_connection *conn_fb)
131: {
132: struct tme_sun2bw2 *sun2bw2;
133: static int y = -1;
134: static int x;
135: unsigned long pixel;
136: unsigned int pixel_byte;
137: tme_uint8_t pixel_bit;
138: int box, box_y, box_x;
139:
140: sun2bw2 = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private;
141:
142: for (box = 0; box < 2; box++) {
143: if (y < 0) {
144: y = 16;
145: x = 0;
146: continue;
147: }
148: for (box_y = 0; box_y < 2; box_y++) {
149: for (box_x = 0; box_x < 2; box_x++) {
150: pixel = (((y + box_y)
151: * TME_SUN2BW2_LO_WIDTH)
152: + x
153: + box_x);
154: pixel_byte = (pixel / 8);
155: pixel_bit = (0x80 >> (pixel % 8));
156: sun2bw2->tme_sun2bw2_fb_memory[pixel_byte] ^= pixel_bit;
157: }
158: }
159: if (box == 0) {
160: x += 2;
161: if (x == TME_SUN2BW2_LO_WIDTH) {
162: x = 0;
163: y += 2;
164: if (y == TME_SUN2BW2_LO_HEIGHT) {
165: y = 0;
166: }
167: }
168: }
169: }
170:
171: return (TME_OK);
172: }
173: #endif /* TME_SUN2BW2_DEBUG */
174:
175: /* the sun2bw2 framebuffer bus cycle handler: */
176: static int
177: _tme_sun2bw2_bus_cycle_fb(void *_sun2bw2, struct tme_bus_cycle *cycle_init)
178: {
179: struct tme_sun2bw2 *sun2bw2;
180:
181: /* recover our data structure: */
182: sun2bw2 = (struct tme_sun2bw2 *) _sun2bw2;
183:
184: /* lock the mutex: */
185: tme_mutex_lock(&sun2bw2->tme_sun2bw2_mutex);
186:
187: /* run the cycle: */
188: assert (cycle_init->tme_bus_cycle_address
189: >= TME_SUN2BW2_REG_MEM);
190: tme_bus_cycle_xfer_memory(cycle_init,
191: (sun2bw2->tme_sun2bw2_fb_memory
192: - TME_SUN2BW2_REG_MEM),
193: sun2bw2->tme_sun2bw2_end_address - 1);
194:
195: /* unlock the mutex: */
196: tme_mutex_unlock(&sun2bw2->tme_sun2bw2_mutex);
197:
198: /* no faults: */
199: return (TME_OK);
200: }
201:
202: /* the sun2bw2 pad bus cycle handler: */
203: static int
204: _tme_sun2bw2_bus_cycle_pad(void *_sun2bw2, struct tme_bus_cycle *cycle_init)
205: {
206: struct tme_sun2bw2 *sun2bw2;
207:
208: /* recover our data structure: */
209: sun2bw2 = (struct tme_sun2bw2 *) _sun2bw2;
210:
211: /* lock the mutex: */
212: tme_mutex_lock(&sun2bw2->tme_sun2bw2_mutex);
213:
214: /* run the cycle: */
215: assert (cycle_init->tme_bus_cycle_address
216: >= sun2bw2->tme_sun2bw2_end_address);
217: assert (sun2bw2->tme_sun2bw2_end_address
218: < TME_SUN2BW2_SIZ_MEM);
219: tme_bus_cycle_xfer_memory(cycle_init,
220: (sun2bw2->tme_sun2bw2_pad_memory
221: - sun2bw2->tme_sun2bw2_end_address),
222: ((TME_SUN2BW2_SIZ_MEM
223: - sun2bw2->tme_sun2bw2_end_address)
224: - 1));
225:
226: /* unlock the mutex: */
227: tme_mutex_unlock(&sun2bw2->tme_sun2bw2_mutex);
228:
229: /* no faults: */
230: return (TME_OK);
231: }
232:
233: /* the sun2bw2 CSR bus cycle handler: */
234: static int
235: _tme_sun2bw2_bus_cycle_csr(void *_sun2bw2, struct tme_bus_cycle *cycle_init)
236: {
237: struct tme_sun2bw2 *sun2bw2;
238: tme_uint16_t csr_old, csr_new;
239: tme_bus_addr_t undecoded;
240:
241: /* recover our data structure: */
242: sun2bw2 = (struct tme_sun2bw2 *) _sun2bw2;
243:
244: /* lock the mutex: */
245: tme_mutex_lock(&sun2bw2->tme_sun2bw2_mutex);
246:
247: /* get the old CSR value: */
248: csr_old = tme_betoh_u16(sun2bw2->tme_sun2bw2_csr);
249:
250: /* the entire 2KB (one page's) worth of addresses at
251: tme_sun2bw2_csr_address are all decoded (or, rather, not decoded)
252: as the CSR: */
253: undecoded
254: = (cycle_init->tme_bus_cycle_address
255: & (TME_SUN2BW2_SIZ_CSR_PAGE - 2));
256: cycle_init->tme_bus_cycle_address
257: -= undecoded;
258:
259: /* run the cycle: */
260: assert (cycle_init->tme_bus_cycle_address
261: >= sun2bw2->tme_sun2bw2_csr_address);
262: tme_bus_cycle_xfer_memory(cycle_init,
263: (((tme_uint8_t *) &sun2bw2->tme_sun2bw2_csr)
264: - sun2bw2->tme_sun2bw2_csr_address),
265: (sun2bw2->tme_sun2bw2_csr_address
266: + sizeof(sun2bw2->tme_sun2bw2_csr)
267: - 1));
268: cycle_init->tme_bus_cycle_address
269: += undecoded;
270:
271: /* get the new CSR value: */
272: csr_new = tme_betoh_u16(sun2bw2->tme_sun2bw2_csr);
273:
274: /* put back the unchanging bits: */
275: csr_new
276: = ((csr_new
277: & ~(TME_SUN2BW2_CSR_INT_ACTIVE
278: | TME_SUN2BW2_CSR_JUMPER_B
279: | TME_SUN2BW2_CSR_JUMPER_A
280: | TME_SUN2BW2_CSR_JUMPER_COLOR
281: | TME_SUN2BW2_CSR_JUMPER_HIRES))
282: | (csr_old
283: & (TME_SUN2BW2_CSR_INT_ACTIVE
284: | TME_SUN2BW2_CSR_JUMPER_B
285: | TME_SUN2BW2_CSR_JUMPER_A
286: | TME_SUN2BW2_CSR_JUMPER_COLOR
287: | TME_SUN2BW2_CSR_JUMPER_HIRES)));
288:
289: /* we do not support these bits: */
290: if (csr_new
291: & (TME_SUN2BW2_CSR_ENABLE_COPY
292: | TME_SUN2BW2_CSR_ENABLE_INT)) {
293: abort();
294: }
295:
296: /* set the new CSR value: */
297: sun2bw2->tme_sun2bw2_csr = tme_htobe_u16(csr_new);
298:
299: /* unlock the mutex: */
300: tme_mutex_unlock(&sun2bw2->tme_sun2bw2_mutex);
301:
302: /* no faults: */
303: return (TME_OK);
304: }
305:
306: /* the sun2bw2 TLB filler: */
307: static int
308: _tme_sun2bw2_tlb_fill(void *_sun2bw2, struct tme_bus_tlb *tlb,
309: tme_bus_addr_t address, unsigned int cycles)
310: {
311: struct tme_sun2bw2 *sun2bw2;
312:
313: /* recover our data structure: */
314: sun2bw2 = (struct tme_sun2bw2 *) _sun2bw2;
315:
316: /* initialize the TLB entry: */
317: tme_bus_tlb_initialize(tlb);
318:
319: /* if the address falls in the CSR: */
320: if ((sun2bw2->tme_sun2bw2_csr_address
321: <= address)
322: && (address
323: < (sun2bw2->tme_sun2bw2_csr_address
324: + TME_SUN2BW2_SIZ_CSR_PAGE))) {
325:
326: tlb->tme_bus_tlb_cycle = _tme_sun2bw2_bus_cycle_csr;
327:
328: /* this TLB entry covers this range: */
329: TME_ATOMIC_WRITE(tme_bus_addr_t,
330: tlb->tme_bus_tlb_addr_first,
331: sun2bw2->tme_sun2bw2_csr_address);
332: TME_ATOMIC_WRITE(tme_bus_addr_t,
333: tlb->tme_bus_tlb_addr_last,
334: (sun2bw2->tme_sun2bw2_csr_address
335: + TME_SUN2BW2_SIZ_CSR
336: - 1));
337:
338: /* this TLB entry cannot allow fast reading, since the page the
339: CSR is on isn't fully decoded - all words on the 2KB page are
340: the CSR: */
341: }
342:
343: /* if this address falls in the displayed framebuffer memory: */
344: else if ((TME_SUN2BW2_REG_MEM
345: <= address)
346: && (address
347: < sun2bw2->tme_sun2bw2_end_address)) {
348:
349: assert (sun2bw2->tme_sun2bw2_fb_connection != NULL);
350:
351: tlb->tme_bus_tlb_cycle = _tme_sun2bw2_bus_cycle_fb;
352:
353: /* this TLB entry covers this range: */
354: TME_ATOMIC_WRITE(tme_bus_addr_t,
355: tlb->tme_bus_tlb_addr_first,
356: TME_SUN2BW2_REG_MEM);
357: TME_ATOMIC_WRITE(tme_bus_addr_t,
358: tlb->tme_bus_tlb_addr_last,
359: sun2bw2->tme_sun2bw2_end_address);
360:
361: /* this TLB entry allows fast reading and writing: */
362: tlb->tme_bus_tlb_emulator_off_read
363: = (sun2bw2->tme_sun2bw2_fb_memory
364: - TME_SUN2BW2_REG_MEM);
365: tlb->tme_bus_tlb_emulator_off_write
366: = (sun2bw2->tme_sun2bw2_fb_memory
367: - TME_SUN2BW2_REG_MEM);
368: }
369:
370: /* if this address falls in the pad memory: */
371: else if ((sun2bw2->tme_sun2bw2_end_address
372: <= address)
373: && (address
374: < (TME_SUN2BW2_REG_MEM
375: + TME_SUN2BW2_SIZ_MEM))) {
376:
377: tlb->tme_bus_tlb_cycle = _tme_sun2bw2_bus_cycle_pad;
378:
379: /* this TLB entry covers this range: */
380: TME_ATOMIC_WRITE(tme_bus_addr_t,
381: tlb->tme_bus_tlb_addr_first,
382: sun2bw2->tme_sun2bw2_end_address);
383: TME_ATOMIC_WRITE(tme_bus_addr_t,
384: tlb->tme_bus_tlb_addr_last,
385: (TME_SUN2BW2_REG_MEM
386: + TME_SUN2BW2_SIZ_MEM));
387:
388: /* this TLB entry allows fast reading and writing: */
389: tlb->tme_bus_tlb_emulator_off_read
390: = (sun2bw2->tme_sun2bw2_pad_memory
391: - sun2bw2->tme_sun2bw2_end_address);
392: tlb->tme_bus_tlb_emulator_off_write
393: = (sun2bw2->tme_sun2bw2_pad_memory
394: - sun2bw2->tme_sun2bw2_end_address);
395: }
396:
397: /* the fast reading and writing rwlock: */
398: tlb->tme_bus_tlb_rwlock = &sun2bw2->tme_sun2bw2_rwlock;
399:
400: /* allow reading and writing: */
401: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
402:
403: /* our bus cycle handler private data: */
404: tlb->tme_bus_tlb_cycle_private = _sun2bw2;
405:
406: return (TME_OK);
407: }
408:
409: /* this makes a new framebuffer connection: */
410: static int
411: _tme_sun2bw2_connection_make(struct tme_connection *conn, unsigned int state)
412: {
413: struct tme_sun2bw2 *sun2bw2;
414: struct tme_fb_connection *conn_fb;
415: struct tme_fb_connection *conn_fb_other;
416: int rc;
417:
418: /* recover our data structures: */
419: sun2bw2 = conn->tme_connection_element->tme_element_private;
420: conn_fb = (struct tme_fb_connection *) conn;
421: conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other;
422:
423: /* both sides must be framebuffer connections: */
424: assert(conn->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
425: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
426:
427: /* lock our mutex: */
428: tme_mutex_lock(&sun2bw2->tme_sun2bw2_mutex);
429:
430: /* once the connection is made, we know whether or not the other
431: side of the connection is supplying specific memory that it wants
432: us to use, or if we should allocate memory ourselves: */
433: if (conn_fb->tme_fb_connection_buffer == NULL) {
434: rc = tme_fb_xlat_alloc_src(conn_fb);
435: assert (rc == TME_OK);
436: sun2bw2->tme_sun2bw2_fb_memory = conn_fb->tme_fb_connection_buffer;
437: }
438:
439: /* we're always set up to answer calls across the connection, so we
440: only have to do work when the connection has gone full, namely
441: taking the other side of the connection: */
442: if (state == TME_CONNECTION_FULL) {
443:
444: /* save our connection: */
445: sun2bw2->tme_sun2bw2_fb_connection = conn_fb_other;
446: }
447:
448: /* unlock our mutex: */
449: tme_mutex_unlock(&sun2bw2->tme_sun2bw2_mutex);
450:
451: return (TME_OK);
452: }
453:
454: /* this breaks a connection: */
455: static int
456: _tme_sun2bw2_connection_break(struct tme_connection *conn, unsigned int state)
457: {
458: abort();
459: }
460:
461: /* this makes a new connection side for a sun2bw2: */
462: static int
463: _tme_sun2bw2_connections_new(struct tme_element *element,
464: const char * const *args,
465: struct tme_connection **_conns,
466: char **_output)
467: {
468: struct tme_sun2bw2 *sun2bw2;
469: struct tme_fb_connection *conn_fb;
470: struct tme_connection *conn;
471: int rc;
472:
473: /* recover our data structure: */
474: sun2bw2 = (struct tme_sun2bw2 *) element->tme_element_private;
475:
476: /* make the generic bus device connection side: */
477: rc = tme_bus_device_connections_new(element, args, _conns, _output);
478: if (rc != TME_OK) {
479: return (rc);
480: }
481:
482: /* if we don't have a framebuffer connection, make one: */
483: if (sun2bw2->tme_sun2bw2_fb_connection == NULL) {
484:
485: /* allocate the new framebuffer connection: */
486: conn_fb = tme_new0(struct tme_fb_connection, 1);
487: conn = &conn_fb->tme_fb_connection;
488:
489: /* fill in the generic connection: */
490: conn->tme_connection_next = *_conns;
491: conn->tme_connection_type = TME_CONNECTION_FRAMEBUFFER;
492: conn->tme_connection_score = tme_fb_connection_score;
493: conn->tme_connection_make = _tme_sun2bw2_connection_make;
494: conn->tme_connection_break = _tme_sun2bw2_connection_break;
495:
496: /* fill in the framebuffer connection: */
497: conn_fb->tme_fb_connection_mode_change = NULL;
498: #ifdef TME_SUN2BW2_DEBUG
499: conn_fb->tme_fb_connection_update = _tme_sun2bw2_update_debug;
500: #else /* !TME_SUN2BW2_DEBUG */
501: conn_fb->tme_fb_connection_update = NULL;
502: #endif /* !TME_SUN2BW2_DEBUG */
503:
504: /* height and width depend on the hires jumper: */
505: if (sun2bw2->tme_sun2bw2_csr
506: & TME_SUN2BW2_CSR_JUMPER_HIRES) {
507: conn_fb->tme_fb_connection_width = TME_SUN2BW2_HI_WIDTH;
508: conn_fb->tme_fb_connection_height = TME_SUN2BW2_HI_HEIGHT;
509: }
510: else {
511: conn_fb->tme_fb_connection_width = TME_SUN2BW2_LO_WIDTH;
512: conn_fb->tme_fb_connection_height = TME_SUN2BW2_LO_HEIGHT;
513: }
514:
515: /* we are monochrome: */
516: conn_fb->tme_fb_connection_depth = 1;
517: conn_fb->tme_fb_connection_bits_per_pixel = 1;
518:
519: /* we skip no pixels at the start of the scanline: */
520: conn_fb->tme_fb_connection_skipx = 0;
521:
522: /* we pad to 32-bit boundaries: */
523: conn_fb->tme_fb_connection_scanline_pad = 32;
524:
525: /* we are big-endian: */
526: conn_fb->tme_fb_connection_order = TME_ENDIAN_BIG;
527:
528: /* we don't allocate memory until the connection is made, in case
529: the other side of the connection wants to provide us with a
530: specific memory region to use (maybe we're on a system with a
531: real bwtwo and we can write directly to its buffer): */
532: conn_fb->tme_fb_connection_buffer = NULL;
533:
534: /* return the connection side possibility: */
535: *_conns = conn;
536: }
537:
538: /* done: */
539: return (TME_OK);
540: }
541:
542: /* the new _sun2bw2 function: */
543: TME_ELEMENT_SUB_NEW_DECL(tme_machine_sun2,bwtwo) {
544: struct tme_sun2bw2 *sun2bw2;
545: struct tme_bus_subregion *subregion;
546: const char *bw2_type;
547: int arg_i;
548: int usage;
549:
550: /* check our arguments: */
551: usage = 0;
552: bw2_type = NULL;
553: arg_i = 1;
554: for (;;) {
555:
556: /* the framebuffer type: */
557: if (TME_ARG_IS(args[arg_i + 0], "type")) {
558: bw2_type = args[arg_i + 1];
559: if (bw2_type == NULL
560: || (strcmp(bw2_type, "obmem")
561: && strcmp(bw2_type, "obio"))) {
562: usage = TRUE;
563: break;
564: }
565: arg_i += 2;
566: }
567:
568: /* if we ran out of arguments: */
569: else if (args[arg_i] == NULL) {
570:
571: break;
572: }
573:
574: /* otherwise this is a bad argument: */
575: else {
576: tme_output_append_error(_output,
577: "%s %s, ",
578: args[arg_i],
579: _("unexpected"));
580: usage = TRUE;
581: break;
582: }
583: }
584:
585: if (usage) {
586: tme_output_append_error(_output,
587: "%s %s type { obmem | obio }",
588: _("usage:"),
589: args[0]);
590: return (EINVAL);
591: }
592:
593: /* start the sun2bw2 structure: */
594: sun2bw2 = tme_new0(struct tme_sun2bw2, 1);
595: sun2bw2->tme_sun2bw2_element = element;
596: tme_mutex_init(&sun2bw2->tme_sun2bw2_mutex);
597: tme_rwlock_init(&sun2bw2->tme_sun2bw2_rwlock);
598:
599: /* set our initial CSR: */
600: sun2bw2->tme_sun2bw2_csr
601: = tme_htobe_u16(TME_SUN2BW2_CSR_ENABLE_VIDEO);
602:
603: /* if we're high-resolution: */
604: if (sun2bw2->tme_sun2bw2_csr
605: & TME_SUN2BW2_CSR_JUMPER_HIRES) {
606:
607: /* set the address after the end of displayed framebuffer memory: */
608: sun2bw2->tme_sun2bw2_end_address
609: = (TME_SUN2BW2_REG_MEM
610: + (TME_SUN2BW2_HI_WIDTH
611: * TME_SUN2BW2_HI_HEIGHT
612: / 8));
613:
614: /* we don't need any pad memory: */
615: sun2bw2->tme_sun2bw2_pad_memory = NULL;
616: }
617:
618: /* otherwise, we're low-resolution: */
619: else {
620:
621: /* set the address after the end of displayed framebuffer memory: */
622: sun2bw2->tme_sun2bw2_end_address
623: = (TME_SUN2BW2_REG_MEM
624: + (TME_SUN2BW2_LO_WIDTH
625: * TME_SUN2BW2_LO_HEIGHT
626: / 8));
627:
628: /* allocate the pad memory: */
629: sun2bw2->tme_sun2bw2_pad_memory
630: = tme_new0(tme_uint8_t,
631: (TME_SUN2BW2_REG_MEM
632: + TME_SUN2BW2_SIZ_MEM
633: - sun2bw2->tme_sun2bw2_end_address));
634: }
635:
636: /* initialize our simple bus device descriptor: */
637: sun2bw2->tme_sun2bw2_device.tme_bus_device_element = element;
638: sun2bw2->tme_sun2bw2_device.tme_bus_device_tlb_fill = _tme_sun2bw2_tlb_fill;
639: subregion = &sun2bw2->tme_sun2bw2_device.tme_bus_device_subregions;
640: subregion->tme_bus_subregion_address_first
641: = TME_SUN2BW2_REG_MEM;
642: subregion->tme_bus_subregion_address_last
643: = TME_SUN2BW2_SIZ_MEM;
644: subregion->tme_bus_subregion_next
645: = (!strcmp(bw2_type, "obmem")
646: ? &_tme_sun2bw2_subregion_csr_obmem
647: : &_tme_sun2bw2_subregion_csr_obio);
648: sun2bw2->tme_sun2bw2_csr_address
649: = subregion->tme_bus_subregion_next->tme_bus_subregion_address_first;
650:
651: /* fill the element: */
652: element->tme_element_private = sun2bw2;
653: element->tme_element_connections_new = _tme_sun2bw2_connections_new;
654:
655: return (TME_OK);
656: }
657:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.