/[gxemul]/upstream/0.3.6.1/src/devices/dev_sgi_ip32.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /upstream/0.3.6.1/src/devices/dev_sgi_ip32.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 17 - (hide annotations)
Mon Oct 8 16:19:05 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 33110 byte(s)
0.3.6.1
1 dpavlin 4 /*
2     * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 14 * $Id: dev_sgi_ip32.c,v 1.32 2005/08/19 09:43:35 debug Exp $
29 dpavlin 4 *
30     * SGI IP32 devices.
31     *
32     * o) CRIME
33     * o) MACE
34     * o) MACE PCI bus
35     * o) mec (ethernet)
36     * o) ust (unknown device)
37     * o) mte (memory transfer engine? details unknown)
38     */
39    
40     #include <stdio.h>
41     #include <stdlib.h>
42     #include <string.h>
43    
44     #include "bus_pci.h"
45     #include "console.h"
46     #include "cpu.h"
47     #include "devices.h"
48     #include "emul.h"
49     #include "machine.h"
50     #include "memory.h"
51     #include "misc.h"
52     #include "net.h"
53    
54     #include "crimereg.h"
55    
56     #include "if_mecreg.h"
57    
58    
59     #define CRIME_TICKSHIFT 14
60     #define CRIME_SPEED_MUL_FACTOR 1
61     #define CRIME_SPEED_DIV_FACTOR 1
62    
63     struct macepci_data {
64     struct pci_data *pci_data;
65     uint32_t reg[DEV_MACEPCI_LENGTH / 4];
66     };
67    
68    
69     /*
70     * dev_crime_tick():
71     *
72     * This function simply updates CRIME_TIME each tick.
73     *
74     * The names DIV and MUL may be a bit confusing. Increasing the
75     * MUL factor will result in an OS running on the emulated machine
76     * detecting a faster CPU. Increasing the DIV factor will result
77     * in a slower detected CPU.
78     *
79     * A R10000 is detected as running at
80     * CRIME_SPEED_FACTOR * 66 MHz. (TODO: this is not correct anymore)
81     */
82     void dev_crime_tick(struct cpu *cpu, void *extra)
83     {
84     int j, carry, old, new, add_byte;
85     uint64_t what_to_add = (1<<CRIME_TICKSHIFT)
86     * CRIME_SPEED_DIV_FACTOR / CRIME_SPEED_MUL_FACTOR;
87     struct crime_data *d = extra;
88    
89     j = 0;
90     carry = 0;
91     while (j < 8) {
92     old = d->reg[CRIME_TIME + 7 - j];
93     add_byte = what_to_add >> ((int64_t)j * 8);
94     add_byte &= 255;
95     new = old + add_byte + carry;
96     d->reg[CRIME_TIME + 7 - j] = new & 255;
97     if (new >= 256)
98     carry = 1;
99     else
100     carry = 0;
101     j++;
102     }
103     }
104    
105    
106     /*
107     * dev_crime_access():
108     */
109     int dev_crime_access(struct cpu *cpu, struct memory *mem,
110     uint64_t relative_addr, unsigned char *data, size_t len,
111     int writeflag, void *extra)
112     {
113     int i;
114     struct crime_data *d = extra;
115     uint64_t idata;
116    
117     idata = memory_readmax64(cpu, data, len);
118    
119     /*
120     * Set crime version/revision:
121     *
122     * This might not be the most elegant or correct solution,
123     * but it seems that the IP32 PROM likes 0x11 for machines
124     * without graphics, and 0xa1 for machines with graphics.
125     *
126     * NetBSD 2.0 complains about "unknown" crime for 0x11,
127     * but I guess that's something one has to live with.
128     *
129     * (TODO?)
130     */
131     d->reg[4] = 0x00; d->reg[5] = 0x00; d->reg[6] = 0x00;
132     d->reg[7] = d->use_fb? 0xa1 : 0x11;
133    
134     /*
135     * Amount of memory. Bit 8 of bank control set ==> 128MB instead
136     * of 32MB per bank (?)
137     *
138     * When the bank control registers contain the same value as the
139     * previous one, that bank is not valid. (?)
140     */
141     d->reg[CRM_MEM_BANK_CTRL0 + 6] = 0; /* lowbit set=128MB, clear=32MB */
142     d->reg[CRM_MEM_BANK_CTRL0 + 7] = 0; /* address * 32MB */
143     d->reg[CRM_MEM_BANK_CTRL1 + 6] = 0; /* lowbit set=128MB, clear=32MB */
144     d->reg[CRM_MEM_BANK_CTRL1 + 7] = 1; /* address * 32MB */
145    
146     if (relative_addr >= CRIME_TIME && relative_addr < CRIME_TIME+8) {
147     if (writeflag == MEM_READ)
148     memcpy(data, &d->reg[relative_addr], len);
149     return 1;
150     }
151    
152     if (writeflag == MEM_WRITE)
153     memcpy(&d->reg[relative_addr], data, len);
154     else
155     memcpy(data, &d->reg[relative_addr], len);
156    
157 dpavlin 10 if ((relative_addr >= 0x18 && relative_addr <= 0x1f) ||
158     (relative_addr+len-1 >= 0x18 && relative_addr+len-1 <= 0x1f)) {
159 dpavlin 4 /*
160     * Force interrupt re-assertion:
161     *
162     * NOTE: Ugly hack. Hopefully CRMERR is never used.
163     */
164     #if 0
165 dpavlin 10 /*
166 dpavlin 4 No. If this is enabled, the mec bugs out on either NetBSD or OpenBSD.
167     TODO.
168 dpavlin 10 */
169 dpavlin 4 cpu_interrupt_ack(cpu, 8); /* CRM_INT_CRMERR); */
170     #endif
171     }
172    
173     switch (relative_addr) {
174     case CRIME_CONTROL: /* 0x008 */
175     /* TODO: 64-bit write to CRIME_CONTROL, but some things
176     (such as NetBSD 1.6.2) write to 0x00c! */
177     if (writeflag == MEM_WRITE) {
178     /*
179     * 0x200 = watchdog timer (according to NetBSD)
180     * 0x800 = "reboot" used by the IP32 PROM
181     */
182     if (idata & 0x200) {
183     idata &= ~0x200;
184     }
185     if (idata & 0x800) {
186     /* This is used by the IP32 PROM's
187     "reboot" command: */
188     for (i=0; i<cpu->machine->ncpus; i++)
189     cpu->machine->cpus[i]->running = 0;
190     cpu->machine->
191     exit_without_entering_debugger = 1;
192     idata &= ~0x800;
193     }
194     if (idata != 0)
195     fatal("[ CRIME_CONTROL: unimplemented "
196     "control 0x%016llx ]\n", (long long)idata);
197     }
198     break;
199 dpavlin 10 #if 0
200 dpavlin 4 case CRIME_INTSTAT: /* 0x010, Current interrupt status */
201     case 0x14:
202     case CRIME_INTMASK: /* 0x018, Current interrupt mask */
203     case 0x1c:
204     case 0x34:
205     /* don't dump debug info for these */
206     break;
207 dpavlin 10 #endif
208 dpavlin 4 default:
209     if (writeflag==MEM_READ) {
210     debug("[ crime: read from 0x%x, len=%i:",
211     (int)relative_addr, len);
212     for (i=0; i<len; i++)
213     debug(" %02x", data[i]);
214     debug(" ]\n");
215     } else {
216     debug("[ crime: write to 0x%x:", (int)relative_addr);
217     for (i=0; i<len; i++)
218     debug(" %02x", data[i]);
219     debug(" (len=%i) ]\n", len);
220     }
221     }
222    
223     return 1;
224     }
225    
226    
227     /*
228     * dev_crime_init():
229     */
230     struct crime_data *dev_crime_init(struct machine *machine, struct memory *mem,
231     uint64_t baseaddr, int irq_nr, int use_fb)
232     {
233     struct crime_data *d;
234    
235     d = malloc(sizeof(struct crime_data));
236     if (d == NULL) {
237     fprintf(stderr, "out of memory\n");
238     exit(1);
239     }
240     memset(d, 0, sizeof(struct crime_data));
241     d->irq_nr = irq_nr;
242     d->use_fb = use_fb;
243    
244     memory_device_register(mem, "crime", baseaddr, DEV_CRIME_LENGTH,
245     dev_crime_access, d, MEM_DEFAULT, NULL);
246     machine_add_tickfunction(machine, dev_crime_tick, d, CRIME_TICKSHIFT);
247    
248     return d;
249     }
250    
251    
252     /****************************************************************************/
253    
254    
255     /*
256     * dev_mace_access():
257     */
258     int dev_mace_access(struct cpu *cpu, struct memory *mem,
259     uint64_t relative_addr, unsigned char *data, size_t len,
260     int writeflag, void *extra)
261     {
262     int i;
263     struct mace_data *d = extra;
264    
265     if (writeflag == MEM_WRITE)
266     memcpy(&d->reg[relative_addr], data, len);
267     else
268     memcpy(data, &d->reg[relative_addr], len);
269    
270 dpavlin 10 if ((relative_addr >= 0x18 && relative_addr <= 0x1f) ||
271     (relative_addr+len-1 >= 0x18 && relative_addr+len-1 <= 0x1f))
272     cpu_interrupt_ack(cpu, 8); /* CRM_INT_CRMERR); */
273    
274 dpavlin 4 switch (relative_addr) {
275     #if 0
276 dpavlin 10 case 0x10: /* Current interrupt assertions */
277     case 0x14:
278 dpavlin 4 /* don't dump debug info for these */
279 dpavlin 10 if (writeflag == MEM_WRITE) {
280     fatal("[ NOTE/TODO: WRITE to mace intr: "
281     "reladdr=0x%x data=", (int)relative_addr);
282     for (i=0; i<len; i++)
283     fatal(" %02x", data[i]);
284     fatal(" (len=%i) ]\n", len);
285     }
286 dpavlin 4 break;
287 dpavlin 10 case 0x18: /* Interrupt mask */
288     case 0x1c:
289     /* don't dump debug info for these */
290     break;
291 dpavlin 4 #endif
292     default:
293 dpavlin 10 if (writeflag == MEM_READ) {
294     debug("[ mace: read from 0x%x:", (int)relative_addr);
295     for (i=0; i<len; i++)
296     debug(" %02x", data[i]);
297     debug(" (len=%i) ]\n", len);
298 dpavlin 4 } else {
299     debug("[ mace: write to 0x%x:", (int)relative_addr);
300     for (i=0; i<len; i++)
301     debug(" %02x", data[i]);
302     debug(" (len=%i) ]\n", len);
303     }
304     }
305    
306     return 1;
307     }
308    
309    
310     /*
311     * dev_mace_init():
312     */
313     struct mace_data *dev_mace_init(struct memory *mem, uint64_t baseaddr,
314     int irqnr)
315     {
316     struct mace_data *d;
317    
318     d = malloc(sizeof(struct mace_data));
319     if (d == NULL) {
320     fprintf(stderr, "out of memory\n");
321     exit(1);
322     }
323     memset(d, 0, sizeof(struct mace_data));
324     d->irqnr = irqnr;
325    
326     memory_device_register(mem, "mace", baseaddr, DEV_MACE_LENGTH,
327     dev_mace_access, d, MEM_DEFAULT, NULL);
328    
329     return d;
330     }
331    
332    
333     /****************************************************************************/
334    
335    
336     /*
337     * dev_macepci_access():
338     */
339     int dev_macepci_access(struct cpu *cpu, struct memory *mem,
340     uint64_t relative_addr, unsigned char *data, size_t len,
341     int writeflag, void *extra)
342     {
343     struct macepci_data *d = (struct macepci_data *) extra;
344     uint64_t idata = 0, odata=0;
345     int regnr, res = 1;
346    
347     idata = memory_readmax64(cpu, data, len);
348     regnr = relative_addr / sizeof(uint32_t);
349    
350     /* Read from/write to the macepci: */
351     switch (relative_addr) {
352     case 0x00: /* Error address */
353     if (writeflag == MEM_WRITE) {
354     } else {
355     odata = 0;
356     }
357     break;
358     case 0x04: /* Error flags */
359     if (writeflag == MEM_WRITE) {
360     } else {
361     odata = 0x06;
362     }
363     break;
364     case 0x0c: /* Revision number */
365     if (writeflag == MEM_WRITE) {
366     } else {
367     odata = 0x01;
368     }
369     break;
370     case 0xcf8: /* PCI ADDR */
371     case 0xcfc: /* PCI DATA */
372     if (writeflag == MEM_WRITE) {
373     res = bus_pci_access(cpu, mem, relative_addr,
374     &idata, writeflag, d->pci_data);
375     } else {
376     res = bus_pci_access(cpu, mem, relative_addr,
377     &odata, writeflag, d->pci_data);
378     /* odata = 0; */
379     }
380     break;
381     default:
382     if (writeflag == MEM_WRITE) {
383     debug("[ macepci: unimplemented write to address "
384     "0x%x, data=0x%02x ]\n",
385     (int)relative_addr, (int)idata);
386     } else {
387     debug("[ macepci: unimplemented read from address "
388     "0x%x ]\n", (int)relative_addr);
389     }
390     }
391    
392     if (writeflag == MEM_READ)
393     memory_writemax64(cpu, data, len, odata);
394    
395     return res;
396     }
397    
398    
399     /*
400     * dev_macepci_init():
401     */
402     struct pci_data *dev_macepci_init(struct memory *mem, uint64_t baseaddr,
403     int pciirq)
404     {
405     struct macepci_data *d = malloc(sizeof(struct macepci_data));
406     if (d == NULL) {
407     fprintf(stderr, "out of memory\n");
408     exit(1);
409     }
410     memset(d, 0, sizeof(struct macepci_data));
411    
412     d->pci_data = bus_pci_init(pciirq);
413    
414     memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH,
415     dev_macepci_access, (void *)d, MEM_DEFAULT, NULL);
416    
417     return d->pci_data;
418     }
419    
420    
421     /****************************************************************************/
422    
423    
424     /*
425     * SGI "mec" ethernet. Used in SGI-IP32.
426     *
427     * Study http://www.openbsd.org/cgi-bin/cvsweb/src/sys/arch/sgi/dev/if_mec.c
428     * and/or NetBSD. TODO:
429     *
430     * x) tx and rx interrupts/ring/slot stuff
431     */
432    
433     #define MEC_TICK_SHIFT 14
434    
435     #define MAX_TX_PACKET_LEN 1700
436     #define N_RX_ADDRESSES 16
437    
438     struct sgi_mec_data {
439     uint64_t reg[DEV_SGI_MEC_LENGTH / sizeof(uint64_t)];
440    
441     int irq_nr;
442     unsigned char macaddr[6];
443    
444     unsigned char cur_tx_packet[MAX_TX_PACKET_LEN];
445     int cur_tx_packet_len;
446    
447     unsigned char *cur_rx_packet;
448     int cur_rx_packet_len;
449    
450     uint64_t rx_addr[N_RX_ADDRESSES];
451     int cur_rx_addr_index_write;
452     int cur_rx_addr_index;
453     };
454    
455    
456     /*
457     * mec_reset():
458     */
459     static void mec_reset(struct sgi_mec_data *d)
460     {
461     if (d->cur_rx_packet != NULL)
462     free(d->cur_rx_packet);
463    
464     memset(d->reg, 0, sizeof(d->reg));
465     }
466    
467    
468     /*
469     * mec_control_write():
470     */
471     static void mec_control_write(struct cpu *cpu, struct sgi_mec_data *d,
472     uint64_t x)
473     {
474     if (x & MEC_MAC_CORE_RESET) {
475     debug("[ sgi_mec: CORE RESET ]\n");
476     mec_reset(d);
477     }
478     }
479    
480    
481     /*
482     * mec_try_rx():
483     */
484     static int mec_try_rx(struct cpu *cpu, struct sgi_mec_data *d)
485     {
486     uint64_t base;
487     unsigned char data[8];
488     int i, res, retval = 0;
489    
490     base = d->rx_addr[d->cur_rx_addr_index];
491     if (base & 0xfff)
492     fatal("[ mec_try_rx(): WARNING! lowest bits of base are "
493     "non-zero (0x%3x). TODO ]\n", (int)(base & 0xfff));
494     base &= 0xfffff000ULL;
495     if (base == 0)
496     goto skip;
497    
498     /* printf("rx base = 0x%016llx\n", (long long)base); */
499    
500     /* Read an rx descriptor from memory: */
501     res = cpu->memory_rw(cpu, cpu->mem, base,
502     &data[0], sizeof(data), MEM_READ, PHYSICAL);
503     if (!res)
504     return 0;
505    
506     #if 0
507     printf("{ mec: rxdesc %i: ", d->cur_rx_addr_index);
508     for (i=0; i<sizeof(data); i++) {
509     if ((i & 3) == 0)
510     printf(" ");
511     printf("%02x", data[i]);
512     }
513     printf(" }\n");
514     #endif
515    
516     /* Is this descriptor already in use? */
517     if (data[0] & 0x80) {
518     /* printf("INTERRUPT for base = 0x%x\n", (int)base); */
519     goto skip_and_advance;
520     }
521    
522     if (d->cur_rx_packet == NULL &&
523     net_ethernet_rx_avail(cpu->machine->emul->net, d))
524     net_ethernet_rx(cpu->machine->emul->net, d,
525     &d->cur_rx_packet, &d->cur_rx_packet_len);
526    
527     if (d->cur_rx_packet == NULL)
528     goto skip;
529    
530     /* Copy the packet data: */
531     /* printf("RX: "); */
532     for (i=0; i<d->cur_rx_packet_len; i++) {
533     res = cpu->memory_rw(cpu, cpu->mem, base + 32 + i + 2,
534     d->cur_rx_packet + i, 1, MEM_WRITE, PHYSICAL);
535     /* printf(" %02x", d->cur_rx_packet[i]); */
536     }
537     /* printf("\n"); */
538    
539 dpavlin 10 #if 0
540 dpavlin 4 printf("RX: %i bytes, index %i, base = 0x%x\n",
541     d->cur_rx_packet_len, d->cur_rx_addr_index, (int)base);
542     #endif
543    
544     /* 4 bytes of CRC at the end. Hm. TODO */
545     d->cur_rx_packet_len += 4;
546    
547     memset(data, 0, sizeof(data));
548     data[6] = (d->cur_rx_packet_len >> 8) & 255;
549     data[7] = d->cur_rx_packet_len & 255;
550     /* TODO: lots of bits :-) */
551     data[4] = 0x04; /* match MAC */
552     data[0] = 0x80; /* 0x80 = received. */
553     res = cpu->memory_rw(cpu, cpu->mem, base,
554     &data[0], sizeof(data), MEM_WRITE, PHYSICAL);
555    
556     /* Free the packet from memory: */
557     free(d->cur_rx_packet);
558     d->cur_rx_packet = NULL;
559    
560     d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |= MEC_INT_RX_THRESHOLD;
561     skip_and_advance:
562     d->cur_rx_addr_index ++;
563     d->cur_rx_addr_index %= N_RX_ADDRESSES;
564     d->reg[MEC_INT_STATUS / sizeof(uint64_t)] &= ~MEC_INT_RX_MCL_FIFO_ALIAS;
565 dpavlin 12 d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |=
566     (d->cur_rx_addr_index & 0x1f) << 8;
567 dpavlin 4 retval = 1;
568    
569     skip:
570     return retval;
571     }
572    
573    
574     /*
575     * mec_try_tx():
576     */
577     static int mec_try_tx(struct cpu *cpu, struct sgi_mec_data *d)
578     {
579     uint64_t base, addr, dma_base;
580     int tx_ring_ptr, ringread, ringwrite, res, i, j;
581     unsigned char data[32];
582     int len, start_offset, dma_ptr_nr, dma_len;
583    
584     base = d->reg[MEC_TX_RING_BASE / sizeof(uint64_t)];
585     tx_ring_ptr = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
586    
587     if (base == 0)
588     return 0;
589    
590     /* printf("base = 0x%016llx\n", base); */
591    
592     ringread = tx_ring_ptr & MEC_TX_RING_READ_PTR;
593     ringwrite = tx_ring_ptr & MEC_TX_RING_WRITE_PTR;
594     ringread >>= 16;
595     /* All done? Then abort. */
596     if (ringread == ringwrite)
597     return 0;
598    
599     tx_ring_ptr &= MEC_TX_RING_READ_PTR;
600     tx_ring_ptr >>= 16;
601    
602     /* Each tx descriptor (+ buffer) is 128 bytes: */
603     addr = base + tx_ring_ptr*128;
604     res = cpu->memory_rw(cpu, cpu->mem, addr,
605     &data[0], sizeof(data), MEM_READ, PHYSICAL);
606     if (!res)
607     return 0;
608    
609     /* Is this packet transmitted already? */
610     if (data[0] & 0x80) {
611     fatal("[ mec_try_tx: tx_ring_ptr = %i, already"
612     " transmitted? ]\n", tx_ring_ptr);
613     goto advance_tx;
614     }
615    
616     len = data[6] * 256 + data[7];
617     start_offset = data[5] & 0x7f;
618    
619     /* Is this packet empty? Then don't transmit. */
620     if (len == 0)
621     return 0;
622    
623     /* Hm. Is len one too little? TODO */
624     len ++;
625    
626     #if 0
627     printf("{ mec: txdesc %i: ", tx_ring_ptr);
628     for (i=0; i<sizeof(data); i++) {
629     if ((i & 3) == 0)
630     printf(" ");
631     printf("%02x", data[i]);
632     }
633     printf(" }\n");
634     #endif
635     dma_ptr_nr = 0;
636    
637     j = 0;
638     d->cur_tx_packet_len = len;
639    
640     for (i=start_offset; i<start_offset+len; i++) {
641     unsigned char ch;
642    
643     if ((i & 0x7f) == 0x00)
644     break;
645    
646     res = cpu->memory_rw(cpu, cpu->mem, addr + i,
647     &ch, sizeof(ch), MEM_READ, PHYSICAL);
648     /* printf(" %02x", ch); */
649    
650     d->cur_tx_packet[j++] = ch;
651     if (j >= MAX_TX_PACKET_LEN) {
652     fatal("[ mec_try_tx: packet too large? ]\n");
653     break;
654     }
655     }
656     /* printf("\n"); */
657    
658     if (j < len) {
659     /* Continue with DMA: */
660     for (;;) {
661     dma_ptr_nr ++;
662     if (dma_ptr_nr >= 4)
663     break;
664     if (!(data[4] & (0x01 << dma_ptr_nr)))
665     break;
666     dma_base = (data[dma_ptr_nr * 8 + 4] << 24)
667     + (data[dma_ptr_nr * 8 + 5] << 16)
668     + (data[dma_ptr_nr * 8 + 6] << 8)
669     + (data[dma_ptr_nr * 8 + 7]);
670     dma_base &= 0xfffffff8ULL;
671     dma_len = (data[dma_ptr_nr * 8 + 2] << 8)
672     + (data[dma_ptr_nr * 8 + 3]) + 1;
673    
674     /* printf("dma_base = %08x, dma_len = %i\n",
675     (int)dma_base, dma_len); */
676    
677     while (dma_len > 0) {
678     unsigned char ch;
679     res = cpu->memory_rw(cpu, cpu->mem, dma_base,
680     &ch, sizeof(ch), MEM_READ, PHYSICAL);
681     /* printf(" %02x", ch); */
682    
683     d->cur_tx_packet[j++] = ch;
684     if (j >= MAX_TX_PACKET_LEN) {
685     fatal("[ mec_try_tx: packet too large?"
686     " ]\n");
687     break;
688     }
689     dma_base ++;
690     dma_len --;
691     }
692     }
693     }
694    
695     if (j < len)
696     fatal("[ mec_try_tx: not enough data? ]\n");
697    
698     net_ethernet_tx(cpu->machine->emul->net, d,
699     d->cur_tx_packet, d->cur_tx_packet_len);
700    
701     /* see openbsd's if_mec.c for details */
702     if (data[4] & 0x01) {
703     d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |=
704     MEC_INT_TX_PACKET_SENT;
705     }
706     memset(data, 0, 6); /* last 2 bytes are len */
707     data[0] = 0x80;
708     data[5] = 0x80;
709    
710     res = cpu->memory_rw(cpu, cpu->mem, addr,
711     &data[0], sizeof(data), MEM_WRITE, PHYSICAL);
712    
713     d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |= MEC_INT_TX_EMPTY;
714     d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |= MEC_INT_TX_PACKET_SENT;
715    
716     advance_tx:
717     /* Advance the ring Read ptr. */
718     tx_ring_ptr = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
719     ringread = tx_ring_ptr & MEC_TX_RING_READ_PTR;
720     ringwrite = tx_ring_ptr & MEC_TX_RING_WRITE_PTR;
721    
722     ringread = (ringread >> 16) + 1;
723     ringread &= 63;
724     ringread <<= 16;
725    
726     d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)] =
727     (ringwrite & MEC_TX_RING_WRITE_PTR) |
728     (ringread & MEC_TX_RING_READ_PTR);
729    
730     d->reg[MEC_INT_STATUS / sizeof(uint64_t)] &=
731     ~MEC_INT_TX_RING_BUFFER_ALIAS;
732     d->reg[MEC_INT_STATUS / sizeof(uint64_t)] |=
733     (d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)] &
734     MEC_INT_TX_RING_BUFFER_ALIAS);
735    
736     return 1;
737     }
738    
739    
740     /*
741     * dev_sgi_mec_tick():
742     */
743     void dev_sgi_mec_tick(struct cpu *cpu, void *extra)
744     {
745     struct sgi_mec_data *d = (struct sgi_mec_data *) extra;
746     int n = 0;
747    
748     while (mec_try_tx(cpu, d))
749     ;
750    
751     while (mec_try_rx(cpu, d) && n < 16)
752     n++;
753    
754     /* Interrupts: (TODO: only when enabled) */
755     if (d->reg[MEC_INT_STATUS / sizeof(uint64_t)] & MEC_INT_STATUS_MASK) {
756     #if 0
757     printf("[%02x]", (int)(d->reg[MEC_INT_STATUS /
758     sizeof(uint64_t)] & MEC_INT_STATUS_MASK));
759     fflush(stdout);
760     #endif
761     cpu_interrupt(cpu, d->irq_nr);
762     } else
763     cpu_interrupt_ack(cpu, d->irq_nr);
764     }
765    
766    
767     /*
768     * dev_sgi_mec_access():
769     */
770     int dev_sgi_mec_access(struct cpu *cpu, struct memory *mem,
771     uint64_t relative_addr, unsigned char *data, size_t len,
772     int writeflag, void *extra)
773     {
774     struct sgi_mec_data *d = (struct sgi_mec_data *) extra;
775     uint64_t idata = 0, odata = 0;
776     int regnr;
777    
778     idata = memory_readmax64(cpu, data, len);
779     regnr = relative_addr / sizeof(uint64_t);
780    
781     /* Treat most registers as read/write, by default. */
782     if (writeflag == MEM_WRITE) {
783     switch (relative_addr) {
784     case MEC_INT_STATUS: /* 0x08 */
785     /* Clear bits on write: (This is just a guess) */
786     d->reg[regnr] = (d->reg[regnr] & ~0xff)
787     | ((d->reg[regnr] & ~idata) & 0xff);
788     break;
789     case MEC_TX_RING_PTR: /* 0x30 */
790     idata &= MEC_TX_RING_WRITE_PTR;
791     d->reg[regnr] = (d->reg[regnr] &
792     ~MEC_TX_RING_WRITE_PTR) | idata;
793     /* TODO */
794     break;
795     default:
796     d->reg[regnr] = idata;
797     }
798     } else
799     odata = d->reg[regnr];
800    
801     switch (relative_addr) {
802     case MEC_MAC_CONTROL: /* 0x00 */
803     if (writeflag)
804     mec_control_write(cpu, d, idata);
805     else {
806     /* Fake "revision 1": */
807     odata &= ~MEC_MAC_REVISION;
808     odata |= 1 << MEC_MAC_REVISION_SHIFT;
809     }
810     break;
811     case MEC_INT_STATUS: /* 0x08 */
812     if (writeflag)
813     debug("[ sgi_mec: write to MEC_INT_STATUS: "
814     "0x%016llx ]\n", (long long)idata);
815     break;
816     case MEC_DMA_CONTROL: /* 0x10 */
817     if (writeflag) {
818     debug("[ sgi_mec: write to MEC_DMA_CONTROL: "
819     "0x%016llx ]\n", (long long)idata);
820     if (!(idata & MEC_DMA_TX_INT_ENABLE)) {
821     /* This should apparently stop the
822     TX Empty interrupt. */
823     d->reg[MEC_INT_STATUS / sizeof(uint64_t)] &=
824     ~MEC_INT_TX_EMPTY;
825     }
826     }
827     break;
828     case MEC_TX_ALIAS: /* 0x20 */
829     if (writeflag) {
830     debug("[ sgi_mec: write to MEC_TX_ALIAS: "
831     "0x%016llx ]\n", (long long)idata);
832     } else {
833     debug("[ sgi_mec: read from MEC_TX_ALIAS: "
834     "0x%016llx ]\n", (long long)idata);
835     odata = d->reg[MEC_TX_RING_PTR / sizeof(uint64_t)];
836     }
837     break;
838     case MEC_RX_ALIAS: /* 0x28 */
839     if (writeflag)
840     debug("[ sgi_mec: write to MEC_RX_ALIAS: "
841     "0x%016llx ]\n", (long long)idata);
842     break;
843     case MEC_TX_RING_PTR: /* 0x30 */
844     if (writeflag)
845     debug("[ sgi_mec: write to MEC_TX_RING_PTR: "
846     "0x%016llx ]\n", (long long)idata);
847     break;
848     case MEC_PHY_DATA: /* 0x64 */
849     if (writeflag)
850     fatal("[ sgi_mec: write to MEC_PHY_DATA: "
851     "0x%016llx ]\n", (long long)idata);
852     else
853     odata = 0; /* ? */
854     break;
855     case MEC_PHY_ADDRESS: /* 0x6c */
856     if (writeflag)
857     debug("[ sgi_mec: write to MEC_PHY_ADDRESS: "
858     "0x%016llx ]\n", (long long)idata);
859     break;
860     case MEC_PHY_READ_INITIATE: /* 0x70 */
861     if (writeflag)
862     debug("[ sgi_mec: write to MEC_PHY_READ_INITIATE: "
863     "0x%016llx ]\n", (long long)idata);
864     break;
865     case 0x74:
866     if (writeflag)
867     debug("[ sgi_mec: write to 0x74: 0x%016llx ]\n",
868     (long long)idata);
869     else
870     debug("[ sgi_mec: read from 0x74 ]\n");
871     break;
872     case MEC_STATION: /* 0xa0 */
873     if (writeflag)
874     debug("[ sgi_mec: setting the MAC address to "
875     "%02x:%02x:%02x:%02x:%02x:%02x ]\n",
876     (idata >> 40) & 255, (idata >> 32) & 255,
877     (idata >> 24) & 255, (idata >> 16) & 255,
878     (idata >> 8) & 255, (idata >> 0) & 255);
879     break;
880     case MEC_STATION_ALT: /* 0xa8 */
881     if (writeflag)
882     debug("[ sgi_mec: setting the ALTERNATIVE MAC address"
883     " to %02x:%02x:%02x:%02x:%02x:%02x ]\n",
884     (idata >> 40) & 255, (idata >> 32) & 255,
885     (idata >> 24) & 255, (idata >> 16) & 255,
886     (idata >> 8) & 255, (idata >> 0) & 255);
887     break;
888     case MEC_MULTICAST: /* 0xb0 */
889     if (writeflag)
890     debug("[ sgi_mec: write to MEC_MULTICAST: "
891     "0x%016llx ]\n", (long long)idata);
892     break;
893     case MEC_TX_RING_BASE: /* 0xb8 */
894     if (writeflag)
895     debug("[ sgi_mec: write to MEC_TX_RING_BASE: "
896     "0x%016llx ]\n", (long long)idata);
897     break;
898     case MEC_MCL_RX_FIFO: /* 0x100 */
899     if (writeflag) {
900     debug("[ sgi_mec: write to MEC_MCL_RX_FIFO: 0x"
901     "%016llx ]\n", (long long)idata);
902     d->rx_addr[d->cur_rx_addr_index_write] = idata;
903     d->cur_rx_addr_index_write ++;
904     d->cur_rx_addr_index_write %= N_RX_ADDRESSES;
905     }
906     break;
907     default:
908     if (writeflag == MEM_WRITE)
909     fatal("[ sgi_mec: unimplemented write to address"
910     " 0x%llx, data=0x%016llx ]\n",
911     (long long)relative_addr, (long long)idata);
912     else
913     fatal("[ sgi_mec: unimplemented read from address"
914     " 0x%llx ]\n", (long long)relative_addr);
915     }
916    
917     if (writeflag == MEM_READ)
918     memory_writemax64(cpu, data, len, odata);
919    
920     dev_sgi_mec_tick(cpu, extra);
921    
922     return 1;
923     }
924    
925    
926     /*
927     * dev_sgi_mec_init():
928     */
929     void dev_sgi_mec_init(struct machine *machine, struct memory *mem,
930     uint64_t baseaddr, int irq_nr, unsigned char *macaddr)
931     {
932     char *name2;
933 dpavlin 10 size_t nlen = 55;
934 dpavlin 4 struct sgi_mec_data *d = malloc(sizeof(struct sgi_mec_data));
935    
936     if (d == NULL) {
937     fprintf(stderr, "out of memory\n");
938     exit(1);
939     }
940     memset(d, 0, sizeof(struct sgi_mec_data));
941     d->irq_nr = irq_nr;
942     memcpy(d->macaddr, macaddr, 6);
943    
944     mec_reset(d);
945    
946 dpavlin 10 name2 = malloc(nlen);
947 dpavlin 4 if (name2 == NULL) {
948     fprintf(stderr, "out of memory in dev_sgi_mec_init()\n");
949     exit(1);
950     }
951 dpavlin 10 snprintf(name2, nlen, "mec [%02x:%02x:%02x:%02x:%02x:%02x]",
952 dpavlin 4 d->macaddr[0], d->macaddr[1], d->macaddr[2],
953     d->macaddr[3], d->macaddr[4], d->macaddr[5]);
954    
955     memory_device_register(mem, name2, baseaddr,
956     DEV_SGI_MEC_LENGTH, dev_sgi_mec_access, (void *)d,
957     MEM_DEFAULT, NULL);
958    
959     machine_add_tickfunction(machine, dev_sgi_mec_tick, d, MEC_TICK_SHIFT);
960    
961     net_add_nic(machine->emul->net, d, macaddr);
962     }
963    
964    
965     /****************************************************************************/
966    
967    
968     struct sgi_ust_data {
969     uint64_t reg[DEV_SGI_UST_LENGTH / sizeof(uint64_t)];
970     };
971    
972    
973     /*
974     * dev_sgi_ust_access():
975     */
976     int dev_sgi_ust_access(struct cpu *cpu, struct memory *mem,
977     uint64_t relative_addr, unsigned char *data, size_t len,
978     int writeflag, void *extra)
979     {
980     struct sgi_ust_data *d = (struct sgi_ust_data *) extra;
981     uint64_t idata = 0, odata = 0;
982     int regnr;
983    
984     idata = memory_readmax64(cpu, data, len);
985     regnr = relative_addr / sizeof(uint64_t);
986    
987     /* Treat all registers as read/write, by default. */
988     if (writeflag == MEM_WRITE)
989     d->reg[regnr] = idata;
990     else
991     odata = d->reg[regnr];
992    
993     switch (relative_addr) {
994     case 0:
995     d->reg[regnr] += 0x2710;
996     break;
997     default:
998     if (writeflag == MEM_WRITE)
999 dpavlin 12 debug("[ sgi_ust: unimplemented write to "
1000     "address 0x%llx, data=0x%016llx ]\n",
1001     (long long)relative_addr, (long long)idata);
1002 dpavlin 4 else
1003 dpavlin 12 debug("[ sgi_ust: unimplemented read from address"
1004     " 0x%llx ]\n", (long long)relative_addr);
1005 dpavlin 4 }
1006    
1007     if (writeflag == MEM_READ)
1008     memory_writemax64(cpu, data, len, odata);
1009    
1010     return 1;
1011     }
1012    
1013    
1014     /*
1015     * dev_sgi_ust_init():
1016     */
1017     void dev_sgi_ust_init(struct memory *mem, uint64_t baseaddr)
1018     {
1019     struct sgi_ust_data *d = malloc(sizeof(struct sgi_ust_data));
1020     if (d == NULL) {
1021     fprintf(stderr, "out of memory\n");
1022     exit(1);
1023     }
1024     memset(d, 0, sizeof(struct sgi_ust_data));
1025    
1026     memory_device_register(mem, "sgi_ust", baseaddr,
1027 dpavlin 12 DEV_SGI_UST_LENGTH, dev_sgi_ust_access, (void *)d,
1028     MEM_DEFAULT, NULL);
1029 dpavlin 4 }
1030    
1031    
1032     /****************************************************************************/
1033    
1034    
1035     /*
1036     * SGI "mte". This device seems to be an accelerator for copying/clearing
1037 dpavlin 12 * memory. Used by (at least) the SGI O2 PROM.
1038     *
1039     * Actually, it seems to be used for graphics output as well. (?)
1040 dpavlin 14 * The O2's PROM uses it to output graphics.
1041 dpavlin 4 */
1042 dpavlin 12 /* #define debug fatal */
1043 dpavlin 14 /* #define MTE_DEBUG */
1044 dpavlin 4 #define ZERO_CHUNK_LEN 4096
1045    
1046     struct sgi_mte_data {
1047 dpavlin 14 uint32_t reg[DEV_SGI_MTE_LENGTH / sizeof(uint32_t)];
1048 dpavlin 4 };
1049    
1050     /*
1051     * dev_sgi_mte_access():
1052     */
1053     int dev_sgi_mte_access(struct cpu *cpu, struct memory *mem,
1054     uint64_t relative_addr, unsigned char *data, size_t len,
1055     int writeflag, void *extra)
1056     {
1057     struct sgi_mte_data *d = (struct sgi_mte_data *) extra;
1058     uint64_t first_addr, last_addr, zerobuflen, fill_addr, fill_len;
1059     unsigned char zerobuf[ZERO_CHUNK_LEN];
1060     uint64_t idata = 0, odata = 0;
1061     int regnr;
1062    
1063     idata = memory_readmax64(cpu, data, len);
1064 dpavlin 14 regnr = relative_addr / sizeof(uint32_t);
1065 dpavlin 4
1066 dpavlin 14 /*
1067     * Treat all registers as read/write, by default. Sometimes these
1068     * are accessed as 32-bit words, sometimes as 64-bit words.
1069     */
1070     if (len != 4) {
1071     if (writeflag == MEM_WRITE) {
1072     d->reg[regnr] = idata >> 32;
1073     d->reg[regnr+1] = idata;
1074     } else
1075     odata = ((uint64_t)d->reg[regnr] << 32) +
1076     d->reg[regnr+1];
1077     }
1078    
1079 dpavlin 4 if (writeflag == MEM_WRITE)
1080     d->reg[regnr] = idata;
1081     else
1082     odata = d->reg[regnr];
1083    
1084 dpavlin 14 #ifdef MTE_DEBUG
1085     if (writeflag == MEM_WRITE && relative_addr >= 0x2000 &&
1086     relative_addr < 0x3000)
1087     fatal("[ MTE: 0x%08x: 0x%016llx ]\n", (int)relative_addr,
1088     (long long)idata);
1089     #endif
1090    
1091 dpavlin 4 /*
1092 dpavlin 12 * I've not found any docs about this 'mte' device at all, so this is
1093     * just a guess. The mte seems to be used for copying and zeroing
1094     * chunks of memory.
1095 dpavlin 4 *
1096 dpavlin 14 * write to 0x3030, data=0x00000000003da000 ] <-- first address
1097     * write to 0x3038, data=0x00000000003f9fff ] <-- last address
1098     * write to 0x3018, data=0x0000000000000000 ] <-- what to fill?
1099     * write to 0x3008, data=0x00000000ffffffff ] <-- ?
1100     * write to 0x3800, data=0x0000000000000011 ] <-- operation
1101     * (0x11 = zerofill)
1102 dpavlin 4 *
1103 dpavlin 14 * write to 0x1700, data=0x80001ea080001ea1 <-- also containing the
1104     * write to 0x1708, data=0x80001ea280001ea3 address to fill (?)
1105     * write to 0x1710, data=0x80001ea480001ea5
1106 dpavlin 4 * ...
1107 dpavlin 14 * write to 0x1770, data=0x80001e9c80001e9d
1108     * write to 0x1778, data=0x80001e9e80001e9f
1109 dpavlin 4 */
1110     switch (relative_addr) {
1111    
1112     /* No warnings for these: */
1113     case 0x3030:
1114     case 0x3038:
1115     break;
1116    
1117     /* Unknown, but no warning: */
1118     case 0x4000:
1119     case 0x3018:
1120     case 0x3008:
1121     case 0x1700:
1122     case 0x1708:
1123     case 0x1710:
1124     case 0x1718:
1125     case 0x1720:
1126     case 0x1728:
1127     case 0x1730:
1128     case 0x1738:
1129     case 0x1740:
1130     case 0x1748:
1131     case 0x1750:
1132     case 0x1758:
1133     case 0x1760:
1134     case 0x1768:
1135     case 0x1770:
1136     case 0x1778:
1137     break;
1138    
1139 dpavlin 14 /* Graphics stuff? No warning: */
1140     case 0x2018:
1141     case 0x2060:
1142     case 0x2070:
1143     case 0x2074:
1144     case 0x20c0:
1145     case 0x20c4:
1146     case 0x20d0:
1147     case 0x21b0:
1148     case 0x21b8:
1149     break;
1150 dpavlin 12
1151 dpavlin 14 /* Perform graphics operation: */
1152     case 0x21f8:
1153     {
1154     uint32_t op = d->reg[0x2060 / sizeof(uint32_t)];
1155     uint32_t color = d->reg[0x20d0 / sizeof(uint32_t)]&255;
1156     uint32_t x1 = (d->reg[0x2070 / sizeof(uint32_t)]
1157     >> 16) & 0xfff;
1158     uint32_t y1 = d->reg[0x2070 / sizeof(uint32_t)]& 0xfff;
1159     uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)]
1160     >> 16) & 0xfff;
1161     uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff;
1162     int y;
1163 dpavlin 12
1164 dpavlin 14 op >>= 24;
1165    
1166     switch (op) {
1167     case 1: /* Unknown. Used after drawing bitmaps? */
1168     break;
1169     case 3: /* Fill: */
1170     if (x2 < x1) {
1171     int tmp = x1; x1 = x2; x2 = tmp;
1172     }
1173     if (y2 < y1) {
1174     int tmp = y1; y1 = y2; y2 = tmp;
1175     }
1176     for (y=y1; y<=y2; y++) {
1177     unsigned char buf[1280];
1178     int length = x2-x1+1;
1179     int addr = (x1 + y*1280);
1180     if (length < 1)
1181     length = 1;
1182     memset(buf, color, length);
1183     if (x1 < 1280 && y < 1024)
1184     cpu->memory_rw(cpu, cpu->mem,
1185     0x38000000 + addr, buf,
1186     length, MEM_WRITE,
1187     NO_EXCEPTIONS | PHYSICAL);
1188     }
1189     break;
1190    
1191     default:fatal("\n--- MTE OP %i color 0x%02x: %i,%i - "
1192     "%i,%i\n\n", op, color, x1,y1, x2,y2);
1193     }
1194     }
1195     break;
1196    
1197     case 0x29f0:
1198     /* Pixel output: */
1199     {
1200     uint32_t data = d->reg[0x20c4 / sizeof(uint32_t)];
1201     uint32_t color = d->reg[0x20d0 / sizeof(uint32_t)]&255;
1202     uint32_t x1 = (d->reg[0x2070 / sizeof(uint32_t)]
1203     >> 16) & 0xfff;
1204     uint32_t y1 = d->reg[0x2070 / sizeof(uint32_t)]& 0xfff;
1205     uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)]
1206     >> 16) & 0xfff;
1207     uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff;
1208     int x,y;
1209     if (x2 < x1) {
1210     int tmp = x1; x1 = x2; x2 = tmp;
1211     }
1212     if (y2 < y1) {
1213     int tmp = y1; y1 = y2; y2 = tmp;
1214     }
1215     if (x2-x1 <= 15)
1216     data <<= 16;
1217     x=x1; y=y1;
1218     while (x <= x2 && y <= y2) {
1219     unsigned char buf = color;
1220     int addr = x + y*1280;
1221     int bit_set = data & 0x80000000UL;
1222     data <<= 1;
1223     if (x < 1280 && y < 1024 && bit_set)
1224     cpu->memory_rw(cpu, cpu->mem,
1225     0x38000000 + addr, &buf,1,MEM_WRITE,
1226     NO_EXCEPTIONS | PHYSICAL);
1227     x++;
1228     if (x > x2) {
1229     x = x1;
1230     y++;
1231     }
1232     }
1233     }
1234     break;
1235    
1236    
1237 dpavlin 4 /* Operations: */
1238     case 0x3800:
1239     if (writeflag == MEM_WRITE) {
1240     switch (idata) {
1241     case 0x11: /* zerofill */
1242 dpavlin 14 first_addr = d->reg[0x3030 / sizeof(uint32_t)];
1243     last_addr = d->reg[0x3038 / sizeof(uint32_t)];
1244 dpavlin 4 zerobuflen = last_addr - first_addr + 1;
1245 dpavlin 14 debug("[ sgi_mte: zerofill: first = 0x%016llx,"
1246     " last = 0x%016llx, length = 0x%llx ]\n",
1247     (long long)first_addr, (long long)
1248     last_addr, (long long)zerobuflen);
1249 dpavlin 4
1250 dpavlin 14 /* TODO: is there a better way to
1251     implement this? */
1252 dpavlin 4 memset(zerobuf, 0, sizeof(zerobuf));
1253     fill_addr = first_addr;
1254     while (zerobuflen != 0) {
1255     if (zerobuflen > sizeof(zerobuf))
1256     fill_len = sizeof(zerobuf);
1257     else
1258     fill_len = zerobuflen;
1259     cpu->memory_rw(cpu, mem, fill_addr,
1260     zerobuf, fill_len, MEM_WRITE,
1261     NO_EXCEPTIONS | PHYSICAL);
1262     fill_addr += fill_len;
1263     zerobuflen -= sizeof(zerobuf);
1264     }
1265    
1266     break;
1267     default:
1268 dpavlin 14 fatal("[ sgi_mte: UNKNOWN operation "
1269     "0x%x ]\n", idata);
1270 dpavlin 4 }
1271     }
1272     break;
1273     default:
1274     if (writeflag == MEM_WRITE)
1275 dpavlin 14 debug("[ sgi_mte: unimplemented write to "
1276     "address 0x%llx, data=0x%016llx ]\n",
1277     (long long)relative_addr, (long long)idata);
1278 dpavlin 4 else
1279 dpavlin 14 debug("[ sgi_mte: unimplemented read from address"
1280     " 0x%llx ]\n", (long long)relative_addr);
1281 dpavlin 4 }
1282    
1283     if (writeflag == MEM_READ)
1284     memory_writemax64(cpu, data, len, odata);
1285    
1286     return 1;
1287     }
1288    
1289    
1290     /*
1291     * dev_sgi_mte_init():
1292     */
1293     void dev_sgi_mte_init(struct memory *mem, uint64_t baseaddr)
1294     {
1295     struct sgi_mte_data *d = malloc(sizeof(struct sgi_mte_data));
1296     if (d == NULL) {
1297     fprintf(stderr, "out of memory\n");
1298     exit(1);
1299     }
1300     memset(d, 0, sizeof(struct sgi_mte_data));
1301    
1302     memory_device_register(mem, "sgi_mte", baseaddr, DEV_SGI_MTE_LENGTH,
1303     dev_sgi_mte_access, (void *)d, MEM_DEFAULT, NULL);
1304     }
1305    

  ViewVC Help
Powered by ViewVC 1.1.26