25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: of.c,v 1.23 2007/03/24 06:40:16 debug Exp $ |
* $Id: of.c,v 1.24 2007/06/15 17:02:40 debug Exp $ |
29 |
* |
* |
30 |
* OpenFirmware emulation. |
* OpenFirmware emulation. |
31 |
* |
* |
473 |
static struct of_device *of_add_device(struct of_data *of_data, char *name, |
static struct of_device *of_add_device(struct of_data *of_data, char *name, |
474 |
char *parentname) |
char *parentname) |
475 |
{ |
{ |
476 |
struct of_device *od = malloc(sizeof(struct of_device)); |
struct of_device *od; |
477 |
if (od == NULL) |
|
478 |
goto bad; |
CHECK_ALLOCATION(od = malloc(sizeof(struct of_device))); |
479 |
memset(od, 0, sizeof(struct of_device)); |
memset(od, 0, sizeof(struct of_device)); |
480 |
|
|
481 |
od->name = strdup(name); |
CHECK_ALLOCATION(od->name = strdup(name)); |
|
if (od->name == NULL) |
|
|
goto bad; |
|
482 |
|
|
483 |
od->handle = of_get_unused_device_handle(of_data); |
od->handle = of_get_unused_device_handle(of_data); |
484 |
od->parent = find_device_handle(of_data, parentname); |
od->parent = find_device_handle(of_data, parentname); |
490 |
|
|
491 |
od->next = of_data->of_devices; |
od->next = of_data->of_devices; |
492 |
of_data->of_devices = od; |
of_data->of_devices = od; |
|
return od; |
|
|
|
|
|
bad: |
|
|
fatal("of_add_device(): out of memory\n"); |
|
|
exit(1); |
|
493 |
|
|
494 |
return NULL; /* Silences a compiler warning */ |
return od; |
495 |
} |
} |
496 |
|
|
497 |
|
|
503 |
static void of_add_prop(struct of_data *of_data, char *devname, |
static void of_add_prop(struct of_data *of_data, char *devname, |
504 |
char *propname, unsigned char *data, uint32_t len, int flags) |
char *propname, unsigned char *data, uint32_t len, int flags) |
505 |
{ |
{ |
506 |
struct of_device_property *pr = |
struct of_device_property *pr; |
|
malloc(sizeof(struct of_device_property)); |
|
507 |
struct of_device *od = of_data->of_devices; |
struct of_device *od = of_data->of_devices; |
508 |
int h = find_device_handle(of_data, devname); |
int h = find_device_handle(of_data, devname); |
509 |
|
|
510 |
|
CHECK_ALLOCATION(pr = malloc(sizeof(struct of_device_property))); |
511 |
|
memset(pr, 0, sizeof(struct of_device_property)); |
512 |
|
|
513 |
OF_FIND(od, od->handle == h); |
OF_FIND(od, od->handle == h); |
514 |
if (od == NULL) { |
if (od == NULL) { |
515 |
fatal("of_add_prop(): device '%s' not registered\n", devname); |
fatal("of_add_prop(): device '%s' not registered\n", devname); |
516 |
exit(1); |
exit(1); |
517 |
} |
} |
518 |
|
|
519 |
if (pr == NULL) |
CHECK_ALLOCATION(pr->name = strdup(propname)); |
|
goto bad; |
|
|
memset(pr, 0, sizeof(struct of_device_property)); |
|
|
|
|
|
pr->name = strdup(propname); |
|
|
if (pr->name == NULL) |
|
|
goto bad; |
|
520 |
pr->data = data; |
pr->data = data; |
521 |
pr->len = len; |
pr->len = len; |
522 |
pr->flags = flags; |
pr->flags = flags; |
523 |
|
|
524 |
pr->next = od->properties; |
pr->next = od->properties; |
525 |
od->properties = pr; |
od->properties = pr; |
|
return; |
|
|
|
|
|
bad: |
|
|
fatal("of_add_device(): out of memory\n"); |
|
|
exit(1); |
|
526 |
} |
} |
527 |
|
|
528 |
|
|
534 |
static void of_add_service(struct of_data *of_data, char *name, |
static void of_add_service(struct of_data *of_data, char *name, |
535 |
int (*f)(OF_SERVICE_ARGS), int n_args, int n_ret_args) |
int (*f)(OF_SERVICE_ARGS), int n_args, int n_ret_args) |
536 |
{ |
{ |
537 |
struct of_service *os = malloc(sizeof(struct of_service)); |
struct of_service *os; |
538 |
if (os == NULL) |
|
539 |
goto bad; |
CHECK_ALLOCATION(os = malloc(sizeof(struct of_service))); |
540 |
memset(os, 0, sizeof(struct of_service)); |
memset(os, 0, sizeof(struct of_service)); |
541 |
|
|
542 |
os->name = strdup(name); |
CHECK_ALLOCATION(os->name = strdup(name)); |
|
if (os->name == NULL) |
|
|
goto bad; |
|
543 |
|
|
544 |
os->f = f; |
os->f = f; |
545 |
os->n_args = n_args; |
os->n_args = n_args; |
547 |
|
|
548 |
os->next = of_data->of_services; |
os->next = of_data->of_services; |
549 |
of_data->of_services = os; |
of_data->of_services = os; |
|
return; |
|
|
|
|
|
bad: |
|
|
fatal("of_add_service(): out of memory\n"); |
|
|
exit(1); |
|
550 |
} |
} |
551 |
|
|
552 |
|
|
633 |
static void of_add_prop_int32(struct of_data *ofd, |
static void of_add_prop_int32(struct of_data *ofd, |
634 |
char *devname, char *propname, uint32_t x) |
char *devname, char *propname, uint32_t x) |
635 |
{ |
{ |
636 |
unsigned char *p = malloc(sizeof(int32_t)); |
unsigned char *p; |
637 |
if (p == NULL) { |
|
638 |
fatal("of_add_prop_int32(): out of memory\n"); |
CHECK_ALLOCATION(p = malloc(sizeof(int32_t))); |
639 |
exit(1); |
|
|
} |
|
640 |
of_store_32bit_in_host(p, x); |
of_store_32bit_in_host(p, x); |
641 |
of_add_prop(ofd, devname, propname, p, sizeof(int32_t), |
of_add_prop(ofd, devname, propname, p, sizeof(int32_t), |
642 |
OF_PROP_INT); |
OF_PROP_INT); |
651 |
static void of_add_prop_str(struct machine *machine, struct of_data *ofd, |
static void of_add_prop_str(struct machine *machine, struct of_data *ofd, |
652 |
char *devname, char *propname, char *data) |
char *devname, char *propname, char *data) |
653 |
{ |
{ |
654 |
char *p = strdup(data); |
char *p; |
655 |
if (p == NULL) { |
|
656 |
fatal("of_add_prop_str(): out of memory\n"); |
CHECK_ALLOCATION(p = strdup(data)); |
|
exit(1); |
|
|
} |
|
657 |
|
|
658 |
of_add_prop(ofd, devname, propname, (unsigned char *)p, strlen(p) + 1, |
of_add_prop(ofd, devname, propname, (unsigned char *)p, strlen(p) + 1, |
659 |
OF_PROP_STRING); |
OF_PROP_STRING); |
669 |
unsigned char *isa_ranges; |
unsigned char *isa_ranges; |
670 |
|
|
671 |
of_add_device(ofd, "isa", "/"); |
of_add_device(ofd, "isa", "/"); |
672 |
isa_ranges = malloc(32); |
|
673 |
if (isa_ranges == NULL) |
CHECK_ALLOCATION(isa_ranges = malloc(32)); |
|
goto bad; |
|
674 |
memset(isa_ranges, 0, 32); |
memset(isa_ranges, 0, 32); |
675 |
|
|
676 |
/* 2 *: isa_phys_hi, isa_phys_lo, parent_phys_start, size */ |
/* 2 *: isa_phys_hi, isa_phys_lo, parent_phys_start, size */ |
677 |
/* MEM space: */ |
/* MEM space: */ |
678 |
of_store_32bit_in_host(isa_ranges + 0, 0); |
of_store_32bit_in_host(isa_ranges + 0, 0); |
682 |
of_store_32bit_in_host(isa_ranges + 20, 0xd0000000); |
of_store_32bit_in_host(isa_ranges + 20, 0xd0000000); |
683 |
|
|
684 |
of_add_prop(ofd, "/isa", "ranges", isa_ranges, 32, 0); |
of_add_prop(ofd, "/isa", "ranges", isa_ranges, 32, 0); |
|
|
|
|
return; |
|
|
|
|
|
bad: |
|
|
fatal("of_emul_init_isa(): out of memory\n"); |
|
|
exit(1); |
|
685 |
} |
} |
686 |
|
|
687 |
|
|
693 |
struct of_data *ofd = machine->md.of_data; |
struct of_data *ofd = machine->md.of_data; |
694 |
unsigned char *adb_interrupts, *adb_reg; |
unsigned char *adb_interrupts, *adb_reg; |
695 |
|
|
696 |
adb_interrupts = malloc(4 * sizeof(uint32_t)); |
CHECK_ALLOCATION(adb_interrupts = malloc(4 * sizeof(uint32_t))); |
697 |
adb_reg = malloc(8 * sizeof(uint32_t)); |
CHECK_ALLOCATION(adb_reg = malloc(8 * sizeof(uint32_t))); |
|
if (adb_interrupts == NULL || adb_reg == NULL) |
|
|
goto bad; |
|
698 |
|
|
699 |
of_add_device(ofd, "adb", "/bandit/gc"); |
of_add_device(ofd, "adb", "/bandit/gc"); |
700 |
of_add_prop_str(machine, ofd, "/bandit/gc/adb", "name", "via-cuda"); |
of_add_prop_str(machine, ofd, "/bandit/gc/adb", "name", "via-cuda"); |
714 |
of_store_32bit_in_host(adb_reg + 28, 0); |
of_store_32bit_in_host(adb_reg + 28, 0); |
715 |
of_add_prop(ofd, "/bandit/gc/adb", "reg", adb_reg, |
of_add_prop(ofd, "/bandit/gc/adb", "reg", adb_reg, |
716 |
8*sizeof(uint32_t), 0); |
8*sizeof(uint32_t), 0); |
|
|
|
|
return; |
|
|
|
|
|
bad: |
|
|
fatal("of_emul_init_adb(): out of memory\n"); |
|
|
exit(1); |
|
717 |
} |
} |
718 |
|
|
719 |
|
|
725 |
struct of_data *ofd = machine->md.of_data; |
struct of_data *ofd = machine->md.of_data; |
726 |
unsigned char *zs_interrupts, *zs_reg; |
unsigned char *zs_interrupts, *zs_reg; |
727 |
|
|
728 |
zs_reg = malloc(6 * sizeof(uint32_t)); |
CHECK_ALLOCATION(zs_reg = malloc(6 * sizeof(uint32_t))); |
|
if (zs_reg == NULL) |
|
|
goto bad; |
|
729 |
|
|
730 |
/* The controller: */ |
/* The controller: */ |
731 |
of_add_device(ofd, "zs", "/bandit/gc"); |
of_add_device(ofd, "zs", "/bandit/gc"); |
740 |
of_add_prop(ofd, "/bandit/gc/zs", "reg", zs_reg, 6*sizeof(uint32_t), 0); |
of_add_prop(ofd, "/bandit/gc/zs", "reg", zs_reg, 6*sizeof(uint32_t), 0); |
741 |
|
|
742 |
/* Port 1: */ |
/* Port 1: */ |
743 |
zs_interrupts = malloc(3 * sizeof(uint32_t)); |
CHECK_ALLOCATION(zs_interrupts = malloc(3 * sizeof(uint32_t))); |
744 |
zs_reg = malloc(6 * sizeof(uint32_t)); |
CHECK_ALLOCATION(zs_reg = malloc(6 * sizeof(uint32_t))); |
|
if (zs_interrupts == NULL || zs_reg == NULL) |
|
|
goto bad; |
|
745 |
|
|
746 |
of_add_device(ofd, "zstty1", "/bandit/gc/zs"); |
of_add_device(ofd, "zstty1", "/bandit/gc/zs"); |
747 |
of_add_prop_str(machine, ofd, "/bandit/gc/zs/zstty1", "name", "ch-a"); |
of_add_prop_str(machine, ofd, "/bandit/gc/zs/zstty1", "name", "ch-a"); |
760 |
"reg", zs_reg, 6*sizeof(uint32_t), 0); |
"reg", zs_reg, 6*sizeof(uint32_t), 0); |
761 |
|
|
762 |
/* Port 0: */ |
/* Port 0: */ |
763 |
zs_interrupts = malloc(3 * sizeof(uint32_t)); |
CHECK_ALLOCATION(zs_interrupts = malloc(3 * sizeof(uint32_t))); |
764 |
zs_reg = malloc(6 * sizeof(uint32_t)); |
CHECK_ALLOCATION(zs_reg = malloc(6 * sizeof(uint32_t))); |
|
if (zs_interrupts == NULL || zs_reg == NULL) |
|
|
goto bad; |
|
765 |
|
|
766 |
of_add_device(ofd, "zstty0", "/bandit/gc/zs"); |
of_add_device(ofd, "zstty0", "/bandit/gc/zs"); |
767 |
of_add_prop_str(machine, ofd, "/bandit/gc/zs/zstty0", "name", "ch-b"); |
of_add_prop_str(machine, ofd, "/bandit/gc/zs/zstty0", "name", "ch-b"); |
778 |
of_store_32bit_in_host(zs_reg + 20, 0x100); |
of_store_32bit_in_host(zs_reg + 20, 0x100); |
779 |
of_add_prop(ofd, "/bandit/gc/zs/zstty0", |
of_add_prop(ofd, "/bandit/gc/zs/zstty0", |
780 |
"reg", zs_reg, 6*sizeof(uint32_t), 0); |
"reg", zs_reg, 6*sizeof(uint32_t), 0); |
|
|
|
|
return; |
|
|
|
|
|
bad: |
|
|
fatal("of_emul_init_zs(): out of memory\n"); |
|
|
exit(1); |
|
781 |
} |
} |
782 |
|
|
783 |
|
|
798 |
of_add_prop_str(machine, ofd, n, "device_type", "pci"); |
of_add_prop_str(machine, ofd, n, "device_type", "pci"); |
799 |
of_add_prop_str(machine, ofd, n, "compatible", "uni-north"); |
of_add_prop_str(machine, ofd, n, "compatible", "uni-north"); |
800 |
|
|
801 |
uninorth_reg = malloc(2 * sizeof(uint32_t)); |
CHECK_ALLOCATION(uninorth_reg = malloc(2 * sizeof(uint32_t))); |
802 |
uninorth_bus_range = malloc(2 * sizeof(uint32_t)); |
CHECK_ALLOCATION(uninorth_bus_range = malloc(2 * sizeof(uint32_t))); |
803 |
uninorth_ranges = malloc(12 * sizeof(uint32_t)); |
CHECK_ALLOCATION(uninorth_ranges = malloc(12 * sizeof(uint32_t))); |
804 |
macio_aa = malloc(5 * sizeof(uint32_t)); |
CHECK_ALLOCATION(macio_aa = malloc(5 * sizeof(uint32_t))); |
805 |
ata_interrupts = malloc(6 * sizeof(uint32_t)); |
CHECK_ALLOCATION(ata_interrupts = malloc(6 * sizeof(uint32_t))); |
806 |
ata_reg = malloc(8 * sizeof(uint32_t)); |
CHECK_ALLOCATION(ata_reg = malloc(8 * sizeof(uint32_t))); |
|
if (uninorth_ranges == NULL || uninorth_bus_range == NULL || |
|
|
uninorth_reg == NULL || macio_aa == NULL || |
|
|
ata_interrupts == NULL || ata_reg == NULL) |
|
|
goto bad; |
|
807 |
|
|
808 |
of_store_32bit_in_host(uninorth_reg + 0, 0xe2000000); |
of_store_32bit_in_host(uninorth_reg + 0, 0xe2000000); |
809 |
of_store_32bit_in_host(uninorth_reg + 4, 0); /* not used? */ |
of_store_32bit_in_host(uninorth_reg + 4, 0); /* not used? */ |
877 |
machine->bootstrap_cpu); |
machine->bootstrap_cpu); |
878 |
device_add(machine, tmpstr); |
device_add(machine, tmpstr); |
879 |
} |
} |
|
|
|
|
return; |
|
|
|
|
|
bad: |
|
|
fatal("of_emul_init_uninorth(): out of memory\n"); |
|
|
exit(1); |
|
880 |
} |
} |
881 |
|
|
882 |
|
|
891 |
unsigned char *memory_reg, *memory_av; |
unsigned char *memory_reg, *memory_av; |
892 |
unsigned char *zs_assigned_addresses; |
unsigned char *zs_assigned_addresses; |
893 |
struct of_device *mmu, *devstdout, *devstdin; |
struct of_device *mmu, *devstdout, *devstdin; |
894 |
struct of_data *ofd = malloc(sizeof(struct of_data)); |
struct of_data *ofd; |
895 |
int i; |
int i; |
896 |
|
|
897 |
if (ofd == NULL) |
CHECK_ALLOCATION(ofd = malloc(sizeof(struct of_data))); |
|
goto bad; |
|
898 |
memset(ofd, 0, sizeof(struct of_data)); |
memset(ofd, 0, sizeof(struct of_data)); |
899 |
|
|
900 |
ofd->vfb_data = vfb_data; |
ofd->vfb_data = vfb_data; |
908 |
devstdin = of_add_device(ofd, "stdin", "/io"); |
devstdin = of_add_device(ofd, "stdin", "/io"); |
909 |
devstdout = of_add_device(ofd, "stdout", "/io"); |
devstdout = of_add_device(ofd, "stdout", "/io"); |
910 |
|
|
911 |
if (machine->use_x11) { |
if (machine->x11_md.in_use) { |
912 |
fatal("!\n! TODO: keyboard + framebuffer for MacPPC\n!\n"); |
fatal("!\n! TODO: keyboard + framebuffer for MacPPC\n!\n"); |
913 |
|
|
914 |
of_add_prop_str(machine, ofd, "/io/stdin", "name", |
of_add_prop_str(machine, ofd, "/io/stdin", "name", |
923 |
of_add_prop_int32(ofd, "/io/stdout", "depth", 8); |
of_add_prop_int32(ofd, "/io/stdout", "depth", 8); |
924 |
of_add_prop_int32(ofd, "/io/stdout", "address", fb_addr); |
of_add_prop_int32(ofd, "/io/stdout", "address", fb_addr); |
925 |
} else { |
} else { |
926 |
zs_assigned_addresses = malloc(12); |
CHECK_ALLOCATION(zs_assigned_addresses = malloc(12)); |
|
if (zs_assigned_addresses == NULL) |
|
|
goto bad; |
|
927 |
memset(zs_assigned_addresses, 0, 12); |
memset(zs_assigned_addresses, 0, 12); |
928 |
|
|
929 |
of_add_prop_str(machine, ofd, "/io/stdin", "name", "ch-b"); |
of_add_prop_str(machine, ofd, "/io/stdin", "name", "ch-b"); |
930 |
of_add_prop_str(machine, ofd, "/io/stdin", "device_type", |
of_add_prop_str(machine, ofd, "/io/stdin", "device_type", |
931 |
"serial"); |
"serial"); |
962 |
of_add_prop_int32(ofd, "/chosen", "stdout", devstdout->handle); |
of_add_prop_int32(ofd, "/chosen", "stdout", devstdout->handle); |
963 |
|
|
964 |
of_add_device(ofd, "memory", "/"); |
of_add_device(ofd, "memory", "/"); |
965 |
memory_reg = malloc(2 * sizeof(uint32_t)); |
CHECK_ALLOCATION(memory_reg = malloc(2 * sizeof(uint32_t))); |
966 |
memory_av = malloc(2 * sizeof(uint32_t)); |
CHECK_ALLOCATION(memory_av = malloc(2 * sizeof(uint32_t))); |
967 |
if (memory_reg == NULL || memory_av == NULL) |
|
|
goto bad; |
|
968 |
of_store_32bit_in_host(memory_reg + 0, 0); |
of_store_32bit_in_host(memory_reg + 0, 0); |
969 |
of_store_32bit_in_host(memory_reg + 4, machine->physical_ram_in_mb<<20); |
of_store_32bit_in_host(memory_reg + 4, machine->physical_ram_in_mb<<20); |
970 |
of_store_32bit_in_host(memory_av + 0, 10 << 20); |
of_store_32bit_in_host(memory_av + 0, 10 << 20); |
999 |
of_dump_all(ofd); |
of_dump_all(ofd); |
1000 |
|
|
1001 |
machine->md.of_data = ofd; |
machine->md.of_data = ofd; |
|
return ofd; |
|
1002 |
|
|
1003 |
bad: |
return ofd; |
|
fatal("of_emul_init(): out of memory\n"); |
|
|
exit(1); |
|
|
|
|
|
return NULL; /* Silences a compiler warning */ |
|
1004 |
} |
} |
1005 |
|
|
1006 |
|
|
1060 |
fatal("TOO MANY ARGS!"); |
fatal("TOO MANY ARGS!"); |
1061 |
continue; |
continue; |
1062 |
} |
} |
1063 |
|
|
1064 |
ptr = load_32bit_word(cpu, base + ofs); |
ptr = load_32bit_word(cpu, base + ofs); |
1065 |
arg[i] = malloc(OF_ARG_MAX_LEN + 1); |
|
1066 |
if (arg[i] == NULL) { |
CHECK_ALLOCATION(arg[i] = malloc(OF_ARG_MAX_LEN + 1)); |
|
fatal("out of memory\n"); |
|
|
exit(1); |
|
|
} |
|
1067 |
memset(arg[i], 0, OF_ARG_MAX_LEN + 1); |
memset(arg[i], 0, OF_ARG_MAX_LEN + 1); |
1068 |
|
|
1069 |
x = ptr; |
x = ptr; |
1070 |
if (x > -256 && x < 256) { |
if (x > -256 && x < 256) { |
1071 |
debug("%i", x); |
debug("%i", x); |