38 |
|
|
39 |
|
Basilisk II is designed to run on many different hardware platforms and on |
40 |
|
many different operating systems. To provide optimal performance under all |
41 |
< |
environments, it can run in three different modes, depending on the features |
42 |
< |
of the underlying environment (the modes are selected with the REAL_ADDRESSING |
43 |
< |
and EMULATED_68K defines in "sysdeps.h"): |
41 |
> |
environments, it can run in four different modes, depending on the features |
42 |
> |
of the underlying environment (the modes are selected with the REAL_ADDRESSING, |
43 |
> |
DIRECT_ADDRESSING and EMULATED_68K defines in "sysdeps.h"): |
44 |
|
|
45 |
|
1. Emulated CPU, "virtual" addressing (EMULATED_68K = 1, REAL_ADDRESSING = 0): |
46 |
|
This mode is designed for non-68k or little-endian systems or systems that |
47 |
< |
don't allow accessing RAM at 0x0000..0x1fff. This is also the only mode that |
48 |
< |
allows 24-bit addressing, and thus the only mode that allows Mac Classic |
49 |
< |
emulation. The 68k processor is emulated with the UAE CPU engine and two |
50 |
< |
memory areas are allocated for Mac RAM and ROM. The memory map seen by the |
51 |
< |
emulated CPU and the host CPU are different. Mac RAM starts at address 0 |
52 |
< |
for the emulated 68k, but it may start at a different address for the host |
53 |
< |
CPU. All memory accesses of the CPU emulation go through memory access |
54 |
< |
functions (do_get_mem_long() etc.) that translate addresses. This slows |
55 |
< |
down the emulator, of course. |
56 |
< |
|
57 |
< |
2. Emulated CPU, "real" addressing (EMULATED_68K = 1, REAL_ADDRESSING = 0): |
58 |
< |
This mode is intended for big-endian non-68k systems that do allow access to |
59 |
< |
RAM at 0x0000..0x1fff. As in the virtual addressing mode, the 68k processor |
60 |
< |
is emulated with the UAE CPU engine and two areas are set up for RAM and ROM |
61 |
< |
but the emulated CPU lives in the same address space as the host CPU. |
62 |
< |
This means that if something is located at a certain address for the 68k, |
63 |
< |
it is located at the exact same address for the host CPU. Mac addresses |
64 |
< |
and host addresses are the same. The memory accesses of the CPU emulation |
65 |
< |
still go through access functions but the address translation is no longer |
66 |
< |
needed, and if the host CPU uses big-endian data layout and can handle |
67 |
< |
unaligned accesses like the 68k, the memory access functions are replaced |
68 |
< |
by direct, inlined memory accesses, making for the fastest possible speed |
69 |
< |
of the emulator. |
47 |
> |
don't allow accessing RAM at 0x0000..0x1fff. This is also the only mode |
48 |
> |
that allows 24-bit addressing, and thus the only mode that allows Mac |
49 |
> |
Classic emulation. The 68k processor is emulated with the UAE CPU engine |
50 |
> |
and two memory areas are allocated for Mac RAM and ROM. The memory map |
51 |
> |
seen by the emulated CPU and the host CPU are different. Mac RAM starts at |
52 |
> |
address 0 for the emulated 68k, but it may start at a different address for |
53 |
> |
the host CPU. |
54 |
> |
|
55 |
> |
In order to handle the particularities of each memory area (RAM, ROM and |
56 |
> |
Frame Buffer), the address space of the emulated 68k is broken down into |
57 |
> |
banks. Each bank is associated with a series of pointers to specific |
58 |
> |
memory access functions that carry out the necessary operations (e.g. |
59 |
> |
byte-swapping, catching illegal writes to memory). A generic memory access |
60 |
> |
function, get_long() for example, goes through the table of memory banks |
61 |
> |
(mem_banks) and fetches the appropriate specific memory access fonction, |
62 |
> |
lget() in our example. This slows down the emulator, of course. |
63 |
> |
|
64 |
> |
2. Emulated CPU, "direct" addressing (EMULATED_68K = 1, DIRECT_ADDRESSING = 1): |
65 |
> |
As in the virtual addressing mode, the 68k processor is emulated with the |
66 |
> |
UAE CPU engine and two memory areas are set up for RAM and ROM. Mac RAM |
67 |
> |
starts at address 0 for the emulated 68k, but it may start at a different |
68 |
> |
address for the host CPU. Besides, the virtual memory areas seen by the |
69 |
> |
emulated 68k are separated by exactly the same amount of bytes as the |
70 |
> |
corresponding memory areas allocated on the host CPU. This means that |
71 |
> |
address translation simply implies the addition of a constant offset |
72 |
> |
(MEMBaseDiff). Therefore, the memory banks are no longer used and the |
73 |
> |
memory access functions are replaced by inline memory accesses. |
74 |
> |
|
75 |
> |
3. Emulated CPU, "real" addressing (EMULATED_68K = 1, REAL_ADDRESSING = 1): |
76 |
> |
This mode is intended for non-68k systems that do allow access to RAM |
77 |
> |
at 0x0000..0x1fff. As in the virtual addressing mode, the 68k processor |
78 |
> |
is emulated with the UAE CPU engine and two areas are allocated for RAM |
79 |
> |
and ROM but the emulated CPU lives in the same address space as the host |
80 |
> |
CPU. This means that if something is located at a certain address for |
81 |
> |
the 68k, it is located at the exact same address for the host CPU. Mac |
82 |
> |
addresses and host addresses are the same. The memory accesses of the CPU |
83 |
> |
emulation still go through access functions but the address translation |
84 |
> |
is no longer needed. The memory access functions are replaced by direct, |
85 |
> |
inlined memory accesses, making for the fastest possible speed of the |
86 |
> |
emulator. On little-endian systems, byte-swapping is still required, of |
87 |
> |
course. |
88 |
> |
|
89 |
|
A usual consequence of the real addressing mode is that the Mac RAM doesn't |
90 |
|
any longer begin at address 0 for the Mac and that the Mac ROM also is not |
91 |
|
located where it usually is on a real Mac. But as the Mac ROM is relocatable |
104 |
|
other systems, it might be possible to use access exception handlers to |
105 |
|
emulate accesses to this area. But if the Low Memory Globals area cannot |
106 |
|
be made available, using the real addressing mode is not possible. |
107 |
+ |
|
108 |
+ |
Note: currently, real addressing mode is known to work only on AmigaOS, |
109 |
+ |
NetBSD/m68k, and Linux/i386. |
110 |
|
|
111 |
< |
3. Native CPU (EMULATED_68K = 0, this also requires REAL_ADDRESSING = 1) |
111 |
> |
4. Native CPU (EMULATED_68K = 0, this also requires REAL_ADDRESSING = 1) |
112 |
|
This mode is designed for systems that use a 68k (68020 or better) processor |
113 |
|
as host CPU and is the technically most difficult mode to handle. The Mac |
114 |
|
CPU is no longer emulated (the UAE CPU emulation is not needed) but MacOS |
127 |
|
priviledged instructions, mostly for interrupt control). So either |
128 |
|
the whole emulator has to be run in supervisor mode (which usually is |
129 |
|
not possible on multitasking systems) or priviledged instructions have |
130 |
< |
to be trapped and emulated. The Amiga version of Basilisk II uses the |
131 |
< |
latter approach (it is possible to run supervisor mode tasks under |
132 |
< |
the AmigaOS multitasking kernel (ShapeShifter does this) but it |
133 |
< |
requires modifying the task switcher and makes the emulator more |
134 |
< |
unstable). |
130 |
> |
to be trapped and emulated. The Amiga and NetBSD/m68k versions of |
131 |
> |
Basilisk II use the latter approach (it is possible to run supervisor |
132 |
> |
mode tasks under the AmigaOS multitasking kernel (ShapeShifter does |
133 |
> |
this) but it requires modifying the Exec task switcher and makes the |
134 |
> |
emulator more unstable). |
135 |
|
c) On multitasking systems, interrupts can usually not be handled as on |
136 |
|
a real Mac (or with the UAE CPU). The interrupt levels of the host |
137 |
|
will not be the same as on a Mac, and the operating systems might not |
223 |
|
currently defined interrupt sources (see main.h): |
224 |
|
|
225 |
|
INTFLAG_60HZ - MacOS 60Hz interrupt (unlike a real Mac, we also handle |
226 |
< |
VBL interrupts, ADB events and the Time Manager here) |
226 |
> |
VBL interrupts and the Time Manager here) |
227 |
> |
INTFLAG_1HZ - MacOS 1Hz interrupt (updates system time) |
228 |
|
INTFLAG_SERIAL - Interrupt for serial driver I/O completion |
229 |
|
INTFLAG_ETHER - Interrupt for Ethernet driver I/O completion and packet |
230 |
|
reception |
231 |
|
INTFLAG_AUDIO - Interrupt for audio "next block" requests |
232 |
|
INTFLAG_TIMER - Reserved for a future implementation of a more precise |
233 |
|
Time Manager (currently not used) |
234 |
+ |
INTFLAG_ADB - Interrupt for mouse/keyboard input |
235 |
+ |
INTFLAG_NMI - NMI for debugging (not supported on all platforms) |
236 |
|
|
237 |
|
An interrupt is triggered by calling SetInterruptFlag() with the desired |
238 |
|
interrupt flag constant and then TriggerInterrupt(). When the UAE 68k |
295 |
|
provides replacements for certain parts of MacOS to redirect input, output |
296 |
|
and system control functions of the Mac hardware to the underlying operating |
297 |
|
systems. This is done by applying patches to the Mac ROM ("ROM patches") and |
298 |
< |
the MacOS system file ("resource patches", because nearly all system software |
299 |
< |
is contained in MacOS resources). Unless resources are written back to disk, |
300 |
< |
the system file patches are not permanent (it would cause many problems if |
301 |
< |
they were permanent, because some of the patches vary with different |
302 |
< |
versions of Basilisk II or even every time the emulator is launched). |
298 |
> |
the MacOS system file ("resource patches", because nearly all system |
299 |
> |
software is contained in MacOS resources). Unless resources are written back |
300 |
> |
to disk, the system file patches are not permanent (it would cause many |
301 |
> |
problems if they were permanent, because some of the patches vary with |
302 |
> |
different versions of Basilisk II or even every time the emulator is |
303 |
> |
launched). |
304 |
|
|
305 |
|
ROM patches are contained in "rom_patches.cpp" and resource patches are |
306 |
< |
contained in "rsrc_patches.cpp". The ROM patches are far more numerous because |
307 |
< |
nearly all the software needed to run MacOS is contained in the Mac ROM (the |
308 |
< |
system file itself consists mainly of ROM patches, in addition to pictures and |
309 |
< |
text). One part of the ROM patches involves the construction of a NuBus slot |
310 |
< |
declaration ROM (in "slot_rom.cpp") which is used to add the video and Ethernet |
311 |
< |
drivers. Apart from the CPU emulation, the ROM and resource patches contain |
312 |
< |
most of the "logic" of the emulator. |
306 |
> |
contained in "rsrc_patches.cpp". The ROM patches are far more numerous |
307 |
> |
because nearly all the software needed to run MacOS is contained in the Mac |
308 |
> |
ROM (the system file itself consists mainly of ROM patches, in addition to |
309 |
> |
pictures and text). One part of the ROM patches involves the construction of |
310 |
> |
a NuBus slot declaration ROM (in "slot_rom.cpp") which is used to add the |
311 |
> |
video and Ethernet drivers. Apart from the CPU emulation, the ROM and |
312 |
> |
resource patches contain most of the "logic" of the emulator. |
313 |
|
|
314 |
|
6.3. PRAM Utilities |
315 |
|
------------------- |
316 |
|
|
317 |
|
MacOS stores certain nonvolatile system parameters in a 256 byte battery |
318 |
< |
backed-up CMOS RAM area called "Parameter RAM", "PRAM" or "XPRAM" (which refers |
319 |
< |
to "Extended PRAM" because the earliest Mac models only had 20 bytes of PRAM). |
320 |
< |
Basilisk II patches the ClkNoMem() MacOS trap which is used to access the XPRAM |
321 |
< |
(apart from some routines which are only used early during system startup) |
322 |
< |
and the real-time clock. The XPRAM is emulated in a 256 byte array which is |
323 |
< |
saved to disk to preserve the contents for the next time Basilisk is launched. |
318 |
> |
backed-up CMOS RAM area called "Parameter RAM", "PRAM" or "XPRAM" (which |
319 |
> |
refers to "Extended PRAM" because the earliest Mac models only had 20 bytes |
320 |
> |
of PRAM). Basilisk II patches the ClkNoMem() MacOS trap which is used to |
321 |
> |
access the XPRAM (apart from some routines which are only used early during |
322 |
> |
system startup) and the real-time clock. The XPRAM is emulated in a 256 byte |
323 |
> |
array which is saved to disk to preserve the contents for the next time |
324 |
> |
Basilisk is launched. |
325 |
|
|
326 |
|
6.4. ADB Manager |
327 |
|
---------------- |
328 |
|
|
329 |
|
For emulating a mouse and a keyboard, Basilisk II patches the ADBOp() MacOS |
330 |
|
trap. Platform-dependant code reports mouse and keyboard events with the |
331 |
< |
ADBMouseDown() etc. functions which are queued and sent to MacOS inside the |
332 |
< |
ADBInterrupt() function (which is called as a part of the 60Hz interrupt |
333 |
< |
handler) by calling the ADB mouse and keyboard handlers with Execute68k(). |
331 |
> |
ADBMouseDown() etc. functions where they are queued, and the INTFLAG_ADB |
332 |
> |
interrupt is triggered. The ADBInterrupt() handler function sends the input |
333 |
> |
events to MacOS by calling the ADB mouse and keyboard handlers with |
334 |
> |
Execute68k(). |
335 |
|
|
336 |
|
6.5. Time Manager |
337 |
|
----------------- |
338 |
|
|
339 |
|
Basilisk II completely replaces the Time Manager (InsTime(), RmvTime(), |
340 |
< |
PrimeTime() and Microseconds() traps). A "TMDesc" structure is associated with |
341 |
< |
each Time Manager task, that contains additional data. The tasks are executed |
342 |
< |
in the TimerInterrupt() function which is currently called inside the 60Hz |
343 |
< |
interrupt handler, thus limiting the resolution of the Time Manager to 16.6ms. |
340 |
> |
PrimeTime() and Microseconds() traps). A "TMDesc" structure is associated |
341 |
> |
with each Time Manager task, that contains additional data. The tasks are |
342 |
> |
executed in the TimerInterrupt() function which is currently called inside |
343 |
> |
the 60Hz interrupt handler, thus limiting the resolution of the Time Manager |
344 |
> |
to 16.6ms. |
345 |
|
|
346 |
|
6.6. SCSI Manager |
347 |
|
----------------- |
348 |
|
|
349 |
|
The (old-style) SCSI Manager is also completely replaced and the MacOS |
350 |
< |
SCSIDispatch() trap redirected to the routines in "scsi.cpp". Under the MacOS, |
351 |
< |
programs have to issue multiple calls for all the different phases of a |
352 |
< |
SCSI bus interaction (arbitration, selection, command transfer etc.). |
350 |
> |
SCSIDispatch() trap redirected to the routines in "scsi.cpp". Under the |
351 |
> |
MacOS, programs have to issue multiple calls for all the different phases of |
352 |
> |
a SCSI bus interaction (arbitration, selection, command transfer etc.). |
353 |
|
Basilisk II maps this API to an atomic API which is used by most modern |
354 |
|
operating systems. All action is deferred until the call to SCSIComplete(). |
355 |
|
The TIB (Transfer Instruction Block) mini-programs used by the MacOS are |
356 |
|
translated into a scatter/gather list of data blocks. Operating systems that |
357 |
< |
don't support scatter/gather SCSI I/O will have to use buffering if more than |
358 |
< |
one data block is being transmitted. Some more advanced (but rarely used) |
359 |
< |
aspects of the SCSI Manager (like messaging and compare operations) are not |
360 |
< |
emulated. |
357 |
> |
don't support scatter/gather SCSI I/O will have to use buffering if more |
358 |
> |
than one data block is being transmitted. Some more advanced (but rarely |
359 |
> |
used) aspects of the SCSI Manager (like messaging and compare operations) |
360 |
> |
are not emulated. |
361 |
|
|
362 |
|
6.7. Video driver |
363 |
|
----------------- |
364 |
|
|
365 |
< |
The NuBus slot declaration ROM constructed in "slot_rom.cpp" contains a driver |
366 |
< |
definition for a video driver. The Control and Status calls of this driver are |
367 |
< |
implemented in "video.cpp". Run-time video mode and depth switching are |
339 |
< |
currently not supported. |
365 |
> |
The NuBus slot declaration ROM constructed in "slot_rom.cpp" contains a |
366 |
> |
driver definition for a video driver. The Control and Status calls of this |
367 |
> |
driver are implemented in "video.cpp". |
368 |
|
|
369 |
|
The host-side initialization of the video system is done in VideoInit(). |
370 |
< |
This function must provide access to a frame buffer for MacOS and supply |
371 |
< |
its address, resolution and color depth in a video_desc structure (there |
372 |
< |
is currently only one video_desc structure, called VideoMonitor; this is |
373 |
< |
going to change once multiple displays are supported). In real addressing |
374 |
< |
mode, this frame buffer must be in a MacOS compatible layout (big-endian |
375 |
< |
and 1, 2, 4 or 8 bits paletted chunky pixels, RGB 5:5:5 or xRGB 8:8:8:8). |
376 |
< |
In virtual addressing mode, the frame buffer is located at address |
377 |
< |
0xa0000000 on the Mac side and you have to supply the host address, size |
378 |
< |
and layout (BasiliskII will do an automatic pixel format conversion in |
379 |
< |
virtual addressing mode) in the variables MacFrameBaseHost, MacFrameSize |
380 |
< |
and MacFrameLayout. |
370 |
> |
This function must fill the VideoModes vector with a list of supported video |
371 |
> |
modes (combinations of color depth and resolution). It must then call |
372 |
> |
video_init_depth_list() and setup the VideoMonitor structure with the |
373 |
> |
default mode information and the address of a frame buffer for MacOS. In |
374 |
> |
real addressing mode, this frame buffer must be in a MacOS compatible layout |
375 |
> |
(big-endian and 1, 2, 4 or 8 bits paletted chunky pixels, RGB 5:5:5 or xRGB |
376 |
> |
8:8:8:8). In virtual addressing mode, the frame buffer is located at address |
377 |
> |
0xa0000000 on the Mac side and you have to supply the host address, size and |
378 |
> |
layout (BasiliskII will do an automatic pixel format conversion in virtual |
379 |
> |
addressing mode) in the variables MacFrameBaseHost, MacFrameSize and |
380 |
> |
MacFrameLayout. |
381 |
> |
|
382 |
> |
There are two functions of the platform-dependant video driver code that get |
383 |
> |
called during runtime: video_set_palette() to update the CLUT (for indexed |
384 |
> |
modes) or gamma table (for direct color modes), and video_switch_to_mode() |
385 |
> |
to switch to a different color depth and/or resolution (in this case the |
386 |
> |
frame buffer base in VideoMonitor must be updated). |
387 |
|
|
388 |
|
6.8. Audio component |
389 |
|
-------------------- |
390 |
|
|
391 |
|
Basilisk II provides a Sound Manager 3.x audio component for sound output. |
392 |
< |
Earlier Sound Manager versions that don't use components but 'snth' resources |
393 |
< |
are not supported. Nearly all component functions are implemented in |
394 |
< |
"audio.cpp". The system-dependant modules ("audio_*.cpp") handle the |
392 |
> |
Earlier Sound Manager versions that don't use components but 'snth' |
393 |
> |
resources are not supported. Nearly all component functions are implemented |
394 |
> |
in "audio.cpp". The system-dependant modules ("audio_*.cpp") handle the |
395 |
|
initialization of the audio hardware/driver, volume controls, and the actual |
396 |
|
sound output. |
397 |
|
|
398 |
|
The mechanism of sound output varies depending on the platform but usually |
399 |
< |
there will be one "streaming thread" (either a thread that continuously writes |
400 |
< |
data buffers to the audio device or a callback function that provides the |
401 |
< |
next data buffer) that reads blocks of sound data from the MacOS Sound Manager |
402 |
< |
and writes them to the audio device. To request the next data buffer, the |
403 |
< |
streaming thread triggers the INTFLAG_AUDIO interrupt which will cause the |
404 |
< |
MacOS thread to eventually call AudioInterrupt(). Inside AudioInterrupt(), |
405 |
< |
the next data block will be read and the streaming thread is signalled that |
406 |
< |
new audio data is available. |
399 |
> |
there will be one "streaming thread" (either a thread that continuously |
400 |
> |
writes data buffers to the audio device or a callback function that provides |
401 |
> |
the next data buffer) that reads blocks of sound data from the MacOS Sound |
402 |
> |
Manager and writes them to the audio device. To request the next data |
403 |
> |
buffer, the streaming thread triggers the INTFLAG_AUDIO interrupt which will |
404 |
> |
cause the MacOS thread to eventually call AudioInterrupt(). Inside |
405 |
> |
AudioInterrupt(), the next data block will be read and the streaming thread |
406 |
> |
is signalled that new audio data is available. |
407 |
|
|
408 |
|
6.9. Floppy, disk and CD-ROM drivers |
409 |
|
------------------------------------ |
410 |
|
|
411 |
< |
Basilisk II contains three MacOS drivers that implement floppy, disk and CD-ROM |
412 |
< |
access ("sony.cpp", "disk.cpp" and "cdrom.cpp"). They rely heavily on the |
413 |
< |
functionality provided by the "sys_*.cpp" module. BTW, the name ".Sony" of the |
414 |
< |
MacOS floppy driver comes from the fact that the 3.5" floppy drive in the first |
415 |
< |
Mac models was custom-built for Apple by Sony (this was one of the first |
416 |
< |
applications of the 3.5" floppy format which was also invented by Sony). |
411 |
> |
Basilisk II contains three MacOS drivers that implement floppy, disk and |
412 |
> |
CD-ROM access ("sony.cpp", "disk.cpp" and "cdrom.cpp"). They rely heavily on |
413 |
> |
the functionality provided by the "sys_*.cpp" module. BTW, the name ".Sony" |
414 |
> |
of the MacOS floppy driver comes from the fact that the 3.5" floppy drive in |
415 |
> |
the first Mac models was custom-built for Apple by Sony (this was one of the |
416 |
> |
first applications of the 3.5" floppy format which was also invented by |
417 |
> |
Sony). |
418 |
|
|
419 |
|
6.10. External file system |
420 |
|
-------------------------- |
421 |
|
|
422 |
|
Basilisk II also provides a method for accessing files and direcories on the |
423 |
< |
host OS from the MacOS side by means of an "external" file system (henceforth |
424 |
< |
called "ExtFS"). The ExtFS is built upon the File System Manager 1.2 interface |
425 |
< |
that is built into MacOS 7.6 (and later) and available as a system extension |
426 |
< |
for earlier MacOS versions. Unlike other parts of Basilisk II, extfs.cpp |
427 |
< |
requires POSIX file I/O and this is not going to change any time soon, so if |
428 |
< |
you are porting Basilisk II to a system without POSIX file functions, you |
429 |
< |
should emulate them. |
423 |
> |
host OS from the MacOS side by means of an "external" file system |
424 |
> |
(henceforth called "ExtFS"). The ExtFS is built upon the File System Manager |
425 |
> |
1.2 interface that is built into MacOS 7.6 (and later) and available as a |
426 |
> |
system extension for earlier MacOS versions. Unlike other parts of Basilisk |
427 |
> |
II, extfs.cpp requires POSIX file I/O and this is not going to change any |
428 |
> |
time soon, so if you are porting Basilisk II to a system without POSIX file |
429 |
> |
functions, you should emulate them. |
430 |
|
|
431 |
|
6.11. Serial drivers |
432 |
|
-------------------- |
439 |
|
platform-dependant code. There are two instances (for port A and B) of the |
440 |
|
subclasses. |
441 |
|
|
442 |
< |
Unlike the disk drivers, the serial driver must be able to handle asynchronous |
443 |
< |
operations. Calls to SerialPrime() will usually not actually transmit or receive |
444 |
< |
data but delegate the action to an independant thread. SerialPrime() then |
445 |
< |
returns "1" to indicate that the I/O operation is not yet completed. The |
446 |
< |
completion of the I/O request is signalled by calling the MacOS trap "IODone". |
447 |
< |
However, this can't be done by the I/O thread because it's not in the right |
448 |
< |
run-time environment to call MacOS functions. Therefore it will trigger the |
449 |
< |
INTFLAG_SERIAL interrupt which causes the MacOS thread to eventually call |
450 |
< |
SerialInterrupt(). SerialInterrupt(), in turn, will not call IODone either but |
451 |
< |
install a Deferred Task to do the job. The Deferred Task will be called by |
452 |
< |
MacOS when it returns to interrupt level 0. This mechanism sounds complicated |
453 |
< |
but is necessary to ensure stable operation of the serial driver. |
442 |
> |
Unlike the disk drivers, the serial driver must be able to handle |
443 |
> |
asynchronous operations. Calls to SerialPrime() will usually not actually |
444 |
> |
transmit or receive data but delegate the action to an independant thread. |
445 |
> |
SerialPrime() then returns "1" to indicate that the I/O operation is not yet |
446 |
> |
completed. The completion of the I/O request is signalled by calling the |
447 |
> |
MacOS trap "IODone". However, this can't be done by the I/O thread because |
448 |
> |
it's not in the right run-time environment to call MacOS functions. |
449 |
> |
Therefore it will trigger the INTFLAG_SERIAL interrupt which causes the |
450 |
> |
MacOS thread to eventually call SerialInterrupt(). SerialInterrupt(), in |
451 |
> |
turn, will not call IODone either but install a Deferred Task to do the job. |
452 |
> |
The Deferred Task will be called by MacOS when it returns to interrupt level |
453 |
> |
0. This mechanism sounds complicated but is necessary to ensure stable |
454 |
> |
operation of the serial driver. |
455 |
|
|
456 |
|
6.12. Ethernet driver |
457 |
|
--------------------- |
464 |
|
or it may require writing special net drivers or add-ons or running with |
465 |
|
superuser priviledges to get access to the raw packets. |
466 |
|
|
467 |
< |
Writing packets works as in the serial drivers. The ether_write() routine may |
468 |
< |
choose to send the packet immediately (e.g. under BeOS) and return noErr or to |
469 |
< |
delegate the sending to a separate thread (e.g. under AmigaOS) and return "1" to |
470 |
< |
indicate that the operation is still in progress. For the latter case, a |
471 |
< |
Deferred Task structure is provided in the ether_data area to call IODone from |
472 |
< |
EtherInterrupt() when the packet write is complete (see above for a description |
473 |
< |
of the mechanism). |
467 |
> |
For situations in which access to raw Ethernet packets is not possible, |
468 |
> |
Basilisk II implements a special "tunneling" mode in which it sends and |
469 |
> |
receives packets via UDP, using BSD socket functions. It simply wraps the |
470 |
> |
Ethernet packets into UDP packets, using dummy Ethernet addresses that are |
471 |
> |
made up of the IP address of the host. Ethernet broadcast and AppleTalk |
472 |
> |
multicast packets are sent to the IP broadcast address. Because of this |
473 |
> |
non-standard way of tunneling, it is only possible to set up a "virtual" |
474 |
> |
network amongst machines running Basilisk II in this way. |
475 |
> |
|
476 |
> |
Writing packets works as in the serial drivers. The ether_write() routine |
477 |
> |
may choose to send the packet immediately (e.g. under BeOS) and return noErr |
478 |
> |
or to delegate the sending to a separate thread (e.g. under AmigaOS) and |
479 |
> |
return "1" to indicate that the operation is still in progress. For the |
480 |
> |
latter case, a Deferred Task structure is provided in the ether_data area to |
481 |
> |
call IODone from EtherInterrupt() when the packet write is complete (see |
482 |
> |
above for a description of the mechanism). |
483 |
|
|
484 |
|
Packet reception is a different story. First of all, there are two methods |
485 |
< |
provided by the MacOS Ethernet driver API to read packets, one of which (ERead/ |
486 |
< |
ERdCancel) is not supported by Basilisk II. Basilisk II only supports reading |
487 |
< |
packets by attaching protocol handlers. This shouldn't be a problem because |
488 |
< |
the only network code I've seen so far that uses ERead is some Apple sample |
489 |
< |
code. AppleTalk, MacTCP, MacIPX, OpenTransport etc. all use protocol handlers. |
490 |
< |
By attaching a protocol handler, the user of the Ethernet driver supplies a |
491 |
< |
handler routine that should be called by the driver upon reception of Ethernet |
492 |
< |
packets of a certain type. 802.2 packets (type/length field of 0..1500 in the |
493 |
< |
packet header) are a bit special: there can be only one protocol handler attached |
494 |
< |
for 802.2 packets (by specifying a packet type of "0"). The MacOS LAP Manager |
495 |
< |
will attach a 802.2 handler upon startup and handle the distribution of 802.2 |
496 |
< |
packets to sub-protocol handlers, but the Basilisk II Ethernet driver is not |
497 |
< |
concerned with this. |
485 |
> |
provided by the MacOS Ethernet driver API to read packets, one of which |
486 |
> |
(ERead/ ERdCancel) is not supported by Basilisk II. Basilisk II only |
487 |
> |
supports reading packets by attaching protocol handlers. This shouldn't be a |
488 |
> |
problem because the only network code I've seen so far that uses ERead is |
489 |
> |
some Apple sample code. AppleTalk, MacTCP, MacIPX, OpenTransport etc. all |
490 |
> |
use protocol handlers. By attaching a protocol handler, the user of the |
491 |
> |
Ethernet driver supplies a handler routine that should be called by the |
492 |
> |
driver upon reception of Ethernet packets of a certain type. 802.2 packets |
493 |
> |
(type/length field of 0..1500 in the packet header) are a bit special: there |
494 |
> |
can be only one protocol handler attached for 802.2 packets (by specifying a |
495 |
> |
packet type of "0"). The MacOS LAP Manager will attach a 802.2 handler upon |
496 |
> |
startup and handle the distribution of 802.2 packets to sub-protocol |
497 |
> |
handlers, but the Basilisk II Ethernet driver is not concerned with this. |
498 |
|
|
499 |
|
When the driver receives a packet, it has to look up the protocol handler |
500 |
|
installed for the respective packet type (if any has been installed at all) |
501 |
< |
and call the packet handler routine. This must be done with Execute68k() from |
502 |
< |
the MacOS thread, so an interrupt (INTFLAG_ETHER) is triggered upon reception |
503 |
< |
of a packet so the EtherInterrupt() routine can call the protocol handler. |
504 |
< |
Before calling the handler, the Ethernet packet header has to be copied to |
505 |
< |
MacOS RAM (the "ed_RHA" field of the ether_data structure is provided for this). |
506 |
< |
The protocol handler will read the packet data by means of the ReadPacket/ReadRest |
507 |
< |
routines supplied by the Ethernet driver. Both routines will eventually end up |
508 |
< |
in EtherReadPacket() which copies the data to Mac address space. EtherReadPacket() |
509 |
< |
requires the host address and length of the packet to be loaded to a0 and d1 |
510 |
< |
before calling the protocol handler. |
501 |
> |
and call the packet handler routine. This must be done with Execute68k() |
502 |
> |
from the MacOS thread, so an interrupt (INTFLAG_ETHER) is triggered upon |
503 |
> |
reception of a packet so the EtherInterrupt() routine can call the protocol |
504 |
> |
handler. Before calling the handler, the Ethernet packet header has to be |
505 |
> |
copied to MacOS RAM (the "ed_RHA" field of the ether_data structure is |
506 |
> |
provided for this). The protocol handler will read the packet data by means |
507 |
> |
of the ReadPacket/ReadRest routines supplied by the Ethernet driver. Both |
508 |
> |
routines will eventually end up in EtherReadPacket() which copies the data |
509 |
> |
to Mac address space. EtherReadPacket() requires the host address and length |
510 |
> |
of the packet to be loaded to a0 and d1 before calling the protocol handler. |
511 |
|
|
512 |
< |
Does this sound complicated? You are probably right. Here is another description |
513 |
< |
of what happens upon reception of a packet: |
512 |
> |
Does this sound complicated? You are probably right. Here is another |
513 |
> |
description of what happens upon reception of a packet: |
514 |
|
1. Ethernet card receives packet and notifies some platform-dependant entity |
515 |
|
inside Basilisk II |
516 |
|
2. This entity will store the packet in some safe place and trigger the |
530 |
|
part of the packet data to Mac RAM using the pointer and length which are |
531 |
|
still in a0/d1 |
532 |
|
|
533 |
< |
For a more detailed description of the Ethernet driver, see "Inside AppleTalk". |
533 |
> |
For a more detailed description of the Ethernet driver, see the book "Inside |
534 |
> |
AppleTalk". |
535 |
|
|
536 |
|
6.13. System-dependant device access |
537 |
|
------------------------------------ |
545 |
|
6.14. User interface strings |
546 |
|
---------------------------- |
547 |
|
|
548 |
< |
To aid in localization, all user interface strings of Basilisk II are collected |
549 |
< |
in "user_strings.cpp" (for common strings) and "user_strings_*.cpp" (for |
550 |
< |
platform-specific strings), and accessed via the GetString() function. This |
551 |
< |
way, Basilisk II may be easily translated to different languages. |
548 |
> |
To aid in localization, all user interface strings of Basilisk II are |
549 |
> |
collected in "user_strings.cpp" (for common strings) and |
550 |
> |
"user_strings_*.cpp" (for platform-specific strings), and accessed via the |
551 |
> |
GetString() function. This way, Basilisk II may be easily translated to |
552 |
> |
different languages. |
553 |
|
|
554 |
|
6.15. Preferences management |
555 |
|
---------------------------- |
558 |
|
Preferences items are accessed with the PrefsAdd*(), PrefsReplace*() and |
559 |
|
PrefsFind*() functions and stored in human-readable and editable text files |
560 |
|
on disk. There are two lists of available preferences items. The first one, |
561 |
< |
common_prefs_items, defines the items which are available on all systems. |
562 |
< |
The second one, platform_prefs_items, is defined in prefs_*.cpp and lists |
563 |
< |
the prefs items which are specific to a certain platform. |
561 |
> |
common_prefs_items, is defined in "prefs_items.cpp" and lists items which |
562 |
> |
are available on all systems. The second one, platform_prefs_items, is |
563 |
> |
defined in "prefs_*.cpp" and lists the prefs items which are specific to a |
564 |
> |
certain platform. |
565 |
|
|
566 |
|
The "prefs_editor_*.cpp" module provides a graphical user interface for |
567 |
|
setting the preferences so users won't have to edit the preferences file |
570 |
|
7. Porting Basilisk II |
571 |
|
---------------------- |
572 |
|
|
573 |
< |
Porting Basilisk II to a new platform should not be hard. These are the steps |
574 |
< |
involved in the process: |
573 |
> |
Porting Basilisk II to a new platform should not be hard. These are the |
574 |
> |
steps involved in the process: |
575 |
|
|
576 |
|
1. Create a new directory inside the "src" directory for your platform. If |
577 |
|
your platform comes in several "flavours" that require adapted files, you |