1 /* $NetBSD: arcbios.c,v 1.19 2020/08/14 16:53:06 skrll Exp $ */
2 /* $OpenBSD: arcbios.c,v 1.3 1998/06/06 06:33:33 mickey Exp $ */
3
4 /*-
5 * Copyright (c) 1996 M. Warner Losh. All rights reserved.
6 * Copyright (c) 1996, 1997, 1998 Per Fogelstrom. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: arcbios.c,v 1.19 2020/08/14 16:53:06 skrll Exp $");
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/proc.h>
39 #include <sys/kcore.h>
40 #include <uvm/uvm_extern.h>
41 #include <dev/cons.h>
42 #include <machine/cpu.h>
43 #include <machine/regdef.h>
44 #include <arc/arc/arcbios.h>
45
46 int Bios_Read(int, char *, int, int *);
47 int Bios_Write(int, char *, int, int *);
48 int Bios_Open(char *, int, u_int *);
49 int Bios_Close(u_int);
50 arc_mem_t *Bios_GetMemoryDescriptor(arc_mem_t *);
51 arc_sid_t *Bios_GetSystemId(void);
52 arc_config_t *Bios_GetChild(arc_config_t *);
53 arc_config_t *Bios_GetPeer(arc_config_t *);
54 arc_dsp_stat_t *Bios_GetDisplayStatus(int);
55
56 static void bios_config_id_copy(arc_config_t *, char *, size_t);
57 static void bios_config_component(arc_config_t *);
58 static void bios_config_subtree(arc_config_t *);
59
60 char arc_vendor_id[sizeof(((arc_sid_t *)0)->vendor) + 1];
61 unsigned char arc_product_id[sizeof(((arc_sid_t *)0)->prodid)];
62
63 char arc_id[64 + 1];
64
65 char arc_displayc_id[64 + 1]; /* DisplayController id */
66 arc_dsp_stat_t arc_displayinfo; /* Save area for display status info. */
67
68 int arc_cpu_l2cache_size = 0;
69
70 /*
71 * BIOS based console, for early stage.
72 */
73
74 int biosgetc(dev_t);
75 void biosputc(dev_t, int);
76
77 /* this is to fake out the console routines, while booting. */
78 struct consdev bioscons = {
79 NULL, NULL, biosgetc, biosputc, nullcnpollc, NULL, NULL,
80 NULL, NODEV, CN_DEAD
81 };
82
83 int
biosgetc(dev_t dev)84 biosgetc(dev_t dev)
85 {
86 int cnt;
87 char buf;
88
89 if (Bios_Read(0, &buf, 1, &cnt) != arc_ESUCCESS)
90 return -1;
91 return buf & 255;
92 }
93
94 void
biosputc(dev_t dev,int ch)95 biosputc(dev_t dev, int ch)
96 {
97 int cnt;
98 char buf;
99
100 buf = ch;
101 Bios_Write(1, &buf, 1, &cnt);
102 }
103
104 void
bios_init_console(void)105 bios_init_console(void)
106 {
107 static int initialized = 0;
108
109 if (!initialized) {
110 initialized = 1;
111 /* fake out the console routines, for now */
112 cn_tab = &bioscons;
113 }
114 }
115
116 /*
117 * Get memory descriptor for the memory configuration and
118 * create a layout database used by pmap init to set up
119 * the memory system.
120 *
121 * Concatenate obvious adjecent segments.
122 */
123 int
bios_configure_memory(int * mem_reserved,phys_ram_seg_t * mem_clusters,int * mem_cluster_cnt_return)124 bios_configure_memory(int *mem_reserved, phys_ram_seg_t *mem_clusters,
125 int *mem_cluster_cnt_return)
126 {
127 int bios_physmem = 0; /* Total physical memory size */
128 int mem_cluster_cnt = 0;
129
130 arc_mem_t *descr = NULL;
131 paddr_t seg_start, seg_end;
132 int i, reserved;
133
134 while ((descr = Bios_GetMemoryDescriptor(descr)) != NULL) {
135 seg_start = descr->BasePage * 4096;
136 seg_end = seg_start + descr->PageCount * 4096;
137
138 #ifdef BIOS_MEMORY_DEBUG
139 printf("memory type:%d, 0x%8lx..%8lx, size:%8ld bytes\n",
140 descr->Type, (u_long)seg_start, (u_long)seg_end,
141 (u_long)(seg_end - seg_start));
142 #endif
143
144 switch (descr->Type) {
145 case BadMemory: /* Have no use for these */
146 break;
147
148 case ExeceptionBlock:
149 case SystemParameterBlock:
150 case FirmwarePermanent:
151 reserved = 1;
152 goto account_it;
153
154 case FreeMemory:
155 case LoadedProgram: /* This is the loaded kernel */
156 case FirmwareTemporary:
157 case FreeContigous:
158 reserved = 0;
159 account_it:
160 bios_physmem += descr->PageCount * 4096;
161
162 for (i = 0; i < mem_cluster_cnt; ) {
163 if (mem_reserved[i] == reserved &&
164 mem_clusters[i].start == seg_end)
165 seg_end += mem_clusters[i].size;
166 else if (mem_reserved[i] == reserved &&
167 mem_clusters[i].start +
168 mem_clusters[i].size == seg_start)
169 seg_start = mem_clusters[i].start;
170 else { /* do not merge the cluster */
171 i++;
172 continue;
173 }
174 --mem_cluster_cnt;
175 mem_reserved[i] = mem_reserved[mem_cluster_cnt];
176 mem_clusters[i] = mem_clusters[mem_cluster_cnt];
177 }
178 /* assert(i == mem_cluster_cnt); */
179 if (mem_cluster_cnt >= VM_PHYSSEG_MAX) {
180 printf("VM_PHYSSEG_MAX too small\n");
181 for (;;)
182 ;
183 }
184 mem_reserved[i] = reserved;
185 mem_clusters[i].start = seg_start;
186 mem_clusters[i].size = seg_end - seg_start;
187 mem_cluster_cnt++;
188 break;
189
190 default: /* Unknown type, leave it alone... */
191 break;
192 }
193 }
194
195 #ifdef BIOS_MEMORY_DEBUG
196 for (i = 0; i < mem_cluster_cnt; i++)
197 printf("mem_clusters[%d] = %d:{ 0x%8lx, 0x%8lx }\n", i,
198 mem_reserved[i],
199 (long)mem_clusters[i].start,
200 (long)mem_clusters[i].size);
201 printf("physmem = %d\n", bios_physmem);
202 #endif
203
204 *mem_cluster_cnt_return = mem_cluster_cnt;
205 return bios_physmem;
206 }
207
208 /*
209 * ARC Firmware present?
210 */
211 int
bios_ident(void)212 bios_ident(void)
213 {
214
215 return (ArcBiosBase->magic == ARC_PARAM_BLK_MAGIC) ||
216 (ArcBiosBase->magic == ARC_PARAM_BLK_MAGIC_BUG);
217 }
218
219 /*
220 * save various information of BIOS for future use.
221 */
222
223 static void
bios_config_id_copy(arc_config_t * cf,char * string,size_t size)224 bios_config_id_copy(arc_config_t *cf, char *string, size_t size)
225 {
226
227 size--;
228 if (size > cf->id_len)
229 size = cf->id_len;
230 memcpy(string, cf->id, size);
231 string[size] = '\0';
232 }
233
234 static void
bios_config_component(arc_config_t * cf)235 bios_config_component(arc_config_t *cf)
236 {
237
238 switch (cf->class) {
239 case arc_SystemClass:
240 if (cf->type == arc_System)
241 bios_config_id_copy(cf, arc_id, sizeof(arc_id));
242 break;
243 case arc_CacheClass:
244 if (cf->type == arc_SecondaryDcache)
245 arc_cpu_l2cache_size = 4096 << (cf->key & 0xffff);
246 break;
247 case arc_ControllerClass:
248 if (cf->type == arc_DisplayController &&
249 arc_displayc_id[0] == '\0' /* first found one. XXX */)
250 bios_config_id_copy(cf, arc_displayc_id,
251 sizeof(arc_displayc_id));
252 break;
253 default:
254 break;
255 }
256 }
257
258 static
bios_config_subtree(arc_config_t * cf)259 void bios_config_subtree(arc_config_t *cf)
260 {
261
262 for (cf = Bios_GetChild(cf); cf != NULL; cf = Bios_GetPeer(cf)) {
263 bios_config_component(cf);
264 bios_config_subtree(cf);
265 }
266 }
267
268 void
bios_save_info(void)269 bios_save_info(void)
270 {
271 arc_sid_t *sid;
272
273 sid = Bios_GetSystemId();
274 if (sid) {
275 memcpy(arc_vendor_id, sid->vendor, sizeof(arc_vendor_id) - 1);
276 arc_vendor_id[sizeof(arc_vendor_id) - 1] = 0;
277 memcpy(arc_product_id, sid->prodid, sizeof(arc_product_id));
278 }
279
280 bios_config_subtree(NULL);
281
282 #ifdef arc
283 arc_displayinfo = *Bios_GetDisplayStatus(1);
284 #endif
285 }
286
287 #ifdef arc
288 /*
289 * Return geometry of the display. Used by pccons.c to set up the
290 * display configuration.
291 */
292 void
bios_display_info(int * xpos,int * ypos,int * xsize,int * ysize)293 bios_display_info(int *xpos, int *ypos, int *xsize, int *ysize)
294 {
295
296 *xpos = arc_displayinfo.CursorXPosition;
297 *ypos = arc_displayinfo.CursorYPosition;
298 *xsize = arc_displayinfo.CursorMaxXPosition;
299 *ysize = arc_displayinfo.CursorMaxYPosition;
300 }
301 #endif
302