2 * Minimalistic overlay demo program.
4 * 2012-17-07, Oliver Schmidt (ol.sc@web.de)
19 /* The symbols _OVERLAY?_LOAD__ and _OVERLAY?_SIZE__ were generated by the
20 * linker. They contain the overlay area address and size specific to a
23 extern void _OVERLAY1_LOAD__, _OVERLAY1_SIZE__;
24 extern void _OVERLAY2_LOAD__, _OVERLAY2_SIZE__;
25 extern void _OVERLAY3_LOAD__, _OVERLAY3_SIZE__;
26 extern void _OVERLAY4_LOAD__, _OVERLAY4_SIZE__;
34 {{"multdemo.1", -1, &_OVERLAY1_LOAD__, (unsigned)&_OVERLAY1_SIZE__},
35 {"multdemo.2", -1, &_OVERLAY2_LOAD__, (unsigned)&_OVERLAY2_SIZE__},
36 {"multdemo.3", -1, &_OVERLAY3_LOAD__, (unsigned)&_OVERLAY3_SIZE__},
37 {"multdemo.4", -1, &_OVERLAY4_LOAD__, (unsigned)&_OVERLAY4_SIZE__}};
39 /* Copy overlays into extended memory up to overlay 3. Overlay 4 is known to
40 * to be loaded only once for onetime initialization purposes so there's no
41 * use in allocating extended memory for it.
43 #define MAX_EM_OVERLAY 3
46 /* Functions resident in an overlay can call back functions resident in the
47 * main program at any time without any precautions. The function log() is
48 * an example for such a function resident in the main program.
52 /* Functions resident in an overlay can access all program variables and
53 * constants at any time without any precautions because those are never
54 * placed in overlays. The string constant below is an example for such
55 * a constant resident in the main program.
57 printf ("Log: %s\n", msg);
61 /* In a real-world overlay program one would probably not use a #pragma but
62 * rather place the all the code of certain source files into the overlay by
63 * compiling them with --code-name OVERLAY1.
65 #pragma code-name (push, "OVERLAY1");
69 log ("Calling main from overlay 1");
72 #pragma code-name (pop);
75 #pragma code-name (push, "OVERLAY2");
79 log ("Calling main from overlay 2");
82 #pragma code-name (pop);
85 #pragma code-name (push, "OVERLAY3");
89 log ("Calling main from overlay 3");
92 #pragma code-name(pop);
95 #pragma code-name (push, "OVERLAY4");
97 unsigned char loademdriver (void)
102 printf ("Dbg: Searching for emdrivers\n");
105 log ("Opening directory failed");
109 while (ent = readdir (dir)) {
112 if (!_DE_ISREG (ent->d_type)) {
116 ext = strrchr (ent->d_name, '.');
117 if (!ext || strcasecmp (ext, ".emd")) {
118 printf ("Dbg: Skipping file %s\n", ent->d_name);
122 printf ("Dbg: Trying emdriver %s\n", ent->d_name);
123 if (em_load_driver (ent->d_name) == EM_ERR_OK) {
124 printf ("Dbg: Loaded emdriver %s\n", ent->d_name);
128 printf ("Dbg: Emdriver %s failed\n", ent->d_name);
135 void copyoverlays (void)
140 for (num = 0; num < MAX_EM_OVERLAY; ++num) {
144 if ((overlay[num].size + EM_PAGE_SIZE - 1) / EM_PAGE_SIZE >
145 em_pagecount () - page) {
146 printf ("Dbg: Not enough memory for overlay %u\n", num + 1);
150 printf ("Dbg: Reading overlay file %s\n", overlay[num].name);
151 file = open (overlay[num].name, O_RDONLY);
153 log ("Opening overlay file failed");
157 overlay[num].page = page;
158 size = overlay[num].size;
162 /* In general one could as well use em_copyto() to copy a fully
163 * loaded overlay into extended memory in one step. However the
164 * "streaming" of an overlay from disk to extended memory shown
165 * here has two advantages:
166 * - It can be done from another overlay (like done here).
167 * - It avoids unnecessary double buffering with emdrivers that
168 * provide a hardware memory window.
170 buf = em_use (page++);
171 size -= read (file, buf, EM_PAGE_SIZE);
175 printf ("Dbg: Stored overlay %u in pages %u-%u\n",
176 num + 1, overlay[num].page, page - 1);
182 #pragma code-name(pop);
185 unsigned char loadoverlay (unsigned char num)
187 if (overlay[num - 1].page < 0) {
190 printf ("Dbg: Loading overlay %u from file\n", num);
191 file = open (overlay[num - 1].name, O_RDONLY);
193 log ("Opening overlay file failed");
196 read (file, overlay[num - 1].addr,
197 overlay[num - 1].size);
201 struct em_copy copyinfo;
203 printf ("Dbg: Loading overlay %u from memory\n", num);
205 copyinfo.page = overlay[num - 1].page;
206 copyinfo.buf = overlay[num - 1].addr;
207 copyinfo.count = overlay[num - 1].size;
208 em_copyfrom (©info);
215 if (loadoverlay (4)) {
216 log ("Loading extended memory driver");
217 if (loademdriver ()) {
218 log ("Copying overlays into ext. memory");
221 log ("No extended memory driver found");
225 log ("Press any key...");
228 if (loadoverlay (1)) {
229 log ("Calling overlay 1 from main");
231 /* The linker makes sure that the call to foo() ends up at the right mem
232 * addr. However it's up to user to make sure that the - right - overlay
233 * is actually loaded before making the the call.
238 /* Replacing one overlay with another one can only happen from the main
239 * program. This implies that an overlay can never load another overlay.
241 if (loadoverlay (2)) {
242 log ("Calling overlay 2 from main");
246 if (loadoverlay (3)) {
247 log ("Calling overlay 3 from main");
251 log ("Press any key...");