ProDOS 8 #21: Identifying ProDOS Devices

Apple II Technical Notes Developer Technical Support

Revised by: Dave Lyons & Matt Deatherage March 1990
Written by: Matt Deatherage & Dan Strnad November 1988

This Technical Note describes how to identify ProDOS devices and their characteristics given the ProDOS unit number. This scheme should only be used under ProDOS 8. Changes since January 1990: Modified AppleTalk call code for compatibility with ProDOS 8 versions earlier than 1.5 and network-booted version 1.4.


There are various reasons why an application would want to identify ProDOS devices. Although ProDOS itself takes great pains to treat all devices equally, it has internal drivers for two types of devices: Disk II drives and the /RAM drive provided on 128K or greater machines. Because all devices really are not equal (i.e., some cannot format while others are read-only, etc.), a developer may need to know how to identify a ProDOS device.

Although the question of how much identification is subjective for each developer, ProDOS 8 offers a fair level of identification; the only devices which cannot be conclusively identified are those devices with RAM-based drivers, and they could be anything. The vast majority of ProDOS devices can be identified, however, so you could prompt the user to insert a disk in UniDisk 3.5 #2, instead of Slot 2, Drive 2, which could be confusing if the user has a IIc or IIGS.

Note that for the majority of applications, this level of identification is unnecessary. Most applications simply prompt the user to insert a disk by its name, and the user can place it in any drive which is capable of working with the media of the disk. You should avoid requiring a certain disk to be in a specific drive since doing so defeats much of the device-independence which gives ProDOS 8 its strength.

When you do need to identify a device (i.e., if you need to format media in a Disk II or /RAM device), however, the process is fairly straightforward. This process consists of a series of tests, any one of which could end with a conclusive device identification. It is not possible to look at a single ID byte to determine a particular device type. You may determine rather quickly that a device is a SmartPort device, or you may go all the way through the procedure to identify a third-party network device. For those developers who absolutely must identify devices, DTS presents the following discussion.

Isn't There Some Kind of "ID Nibble?"

ProDOS 8 does not support an "ID nibble." Section 5.2.4 of the ProDOS 8 Technical Reference Manual states that the low nibble of each unit number in the device list "is a device identification: 0Ê= Disk II, 4 = Profile, $F = /RAM."

When ProDOS 8 finds a "smart" ProDOS block device while doing its search of the slots and ports, it copies the high nibble of $CnFE (where n is the slot number) into the low nibble of the unit number in the global page. The low nibble then has the following definition:

    Bit 3:    Medium is removable
    Bit 2:    Device is interruptible
    Bit 1-0:  Number of volumes on the device (minus one)

As you can see, it is quite easy for the second definition to produce one of the original values (e.g., 0, 4, or $F) in the same nibble for completely different reasons. You should ignore the low nibble in the unit number in the global page when identifying devices since the first definition is insufficient to uniquely identify devices and the second definition contains no information to specifically identify devices. Once you do identify a ProDOS block device, however, you may look at $CnFE to obtain the information in the second definition above, as well as information on reading, writing, formatting, and status availability.

When identifying ProDOS devices, start with a list of unit numbers for all currently installed disk devices. As you progress through the identification process, you identify some devices immediately, while others must wait until the end of the process for identification.

Starting with the Unit Number

ProDOS unit numbers (unit_number) are bytes where the bits are arranged in the pattern DSSS0000, where D = 0 for drive one and D = 1 for drive two, SSS is a three-bit integer with values from one through seven indicating the device slot number (zero is not a valid slot number), and the low nibble is ignored.

To obtain a list of the unit numbers for all currently installed ProDOS disk devices, you can perform a ProDOS MLI ON_LINE call with a unit number of $00. This call returns a unit number and a volume name for every device in the device list. ProDOS stores the length of the volume name in the low nibble of the unit number which ON_LINE returns; if an error occurs, the low nibble contains $0 and the byte immediately following the unit number contains an error code. For more information on the ON_LINE call, see section 4.4.6 of the ProDOS 8 Technical Reference Manual. A more detailed discussion of the error codes follows later in this Note.

To identify the devices in the device list, you need to know in which physical slot the hardware resides, so you can look at the slot I/O ROM space and check the device's identification bytes. Note that the slot-number portion of the unit number does not always represent the physical slot of the device, rather, it sometimes represents the logical slot where you can find the address of the device's driver entry point in the ProDOS global page. For example, if a SmartPort device interface in slot 5 has more than two connected devices, the third and fourth devices are mapped to slot 2; this mapping gives these two devices unit numbers of $20 and $A0 respectively, but the device's driver entry point is still in the $C5xx address space.

ProDOS 8 Technical Note #20, Mirrored Devices and SmartPort, discusses this kind of mapping in detail. It also presents a code example which gives you the correct device-driver entry point (from the global page) given the unit number as input. Here is the code example from that Note for your benefit. It assumes the unit_number is in the accumulator.

devcnt equ $BF31 devlst equ $BF32 devadr equ $BF10

devget      sta    unitno      ; store for later compare instruction
            ldx    devcnt      ; get count-1 from $BF31
