1 |
/* |
/* |
2 |
* Copyright (C) 2003-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2003-2007 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.45 2006/03/04 12:38:48 debug Exp $ |
* $Id: dev_sgi_ip32.c,v 1.53 2007/06/15 19:57:34 debug Exp $ |
29 |
* |
* |
30 |
* SGI IP32 devices. |
* COMMENT: SGI IP32 stuff (CRIME, MACE, MACEPCI, mec, ust, mte) |
31 |
* |
* |
32 |
* o) CRIME |
* o) CRIME |
33 |
* o) MACE |
* o) MACE |
44 |
#include "bus_pci.h" |
#include "bus_pci.h" |
45 |
#include "console.h" |
#include "console.h" |
46 |
#include "cpu.h" |
#include "cpu.h" |
47 |
|
#include "device.h" |
48 |
#include "devices.h" |
#include "devices.h" |
49 |
#include "emul.h" |
#include "emul.h" |
50 |
#include "machine.h" |
#include "machine.h" |
53 |
#include "net.h" |
#include "net.h" |
54 |
|
|
55 |
#include "crimereg.h" |
#include "crimereg.h" |
|
|
|
56 |
#include "if_mecreg.h" |
#include "if_mecreg.h" |
57 |
|
#include "sgi_macereg.h" |
58 |
|
|
59 |
|
|
60 |
#define CRIME_TICKSHIFT 14 |
#define CRIME_TICKSHIFT 14 |
66 |
uint32_t reg[DEV_MACEPCI_LENGTH / 4]; |
uint32_t reg[DEV_MACEPCI_LENGTH / 4]; |
67 |
}; |
}; |
68 |
|
|
69 |
|
#define DEV_CRIME_LENGTH 0x1000 |
70 |
|
struct crime_data { |
71 |
|
unsigned char reg[DEV_CRIME_LENGTH]; |
72 |
|
struct interrupt irq; |
73 |
|
int use_fb; |
74 |
|
}; |
75 |
|
|
76 |
|
|
77 |
|
/* |
78 |
|
* crime_interrupt_assert(): |
79 |
|
* crime_interrupt_deassert(): |
80 |
|
*/ |
81 |
|
void crime_interrupt_assert(struct interrupt *interrupt) |
82 |
|
{ |
83 |
|
struct crime_data *d = (struct crime_data *) interrupt->extra; |
84 |
|
uint32_t line = interrupt->line, asserted; |
85 |
|
|
86 |
|
d->reg[CRIME_INTSTAT + 4] |= ((line >> 24) & 255); |
87 |
|
d->reg[CRIME_INTSTAT + 5] |= ((line >> 16) & 255); |
88 |
|
d->reg[CRIME_INTSTAT + 6] |= ((line >> 8) & 255); |
89 |
|
d->reg[CRIME_INTSTAT + 7] |= (line & 255); |
90 |
|
|
91 |
|
asserted = |
92 |
|
(d->reg[CRIME_INTSTAT + 4] & d->reg[CRIME_INTMASK + 4]) | |
93 |
|
(d->reg[CRIME_INTSTAT + 5] & d->reg[CRIME_INTMASK + 5]) | |
94 |
|
(d->reg[CRIME_INTSTAT + 6] & d->reg[CRIME_INTMASK + 6]) | |
95 |
|
(d->reg[CRIME_INTSTAT + 7] & d->reg[CRIME_INTMASK + 7]); |
96 |
|
|
97 |
|
if (asserted) |
98 |
|
INTERRUPT_ASSERT(d->irq); |
99 |
|
} |
100 |
|
void crime_interrupt_deassert(struct interrupt *interrupt) |
101 |
|
{ |
102 |
|
struct crime_data *d = (struct crime_data *) interrupt->extra; |
103 |
|
uint32_t line = interrupt->line, asserted; |
104 |
|
|
105 |
|
d->reg[CRIME_INTSTAT + 4] &= ~((line >> 24) & 255); |
106 |
|
d->reg[CRIME_INTSTAT + 5] &= ~((line >> 16) & 255); |
107 |
|
d->reg[CRIME_INTSTAT + 6] &= ~((line >> 8) & 255); |
108 |
|
d->reg[CRIME_INTSTAT + 7] &= ~(line & 255); |
109 |
|
|
110 |
|
asserted = |
111 |
|
(d->reg[CRIME_INTSTAT + 4] & d->reg[CRIME_INTMASK + 4]) | |
112 |
|
(d->reg[CRIME_INTSTAT + 5] & d->reg[CRIME_INTMASK + 5]) | |
113 |
|
(d->reg[CRIME_INTSTAT + 6] & d->reg[CRIME_INTMASK + 6]) | |
114 |
|
(d->reg[CRIME_INTSTAT + 7] & d->reg[CRIME_INTMASK + 7]); |
115 |
|
|
116 |
|
if (!asserted) |
117 |
|
INTERRUPT_DEASSERT(d->irq); |
118 |
|
} |
119 |
|
|
120 |
|
|
121 |
/* |
/* |
122 |
* dev_crime_tick(): |
* dev_crime_tick(): |
131 |
* A R10000 is detected as running at |
* A R10000 is detected as running at |
132 |
* CRIME_SPEED_FACTOR * 66 MHz. (TODO: this is not correct anymore) |
* CRIME_SPEED_FACTOR * 66 MHz. (TODO: this is not correct anymore) |
133 |
*/ |
*/ |
134 |
void dev_crime_tick(struct cpu *cpu, void *extra) |
DEVICE_TICK(crime) |
135 |
{ |
{ |
136 |
int j, carry, old, new, add_byte; |
int j, carry, old, new, add_byte; |
137 |
uint64_t what_to_add = (1<<CRIME_TICKSHIFT) |
uint64_t what_to_add = (1<<CRIME_TICKSHIFT) |
155 |
} |
} |
156 |
|
|
157 |
|
|
|
/* |
|
|
* dev_crime_access(): |
|
|
*/ |
|
158 |
DEVICE_ACCESS(crime) |
DEVICE_ACCESS(crime) |
159 |
{ |
{ |
160 |
struct crime_data *d = extra; |
struct crime_data *d = extra; |
200 |
else |
else |
201 |
memcpy(data, &d->reg[relative_addr], len); |
memcpy(data, &d->reg[relative_addr], len); |
202 |
|
|
|
if ((relative_addr >= 0x18 && relative_addr <= 0x1f) || |
|
|
(relative_addr+len-1 >= 0x18 && relative_addr+len-1 <= 0x1f)) { |
|
|
/* |
|
|
* Force interrupt re-assertion: |
|
|
* |
|
|
* NOTE: Ugly hack. Hopefully CRMERR is never used. |
|
|
*/ |
|
|
#if 0 |
|
|
/* |
|
|
No. If this is enabled, the mec bugs out on either NetBSD or OpenBSD. |
|
|
TODO. |
|
|
*/ |
|
|
cpu_interrupt_ack(cpu, 8); /* CRM_INT_CRMERR); */ |
|
|
#endif |
|
|
} |
|
|
|
|
203 |
switch (relative_addr) { |
switch (relative_addr) { |
204 |
case CRIME_CONTROL: /* 0x008 */ |
case CRIME_CONTROL: /* 0x008 */ |
205 |
/* TODO: 64-bit write to CRIME_CONTROL, but some things |
/* TODO: 64-bit write to CRIME_CONTROL, but some things |
228 |
"control 0x%016llx ]\n", (long long)idata); |
"control 0x%016llx ]\n", (long long)idata); |
229 |
} |
} |
230 |
break; |
break; |
231 |
#if 0 |
|
232 |
case CRIME_INTSTAT: /* 0x010, Current interrupt status */ |
case CRIME_INTSTAT: /* 0x010, Current interrupt status */ |
233 |
case 0x14: |
case CRIME_INTSTAT + 4: |
234 |
case CRIME_INTMASK: /* 0x018, Current interrupt mask */ |
case CRIME_INTMASK: /* 0x018, Current interrupt mask */ |
235 |
case 0x1c: |
case CRIME_INTMASK + 4: |
236 |
|
if ((d->reg[CRIME_INTSTAT + 4] & d->reg[CRIME_INTMASK + 4]) | |
237 |
|
(d->reg[CRIME_INTSTAT + 5] & d->reg[CRIME_INTMASK + 5]) | |
238 |
|
(d->reg[CRIME_INTSTAT + 6] & d->reg[CRIME_INTMASK + 6]) | |
239 |
|
(d->reg[CRIME_INTSTAT + 7] & d->reg[CRIME_INTMASK + 7]) ) |
240 |
|
INTERRUPT_ASSERT(d->irq); |
241 |
|
else |
242 |
|
INTERRUPT_DEASSERT(d->irq); |
243 |
|
break; |
244 |
case 0x34: |
case 0x34: |
245 |
/* don't dump debug info for these */ |
/* don't dump debug info for these */ |
246 |
break; |
break; |
247 |
#endif |
|
248 |
default: |
default: |
249 |
if (writeflag==MEM_READ) { |
if (writeflag==MEM_READ) { |
250 |
debug("[ crime: read from 0x%x, len=%i:", |
debug("[ crime: read from 0x%x, len=%i:", |
267 |
/* |
/* |
268 |
* dev_crime_init(): |
* dev_crime_init(): |
269 |
*/ |
*/ |
270 |
struct crime_data *dev_crime_init(struct machine *machine, struct memory *mem, |
void dev_crime_init(struct machine *machine, struct memory *mem, |
271 |
uint64_t baseaddr, int irq_nr, int use_fb) |
uint64_t baseaddr, char *irq_path, int use_fb) |
272 |
{ |
{ |
273 |
struct crime_data *d; |
struct crime_data *d; |
274 |
|
char tmpstr[200]; |
275 |
|
int i; |
276 |
|
|
277 |
d = malloc(sizeof(struct crime_data)); |
CHECK_ALLOCATION(d = malloc(sizeof(struct crime_data))); |
|
if (d == NULL) { |
|
|
fprintf(stderr, "out of memory\n"); |
|
|
exit(1); |
|
|
} |
|
278 |
memset(d, 0, sizeof(struct crime_data)); |
memset(d, 0, sizeof(struct crime_data)); |
279 |
d->irq_nr = irq_nr; |
|
280 |
d->use_fb = use_fb; |
d->use_fb = use_fb; |
281 |
|
|
282 |
|
INTERRUPT_CONNECT(irq_path, d->irq); |
283 |
|
|
284 |
|
/* Register 32 crime interrupts (hexadecimal names): */ |
285 |
|
for (i=0; i<32; i++) { |
286 |
|
struct interrupt template; |
287 |
|
char name[400]; |
288 |
|
snprintf(name, sizeof(name), "%s.crime.0x%x", irq_path, 1 << i); |
289 |
|
memset(&template, 0, sizeof(template)); |
290 |
|
template.line = 1 << i; |
291 |
|
template.name = name; |
292 |
|
template.extra = d; |
293 |
|
template.interrupt_assert = crime_interrupt_assert; |
294 |
|
template.interrupt_deassert = crime_interrupt_deassert; |
295 |
|
interrupt_handler_register(&template); |
296 |
|
} |
297 |
|
|
298 |
memory_device_register(mem, "crime", baseaddr, DEV_CRIME_LENGTH, |
memory_device_register(mem, "crime", baseaddr, DEV_CRIME_LENGTH, |
299 |
dev_crime_access, d, DM_DEFAULT, NULL); |
dev_crime_access, d, DM_DEFAULT, NULL); |
|
machine_add_tickfunction(machine, dev_crime_tick, d, |
|
|
CRIME_TICKSHIFT, 0.0); |
|
300 |
|
|
301 |
return d; |
snprintf(tmpstr, sizeof(tmpstr), "mace addr=0x1f310000 irq=%s.crime", |
302 |
|
irq_path); |
303 |
|
device_add(machine, tmpstr); |
304 |
|
|
305 |
|
machine_add_tickfunction(machine, dev_crime_tick, d, |
306 |
|
CRIME_TICKSHIFT); |
307 |
} |
} |
308 |
|
|
309 |
|
|
310 |
/****************************************************************************/ |
/****************************************************************************/ |
311 |
|
|
312 |
|
|
313 |
|
#define DEV_MACE_LENGTH 0x100 |
314 |
|
struct mace_data { |
315 |
|
unsigned char reg[DEV_MACE_LENGTH]; |
316 |
|
struct interrupt irq_periph; |
317 |
|
struct interrupt irq_misc; |
318 |
|
}; |
319 |
|
|
320 |
|
|
321 |
/* |
/* |
322 |
* dev_mace_access(): |
* mace_interrupt_assert(): |
323 |
|
* mace_interrupt_deassert(): |
324 |
*/ |
*/ |
325 |
|
void mace_interrupt_assert(struct interrupt *interrupt) |
326 |
|
{ |
327 |
|
struct mace_data *d = (struct mace_data *) interrupt->extra; |
328 |
|
uint32_t line = 1 << interrupt->line; |
329 |
|
|
330 |
|
d->reg[MACE_ISA_INT_STATUS + 4] |= ((line >> 24) & 255); |
331 |
|
d->reg[MACE_ISA_INT_STATUS + 5] |= ((line >> 16) & 255); |
332 |
|
d->reg[MACE_ISA_INT_STATUS + 6] |= ((line >> 8) & 255); |
333 |
|
d->reg[MACE_ISA_INT_STATUS + 7] |= (line & 255); |
334 |
|
|
335 |
|
/* High bits = PERIPH */ |
336 |
|
if ((d->reg[MACE_ISA_INT_STATUS+4] & d->reg[MACE_ISA_INT_MASK+4]) | |
337 |
|
(d->reg[MACE_ISA_INT_STATUS+5] & d->reg[MACE_ISA_INT_MASK+5])) |
338 |
|
INTERRUPT_ASSERT(d->irq_periph); |
339 |
|
|
340 |
|
/* Low bits = MISC */ |
341 |
|
if ((d->reg[MACE_ISA_INT_STATUS+6] & d->reg[MACE_ISA_INT_MASK+6]) | |
342 |
|
(d->reg[MACE_ISA_INT_STATUS+7] & d->reg[MACE_ISA_INT_MASK+7])) |
343 |
|
INTERRUPT_ASSERT(d->irq_misc); |
344 |
|
} |
345 |
|
void mace_interrupt_deassert(struct interrupt *interrupt) |
346 |
|
{ |
347 |
|
struct mace_data *d = (struct mace_data *) interrupt->extra; |
348 |
|
uint32_t line = 1 << interrupt->line; |
349 |
|
|
350 |
|
d->reg[MACE_ISA_INT_STATUS + 4] |= ((line >> 24) & 255); |
351 |
|
d->reg[MACE_ISA_INT_STATUS + 5] |= ((line >> 16) & 255); |
352 |
|
d->reg[MACE_ISA_INT_STATUS + 6] |= ((line >> 8) & 255); |
353 |
|
d->reg[MACE_ISA_INT_STATUS + 7] |= (line & 255); |
354 |
|
|
355 |
|
/* High bits = PERIPH */ |
356 |
|
if (!((d->reg[MACE_ISA_INT_STATUS+4] & d->reg[MACE_ISA_INT_MASK+4]) | |
357 |
|
(d->reg[MACE_ISA_INT_STATUS+5] & d->reg[MACE_ISA_INT_MASK+5]))) |
358 |
|
INTERRUPT_DEASSERT(d->irq_periph); |
359 |
|
|
360 |
|
/* Low bits = MISC */ |
361 |
|
if (!((d->reg[MACE_ISA_INT_STATUS+6] & d->reg[MACE_ISA_INT_MASK+6]) | |
362 |
|
(d->reg[MACE_ISA_INT_STATUS+7] & d->reg[MACE_ISA_INT_MASK+7]))) |
363 |
|
INTERRUPT_DEASSERT(d->irq_misc); |
364 |
|
} |
365 |
|
|
366 |
|
|
367 |
DEVICE_ACCESS(mace) |
DEVICE_ACCESS(mace) |
368 |
{ |
{ |
369 |
size_t i; |
size_t i; |
374 |
else |
else |
375 |
memcpy(data, &d->reg[relative_addr], len); |
memcpy(data, &d->reg[relative_addr], len); |
376 |
|
|
|
if ((relative_addr >= 0x18 && relative_addr <= 0x1f) || |
|
|
(relative_addr+len-1 >= 0x18 && relative_addr+len-1 <= 0x1f)) |
|
|
cpu_interrupt_ack(cpu, 8); /* CRM_INT_CRMERR); */ |
|
|
|
|
377 |
switch (relative_addr) { |
switch (relative_addr) { |
378 |
#if 0 |
|
379 |
case 0x10: /* Current interrupt assertions */ |
case MACE_ISA_INT_STATUS: /* Current interrupt assertions */ |
380 |
case 0x14: |
case MACE_ISA_INT_STATUS + 4: |
381 |
/* don't dump debug info for these */ |
/* don't dump debug info for these */ |
382 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
383 |
fatal("[ NOTE/TODO: WRITE to mace intr: " |
fatal("[ NOTE/TODO: WRITE to mace intr: " |
387 |
fatal(" (len=%i) ]\n", len); |
fatal(" (len=%i) ]\n", len); |
388 |
} |
} |
389 |
break; |
break; |
390 |
case 0x18: /* Interrupt mask */ |
case MACE_ISA_INT_MASK: /* Current interrupt mask */ |
391 |
case 0x1c: |
case MACE_ISA_INT_MASK + 4: |
392 |
/* don't dump debug info for these */ |
if ((d->reg[MACE_ISA_INT_STATUS+4]&d->reg[MACE_ISA_INT_MASK+4])| |
393 |
|
(d->reg[MACE_ISA_INT_STATUS+5]&d->reg[MACE_ISA_INT_MASK+5])) |
394 |
|
INTERRUPT_ASSERT(d->irq_periph); |
395 |
|
else |
396 |
|
INTERRUPT_DEASSERT(d->irq_periph); |
397 |
|
|
398 |
|
if ((d->reg[MACE_ISA_INT_STATUS+6]&d->reg[MACE_ISA_INT_MASK+6])| |
399 |
|
(d->reg[MACE_ISA_INT_STATUS+7]&d->reg[MACE_ISA_INT_MASK+7])) |
400 |
|
INTERRUPT_ASSERT(d->irq_misc); |
401 |
|
else |
402 |
|
INTERRUPT_DEASSERT(d->irq_misc); |
403 |
break; |
break; |
404 |
#endif |
|
405 |
default: |
default: |
406 |
if (writeflag == MEM_READ) { |
if (writeflag == MEM_READ) { |
407 |
debug("[ mace: read from 0x%x:", (int)relative_addr); |
debug("[ mace: read from 0x%x:", (int)relative_addr); |
420 |
} |
} |
421 |
|
|
422 |
|
|
423 |
/* |
DEVINIT(mace) |
|
* dev_mace_init(): |
|
|
*/ |
|
|
struct mace_data *dev_mace_init(struct memory *mem, uint64_t baseaddr, |
|
|
int irqnr) |
|
424 |
{ |
{ |
425 |
struct mace_data *d; |
struct mace_data *d; |
426 |
|
char tmpstr[300]; |
427 |
|
int i; |
428 |
|
|
429 |
d = malloc(sizeof(struct mace_data)); |
CHECK_ALLOCATION(d = malloc(sizeof(struct mace_data))); |
|
if (d == NULL) { |
|
|
fprintf(stderr, "out of memory\n"); |
|
|
exit(1); |
|
|
} |
|
430 |
memset(d, 0, sizeof(struct mace_data)); |
memset(d, 0, sizeof(struct mace_data)); |
|
d->irqnr = irqnr; |
|
431 |
|
|
432 |
memory_device_register(mem, "mace", baseaddr, DEV_MACE_LENGTH, |
snprintf(tmpstr, sizeof(tmpstr), "%s.0x%x", |
433 |
dev_mace_access, d, DM_DEFAULT, NULL); |
devinit->interrupt_path, MACE_PERIPH_SERIAL); |
434 |
|
INTERRUPT_CONNECT(tmpstr, d->irq_periph); |
435 |
|
|
436 |
|
snprintf(tmpstr, sizeof(tmpstr), "%s.0x%x", |
437 |
|
devinit->interrupt_path, MACE_PERIPH_SERIAL); |
438 |
|
INTERRUPT_CONNECT(tmpstr, d->irq_misc); |
439 |
|
|
440 |
return d; |
/* |
441 |
|
* For Mace interrupts MACE_PERIPH_SERIAL and MACE_PERIPH_MISC, |
442 |
|
* register 32 mace interrupts each. |
443 |
|
*/ |
444 |
|
/* Register 32 crime interrupts (hexadecimal names): */ |
445 |
|
for (i=0; i<32; i++) { |
446 |
|
struct interrupt template; |
447 |
|
char name[400]; |
448 |
|
snprintf(name, sizeof(name), "%s.0x%x.mace.%i", |
449 |
|
devinit->interrupt_path, MACE_PERIPH_SERIAL, i); |
450 |
|
memset(&template, 0, sizeof(template)); |
451 |
|
template.line = i; |
452 |
|
template.name = name; |
453 |
|
template.extra = d; |
454 |
|
template.interrupt_assert = mace_interrupt_assert; |
455 |
|
template.interrupt_deassert = mace_interrupt_deassert; |
456 |
|
interrupt_handler_register(&template); |
457 |
|
|
458 |
|
snprintf(name, sizeof(name), "%s.0x%x.mace.%i", |
459 |
|
devinit->interrupt_path, MACE_PERIPH_MISC, i); |
460 |
|
memset(&template, 0, sizeof(template)); |
461 |
|
template.line = i; |
462 |
|
template.name = name; |
463 |
|
template.extra = d; |
464 |
|
template.interrupt_assert = mace_interrupt_assert; |
465 |
|
template.interrupt_deassert = mace_interrupt_deassert; |
466 |
|
interrupt_handler_register(&template); |
467 |
|
} |
468 |
|
|
469 |
|
memory_device_register(devinit->machine->memory, devinit->name, |
470 |
|
devinit->addr, DEV_MACE_LENGTH, dev_mace_access, d, |
471 |
|
DM_DEFAULT, NULL); |
472 |
|
|
473 |
|
devinit->return_ptr = d; |
474 |
|
return 1; |
475 |
} |
} |
476 |
|
|
477 |
|
|
478 |
/****************************************************************************/ |
/****************************************************************************/ |
479 |
|
|
480 |
|
|
|
/* |
|
|
* dev_macepci_access(): |
|
|
*/ |
|
481 |
DEVICE_ACCESS(macepci) |
DEVICE_ACCESS(macepci) |
482 |
{ |
{ |
483 |
struct macepci_data *d = (struct macepci_data *) extra; |
struct macepci_data *d = extra; |
484 |
uint64_t idata = 0, odata=0; |
uint64_t idata = 0, odata=0; |
485 |
int regnr, res = 1, bus, dev, func, pcireg; |
int regnr, res = 1, bus, dev, func, pcireg; |
486 |
|
|
545 |
* dev_macepci_init(): |
* dev_macepci_init(): |
546 |
*/ |
*/ |
547 |
struct pci_data *dev_macepci_init(struct machine *machine, |
struct pci_data *dev_macepci_init(struct machine *machine, |
548 |
struct memory *mem, uint64_t baseaddr, int pciirq) |
struct memory *mem, uint64_t baseaddr, char *irq_path) |
549 |
{ |
{ |
550 |
struct macepci_data *d = malloc(sizeof(struct macepci_data)); |
struct macepci_data *d; |
551 |
if (d == NULL) { |
|
552 |
fprintf(stderr, "out of memory\n"); |
CHECK_ALLOCATION(d = malloc(sizeof(struct macepci_data))); |
|
exit(1); |
|
|
} |
|
553 |
memset(d, 0, sizeof(struct macepci_data)); |
memset(d, 0, sizeof(struct macepci_data)); |
554 |
|
|
555 |
d->pci_data = bus_pci_init(machine, pciirq, 0,0, 0,0,0, 0,0,0); |
/* TODO: PCI vs ISA interrupt? */ |
556 |
|
|
557 |
|
d->pci_data = bus_pci_init(machine, |
558 |
|
irq_path, |
559 |
|
0, |
560 |
|
0, |
561 |
|
0, |
562 |
|
0, |
563 |
|
"TODO: pci irq path", |
564 |
|
0x18000003, /* ISA portbase */ |
565 |
|
0, |
566 |
|
irq_path); |
567 |
|
|
568 |
memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH, |
memory_device_register(mem, "macepci", baseaddr, DEV_MACEPCI_LENGTH, |
569 |
dev_macepci_access, (void *)d, DM_DEFAULT, NULL); |
dev_macepci_access, (void *)d, DM_DEFAULT, NULL); |
592 |
struct sgi_mec_data { |
struct sgi_mec_data { |
593 |
uint64_t reg[DEV_SGI_MEC_LENGTH / sizeof(uint64_t)]; |
uint64_t reg[DEV_SGI_MEC_LENGTH / sizeof(uint64_t)]; |
594 |
|
|
595 |
int irq_nr; |
struct interrupt irq; |
596 |
unsigned char macaddr[6]; |
unsigned char macaddr[6]; |
597 |
|
|
598 |
unsigned char cur_tx_packet[MAX_TX_PACKET_LEN]; |
unsigned char cur_tx_packet[MAX_TX_PACKET_LEN]; |
891 |
} |
} |
892 |
|
|
893 |
|
|
894 |
/* |
DEVICE_TICK(sgi_mec) |
|
* dev_sgi_mec_tick(): |
|
|
*/ |
|
|
void dev_sgi_mec_tick(struct cpu *cpu, void *extra) |
|
895 |
{ |
{ |
896 |
struct sgi_mec_data *d = (struct sgi_mec_data *) extra; |
struct sgi_mec_data *d = extra; |
897 |
int n = 0; |
int n = 0; |
898 |
|
|
899 |
while (mec_try_tx(cpu, d)) |
while (mec_try_tx(cpu, d)) |
909 |
sizeof(uint64_t)] & MEC_INT_STATUS_MASK)); |
sizeof(uint64_t)] & MEC_INT_STATUS_MASK)); |
910 |
fflush(stdout); |
fflush(stdout); |
911 |
#endif |
#endif |
912 |
cpu_interrupt(cpu, d->irq_nr); |
INTERRUPT_ASSERT(d->irq); |
913 |
} else |
} else |
914 |
cpu_interrupt_ack(cpu, d->irq_nr); |
INTERRUPT_DEASSERT(d->irq); |
915 |
} |
} |
916 |
|
|
917 |
|
|
|
/* |
|
|
* dev_sgi_mec_access(): |
|
|
*/ |
|
918 |
DEVICE_ACCESS(sgi_mec) |
DEVICE_ACCESS(sgi_mec) |
919 |
{ |
{ |
920 |
struct sgi_mec_data *d = (struct sgi_mec_data *) extra; |
struct sgi_mec_data *d = extra; |
921 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
922 |
int regnr; |
int regnr; |
923 |
|
|
1075 |
* dev_sgi_mec_init(): |
* dev_sgi_mec_init(): |
1076 |
*/ |
*/ |
1077 |
void dev_sgi_mec_init(struct machine *machine, struct memory *mem, |
void dev_sgi_mec_init(struct machine *machine, struct memory *mem, |
1078 |
uint64_t baseaddr, int irq_nr, unsigned char *macaddr) |
uint64_t baseaddr, char *irq_path, unsigned char *macaddr) |
1079 |
{ |
{ |
1080 |
char *name2; |
char *name2; |
1081 |
size_t nlen = 55; |
size_t nlen = 55; |
1082 |
struct sgi_mec_data *d = malloc(sizeof(struct sgi_mec_data)); |
struct sgi_mec_data *d; |
1083 |
|
|
1084 |
if (d == NULL) { |
CHECK_ALLOCATION(d = malloc(sizeof(struct sgi_mec_data))); |
|
fprintf(stderr, "out of memory\n"); |
|
|
exit(1); |
|
|
} |
|
1085 |
memset(d, 0, sizeof(struct sgi_mec_data)); |
memset(d, 0, sizeof(struct sgi_mec_data)); |
|
d->irq_nr = irq_nr; |
|
|
memcpy(d->macaddr, macaddr, 6); |
|
1086 |
|
|
1087 |
|
INTERRUPT_CONNECT(irq_path, d->irq); |
1088 |
|
memcpy(d->macaddr, macaddr, 6); |
1089 |
mec_reset(d); |
mec_reset(d); |
1090 |
|
|
1091 |
name2 = malloc(nlen); |
CHECK_ALLOCATION(name2 = malloc(nlen)); |
|
if (name2 == NULL) { |
|
|
fprintf(stderr, "out of memory in dev_sgi_mec_init()\n"); |
|
|
exit(1); |
|
|
} |
|
1092 |
snprintf(name2, nlen, "mec [%02x:%02x:%02x:%02x:%02x:%02x]", |
snprintf(name2, nlen, "mec [%02x:%02x:%02x:%02x:%02x:%02x]", |
1093 |
d->macaddr[0], d->macaddr[1], d->macaddr[2], |
d->macaddr[0], d->macaddr[1], d->macaddr[2], |
1094 |
d->macaddr[3], d->macaddr[4], d->macaddr[5]); |
d->macaddr[3], d->macaddr[4], d->macaddr[5]); |
1098 |
DM_DEFAULT, NULL); |
DM_DEFAULT, NULL); |
1099 |
|
|
1100 |
machine_add_tickfunction(machine, dev_sgi_mec_tick, d, |
machine_add_tickfunction(machine, dev_sgi_mec_tick, d, |
1101 |
MEC_TICK_SHIFT, 0.0); |
MEC_TICK_SHIFT); |
1102 |
|
|
1103 |
net_add_nic(machine->emul->net, d, macaddr); |
net_add_nic(machine->emul->net, d, macaddr); |
1104 |
} |
} |
1112 |
}; |
}; |
1113 |
|
|
1114 |
|
|
|
/* |
|
|
* dev_sgi_ust_access(): |
|
|
*/ |
|
1115 |
DEVICE_ACCESS(sgi_ust) |
DEVICE_ACCESS(sgi_ust) |
1116 |
{ |
{ |
1117 |
struct sgi_ust_data *d = (struct sgi_ust_data *) extra; |
struct sgi_ust_data *d = extra; |
1118 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
1119 |
int regnr; |
int regnr; |
1120 |
|
|
1153 |
*/ |
*/ |
1154 |
void dev_sgi_ust_init(struct memory *mem, uint64_t baseaddr) |
void dev_sgi_ust_init(struct memory *mem, uint64_t baseaddr) |
1155 |
{ |
{ |
1156 |
struct sgi_ust_data *d = malloc(sizeof(struct sgi_ust_data)); |
struct sgi_ust_data *d; |
1157 |
if (d == NULL) { |
|
1158 |
fprintf(stderr, "out of memory\n"); |
CHECK_ALLOCATION(d = malloc(sizeof(struct sgi_ust_data))); |
|
exit(1); |
|
|
} |
|
1159 |
memset(d, 0, sizeof(struct sgi_ust_data)); |
memset(d, 0, sizeof(struct sgi_ust_data)); |
1160 |
|
|
1161 |
memory_device_register(mem, "sgi_ust", baseaddr, |
memory_device_register(mem, "sgi_ust", baseaddr, |
1182 |
uint32_t reg[DEV_SGI_MTE_LENGTH / sizeof(uint32_t)]; |
uint32_t reg[DEV_SGI_MTE_LENGTH / sizeof(uint32_t)]; |
1183 |
}; |
}; |
1184 |
|
|
1185 |
/* |
|
|
* dev_sgi_mte_access(): |
|
|
*/ |
|
1186 |
DEVICE_ACCESS(sgi_mte) |
DEVICE_ACCESS(sgi_mte) |
1187 |
{ |
{ |
1188 |
struct sgi_mte_data *d = (struct sgi_mte_data *) extra; |
struct sgi_mte_data *d = extra; |
1189 |
uint64_t first_addr, last_addr, zerobuflen, fill_addr, fill_len; |
uint64_t first_addr, last_addr, zerobuflen, fill_addr, fill_len; |
1190 |
unsigned char zerobuf[ZERO_CHUNK_LEN]; |
unsigned char zerobuf[ZERO_CHUNK_LEN]; |
1191 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
1425 |
*/ |
*/ |
1426 |
void dev_sgi_mte_init(struct memory *mem, uint64_t baseaddr) |
void dev_sgi_mte_init(struct memory *mem, uint64_t baseaddr) |
1427 |
{ |
{ |
1428 |
struct sgi_mte_data *d = malloc(sizeof(struct sgi_mte_data)); |
struct sgi_mte_data *d; |
1429 |
if (d == NULL) { |
|
1430 |
fprintf(stderr, "out of memory\n"); |
CHECK_ALLOCATION(d = malloc(sizeof(struct sgi_mte_data))); |
|
exit(1); |
|
|
} |
|
1431 |
memset(d, 0, sizeof(struct sgi_mte_data)); |
memset(d, 0, sizeof(struct sgi_mte_data)); |
1432 |
|
|
1433 |
memory_device_register(mem, "sgi_mte", baseaddr, DEV_SGI_MTE_LENGTH, |
memory_device_register(mem, "sgi_mte", baseaddr, DEV_SGI_MTE_LENGTH, |