1 |
/* |
/* |
2 |
* Copyright (C) 2003-2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-2006 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_sgi_ip32.c,v 1.29 2005/08/13 08:25:48 debug Exp $ |
* $Id: dev_sgi_ip32.c,v 1.45 2006/03/04 12:38:48 debug Exp $ |
29 |
* |
* |
30 |
* SGI IP32 devices. |
* SGI IP32 devices. |
31 |
* |
* |
106 |
/* |
/* |
107 |
* dev_crime_access(): |
* dev_crime_access(): |
108 |
*/ |
*/ |
109 |
int dev_crime_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(crime) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
110 |
{ |
{ |
|
int i; |
|
111 |
struct crime_data *d = extra; |
struct crime_data *d = extra; |
112 |
uint64_t idata; |
uint64_t idata = 0; |
113 |
|
size_t i; |
114 |
|
|
115 |
idata = memory_readmax64(cpu, data, len); |
if (writeflag == MEM_WRITE) |
116 |
|
idata = memory_readmax64(cpu, data, len); |
117 |
|
|
118 |
/* |
/* |
119 |
* Set crime version/revision: |
* Set crime version/revision: |
120 |
* |
* |
121 |
* This might not be the most elegant or correct solution, |
* This might not be the most elegant or correct solution, but it |
122 |
* but it seems that the IP32 PROM likes 0x11 for machines |
* seems that the IP32 PROM likes 0x11 for machines without graphics, |
123 |
* without graphics, and 0xa1 for machines with graphics. |
* and 0xa1 for machines with graphics. |
124 |
* |
* |
125 |
* NetBSD 2.0 complains about "unknown" crime for 0x11, |
* NetBSD 2.0 complains about "unknown" crime for 0x11, but I guess |
126 |
* but I guess that's something one has to live with. |
* that's something one has to live with. (TODO?) |
|
* |
|
|
* (TODO?) |
|
127 |
*/ |
*/ |
128 |
d->reg[4] = 0x00; d->reg[5] = 0x00; d->reg[6] = 0x00; |
d->reg[4] = 0x00; d->reg[5] = 0x00; d->reg[6] = 0x00; |
129 |
d->reg[7] = d->use_fb? 0xa1 : 0x11; |
d->reg[7] = d->use_fb? 0xa1 : 0x11; |
180 |
idata &= ~0x200; |
idata &= ~0x200; |
181 |
} |
} |
182 |
if (idata & 0x800) { |
if (idata & 0x800) { |
183 |
|
int j; |
184 |
|
|
185 |
/* This is used by the IP32 PROM's |
/* This is used by the IP32 PROM's |
186 |
"reboot" command: */ |
"reboot" command: */ |
187 |
for (i=0; i<cpu->machine->ncpus; i++) |
for (j=0; j<cpu->machine->ncpus; j++) |
188 |
cpu->machine->cpus[i]->running = 0; |
cpu->machine->cpus[j]->running = 0; |
189 |
cpu->machine-> |
cpu->machine-> |
190 |
exit_without_entering_debugger = 1; |
exit_without_entering_debugger = 1; |
191 |
idata &= ~0x800; |
idata &= ~0x800; |
241 |
d->use_fb = use_fb; |
d->use_fb = use_fb; |
242 |
|
|
243 |
memory_device_register(mem, "crime", baseaddr, DEV_CRIME_LENGTH, |
memory_device_register(mem, "crime", baseaddr, DEV_CRIME_LENGTH, |
244 |
dev_crime_access, d, MEM_DEFAULT, NULL); |
dev_crime_access, d, DM_DEFAULT, NULL); |
245 |
machine_add_tickfunction(machine, dev_crime_tick, d, CRIME_TICKSHIFT); |
machine_add_tickfunction(machine, dev_crime_tick, d, |
246 |
|
CRIME_TICKSHIFT, 0.0); |
247 |
|
|
248 |
return d; |
return d; |
249 |
} |
} |
255 |
/* |
/* |
256 |
* dev_mace_access(): |
* dev_mace_access(): |
257 |
*/ |
*/ |
258 |
int dev_mace_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(mace) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
259 |
{ |
{ |
260 |
int i; |
size_t i; |
261 |
struct mace_data *d = extra; |
struct mace_data *d = extra; |
262 |
|
|
263 |
if (writeflag == MEM_WRITE) |
if (writeflag == MEM_WRITE) |
322 |
d->irqnr = irqnr; |
d->irqnr = irqnr; |
323 |
|
|
324 |
memory_device_register(mem, "mace", baseaddr, DEV_MACE_LENGTH, |
memory_device_register(mem, "mace", baseaddr, DEV_MACE_LENGTH, |
325 |
dev_mace_access, d, MEM_DEFAULT, NULL); |
dev_mace_access, d, DM_DEFAULT, NULL); |
326 |
|
|
327 |
return d; |
return d; |
328 |
} |
} |
334 |
/* |
/* |
335 |
* dev_macepci_access(): |
* dev_macepci_access(): |
336 |
*/ |
*/ |
337 |
int dev_macepci_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(macepci) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
338 |
{ |
{ |
339 |
struct macepci_data *d = (struct macepci_data *) extra; |
struct macepci_data *d = (struct macepci_data *) extra; |
340 |
uint64_t idata = 0, odata=0; |
uint64_t idata = 0, odata=0; |
341 |
int regnr, res = 1; |
int regnr, res = 1, bus, dev, func, pcireg; |
342 |
|
|
343 |
|
if (writeflag == MEM_WRITE) |
344 |
|
idata = memory_readmax64(cpu, data, len); |
345 |
|
|
|
idata = memory_readmax64(cpu, data, len); |
|
346 |
regnr = relative_addr / sizeof(uint32_t); |
regnr = relative_addr / sizeof(uint32_t); |
347 |
|
|
348 |
/* Read from/write to the macepci: */ |
/* Read from/write to the macepci: */ |
349 |
switch (relative_addr) { |
switch (relative_addr) { |
350 |
|
|
351 |
case 0x00: /* Error address */ |
case 0x00: /* Error address */ |
352 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
353 |
} else { |
} else { |
354 |
odata = 0; |
odata = 0; |
355 |
} |
} |
356 |
break; |
break; |
357 |
|
|
358 |
case 0x04: /* Error flags */ |
case 0x04: /* Error flags */ |
359 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
360 |
} else { |
} else { |
361 |
odata = 0x06; |
odata = 0x06; |
362 |
} |
} |
363 |
break; |
break; |
364 |
|
|
365 |
case 0x0c: /* Revision number */ |
case 0x0c: /* Revision number */ |
366 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
367 |
} else { |
} else { |
368 |
odata = 0x01; |
odata = 0x01; |
369 |
} |
} |
370 |
break; |
break; |
371 |
|
|
372 |
case 0xcf8: /* PCI ADDR */ |
case 0xcf8: /* PCI ADDR */ |
373 |
|
bus_pci_decompose_1(idata, &bus, &dev, &func, &pcireg); |
374 |
|
bus_pci_setaddr(cpu, d->pci_data, bus, dev, func, pcireg); |
375 |
|
break; |
376 |
|
|
377 |
case 0xcfc: /* PCI DATA */ |
case 0xcfc: /* PCI DATA */ |
378 |
if (writeflag == MEM_WRITE) { |
bus_pci_data_access(cpu, d->pci_data, writeflag == MEM_READ? |
379 |
res = bus_pci_access(cpu, mem, relative_addr, |
&odata : &idata, len, writeflag); |
|
&idata, writeflag, d->pci_data); |
|
|
} else { |
|
|
res = bus_pci_access(cpu, mem, relative_addr, |
|
|
&odata, writeflag, d->pci_data); |
|
|
/* odata = 0; */ |
|
|
} |
|
380 |
break; |
break; |
381 |
|
|
382 |
default: |
default: |
383 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
384 |
debug("[ macepci: unimplemented write to address " |
debug("[ macepci: unimplemented write to address " |
400 |
/* |
/* |
401 |
* dev_macepci_init(): |
* dev_macepci_init(): |
402 |
*/ |
*/ |
403 |
struct pci_data *dev_macepci_init(struct memory *mem, uint64_t baseaddr, |
struct pci_data *dev_macepci_init(struct machine *machine, |
404 |
int pciirq) |
struct memory *mem, uint64_t baseaddr, int pciirq) |
405 |
{ |
{ |
406 |
struct macepci_data *d = malloc(sizeof(struct macepci_data)); |
struct macepci_data *d = malloc(sizeof(struct macepci_data)); |
407 |
if (d == NULL) { |
if (d == NULL) { |
410 |
} |
} |
411 |
memset(d, 0, sizeof(struct macepci_data)); |
memset(d, 0, sizeof(struct macepci_data)); |
412 |
|
|
413 |
d->pci_data = bus_pci_init(pciirq); |
d->pci_data = bus_pci_init(machine, pciirq, 0,0, 0,0,0, 0,0,0); |
414 |
|
|
415 |
memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH, |
memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH, |
416 |
dev_macepci_access, (void *)d, MEM_DEFAULT, NULL); |
dev_macepci_access, (void *)d, DM_DEFAULT, NULL); |
417 |
|
|
418 |
return d->pci_data; |
return d->pci_data; |
419 |
} |
} |
768 |
/* |
/* |
769 |
* dev_sgi_mec_access(): |
* dev_sgi_mec_access(): |
770 |
*/ |
*/ |
771 |
int dev_sgi_mec_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(sgi_mec) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
772 |
{ |
{ |
773 |
struct sgi_mec_data *d = (struct sgi_mec_data *) extra; |
struct sgi_mec_data *d = (struct sgi_mec_data *) extra; |
774 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
775 |
int regnr; |
int regnr; |
776 |
|
|
777 |
idata = memory_readmax64(cpu, data, len); |
if (writeflag == MEM_WRITE) |
778 |
|
idata = memory_readmax64(cpu, data, len); |
779 |
|
|
780 |
regnr = relative_addr / sizeof(uint64_t); |
regnr = relative_addr / sizeof(uint64_t); |
781 |
|
|
782 |
/* Treat most registers as read/write, by default. */ |
/* Treat most registers as read/write, by default. */ |
955 |
|
|
956 |
memory_device_register(mem, name2, baseaddr, |
memory_device_register(mem, name2, baseaddr, |
957 |
DEV_SGI_MEC_LENGTH, dev_sgi_mec_access, (void *)d, |
DEV_SGI_MEC_LENGTH, dev_sgi_mec_access, (void *)d, |
958 |
MEM_DEFAULT, NULL); |
DM_DEFAULT, NULL); |
959 |
|
|
960 |
machine_add_tickfunction(machine, dev_sgi_mec_tick, d, MEC_TICK_SHIFT); |
machine_add_tickfunction(machine, dev_sgi_mec_tick, d, |
961 |
|
MEC_TICK_SHIFT, 0.0); |
962 |
|
|
963 |
net_add_nic(machine->emul->net, d, macaddr); |
net_add_nic(machine->emul->net, d, macaddr); |
964 |
} |
} |
975 |
/* |
/* |
976 |
* dev_sgi_ust_access(): |
* dev_sgi_ust_access(): |
977 |
*/ |
*/ |
978 |
int dev_sgi_ust_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(sgi_ust) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
979 |
{ |
{ |
980 |
struct sgi_ust_data *d = (struct sgi_ust_data *) extra; |
struct sgi_ust_data *d = (struct sgi_ust_data *) extra; |
981 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
1025 |
|
|
1026 |
memory_device_register(mem, "sgi_ust", baseaddr, |
memory_device_register(mem, "sgi_ust", baseaddr, |
1027 |
DEV_SGI_UST_LENGTH, dev_sgi_ust_access, (void *)d, |
DEV_SGI_UST_LENGTH, dev_sgi_ust_access, (void *)d, |
1028 |
MEM_DEFAULT, NULL); |
DM_DEFAULT, NULL); |
1029 |
} |
} |
1030 |
|
|
1031 |
|
|
1037 |
* memory. Used by (at least) the SGI O2 PROM. |
* memory. Used by (at least) the SGI O2 PROM. |
1038 |
* |
* |
1039 |
* Actually, it seems to be used for graphics output as well. (?) |
* Actually, it seems to be used for graphics output as well. (?) |
1040 |
* TODO: Run the O2's prom and try to figure out what it really does. |
* The O2's PROM uses it to output graphics. |
1041 |
*/ |
*/ |
1042 |
/* #define debug fatal */ |
/* #define debug fatal */ |
1043 |
|
/* #define MTE_DEBUG */ |
1044 |
#define ZERO_CHUNK_LEN 4096 |
#define ZERO_CHUNK_LEN 4096 |
1045 |
|
|
1046 |
struct sgi_mte_data { |
struct sgi_mte_data { |
1047 |
uint64_t reg[DEV_SGI_MTE_LENGTH / sizeof(uint64_t)]; |
uint32_t reg[DEV_SGI_MTE_LENGTH / sizeof(uint32_t)]; |
1048 |
}; |
}; |
1049 |
|
|
1050 |
/* |
/* |
1051 |
* dev_sgi_mte_access(): |
* dev_sgi_mte_access(): |
1052 |
*/ |
*/ |
1053 |
int dev_sgi_mte_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(sgi_mte) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
1054 |
{ |
{ |
1055 |
struct sgi_mte_data *d = (struct sgi_mte_data *) extra; |
struct sgi_mte_data *d = (struct sgi_mte_data *) extra; |
1056 |
uint64_t first_addr, last_addr, zerobuflen, fill_addr, fill_len; |
uint64_t first_addr, last_addr, zerobuflen, fill_addr, fill_len; |
1059 |
int regnr; |
int regnr; |
1060 |
|
|
1061 |
idata = memory_readmax64(cpu, data, len); |
idata = memory_readmax64(cpu, data, len); |
1062 |
regnr = relative_addr / sizeof(uint64_t); |
regnr = relative_addr / sizeof(uint32_t); |
1063 |
|
|
1064 |
|
/* |
1065 |
|
* Treat all registers as read/write, by default. Sometimes these |
1066 |
|
* are accessed as 32-bit words, sometimes as 64-bit words. |
1067 |
|
*/ |
1068 |
|
if (len != 4) { |
1069 |
|
if (writeflag == MEM_WRITE) { |
1070 |
|
d->reg[regnr] = idata >> 32; |
1071 |
|
d->reg[regnr+1] = idata; |
1072 |
|
} else |
1073 |
|
odata = ((uint64_t)d->reg[regnr] << 32) + |
1074 |
|
d->reg[regnr+1]; |
1075 |
|
} |
1076 |
|
|
|
/* Treat all registers as read/write, by default. */ |
|
1077 |
if (writeflag == MEM_WRITE) |
if (writeflag == MEM_WRITE) |
1078 |
d->reg[regnr] = idata; |
d->reg[regnr] = idata; |
1079 |
else |
else |
1080 |
odata = d->reg[regnr]; |
odata = d->reg[regnr]; |
1081 |
|
|
1082 |
|
#ifdef MTE_DEBUG |
1083 |
|
if (writeflag == MEM_WRITE && relative_addr >= 0x2000 && |
1084 |
|
relative_addr < 0x3000) |
1085 |
|
fatal("[ MTE: 0x%08x: 0x%016llx ]\n", (int)relative_addr, |
1086 |
|
(long long)idata); |
1087 |
|
#endif |
1088 |
|
|
1089 |
/* |
/* |
1090 |
* I've not found any docs about this 'mte' device at all, so this is |
* I've not found any docs about this 'mte' device at all, so this is |
1091 |
* just a guess. The mte seems to be used for copying and zeroing |
* just a guess. The mte seems to be used for copying and zeroing |
1092 |
* chunks of memory. |
* chunks of memory. |
1093 |
* |
* |
1094 |
* [ sgi_mte: unimplemented write to address 0x3030, data=0x00000000003da000 ] <-- first address |
* write to 0x3030, data=0x00000000003da000 ] <-- first address |
1095 |
* [ sgi_mte: unimplemented write to address 0x3038, data=0x00000000003f9fff ] <-- last address |
* write to 0x3038, data=0x00000000003f9fff ] <-- last address |
1096 |
* [ sgi_mte: unimplemented write to address 0x3018, data=0x0000000000000000 ] <-- what to fill? |
* write to 0x3018, data=0x0000000000000000 ] <-- what to fill? |
1097 |
* [ sgi_mte: unimplemented write to address 0x3008, data=0x00000000ffffffff ] <-- ? |
* write to 0x3008, data=0x00000000ffffffff ] <-- ? |
1098 |
* [ sgi_mte: unimplemented write to address 0x3800, data=0x0000000000000011 ] <-- operation (0x11 = zerofill) |
* write to 0x3800, data=0x0000000000000011 ] <-- operation |
1099 |
|
* (0x11 = zerofill) |
1100 |
* |
* |
1101 |
* [ sgi_mte: unimplemented write to address 0x1700, data=0x80001ea080001ea1 ] <-- also containing the address to fill (?) |
* write to 0x1700, data=0x80001ea080001ea1 <-- also containing the |
1102 |
* [ sgi_mte: unimplemented write to address 0x1708, data=0x80001ea280001ea3 ] |
* write to 0x1708, data=0x80001ea280001ea3 address to fill (?) |
1103 |
* [ sgi_mte: unimplemented write to address 0x1710, data=0x80001ea480001ea5 ] |
* write to 0x1710, data=0x80001ea480001ea5 |
1104 |
* ... |
* ... |
1105 |
* [ sgi_mte: unimplemented write to address 0x1770, data=0x80001e9c80001e9d ] |
* write to 0x1770, data=0x80001e9c80001e9d |
1106 |
* [ sgi_mte: unimplemented write to address 0x1778, data=0x80001e9e80001e9f ] |
* write to 0x1778, data=0x80001e9e80001e9f |
1107 |
*/ |
*/ |
1108 |
switch (relative_addr) { |
switch (relative_addr) { |
1109 |
|
|
1134 |
case 0x1778: |
case 0x1778: |
1135 |
break; |
break; |
1136 |
|
|
1137 |
#if 1 |
/* Graphics stuff? No warning: */ |
1138 |
case 0x2074: |
case 0x2018: |
1139 |
{ |
case 0x2060: |
1140 |
/* This seems to have to do with graphical output: |
case 0x2070: |
1141 |
0x000000000xxx0yyy where x is usually 0..1279 and y is 0..1023? */ |
case 0x2074: |
1142 |
/* Gaaah... */ |
case 0x20c0: |
1143 |
int x = (idata >> 16) & 0xfff; |
case 0x20c4: |
1144 |
int y = idata & 0xfff; |
case 0x20d0: |
1145 |
int addr; |
case 0x21b0: |
1146 |
unsigned char buf[3]; |
case 0x21b8: |
1147 |
printf("x = %i, y = %i\n", x, y); |
break; |
1148 |
buf[0] = buf[1] = buf[2] = random() | 0x80; |
|
1149 |
addr = (x/2 + (y/2)*640) * 3; |
/* Perform graphics operation: */ |
1150 |
if (x < 640 && y < 480) |
case 0x21f8: |
1151 |
cpu->memory_rw(cpu, cpu->mem, 0x38000000 + addr, |
{ |
1152 |
buf, 3, MEM_WRITE, NO_EXCEPTIONS | PHYSICAL); |
uint32_t op = d->reg[0x2060 / sizeof(uint32_t)]; |
1153 |
|
uint32_t color = d->reg[0x20d0 / sizeof(uint32_t)]&255; |
1154 |
|
uint32_t x1 = (d->reg[0x2070 / sizeof(uint32_t)] |
1155 |
|
>> 16) & 0xfff; |
1156 |
|
uint32_t y1 = d->reg[0x2070 / sizeof(uint32_t)]& 0xfff; |
1157 |
|
uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)] |
1158 |
|
>> 16) & 0xfff; |
1159 |
|
uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff; |
1160 |
|
uint32_t y; |
1161 |
|
|
1162 |
|
op >>= 24; |
1163 |
|
|
1164 |
|
switch (op) { |
1165 |
|
case 1: /* Unknown. Used after drawing bitmaps? */ |
1166 |
|
break; |
1167 |
|
case 3: /* Fill: */ |
1168 |
|
if (x2 < x1) { |
1169 |
|
int tmp = x1; x1 = x2; x2 = tmp; |
1170 |
|
} |
1171 |
|
if (y2 < y1) { |
1172 |
|
int tmp = y1; y1 = y2; y2 = tmp; |
1173 |
|
} |
1174 |
|
for (y=y1; y<=y2; y++) { |
1175 |
|
unsigned char buf[1280]; |
1176 |
|
int length = x2-x1+1; |
1177 |
|
int addr = (x1 + y*1280); |
1178 |
|
if (length < 1) |
1179 |
|
length = 1; |
1180 |
|
memset(buf, color, length); |
1181 |
|
if (x1 < 1280 && y < 1024) |
1182 |
|
cpu->memory_rw(cpu, cpu->mem, |
1183 |
|
0x38000000 + addr, buf, |
1184 |
|
length, MEM_WRITE, |
1185 |
|
NO_EXCEPTIONS | PHYSICAL); |
1186 |
|
} |
1187 |
|
break; |
1188 |
|
|
1189 |
|
default:fatal("\n--- MTE OP %i color 0x%02x: %i,%i - " |
1190 |
|
"%i,%i\n\n", op, color, x1,y1, x2,y2); |
1191 |
|
} |
1192 |
|
} |
1193 |
|
break; |
1194 |
|
|
1195 |
|
case 0x29f0: |
1196 |
|
/* Pixel output: */ |
1197 |
|
{ |
1198 |
|
uint32_t data = d->reg[0x20c4 / sizeof(uint32_t)]; |
1199 |
|
uint32_t color = d->reg[0x20d0 / sizeof(uint32_t)]&255; |
1200 |
|
uint32_t x1 = (d->reg[0x2070 / sizeof(uint32_t)] |
1201 |
|
>> 16) & 0xfff; |
1202 |
|
uint32_t y1 = d->reg[0x2070 / sizeof(uint32_t)]& 0xfff; |
1203 |
|
uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)] |
1204 |
|
>> 16) & 0xfff; |
1205 |
|
uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff; |
1206 |
|
size_t x, y; |
1207 |
|
|
1208 |
|
if (x2 < x1) { |
1209 |
|
int tmp = x1; x1 = x2; x2 = tmp; |
1210 |
|
} |
1211 |
|
if (y2 < y1) { |
1212 |
|
int tmp = y1; y1 = y2; y2 = tmp; |
1213 |
|
} |
1214 |
|
if (x2-x1 <= 15) |
1215 |
|
data <<= 16; |
1216 |
|
|
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 |
|
|
|
} |
|
|
break; |
|
|
#endif |
|
1236 |
|
|
1237 |
/* Operations: */ |
/* Operations: */ |
1238 |
case 0x3800: |
case 0x3800: |
1239 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
1240 |
switch (idata) { |
switch (idata) { |
1241 |
case 0x11: /* zerofill */ |
case 0x11: /* zerofill */ |
1242 |
first_addr = d->reg[0x3030 / sizeof(uint64_t)]; |
first_addr = d->reg[0x3030 / sizeof(uint32_t)]; |
1243 |
last_addr = d->reg[0x3038 / sizeof(uint64_t)]; |
last_addr = d->reg[0x3038 / sizeof(uint32_t)]; |
1244 |
zerobuflen = last_addr - first_addr + 1; |
zerobuflen = last_addr - first_addr + 1; |
1245 |
debug("[ sgi_mte: zerofill: first = 0x%016llx, last = 0x%016llx, length = 0x%llx ]\n", |
debug("[ sgi_mte: zerofill: first = 0x%016llx," |
1246 |
(long long)first_addr, (long long)last_addr, (long long)zerobuflen); |
" last = 0x%016llx, length = 0x%llx ]\n", |
1247 |
|
(long long)first_addr, (long long) |
1248 |
|
last_addr, (long long)zerobuflen); |
1249 |
|
|
1250 |
/* TODO: is there a better way to implement this? */ |
/* TODO: is there a better way to |
1251 |
|
implement this? */ |
1252 |
memset(zerobuf, 0, sizeof(zerobuf)); |
memset(zerobuf, 0, sizeof(zerobuf)); |
1253 |
fill_addr = first_addr; |
fill_addr = first_addr; |
1254 |
while (zerobuflen != 0) { |
while (zerobuflen != 0) { |
1265 |
|
|
1266 |
break; |
break; |
1267 |
default: |
default: |
1268 |
fatal("[ sgi_mte: UNKNOWN operation 0x%x ]\n", idata); |
fatal("[ sgi_mte: UNKNOWN operation " |
1269 |
|
"0x%x ]\n", idata); |
1270 |
} |
} |
1271 |
} |
} |
1272 |
break; |
break; |
1273 |
default: |
default: |
1274 |
if (writeflag == MEM_WRITE) |
if (writeflag == MEM_WRITE) |
1275 |
debug("[ sgi_mte: unimplemented write to address 0x%llx, data=0x%016llx ]\n", (long long)relative_addr, (long long)idata); |
debug("[ sgi_mte: unimplemented write to " |
1276 |
|
"address 0x%llx, data=0x%016llx ]\n", |
1277 |
|
(long long)relative_addr, (long long)idata); |
1278 |
else |
else |
1279 |
debug("[ sgi_mte: unimplemented read from address 0x%llx ]\n", (long long)relative_addr); |
debug("[ sgi_mte: unimplemented read from address" |
1280 |
|
" 0x%llx ]\n", (long long)relative_addr); |
1281 |
} |
} |
1282 |
|
|
1283 |
if (writeflag == MEM_READ) |
if (writeflag == MEM_READ) |
1300 |
memset(d, 0, sizeof(struct sgi_mte_data)); |
memset(d, 0, sizeof(struct sgi_mte_data)); |
1301 |
|
|
1302 |
memory_device_register(mem, "sgi_mte", baseaddr, DEV_SGI_MTE_LENGTH, |
memory_device_register(mem, "sgi_mte", baseaddr, DEV_SGI_MTE_LENGTH, |
1303 |
dev_sgi_mte_access, (void *)d, MEM_DEFAULT, NULL); |
dev_sgi_mte_access, (void *)d, DM_DEFAULT, NULL); |
1304 |
} |
} |
1305 |
|
|