devloop     lda    devlst,x    ; get entry in list
            and    #$F0        ; mask off low nibble
devcomp     cmp    unitno      ; compare to the unit_number we filled in
            beq    goodnum     ;
            dex
            bpl    devloop     ; loop again if still less than $80
            bmi    badunitno   ; error: bad unit number
goodnum     lda    unitno      ; get good copy of unit_number
            lsr    a           ; divide it by 8
            lsr    a           ; (not sixteen because devadr entries are
            lsr    a           ; two bytes wide)
            tax
            lda    devadr,x    ; low byte of device driver address
            sta    addr
            lda    devadr+1,x  ; high byte of device driver address
            sta    addr+1
            rts
addr        dw     0           ; address will be filled in here by goodnum
unitno      dfb    0           ; unit number storage

Warning: Attempting to construct the device-driver entry point from the unit number is very dangerous. Always use the technique presented above.

Network Volumes

AppleTalk volumes present a special problem to some developers since they appear as "phantom devices," or devices which do not always have a device driver installed in the ProDOS global page. Fortunately, the ProDOS Filing Interface (PFI) to AppleTalk provides a way to identify network volumes through an MLI call. The ProDOS Filing Interface call FIListSessions is used to retrieve a list of the current sessions being maintained through PFI and any volumes mounted for those sessions.

In the following example, note the check for ProDOS 8 version 1.5 or higher, and the simulation of a bad command error under older versions (the $42 call under ProDOS 8 version 1.4 always crashes if ProDOS was launched from a local disk):

Network     LDA    #$04        ;require at least ProDOS 8 1.4
            CMP    $BFFF       ;KVERSION (ProDOS 8 version)
            BEQ    MoreNetwork ;have to check further
            LDA    #$01        ;simulate bad command error
            BCS    ERROR       ;if 3 or less, no possibility of network
            BCC    NetCall     ;otherwise, try the network call
MoreNetwork LDA    $BF02       ;high byte of the MLI entry point
            AND    #$F0        ;strip off the low nibble
            CMP    #$C0        ;is the entry into the $Cn00 space?
            BEQ    NetCall     ;yes, so try AppleTalk
            LDA    #$01
            SEC
            BCS    ERROR       ;simulate bad command error
NetCall     JSR    $BF00        ;ProDOS MLI
            DFB    $42          ;AppleTalk command number
            DW     ParamAddr    ;Address of Parameter Table
            BCS    ERROR        ;error occurred
ParamAddr   DFB    $00          ;Async Flag (0 means synchronous only)
                                ;note there is no parameter count
            DFB    $2F          ;command for FIListSessions
            DW     $0000        ;AppleTalk Result Code returned here
            DW     BufLength    ;length of the buffer supplied
            DW     BufPointer   ;low word of pointer to buffer
            DW     $0000        ;high word of pointer to buffer
                                ;(THIS WILL NOT BE ZERO IF THE BUFFER IS
                                ;NOT IN BANK ZERO!)
            DFB    $00          ;Number of entries returned here

If the FIListSessions call fails with a bad command error ($01), then AppleShare is not installed; therefore, there are no networks volumes mounted. If there is a network error, the accumulator contains $88 (Network Error), and the result code in the parameter block contains the specific error code. The list of current sessions is placed into the buffer (at the address BufPointer in the example above), but if the buffer is not large enough to hold the list, it retains the maximum number of current sessions possible and returns an error with a result code of $0A0B (Buffer Too Small). The buffer format is as follows:

SesnRef DFB $00 ;Sessions Reference number (result) UnitNum DFB $00 ;Unit Number (result)

VolName     DS     28           ;28 byte space for Volume Name
                                ;(starts with a length byte)
VolumeID    DW    $0000         ;Volume ID (result)

This list is repeated for every volume mounted for each session (the number is placed into the last byte of the parameter list you passed to the ProDOS MLI). For example, if there are two volumes mounted for session one, then session one is listed two times. The UnitNum field contains the slot and drive number in unit-number format, and note that bit zero of this byte is set if the volume is a user volume (i.e., it contains a special "users" folder). This distinction is unimportant for identifying a ProDOS device as a network pseudo-device, but it is necessary for applications which need to know the location of the user volume. Note that if you mount two servers or more with each having its own user volume, the user volume found first in the list (scanned top to bottom) returned by FIListSessions specifies the user volume that an application should use. See the AppleShare Programmer's Guide for the Apple IIGS for more information on programming for network volumes.

If you keep a list of all unit numbers returned by the ON_LINE call and mark each one "identified" as you identify it, keep in mind that the unit numbers returned by FIListSessions and ON_LINE have different low nibbles which should be masked off before you make any comparisons.

Note: You should mark the network volumes as identified and not try to identify them further with the following methods.

What Slot is it Really In?

Once you have the address of the device driver's entry point and know that the device is not a network pseudo-device, you can determine in what physical slot the device resides. If the high byte of the device driver's entry point is of the form $Cn, then n is the physical slot number of the device. A SmartPort device mirrored to slot 2 has a device driver address of $C5xx, giving 5 as the physical slot number.

If the high byte of the device driver entry point is not of the form $Cn, then there are three other possibilities: