1/*
2 * Copyright (C) Paul Mackerras 1997.
3 * Copyright (C) Leigh Brown 2002.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10
11#include "of1275.h"
12#include "nonstdio.h"
13
14/*
15 * Older OF's require that when claiming a specific range of addresses,
16 * we claim the physical space in the /memory node and the virtual
17 * space in the chosen mmu node, and then do a map operation to
18 * map virtual to physical.
19 */
20static int need_map = -1;
21static ihandle chosen_mmu;
22static phandle memory;
23
24/* returns true if s2 is a prefix of s1 */
25static int string_match(const char *s1, const char *s2)
26{
27	for (; *s2; ++s2)
28		if (*s1++ != *s2)
29			return 0;
30	return 1;
31}
32
33static int check_of_version(void)
34{
35	phandle oprom, chosen;
36	char version[64];
37
38	oprom = finddevice("/openprom");
39	if (oprom == OF_INVALID_HANDLE)
40		return 0;
41	if (getprop(oprom, "model", version, sizeof(version)) <= 0)
42		return 0;
43	version[sizeof(version)-1] = 0;
44	printf("OF version = '%s'\n", version);
45	if (!string_match(version, "Open Firmware, 1.")
46	    && !string_match(version, "FirmWorks,3."))
47		return 0;
48	chosen = finddevice("/chosen");
49	if (chosen == OF_INVALID_HANDLE) {
50		chosen = finddevice("/chosen@0");
51		if (chosen == OF_INVALID_HANDLE) {
52			printf("no chosen\n");
53			return 0;
54		}
55	}
56	if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
57		printf("no mmu\n");
58		return 0;
59	}
60	memory = (ihandle) call_prom("open", 1, 1, "/memory");
61	if (memory == OF_INVALID_HANDLE) {
62		memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
63		if (memory == OF_INVALID_HANDLE) {
64			printf("no memory node\n");
65			return 0;
66		}
67	}
68	printf("old OF detected\n");
69	return 1;
70}
71
72void *claim(unsigned int virt, unsigned int size, unsigned int align)
73{
74	int ret;
75	unsigned int result;
76
77	if (need_map < 0)
78		need_map = check_of_version();
79	if (align || !need_map)
80		return (void *) call_prom("claim", 3, 1, virt, size, align);
81
82	ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
83			    align, size, virt);
84	if (ret != 0 || result == -1)
85		return (void *) -1;
86	ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
87			    align, size, virt);
88	/* 0x12 == coherent + read/write */
89	ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
90			0x12, size, virt, virt);
91	return virt;
92}
93