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.32 2005/08/19 09:43:35 debug Exp $ |
* $Id: dev_sgi_ip32.c,v 1.46 2006/08/30 15:07:47 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. |
|
* |
|
|
* NetBSD 2.0 complains about "unknown" crime for 0x11, |
|
|
* but I guess that's something one has to live with. |
|
124 |
* |
* |
125 |
* (TODO?) |
* NetBSD 2.0 complains about "unknown" crime for 0x11, but I guess |
126 |
|
* that's something one has to live with. (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, |
414 |
|
pciirq, |
415 |
|
0, |
416 |
|
0, |
417 |
|
0, |
418 |
|
0, |
419 |
|
0, |
420 |
|
0x18000003, /* ISA portbase */ |
421 |
|
0, |
422 |
|
0); |
423 |
|
|
424 |
memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH, |
memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH, |
425 |
dev_macepci_access, (void *)d, MEM_DEFAULT, NULL); |
dev_macepci_access, (void *)d, DM_DEFAULT, NULL); |
426 |
|
|
427 |
return d->pci_data; |
return d->pci_data; |
428 |
} |
} |
777 |
/* |
/* |
778 |
* dev_sgi_mec_access(): |
* dev_sgi_mec_access(): |
779 |
*/ |
*/ |
780 |
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) |
|
781 |
{ |
{ |
782 |
struct sgi_mec_data *d = (struct sgi_mec_data *) extra; |
struct sgi_mec_data *d = (struct sgi_mec_data *) extra; |
783 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
784 |
int regnr; |
int regnr; |
785 |
|
|
786 |
idata = memory_readmax64(cpu, data, len); |
if (writeflag == MEM_WRITE) |
787 |
|
idata = memory_readmax64(cpu, data, len); |
788 |
|
|
789 |
regnr = relative_addr / sizeof(uint64_t); |
regnr = relative_addr / sizeof(uint64_t); |
790 |
|
|
791 |
/* Treat most registers as read/write, by default. */ |
/* Treat most registers as read/write, by default. */ |
964 |
|
|
965 |
memory_device_register(mem, name2, baseaddr, |
memory_device_register(mem, name2, baseaddr, |
966 |
DEV_SGI_MEC_LENGTH, dev_sgi_mec_access, (void *)d, |
DEV_SGI_MEC_LENGTH, dev_sgi_mec_access, (void *)d, |
967 |
MEM_DEFAULT, NULL); |
DM_DEFAULT, NULL); |
968 |
|
|
969 |
machine_add_tickfunction(machine, dev_sgi_mec_tick, d, MEC_TICK_SHIFT); |
machine_add_tickfunction(machine, dev_sgi_mec_tick, d, |
970 |
|
MEC_TICK_SHIFT, 0.0); |
971 |
|
|
972 |
net_add_nic(machine->emul->net, d, macaddr); |
net_add_nic(machine->emul->net, d, macaddr); |
973 |
} |
} |
984 |
/* |
/* |
985 |
* dev_sgi_ust_access(): |
* dev_sgi_ust_access(): |
986 |
*/ |
*/ |
987 |
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) |
|
988 |
{ |
{ |
989 |
struct sgi_ust_data *d = (struct sgi_ust_data *) extra; |
struct sgi_ust_data *d = (struct sgi_ust_data *) extra; |
990 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
1034 |
|
|
1035 |
memory_device_register(mem, "sgi_ust", baseaddr, |
memory_device_register(mem, "sgi_ust", baseaddr, |
1036 |
DEV_SGI_UST_LENGTH, dev_sgi_ust_access, (void *)d, |
DEV_SGI_UST_LENGTH, dev_sgi_ust_access, (void *)d, |
1037 |
MEM_DEFAULT, NULL); |
DM_DEFAULT, NULL); |
1038 |
} |
} |
1039 |
|
|
1040 |
|
|
1059 |
/* |
/* |
1060 |
* dev_sgi_mte_access(): |
* dev_sgi_mte_access(): |
1061 |
*/ |
*/ |
1062 |
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) |
|
1063 |
{ |
{ |
1064 |
struct sgi_mte_data *d = (struct sgi_mte_data *) extra; |
struct sgi_mte_data *d = (struct sgi_mte_data *) extra; |
1065 |
uint64_t first_addr, last_addr, zerobuflen, fill_addr, fill_len; |
uint64_t first_addr, last_addr, zerobuflen, fill_addr, fill_len; |
1166 |
uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)] |
uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)] |
1167 |
>> 16) & 0xfff; |
>> 16) & 0xfff; |
1168 |
uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff; |
uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff; |
1169 |
int y; |
uint32_t y; |
1170 |
|
|
1171 |
op >>= 24; |
op >>= 24; |
1172 |
|
|
1212 |
uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)] |
uint32_t x2 = (d->reg[0x2074 / sizeof(uint32_t)] |
1213 |
>> 16) & 0xfff; |
>> 16) & 0xfff; |
1214 |
uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff; |
uint32_t y2 = d->reg[0x2074 / sizeof(uint32_t)]& 0xfff; |
1215 |
int x,y; |
size_t x, y; |
1216 |
|
|
1217 |
if (x2 < x1) { |
if (x2 < x1) { |
1218 |
int tmp = x1; x1 = x2; x2 = tmp; |
int tmp = x1; x1 = x2; x2 = tmp; |
1219 |
} |
} |
1222 |
} |
} |
1223 |
if (x2-x1 <= 15) |
if (x2-x1 <= 15) |
1224 |
data <<= 16; |
data <<= 16; |
1225 |
|
|
1226 |
x=x1; y=y1; |
x=x1; y=y1; |
1227 |
while (x <= x2 && y <= y2) { |
while (x <= x2 && y <= y2) { |
1228 |
unsigned char buf = color; |
unsigned char buf = color; |
1309 |
memset(d, 0, sizeof(struct sgi_mte_data)); |
memset(d, 0, sizeof(struct sgi_mte_data)); |
1310 |
|
|
1311 |
memory_device_register(mem, "sgi_mte", baseaddr, DEV_SGI_MTE_LENGTH, |
memory_device_register(mem, "sgi_mte", baseaddr, DEV_SGI_MTE_LENGTH, |
1312 |
dev_sgi_mte_access, (void *)d, MEM_DEFAULT, NULL); |
dev_sgi_mte_access, (void *)d, DM_DEFAULT, NULL); |
1313 |
} |
} |
1314 |
|
|