2 * Extended memory overlay demo program.
4 * 2012-17-07, Oliver Schmidt (ol.sc@web.de)
20 /* The symbols _OVERLAY?_LOAD__ and _OVERLAY?_SIZE__ were generated by the
21 * linker. They contain the overlay area address and size specific to a
24 extern void _OVERLAY1_LOAD__, _OVERLAY1_SIZE__;
25 extern void _OVERLAY2_LOAD__, _OVERLAY2_SIZE__;
26 extern void _OVERLAY3_LOAD__, _OVERLAY3_SIZE__;
27 extern void _OVERLAY4_LOAD__, _OVERLAY4_SIZE__;
35 {{"multdemo.1", -1, &_OVERLAY1_LOAD__, (unsigned)&_OVERLAY1_SIZE__},
36 {"multdemo.2", -1, &_OVERLAY2_LOAD__, (unsigned)&_OVERLAY2_SIZE__},
37 {"multdemo.3", -1, &_OVERLAY3_LOAD__, (unsigned)&_OVERLAY3_SIZE__},
38 {"multdemo.4", -1, &_OVERLAY4_LOAD__, (unsigned)&_OVERLAY4_SIZE__}};
40 /* Copy overlays into extended memory up to overlay 3. Overlay 4 is known to
41 * to be loaded only once for onetime initialization purposes so there's no
42 * use in allocating extended memory for it.
44 #define MAX_EM_OVERLAY 3
48 /* Functions resident in an overlay can call back functions resident in the
49 * main program at any time without any precautions. The function log() is
50 * an example for such a function resident in the main program.
54 /* Functions resident in an overlay can access all program variables and
55 * constants at any time without any precautions because those are never
56 * placed in overlays. The string constant below is an example for such
57 * a constant resident in the main program.
59 printf ("Log: %s\n", msg);
63 /* In a real-world overlay program one would probably not use a #pragma but
64 * rather place the all the code of certain source files into the overlay by
65 * compiling them with --code-name OVERLAY1.
67 #pragma code-name (push, "OVERLAY1");
71 log ("Calling main from overlay 1");
74 #pragma code-name (pop);
77 #pragma code-name (push, "OVERLAY2");
81 log ("Calling main from overlay 2");
84 #pragma code-name (pop);
87 #pragma code-name (push, "OVERLAY3");
91 log ("Calling main from overlay 3");
94 #pragma code-name(pop);
97 #pragma code-name (push, "OVERLAY4");
99 unsigned char loademdriver (void)
104 unsigned char max = 0;
107 printf ("Dbg: Searching for emdrivers\n");
110 log ("Opening directory failed");
114 while (ent = readdir (dir)) {
117 if (!_DE_ISREG (ent->d_type)) {
121 ext = strrchr (ent->d_name, '.');
122 if (!ext || strcasecmp (ext, ".emd")) {
123 printf ("Dbg: Skipping file %s\n", ent->d_name);
127 printf ("Dbg: Memorizing file %s\n", ent->d_name);
128 emd = realloc (emd, FILENAME_MAX * (max + 1));
129 strcpy (emd + FILENAME_MAX * max++, ent->d_name);
133 for (num = 0; num < max; ++num) {
136 drv = emd + FILENAME_MAX * num;
137 printf ("Dbg: Trying emdriver %s\n", drv);
138 if (em_load_driver (drv) == EM_ERR_OK) {
139 printf ("Dbg: Loaded emdriver %s\n", drv);
144 printf ("Dbg: Emdriver %s failed\n", drv);
151 void copyoverlays (void)
156 for (num = 0; num < MAX_EM_OVERLAY; ++num) {
160 if ((overlay[num].size + EM_PAGE_SIZE - 1) / EM_PAGE_SIZE >
161 em_pagecount () - page) {
162 printf ("Dbg: Not enough memory for overlay %u\n", num + 1);
166 printf ("Dbg: Reading overlay file %s\n", overlay[num].name);
167 file = open (overlay[num].name, O_RDONLY);
169 log ("Opening overlay file failed");
173 overlay[num].page = page;
174 size = overlay[num].size;
178 /* In general one could as well use em_copyto() to copy a fully
179 * loaded overlay into extended memory in one step. However the
180 * "streaming" of an overlay from disk to extended memory shown
181 * here has two advantages:
182 * - It can be done from another overlay (like done here).
183 * - It avoids unnecessary double buffering with emdrivers that
184 * provide a hardware memory window.
186 buf = em_use (page++);
187 size -= read (file, buf, EM_PAGE_SIZE);
191 printf ("Dbg: Stored overlay %u in pages %u-%u\n",
192 num + 1, overlay[num].page, page - 1);
198 #pragma code-name(pop);
201 unsigned char loadoverlay (unsigned char num)
203 if (overlay[num - 1].page < 0) {
206 printf ("Dbg: Loading overlay %u from file\n", num);
207 file = open (overlay[num - 1].name, O_RDONLY);
209 log ("Opening overlay file failed");
212 read (file, overlay[num - 1].addr,
213 overlay[num - 1].size);
217 struct em_copy copyinfo;
219 printf ("Dbg: Loading overlay %u from memory\n", num);
221 copyinfo.page = overlay[num - 1].page;
222 copyinfo.buf = overlay[num - 1].addr;
223 copyinfo.count = overlay[num - 1].size;
224 em_copyfrom (©info);
231 if (loadoverlay (4)) {
232 log ("Loading extended memory driver");
233 if (loademdriver ()) {
234 log ("Copying overlays into ext. memory");
237 log ("No extended memory driver found");
241 log ("Press any key...");
244 if (loadoverlay (1)) {
245 log ("Calling overlay 1 from main");
247 /* The linker makes sure that the call to foo() ends up at the right mem
248 * addr. However it's up to user to make sure that the - right - overlay
249 * is actually loaded before making the the call.
254 /* Replacing one overlay with another one can only happen from the main
255 * program. This implies that an overlay can never load another overlay.
257 if (loadoverlay (2)) {
258 log ("Calling overlay 2 from main");
262 if (loadoverlay (3)) {
263 log ("Calling overlay 3 from main");
267 log ("Press any key...");