home *** CD-ROM | disk | FTP | other *** search
- ;*********************************************************************
- ;* Origin and Purpose *
- ;* *
- ;* This device represents things I would liked to have known when *
- ;* starting out writing devices. I found it hard to get firm data *
- ;* on device design, and collected everything I could find into this *
- ;* file. Sure it has lots of comments, but it makes a great basic *
- ;* skeleton or classroom presentation. *
- ;* *
- ;* I apologize in advance for any bugs, oversights or errors. As *
- ;* always, corrections and design tips are welcome. *
- ;* *
- ;* Send comments, flames, etc. to the following: *
- ;* *
- ;* Tau Productions *
- ;* Jeff Rush *
- ;* BIX: jrush *
- ;* BBS: (214) 231-1372 Rising Star *
- ;* Fidonet: 1:124/4206 (Dallas, Tx) *
- ;* *
- ;* All changes I made are hereby in the Public Domain. Commodore *
- ;* retains its copyright, if any, of the original code in the Rom *
- ;* Kernel manuals since this is a derivative work. *
- ;* *
- ;*********************************************************************
- ;* History *
- ;* *
- ;* 20Sep89 jrr Original crib from Amiga Rom Kernel Manual. *
- ;* 23Jul90 jrr Extensive descriptive prose added. *
- ;* 10Sep90 jrr Uploaded to BIX and made available on my BBS. *
- ;* *
- ;*********************************************************************
- ;* Whats Different from the Rom Kernel Example *
- ;* *
- ;* The following Exec device represents a very simple skeleton for *
- ;* use as a starting point for authors. It was derived from the *
- ;* sample device in the Amiga ROM Kernel: Includes & Autodocs, but *
- ;* has had documentation and folklore from various places folded *
- ;* into the comments in order to explain some of the 'magic'. *
- ;* *
- ;* For simplicity, the following components of the original example *
- ;* have been stripped out: *
- ;* o Automount at Autoconfig time when a matching board is found *
- ;* o Hardware interrupt fielding support *
- ;* o AmigaDOS volume/device support *
- ;* *
- ;* I also stripped out all code that make this device implement a *
- ;* ram disk. I found the assumption that the device was a disk *
- ;* tended to bias the structure away from a character device a bit. *
- ;* I hope I made it more generic, albeit less practical. This code *
- ;* implements a null device that does nothing except go through the *
- ;* motions. *
- ;* *
- ;* I added code to implement a signal semaphore to arbitrate access *
- ;* to the device's internal global data. I would like to add code *
- ;* to make the unit task a full process so that it can perform DOS *
- ;* operations if needed in a real design, but have not yet done so. *
- ;* *
- ;*********************************************************************
- ;* Exec-Style Device Skeleton *
- ;* *
- ;* What is a Device? *
- ;* *
- ;* An Exec-style device is a logical abstraction of standard and *
- ;* custom functions used to manage a piece of either real or *
- ;* simulated hardware. The term 'device' in this file refers to the *
- ;* abstraction as represented by this software, not the hardware *
- ;* itself. A device is an Exec shared library that by convention *
- ;* a few extra function vectors that caller's can utilize for *
- ;* control. Except for this and the fact that the code resides in a *
- ;* different directory, it -is- a shared library. By convention a *
- ;* device can spin off background tasks to handle work, but shared *
- ;* libraries are capable of this too, they just tend not to. So a *
- ;* 'static' library or passive piece of code is what we call a *
- ;* library, and a 'dynamic' library or active piece of code with a *
- ;* life of its own we call a device. *
- ;* *
- ;* For those with IBM-PC backgrounds, an Exec-style device can *
- ;* functionally be thought of as a BIOS rom. Although BIOS roms do *
- ;* not act as independent tasks, the low-level nature of the BIOS *
- ;* interface is similar to a device. You wouldn't think of using *
- ;* the PCDOS Copy command to send a file to the screen using INT 10H *
- ;* (Video), and AmigaDOS commands cannot necessarily be used to talk *
- ;* to Exec devices directly. *
- ;* *
- ;* A device can be activated in one of three ways. *
- ;* *
- ;* a) It can auto-mounted by the BindDrivers AmigaDOS command in *
- ;* response to the presence of a piece of vendor hardware. It is *
- ;* matched up with the hardware by checking the autoconfigure *
- ;* manufacturer ID built into the hardware with the product code *
- ;* within the tooltype of a icon in the expansion directory. The *
- ;* icon is for the file containing the device code. *
- ;* *
- ;* b) It can be manually mounted by a user in response to the Mount *
- ;* AmigaDOS command. This requires that an entry be defined in *
- ;* a 'mountlist' file defining the configuration of the device. *
- ;* *
- ;* c) It can be activated by an application calling the Exec routine *
- ;* OpenDevice() for use within the application. *
- ;* *
- ;* Method a) and b) above are typically used when AmigaDOS needs to *
- ;* be made aware of the device, either as a logical name (PRT:) or *
- ;* as a raw media on which a filesystem resides (DF0:). Method c) *
- ;* is used when AmigaDOS does not need to be aware of the device *
- ;* and/or the device represents internal or low-level functionality, *
- ;* like a LAN adapter interface. *
- ;* *
- ;*********************************************************************
- ;* ! Obscure Bug Alert ! *
- ;* You should be aware that there is a bug in the Exec v1.3 function *
- ;* MakeLibrary(). If the device name within the code is different *
- ;* from the name used in the OpenDevice() call, either in case or *
- ;* spelling, the device will be loaded into memory, the code for its *
- ;* initialization will be executed, and then Exec will deallocate *
- ;* the device node *** while leaving the node linked into the system *
- ;* lists ***!! This results in very strange system behavior and a *
- ;* crash during an Expunge. This is because AmigaDOS is *
- ;* case-INsensitive, but Exec is case-sensitive. Also, the name in *
- ;* the OpenDevice() is used to locate the file to load, but the name *
- ;* inside the code is used to reference the device in memory. *
- ;* *
- ;* The moral: Insure device names match *exactly* in all cases. *
- ;* *
- ;*********************************************************************
- ;* The Role and Importance of Single-Threading (Forbid'ing) *
- ;* *
- ;* At Load Initialization Time: *
- ;* *
- ;* During the setup of an Exec-style device, there is a window of *
- ;* vulnerability due to the multitasking nature of the Amiga. It is *
- ;* possible for two separate applications to attempt to open a *
- ;* device concurrently. *
- ;* *
- ;* Application A issues an open request, whereupon AmigaDOS loads *
- ;* the code into memory and executes the LoadInitRoutine function *
- ;* within the device. This function is single-threaded by Exec who *
- ;* does a Forbid() before executing the device's LoadInitRoutine. *
- ;* This is because the device node is not yet on the system list of *
- ;* known devices and if a request from Application B came along, *
- ;* there would now be two copies of the device in memory and trying *
- ;* to initialize. *
- ;* *
- ;* This means that the LoadInitRoutine should -not- break the *
- ;* Forbid() by doing a Wait(), either directly or indirectly by *
- ;* calling AmigaDOS or other functions that could do a Wait(). This *
- ;* means no OpenLibrary(), OpenDevice() or file operations. *
- ;* *
- ;* At Device Open Time: *
- ;* *
- ;* When the DevOpen entry point of the device is called by Exec, *
- ;* either right after the code is loaded or on subsequent opens, the *
- ;* device node is on the system list of known devices. This means *
- ;* that there is no risk of Exec trying to load duplicate copies of *
- ;* the device. However, there is a risk of two tasks trying to *
- ;* perform the open setup within DevOpen in the device at the same *
- ;* time. Depending upon the nature of the open setup code in your *
- ;* device, this may be fine or dangerous. For this reason Exec *
- ;* single-threads device opens just as it does device initialization *
- ;* (as detailed above). If your code does not need this protection, *
- ;* it may break the Forbid() to perform some special setup you need. *
- ;* *
- ;* If by chance your device needs to break the Forbid() but still do *
- ;* its open setup in an exclusive fashion, there is a solution *
- ;* (proposed by Bill Hawes on BIX in Amiga.Sw/Exec). You define a *
- ;* signal semaphore in your device global data and obtain a lock at *
- ;* the start of your open setup. This allows other tasks to run and *
- ;* yet single-threads your open setup code. *
- ;* *
- ;* Also don't forget that if there is some operation that must be *
- ;* performed on the first open of a device only and that cannot be *
- ;* done at load initialization time, you can use the open count kept *
- ;* within the device node to detect the first open/last close. You *
- ;* should do this -after- locking your device semaphore to insure *
- ;* you remain the first opener/last closer during the operation. *
- ;* *
- ;*********************************************************************
- ;* The Ramifications of Being a Task Versus a Process *
- ;* *
- ;* An Exec-style device must never assume that its caller is a full *
- ;* process and not a task. Remember that tasks are scheduling *
- ;* entities and cannot perform any DOS operations such as file opens *
- ;* or open libraries or devices which may indirectly do a file open. *
- ;* When a device is invoked via BeginIO(), AbortIO() or *
- ;* CloseDevice(), the caller may quite likely be a task which means *
- ;* you are restricted to things a task can do. However, when the *
- ;* device is servicing an OpenDevice(), it obviously is running in a *
- ;* process or the DOS call by Exec to open the device file and load *
- ;* it would have failed. This means that during opens, you may *
- ;* perform DOS functions, although this assumption may yet be wrong. *
- ;* *
- ;* In addition, the unit task created by a device to handle I/O *
- ;* requests is typically a task. This device contains additional *
- ;* code to promote the unit task into a full process for maximum *
- ;* flexibility. This adds only a little code at open time and a *
- ;* little larger task control block. A process does -not- consume *
- ;* more CPU time during execution than a task. The Exec scheduler *
- ;* treats them equally. *
- ;* *
- ;*********************************************************************
-
-