|
|
1.1 root 1: /* $Id: sun-bwtwo.c,v 1.2 2005/04/30 15:12:56 fredette Exp $ */
2:
3: /* machine/sun/sun-bwtwo.c - Sun bwtwo emulation: */
4:
5: /*
6: * Copyright (c) 2003, 2004 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: sun-bwtwo.c,v 1.2 2005/04/30 15:12:56 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: #include "sun-fb.h"
44:
45: /* macros: */
46:
47: /* bwtwo types: */
48: #define TME_SUNBW2_TYPE_NULL (0)
49: #define TME_SUNBW2_TYPE_MULTIBUS (1)
50: #define TME_SUNBW2_TYPE_OLD_ONBOARD (2)
51: #define TME_SUNBW2_TYPE_ONBOARD (3)
52: #define TME_SUNBW2_TYPE_P4 (4)
53:
54: /* register offsets and sizes: */
55: #define TME_SUNBW2_REG_CSR_MULTIBUS (0x81800)
56: #define TME_SUNBW2_REG_CSR_OLD_ONBOARD (0x20000)
57: #define TME_SUNBW2_SIZ_CSR (0x00002)
58: #define TME_SUNBW2_SIZ_CSR_PAGE (0x00800)
59: #define TME_SUNBW2_REG_P4 (0x00000)
60: #define TME_SUNBW2_SIZ_P4_PAGE (sizeof(tme_uint32_t))
61:
62: /* the bits in the Multibus and old-onboard Control/Status register: */
63: #define TME_SUNBW2_CSR_ENABLE_VIDEO (0x8000) /* enable video */
64: #define TME_SUNBW2_CSR_ENABLE_COPY (0x4000) /* enable copy mode */
65: #define TME_SUNBW2_CSR_ENABLE_INT (0x2000) /* interrupt enable */
66: #define TME_SUNBW2_CSR_INT_ACTIVE (0x1000) /* interrupt is active */
67: #define TME_SUNBW2_CSR_JUMPER_B (0x0800) /* jumper B */
68: #define TME_SUNBW2_CSR_JUMPER_A (0x0400) /* jumper A */
69: #define TME_SUNBW2_CSR_JUMPER_COLOR (0x0200) /* jumper color */
70: #define TME_SUNBW2_CSR_JUMPER_HIRES (0x0100) /* jumper hires */
71: #define TME_SUNBW2_CSR_COPYBASE_MASK (0x007E) /* copybase mask */
72:
73: #if 0
74: #define TME_SUNBW2_DEBUG
75: #endif
76:
77: /* structures: */
78:
79: /* the card: */
80: struct tme_sunbw2 {
81:
82: /* our simple bus device header: */
83: struct tme_bus_device tme_sunbw2_device;
84: #define tme_sunbw2_element tme_sunbw2_device.tme_bus_device_element
85:
86: /* the mutex protecting the card: */
87: tme_mutex_t tme_sunbw2_mutex;
88:
89: /* the rwlock protecting the card: */
90: tme_rwlock_t tme_sunbw2_rwlock;
91:
92: /* the framebuffer connection: */
93: struct tme_fb_connection *tme_sunbw2_fb_connection;
94:
95: /* the type of the bwtwo: */
96: tme_uint32_t tme_sunbw2_type;
97:
98: /* the size of the bwtwo: */
99: tme_uint32_t tme_sunbw2_size;
100:
101: /* the (relative) bus address of our csr register: */
102: tme_bus_addr_t tme_sunbw2_csr_address;
103:
104: /* the (relative) bus addresses of the first byte of framebuffer
105: memory, the last byte of displayed framebuffer memory, and the
106: last byte of framebuffer memory: */
107: tme_bus_addr_t tme_sunbw2_fb_address_first;
108: tme_bus_addr_t tme_sunbw2_fb_address_last_displayed;
109: tme_bus_addr_t tme_sunbw2_fb_address_last;
110:
111: /* the framebuffer memory: */
112: tme_uint8_t *tme_sunbw2_fb_memory;
113:
114: /* any pad memory: */
115: tme_uint8_t *tme_sunbw2_pad_memory;
116:
117: /* our csr: */
118: tme_uint16_t tme_sunbw2_csr;
119:
120: /* our P4 register: */
121: tme_uint32_t tme_sunbw2_p4;
122:
123: /* our second bus subregion: */
124: struct tme_bus_subregion tme_sunbw2_subregion1;
125: };
126:
127: #ifdef TME_SUNBW2_DEBUG
128: #define TME_SUNBW2_LO_WIDTH (1152)
129: #define TME_SUNBW2_LO_HEIGHT (900)
130: static int
131: _tme_sunbw2_update_debug(struct tme_fb_connection *conn_fb)
132: {
133: struct tme_sunbw2 *sunbw2;
134: static int y = -1;
135: static int x;
136: unsigned long pixel;
137: unsigned int pixel_byte;
138: tme_uint8_t pixel_bit;
139: int box, box_y, box_x;
140:
141: sunbw2 = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private;
142:
143: for (box = 0; box < 2; box++) {
144: if (y < 0) {
145: y = 16;
146: x = 0;
147: continue;
148: }
149: for (box_y = 0; box_y < 2; box_y++) {
150: for (box_x = 0; box_x < 2; box_x++) {
151: pixel = (((y + box_y)
152: * TME_SUNBW2_LO_WIDTH)
153: + x
154: + box_x);
155: pixel_byte = (pixel / 8);
156: pixel_bit = (0x80 >> (pixel % 8));
157: sunbw2->tme_sunbw2_fb_memory[pixel_byte] ^= pixel_bit;
158: }
159: }
160: if (box == 0) {
161: x += 2;
162: if (x == TME_SUNBW2_LO_WIDTH) {
163: x = 0;
164: y += 2;
165: if (y == TME_SUNBW2_LO_HEIGHT) {
166: y = 0;
167: }
168: }
169: }
170: }
171:
172: return (TME_OK);
173: }
174: #undef TME_SUNBW2_LO_WIDTH
175: #undef TME_SUNBW2_LO_HEIGHT
176: #endif /* TME_SUNBW2_DEBUG */
177:
178: /* the sunbw2 framebuffer bus cycle handler: */
179: static int
180: _tme_sunbw2_bus_cycle_fb(void *_sunbw2, struct tme_bus_cycle *cycle_init)
181: {
182: struct tme_sunbw2 *sunbw2;
183:
184: /* recover our data structure: */
185: sunbw2 = (struct tme_sunbw2 *) _sunbw2;
186:
187: /* lock the mutex: */
188: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex);
189:
190: /* run the cycle: */
191: assert (cycle_init->tme_bus_cycle_address
192: >= sunbw2->tme_sunbw2_fb_address_first);
193: tme_bus_cycle_xfer_memory(cycle_init,
194: (sunbw2->tme_sunbw2_fb_memory
195: - sunbw2->tme_sunbw2_fb_address_first),
196: sunbw2->tme_sunbw2_fb_address_last_displayed);
197:
198: /* unlock the mutex: */
199: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex);
200:
201: /* no faults: */
202: return (TME_OK);
203: }
204:
205: /* the sunbw2 pad bus cycle handler: */
206: static int
207: _tme_sunbw2_bus_cycle_pad(void *_sunbw2, struct tme_bus_cycle *cycle_init)
208: {
209: struct tme_sunbw2 *sunbw2;
210:
211: /* recover our data structure: */
212: sunbw2 = (struct tme_sunbw2 *) _sunbw2;
213:
214: /* lock the mutex: */
215: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex);
216:
217: /* run the cycle: */
218: assert (cycle_init->tme_bus_cycle_address
219: > sunbw2->tme_sunbw2_fb_address_last_displayed);
220: tme_bus_cycle_xfer_memory(cycle_init,
221: (sunbw2->tme_sunbw2_pad_memory
222: - (sunbw2->tme_sunbw2_fb_address_last_displayed
223: + 1)),
224: sunbw2->tme_sunbw2_fb_address_last);
225:
226: /* unlock the mutex: */
227: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex);
228:
229: /* no faults: */
230: return (TME_OK);
231: }
232:
233: /* the sunbw2 CSR bus cycle handler: */
234: static int
235: _tme_sunbw2_bus_cycle_csr(void *_sunbw2, struct tme_bus_cycle *cycle_init)
236: {
237: struct tme_sunbw2 *sunbw2;
238: tme_uint16_t csr_old, csr_new;
239: tme_bus_addr_t undecoded;
240:
241: /* recover our data structure: */
242: sunbw2 = (struct tme_sunbw2 *) _sunbw2;
243:
244: /* lock the mutex: */
245: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex);
246:
247: /* get the old CSR value: */
248: csr_old = tme_betoh_u16(sunbw2->tme_sunbw2_csr);
249:
250: /* the entire 2KB (one page's) worth of addresses at
251: tme_sunbw2_csr_address are all decoded (or, rather, not decoded)
252: as the CSR: */
253: undecoded
254: = (cycle_init->tme_bus_cycle_address
255: & (TME_SUNBW2_SIZ_CSR_PAGE - sizeof(sunbw2->tme_sunbw2_csr)));
256: cycle_init->tme_bus_cycle_address
257: -= undecoded;
258:
259: /* run the cycle: */
260: assert (cycle_init->tme_bus_cycle_address
261: >= sunbw2->tme_sunbw2_csr_address);
262: tme_bus_cycle_xfer_memory(cycle_init,
263: (((tme_uint8_t *) &sunbw2->tme_sunbw2_csr)
264: - sunbw2->tme_sunbw2_csr_address),
265: (sunbw2->tme_sunbw2_csr_address
266: + sizeof(sunbw2->tme_sunbw2_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(sunbw2->tme_sunbw2_csr);
273:
274: /* put back the unchanging bits: */
275: csr_new
276: = ((csr_new
277: & ~(TME_SUNBW2_CSR_INT_ACTIVE
278: | TME_SUNBW2_CSR_JUMPER_B
279: | TME_SUNBW2_CSR_JUMPER_A
280: | TME_SUNBW2_CSR_JUMPER_COLOR
281: | TME_SUNBW2_CSR_JUMPER_HIRES))
282: | (csr_old
283: & (TME_SUNBW2_CSR_INT_ACTIVE
284: | TME_SUNBW2_CSR_JUMPER_B
285: | TME_SUNBW2_CSR_JUMPER_A
286: | TME_SUNBW2_CSR_JUMPER_COLOR
287: | TME_SUNBW2_CSR_JUMPER_HIRES)));
288:
289: /* we do not support these bits: */
290: if (csr_new
291: & (TME_SUNBW2_CSR_ENABLE_COPY
292: | TME_SUNBW2_CSR_ENABLE_INT)) {
293: abort();
294: }
295:
296: /* set the new CSR value: */
297: sunbw2->tme_sunbw2_csr = tme_htobe_u16(csr_new);
298:
299: /* unlock the mutex: */
300: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex);
301:
302: /* no faults: */
303: return (TME_OK);
304: }
305:
306: /* the sunbw2 P4 bus cycle handler: */
307: static int
308: _tme_sunbw2_bus_cycle_p4(void *_sunbw2, struct tme_bus_cycle *cycle_init)
309: {
310: struct tme_sunbw2 *sunbw2;
311: tme_uint32_t p4_old, p4_new;
312: tme_bus_addr_t undecoded;
313:
314: /* recover our data structure: */
315: sunbw2 = (struct tme_sunbw2 *) _sunbw2;
316:
317: /* lock the mutex: */
318: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex);
319:
320: /* get the old P4 value: */
321: p4_old = tme_betoh_u32(sunbw2->tme_sunbw2_p4);
322:
323: /* the entire ?KB (one page's) worth of addresses at
324: TME_SUNBW2_REG_P4 are all decoded (or, rather, not decoded)
325: as the P4: */
326: undecoded
327: = (cycle_init->tme_bus_cycle_address
328: & (TME_SUNBW2_SIZ_P4_PAGE - sizeof(sunbw2->tme_sunbw2_p4)));
329: cycle_init->tme_bus_cycle_address
330: -= undecoded;
331:
332: /* run the cycle: */
333: assert (cycle_init->tme_bus_cycle_address
334: >= TME_SUNBW2_REG_P4);
335: tme_bus_cycle_xfer_memory(cycle_init,
336: (((tme_uint8_t *) &sunbw2->tme_sunbw2_p4)
337: - TME_SUNBW2_REG_P4),
338: (TME_SUNBW2_REG_P4
339: + sizeof(sunbw2->tme_sunbw2_p4)
340: - 1));
341: cycle_init->tme_bus_cycle_address
342: += undecoded;
343:
344: /* get the new P4 value: */
345: p4_new = tme_betoh_u32(sunbw2->tme_sunbw2_p4);
346:
347: /* put back the unchanging bits: */
348: p4_new
349: = ((p4_new
350: & ~TME_SUN_P4_RO_MASK)
351: | (p4_old
352: & TME_SUN_P4_RO_MASK));
353:
354: /* we do not support these bits: */
355: if (p4_new
356: & (TME_SUN_P4_REG_SYNC_RAMDAC
357: | TME_SUN_P4_REG_ENABLE_INT)) {
358: abort();
359: }
360:
361: /* set the new P4 value: */
362: sunbw2->tme_sunbw2_p4 = tme_htobe_u32(p4_new);
363:
364: /* unlock the mutex: */
365: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex);
366:
367: /* no faults: */
368: return (TME_OK);
369: }
370:
371: /* the sunbw2 TLB filler: */
372: static int
373: _tme_sunbw2_tlb_fill(void *_sunbw2, struct tme_bus_tlb *tlb,
374: tme_bus_addr_t address, unsigned int cycles)
375: {
376: struct tme_sunbw2 *sunbw2;
377:
378: /* recover our data structure: */
379: sunbw2 = (struct tme_sunbw2 *) _sunbw2;
380:
381: /* initialize the TLB entry: */
382: tme_bus_tlb_initialize(tlb);
383:
384: /* if this is a Multibus or old-onboard bwtwo, and the address falls in the CSR: */
385: if (((sunbw2->tme_sunbw2_type
386: == TME_SUNBW2_TYPE_MULTIBUS)
387: || (sunbw2->tme_sunbw2_type
388: == TME_SUNBW2_TYPE_OLD_ONBOARD))
389: && (sunbw2->tme_sunbw2_csr_address
390: <= address)
391: && (address
392: < (sunbw2->tme_sunbw2_csr_address
393: + TME_SUNBW2_SIZ_CSR_PAGE))) {
394:
395: tlb->tme_bus_tlb_cycle = _tme_sunbw2_bus_cycle_csr;
396:
397: /* this TLB entry covers this range: */
398: TME_ATOMIC_WRITE(tme_bus_addr_t,
399: tlb->tme_bus_tlb_addr_first,
400: sunbw2->tme_sunbw2_csr_address);
401: TME_ATOMIC_WRITE(tme_bus_addr_t,
402: tlb->tme_bus_tlb_addr_last,
403: (sunbw2->tme_sunbw2_csr_address
404: + TME_SUNBW2_SIZ_CSR
405: - 1));
406:
407: /* this TLB entry cannot allow fast reading, since the page the
408: CSR is on isn't fully decoded - all words on the 2KB page are
409: the CSR: */
410: }
411:
412: /* if this is a P4 bwtwo, and the address falls in the P4 register: */
413: else if ((sunbw2->tme_sunbw2_type
414: == TME_SUNBW2_TYPE_P4)
415: && (address
416: < (TME_SUNBW2_REG_P4
417: + TME_SUNBW2_SIZ_P4_PAGE))) {
418:
419: tlb->tme_bus_tlb_cycle = _tme_sunbw2_bus_cycle_p4;
420:
421: /* this TLB entry covers this range: */
422: TME_ATOMIC_WRITE(tme_bus_addr_t,
423: tlb->tme_bus_tlb_addr_first,
424: TME_SUNBW2_REG_P4);
425: TME_ATOMIC_WRITE(tme_bus_addr_t,
426: tlb->tme_bus_tlb_addr_last,
427: (TME_SUNBW2_REG_P4
428: + TME_SUNBW2_SIZ_P4_PAGE
429: - 1));
430:
431: /* this TLB entry cannot allow fast reading, since the page the
432: P4 register is on isn't fully decoded - all words on the ?KB page are
433: the P4 register: */
434: }
435:
436: /* if this address falls in the displayed framebuffer memory: */
437: else if ((sunbw2->tme_sunbw2_fb_address_first
438: <= address)
439: && (address
440: <= sunbw2->tme_sunbw2_fb_address_last_displayed)) {
441:
442: assert (sunbw2->tme_sunbw2_fb_connection != NULL);
443:
444: tlb->tme_bus_tlb_cycle = _tme_sunbw2_bus_cycle_fb;
445:
446: /* this TLB entry covers this range: */
447: TME_ATOMIC_WRITE(tme_bus_addr_t,
448: tlb->tme_bus_tlb_addr_first,
449: sunbw2->tme_sunbw2_fb_address_first);
450: TME_ATOMIC_WRITE(tme_bus_addr_t,
451: tlb->tme_bus_tlb_addr_last,
452: sunbw2->tme_sunbw2_fb_address_last_displayed);
453:
454: /* this TLB entry allows fast reading and writing: */
455: tlb->tme_bus_tlb_emulator_off_read
456: = (sunbw2->tme_sunbw2_fb_memory
457: - sunbw2->tme_sunbw2_fb_address_first);
458: tlb->tme_bus_tlb_emulator_off_write
459: = (sunbw2->tme_sunbw2_fb_memory
460: - sunbw2->tme_sunbw2_fb_address_first);
461: }
462:
463: /* if this address falls in the pad memory: */
464: else if ((sunbw2->tme_sunbw2_fb_address_last_displayed
465: < address)
466: && (address
467: <= sunbw2->tme_sunbw2_fb_address_last)) {
468:
469: tlb->tme_bus_tlb_cycle = _tme_sunbw2_bus_cycle_pad;
470:
471: /* this TLB entry covers this range: */
472: TME_ATOMIC_WRITE(tme_bus_addr_t,
473: tlb->tme_bus_tlb_addr_first,
474: (sunbw2->tme_sunbw2_fb_address_last_displayed
475: + 1));
476: TME_ATOMIC_WRITE(tme_bus_addr_t,
477: tlb->tme_bus_tlb_addr_last,
478: sunbw2->tme_sunbw2_fb_address_last);
479:
480: /* this TLB entry allows fast reading and writing: */
481: tlb->tme_bus_tlb_emulator_off_read
482: = (sunbw2->tme_sunbw2_pad_memory
483: - (sunbw2->tme_sunbw2_fb_address_last_displayed
484: + 1));
485: tlb->tme_bus_tlb_emulator_off_write
486: = (sunbw2->tme_sunbw2_pad_memory
487: - (sunbw2->tme_sunbw2_fb_address_last_displayed
488: + 1));
489: }
490:
491: /* the fast reading and writing rwlock: */
492: tlb->tme_bus_tlb_rwlock = &sunbw2->tme_sunbw2_rwlock;
493:
494: /* allow reading and writing: */
495: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
496:
497: /* our bus cycle handler private data: */
498: tlb->tme_bus_tlb_cycle_private = _sunbw2;
499:
500: return (TME_OK);
501: }
502:
503: /* this makes a new framebuffer connection: */
504: static int
505: _tme_sunbw2_connection_make(struct tme_connection *conn, unsigned int state)
506: {
507: struct tme_sunbw2 *sunbw2;
508: struct tme_fb_connection *conn_fb;
509: struct tme_fb_connection *conn_fb_other;
510: int rc;
511:
512: /* recover our data structures: */
513: sunbw2 = conn->tme_connection_element->tme_element_private;
514: conn_fb = (struct tme_fb_connection *) conn;
515: conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other;
516:
517: /* both sides must be framebuffer connections: */
518: assert(conn->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
519: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_FRAMEBUFFER);
520:
521: /* lock our mutex: */
522: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex);
523:
524: /* once the connection is made, we know whether or not the other
525: side of the connection is supplying specific memory that it wants
526: us to use, or if we should allocate memory ourselves: */
527: if (conn_fb->tme_fb_connection_buffer == NULL) {
528: rc = tme_fb_xlat_alloc_src(conn_fb);
529: assert (rc == TME_OK);
530: }
531: sunbw2->tme_sunbw2_fb_memory = conn_fb->tme_fb_connection_buffer;
532:
533: /* we're always set up to answer calls across the connection, so we
534: only have to do work when the connection has gone full, namely
535: taking the other side of the connection: */
536: if (state == TME_CONNECTION_FULL) {
537:
538: /* save our connection: */
539: sunbw2->tme_sunbw2_fb_connection = conn_fb_other;
540: }
541:
542: /* unlock our mutex: */
543: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex);
544:
545: return (TME_OK);
546: }
547:
548: /* this breaks a connection: */
549: static int
550: _tme_sunbw2_connection_break(struct tme_connection *conn, unsigned int state)
551: {
552: abort();
553: }
554:
555: /* this makes a new connection side for a sunbw2: */
556: static int
557: _tme_sunbw2_connections_new(struct tme_element *element,
558: const char * const *args,
559: struct tme_connection **_conns,
560: char **_output)
561: {
562: struct tme_sunbw2 *sunbw2;
563: struct tme_fb_connection *conn_fb;
564: struct tme_connection *conn;
565: int rc;
566:
567: /* recover our data structure: */
568: sunbw2 = (struct tme_sunbw2 *) element->tme_element_private;
569:
570: /* make the generic bus device connection side: */
571: rc = tme_bus_device_connections_new(element, args, _conns, _output);
572: if (rc != TME_OK) {
573: return (rc);
574: }
575:
576: /* if we don't have a framebuffer connection, make one: */
577: if (sunbw2->tme_sunbw2_fb_connection == NULL) {
578:
579: /* allocate the new framebuffer connection: */
580: conn_fb = tme_new0(struct tme_fb_connection, 1);
581: conn = &conn_fb->tme_fb_connection;
582:
583: /* fill in the generic connection: */
584: conn->tme_connection_next = *_conns;
585: conn->tme_connection_type = TME_CONNECTION_FRAMEBUFFER;
586: conn->tme_connection_score = tme_fb_connection_score;
587: conn->tme_connection_make = _tme_sunbw2_connection_make;
588: conn->tme_connection_break = _tme_sunbw2_connection_break;
589:
590: /* fill in the framebuffer connection: */
591: conn_fb->tme_fb_connection_mode_change = NULL;
592: #ifdef TME_SUNBW2_DEBUG
593: conn_fb->tme_fb_connection_update = _tme_sunbw2_update_debug;
594: #else /* !TME_SUNBW2_DEBUG */
595: conn_fb->tme_fb_connection_update = NULL;
596: #endif /* !TME_SUNBW2_DEBUG */
597:
598: /* height and width: */
599: conn_fb->tme_fb_connection_width = tme_sun_fb_p4_size_width(sunbw2->tme_sunbw2_size);
600: conn_fb->tme_fb_connection_height = tme_sun_fb_p4_size_height(sunbw2->tme_sunbw2_size);
601:
602: /* we are monochrome: */
603: conn_fb->tme_fb_connection_class = TME_FB_XLAT_CLASS_MONOCHROME;
604: conn_fb->tme_fb_connection_depth = 1;
605: conn_fb->tme_fb_connection_bits_per_pixel = 1;
606:
607: /* we skip no pixels at the start of the scanline: */
608: conn_fb->tme_fb_connection_skipx = 0;
609:
610: /* we pad to 32-bit boundaries: */
611: conn_fb->tme_fb_connection_scanline_pad = 32;
612:
613: /* we are big-endian: */
614: conn_fb->tme_fb_connection_order = TME_ENDIAN_BIG;
615:
616: /* we don't allocate memory until the connection is made, in case
617: the other side of the connection wants to provide us with a
618: specific memory region to use (maybe we're on a system with a
619: real bwtwo and we can write directly to its buffer): */
620: conn_fb->tme_fb_connection_buffer = NULL;
621:
622: /* our pixels don't have subfields: */
623: conn_fb->tme_fb_connection_mask_g = 0;
624: conn_fb->tme_fb_connection_mask_r = 0;
625: conn_fb->tme_fb_connection_mask_b = 0;
626:
627: /* intensities are a single bit, linearly mapped, but inverted: */
628: conn_fb->tme_fb_connection_map_bits = 1;
629: conn_fb->tme_fb_connection_map_g = NULL;
630: conn_fb->tme_fb_connection_map_r = NULL;
631: conn_fb->tme_fb_connection_map_b = NULL;
632: conn_fb->tme_fb_connection_inverted = TRUE;
633:
634: /* return the connection side possibility: */
635: *_conns = conn;
636: }
637:
638: /* done: */
639: return (TME_OK);
640: }
641:
642: /* the new sun bwtwo function: */
643: int
644: tme_sun_bwtwo(struct tme_element *element, const char * const *args, char **_output)
645: {
646: struct tme_sunbw2 *sunbw2;
647: struct tme_bus_subregion *fb_subregion;
648: struct tme_bus_subregion *reg_subregion;
649: tme_uint32_t bw2_type;
650: tme_uint32_t bw2_size;
651: tme_bus_addr_t fb_size;
652: int arg_i;
653: int usage;
654:
655: /* check our arguments: */
656: usage = 0;
657: bw2_type = TME_SUNBW2_TYPE_NULL;
658: bw2_size = TME_SUN_P4_SIZE_1152_900;
659: arg_i = 1;
660: for (;;) {
661:
662: /* the framebuffer type: */
663: if (TME_ARG_IS(args[arg_i + 0], "type")) {
664: if (TME_ARG_IS(args[arg_i + 1], "multibus")) {
665: bw2_type = TME_SUNBW2_TYPE_MULTIBUS;
666: }
667: else if (TME_ARG_IS(args[arg_i + 1], "old-onboard")) {
668: bw2_type = TME_SUNBW2_TYPE_OLD_ONBOARD;
669: }
670: else if (TME_ARG_IS(args[arg_i + 1], "onboard")) {
671: bw2_type = TME_SUNBW2_TYPE_ONBOARD;
672: }
673: else if (TME_ARG_IS(args[arg_i + 1], "P4")) {
674: bw2_type = TME_SUNBW2_TYPE_P4;
675: }
676: else {
677: usage = TRUE;
678: break;
679: }
680: arg_i += 2;
681: }
682:
683: /* the framebuffer size: */
684: else if (TME_ARG_IS(args[arg_i + 0], "size")) {
685: bw2_size = tme_sun_fb_p4_size(args[arg_i + 1]);
686: if (bw2_size == TME_SUN_P4_SIZE_NULL) {
687: usage = TRUE;
688: break;
689: }
690: arg_i += 2;
691: }
692:
693: /* if we ran out of arguments: */
694: else if (args[arg_i] == NULL) {
695:
696: break;
697: }
698:
699: /* otherwise this is a bad argument: */
700: else {
701: tme_output_append_error(_output,
702: "%s %s, ",
703: args[arg_i],
704: _("unexpected"));
705: usage = TRUE;
706: break;
707: }
708: }
709:
710: /* dispatch on the bwtwo type to check that it and the size are
711: valid: */
712: switch (bw2_type) {
713:
714: /* no bwtwo type was specified: */
715: case TME_SUNBW2_TYPE_NULL:
716: /* XXX TBD */
717: usage = TRUE;
718: break;
719:
720: /* the original Multibus bwtwo and onboard bwtwo only support
721: 1152x900 and 1024x1024: */
722: case TME_SUNBW2_TYPE_MULTIBUS:
723: case TME_SUNBW2_TYPE_OLD_ONBOARD:
724: if (bw2_size != TME_SUN_P4_SIZE_1152_900
725: && bw2_size != TME_SUN_P4_SIZE_1024_1024) {
726: /* XXX TBD */
727: usage = TRUE;
728: }
729: break;
730:
731: /* the sizes supported by a CSR-less bwtwo appear to depend on the
732: actual model; we assume the user knows what he is doing: */
733: case TME_SUNBW2_TYPE_ONBOARD:
734: break;
735:
736: /* we allow creating a P4 bwtwo with any of the P4 sizes, again
737: assuming that the user knows what he is doing: */
738: case TME_SUNBW2_TYPE_P4:
739: break;
740:
741: default:
742: assert(FALSE);
743: break;
744: }
745:
746: if (usage) {
747: tme_output_append_error(_output,
748: "%s %s type { multibus | old-onboard | onboard | P4 } [ size { 1600x1280 | 1152x900 | 1024x1024 | 1280x1024 | 1440x1440 | 640x480 } ]",
749: _("usage:"),
750: args[0]);
751: return (EINVAL);
752: }
753:
754: /* start the sunbw2 structure: */
755: sunbw2 = tme_new0(struct tme_sunbw2, 1);
756: sunbw2->tme_sunbw2_element = element;
757: tme_mutex_init(&sunbw2->tme_sunbw2_mutex);
758: tme_rwlock_init(&sunbw2->tme_sunbw2_rwlock);
759:
760: /* set the bwtwo type: */
761: sunbw2->tme_sunbw2_type = bw2_type;
762:
763: /* set the bwtwo size: */
764: sunbw2->tme_sunbw2_size = bw2_size;
765:
766: /* assume the (relative) bus address of the first byte of displayed
767: framebuffer memory: */
768: sunbw2->tme_sunbw2_fb_address_first = 0;
769:
770: /* assume that the number of bytes of framebuffer memory is the
771: minimum number of bytes required, rounded up to the nearest power
772: of two: */
773: fb_size = ((tme_sun_fb_p4_size_width(bw2_size)
774: * tme_sun_fb_p4_size_height(bw2_size))
775: / 8);
776: if ((fb_size & (fb_size - 1)) != 0) {
777: for (; (fb_size & (fb_size - 1)) != 0; fb_size &= (fb_size - 1));
778: fb_size <<= 1;
779: }
780:
781: /* assume that we will attach to two bus subregions, and that the
782: framebuffer memory will be first: */
783: fb_subregion = &sunbw2->tme_sunbw2_device.tme_bus_device_subregions;
784: fb_subregion->tme_bus_subregion_next = &sunbw2->tme_sunbw2_subregion1;
785: sunbw2->tme_sunbw2_subregion1.tme_bus_subregion_next = NULL;
786:
787: /* dispatch on the bwtwo type: */
788: switch (bw2_type) {
789: case TME_SUNBW2_TYPE_MULTIBUS:
790: case TME_SUNBW2_TYPE_OLD_ONBOARD:
791:
792: /* set our initial CSR: */
793: sunbw2->tme_sunbw2_csr
794: = tme_htobe_u16(TME_SUNBW2_CSR_ENABLE_VIDEO
795: | (bw2_size == TME_SUN_P4_SIZE_1024_1024
796: ? TME_SUNBW2_CSR_JUMPER_HIRES
797: : 0));
798:
799: /* set our CSR address: */
800: sunbw2->tme_sunbw2_csr_address
801: = (bw2_type == TME_SUNBW2_TYPE_MULTIBUS
802: ? TME_SUNBW2_REG_CSR_MULTIBUS
803: : TME_SUNBW2_REG_CSR_OLD_ONBOARD);
804:
805: /* our second bus subregion is for the CSR: */
806: reg_subregion = &sunbw2->tme_sunbw2_subregion1;
807: reg_subregion->tme_bus_subregion_address_first
808: = sunbw2->tme_sunbw2_csr_address;
809: reg_subregion->tme_bus_subregion_address_last
810: = (reg_subregion->tme_bus_subregion_address_first
811: + TME_SUNBW2_SIZ_CSR_PAGE
812: - 1);
813: break;
814:
815: case TME_SUNBW2_TYPE_ONBOARD:
816:
817: /* we attach to only one bus subregion: */
818: fb_subregion->tme_bus_subregion_next = NULL;
819: break;
820:
821: case TME_SUNBW2_TYPE_P4:
822:
823: /* set our initial P4 register: */
824: sunbw2->tme_sunbw2_p4
825: = tme_htobe_u16(TME_SUN_P4_ID_BWTWO
826: | bw2_size
827: | TME_SUN_P4_REG_ENABLE_VIDEO);
828:
829: /* the framebuffer memory begins at a fixed offset after the P4 register: */
830: sunbw2->tme_sunbw2_fb_address_first = TME_SUN_P4_OFFSET_BWTWO;
831:
832: /* we attach the P4 register first, and the framebuffer memory second: */
833: reg_subregion = &sunbw2->tme_sunbw2_device.tme_bus_device_subregions;
834: fb_subregion = &sunbw2->tme_sunbw2_subregion1;
835: reg_subregion->tme_bus_subregion_address_first = 0;
836: reg_subregion->tme_bus_subregion_address_last
837: = (reg_subregion->tme_bus_subregion_address_first
838: + sizeof(sunbw2->tme_sunbw2_p4)
839: - 1);
840: break;
841: }
842:
843: /* set the (relative) bus address of the last byte of displayed
844: framebuffer memory: */
845: sunbw2->tme_sunbw2_fb_address_last_displayed
846: = (sunbw2->tme_sunbw2_fb_address_first
847: + ((tme_sun_fb_p4_size_width(bw2_size)
848: * tme_sun_fb_p4_size_height(bw2_size))
849: / 8)
850: - 1);
851:
852: /* set the (relative) bus address of the last byte of framebuffer
853: memory: */
854: sunbw2->tme_sunbw2_fb_address_last
855: = (sunbw2->tme_sunbw2_fb_address_first
856: + fb_size
857: - 1);
858:
859: /* finish the framebuffer memory subregion: */
860: fb_subregion->tme_bus_subregion_address_first
861: = sunbw2->tme_sunbw2_fb_address_first;
862: fb_subregion->tme_bus_subregion_address_last
863: = sunbw2->tme_sunbw2_fb_address_last;
864:
865: /* assume that we don't need any pad (undisplayed) framebuffer memory: */
866: sunbw2->tme_sunbw2_pad_memory = NULL;
867: assert (sunbw2->tme_sunbw2_fb_address_last
868: >= sunbw2->tme_sunbw2_fb_address_last_displayed);
869:
870: /* if we need to, allocate pad (undisplayed) framebuffer memory: */
871: if (sunbw2->tme_sunbw2_fb_address_last
872: > sunbw2->tme_sunbw2_fb_address_last_displayed) {
873:
874: /* allocate the pad memory: */
875: sunbw2->tme_sunbw2_pad_memory
876: = tme_new0(tme_uint8_t,
877: (sunbw2->tme_sunbw2_fb_address_last
878: - sunbw2->tme_sunbw2_fb_address_last_displayed));
879: }
880:
881: /* initialize our simple bus device descriptor: */
882: sunbw2->tme_sunbw2_device.tme_bus_device_element = element;
883: sunbw2->tme_sunbw2_device.tme_bus_device_tlb_fill = _tme_sunbw2_tlb_fill;
884:
885: /* fill the element: */
886: element->tme_element_private = sunbw2;
887: element->tme_element_connections_new = _tme_sunbw2_connections_new;
888:
889: return (TME_OK);
890: }
891:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.