Random Block File Manager

From NitrOS-9
Jump to: navigation, search

Random Block File Manager

The random block file manager (RBF manager) supports disk storage. It is a re-entrant subroutine package called by the I/O manager for I/O system calls to random-access devices. It maintains the logical and physical file structures.

During normal operation, the RBF manager requests allocation and deallocation of 256-byte data buffers. Usually, one buffer is required for each open file. When physical I/O functions are necessary, the RBF manager directly calls the subroutines in the associated device drivers. All data transfers are performed using 256-byte data blocks (pages).

The RBF manager does not deal directly with physical addresses such as tracks and cylinders. Instead, it passes to the device drivers address parameters, using a standard address called a logical sector number, or LSN. LSNs are integers from 0 to n-1, where n is the maximum number of sectors on the media. The driver translates the logical sector number to actual cylinder/track/sector values.

Because the RBF manager supports many devices that have different performance and storage capacities, it is highly parameter-driven. They physical parameters it uses are stored on the media itself.

On disk systems, the parameters are written on the first few sectors of Track 0. The device drivers also use the information, particularly the physical parameters stored on Sector 0. These parameters are written by the FORMAT program that initializes and tests the disk.

Logical and Physical Disk Organization

All disks used by NitrOS-9 store basic information, file structure, and storage allocation information on these first few sectors.

LSN 0 is the identification sector. LSN 1 is the disk allocation map sector. LSN 2 marks the beginning of the disk’s root directory. The following section tells more about LSN 0 and LSN 1.

Identification Sector (LSN 0)

LSN 0 contains a description of the physical and logical characteristics of the disk. These characteristics are set by the FORMAT command program when the disk is initialized.

The following table gives the NitrOS-9 mnemonic name, byte address, size, and description of each value stored in this LSN 0.

Name
Relative
Address
Size
(Bytes)
Use
DD.TOT
$00
3
Number of sectors on disk
DD.TKS
$03
1
Track size (in sectors)
DD.MAP
$04
2
Number of bytes in the allocation bit map
DD.BIT
$06
2
Number of sectors per cluster
DD.DIR
$08
3
Starting sector of the root directory
DD.OWN
$0B
2
Owner’s user number
DD.ATT
$0D
1
Disk attributes
DD.DSK
$0E
2
Disk identification (for internal use)
DD.FMT
$10
1
Disk format, density, number of sides
DD.SPT
$11
2
Number of sectors per track
DD.RES
$13
2
Reserved for future use
DD.BT
$15
3
Starting sector of the bootstrap file
DD.BSZ
$18
2
Size of the bootstrap file (in bytes)
DD.DAT
$1A
5
Time of creation (Y:M:D:H:M)
DD.NAM
$1F
32
Volume name in which the last character has the most significant bit set
DD.OPT
$3F
  Path descriptor options (detailed below)
PD.DTP
$3F
1
Device class (0=SCF, 1=RBF, 2=PIPE, 3=SBF)
PD.DRV
$40
1
Drive number (0..N)
PD.STP
$41
1
Step rate
PD.TYP
$42
1
Device type
PD.DNS
$43
1
Density capability
PD.CYL
$44
2
Number of cylinders (tracks)
PD.SID
$46
1
Number of sides (surfaces)
PD.VFY
$47
1
0 = Verify disk writes
PD.SCT
$48
2
Default number of sectors/track
PD.T0S
$4A
2
Default number of sectors/track (Track 0)
PD.ILV
$4C
1
Sector interleave factor
PD.SAS
$4D
1
Segment allocation size
PD.TFM
$4E
1
DMA Transfer Mode (Level 2 only)
PD.Exten
$4F
2
Sector/Track offsets (Level 2 only)
PD.SToff
$51
1
Path Extension for record (Level 2 only)
PD.ATT
$52
1
File attributes (D S PE PW PR E W R)
PD.FD
$53
3
File descriptor PSN (physical sector number)
PD.DFD
$56
3
Directory file descriptor PSN
PD.DCP
$59
4
File's directory entry pointer
PD.DVT
$5D
2
Address of device table entry
DD.RES1 (OS-9/68000)
$5F
1
 
DD.SYNC (OS-9/68000)
$60
4
 
DD.MAPLSN (OS-9/68000)
$64
4
 
DD.LSNSIZE (OS-9/68000)
$68
2
 
DD.VERSID (OS-9/68000)
$6A
2
 

Disk Allocation Map Sector (LSN 1)

LSN 1 contains the disk allocation map, which is created by FORMAT. This map shows which sectors are allocated to the files and which are free for future use.

Each bit in the allocation map represents a sector or cluster of sectors on the disk. If the bit is set, the sector is considered to be in use, defective, or non-existent. If the bit is cleared, the corresponding cluster is available. The allocation map usually starts at LSN 1. The number of sectors it requires varies according to how many bits are needed for the map. DD.MAP specifies the actual number of bytes used in the map.

Multiple sector allocation maps allow the number of sectors/cluster to be as small as possible for high volume media.

The FORMAT utility bases the size of the allocation map on the size and number of sectors per cluster.

The DD.MAP value in LSN 0 specifies the number of bytes (in LSN 1) that are used in the map.

Each bit in the disk allocation map corresponds to one sector cluster on the disk. The DD.BIT value in LSN 0 specifies the number of sectors per cluster. The number is an integral power of 2 (1, 2, 4, 8, 16, and so on).

If a cluster is available, the corresponding bit is cleared. If it is allocated, non-existent, or physically defective, the corresponding bit is set.

Root Directory

The file is the parent directory of all other files and directories on the disk. It is the directory accessed using the physical device name (such as /D1). Usually, it immediately follows the Allocation Map. The location of the root directory file descriptor is specified in DD.DIR. The root directory contains an entry for each file that resides in the directory, including other directories.

File Descriptor Sector

The first sector of every file is the file descriptor. It contains the logical and physical description of the file.

The following table describes the contents of the file descriptor.

Name Relative Address Size (Bytes) Use
FD.ATT $00 1 File attributes: D S PE PW PR E W R (see next chart)
FD.OWN $01 2 Owner’s user ID
FD.DAT $03 5 Date last modified (Y M D H M)
FD.LNK $08 1 Link count
FD.SIZ $09 4 File size (number of bytes)
FD.CREAT $0D 3 Date created (Y M D)
FD.SEG $10 240 Segment list (see next chart)

FD.ATT. The attribute byte contains the file permission bits. When set the bits indicate the following

Bit 7 Directory

Bit 6 Single user

Bit 5 Public execute

Bit 4 Public write

Bit 3 Public read

Bit 2 Execute

Bit 1 Write

Bit 0 Read

FD.SEG. The segment list consists of a maximum of 48 5-byte entries that have the size and address of each file block in logical order. Each entry has the block’s 3-byte LSN and 2-byte size (in sectors). The entry following the last segment is zero.

After creation, a file has no data segments allocated to it until the first write. (Write operations past the current end-of-file cause sectors to be added to the file. The first write is always past the end-of-file.)

If the file has no segments, it is given an initial segment. Usually, this segment has the number of sectors specified by the minimum allocation entry in the device descriptor. If, however, the number of sectors requested is more than the minimum, the initial segment has the requested number.

Later expansions of the file usually are also made in minimum allocation increments. Whenever possible, NitrOS-9 expands the last segment instead of adding a segment. When the file is closed, NitrOS-9 truncates unused sectors in the last segment.

NitrOS-9 tries to minimize the number of storage segments used in a file. In fact, many files have only one segment. In such cases, no extra read operations are needed to randomly access any byte in the file.

If a file is repeatedly closed, opened, and expanded, it can become fragmented so that it has many segments. You can avoid this fragmentation by writing a byte at the highest address you want to be used on a file. Do this before writing any other data.

Directory

Disk directories are files that have the D attribute set. A directory contains an integral number of entries, each of which can hold the name and LSN of a file or another directory.

Each directory entry contains 29 bytes for the filename followed by three bytes for the LSN of the file’s descriptor sector. The filename is left-justified in the field with the most significant bit of the last character set. Unused entries have a zero byte in the first filename character position.

Every disk has a master directory called the root directory. The DD.DIR value in LSN 0 (identification sector) specifies the starting sector of the root directory.

The RBF Manager Definitions of the Path Descriptor

As stated earlier in this chapter, the PD.FST section of the path descriptor is reserved for and defined by the file manager. The following table describes the use of this section by the RBF manager. For your convenience, it also includes the other sections of the PD.

Name Relative Address Size (Bytes) Use
Universal Section (Same for all file managers and device drivers)
PD.PD $00 1 Path number
PD.MOD $01 1 Access mode
1 = read
2 = write
3 = update
PD.CNT $02 1 Number of open images (paths using this PD)
PD.DEV $03 2 Address of the associated device table entry
PD.CPR $05 1 Current process ID
PD.RGS $06 2 Address of the caller’s 6809 register stack
PD.BUF $08 2 Address of the 256-byte data buffer (if used)
The RBF manager Path Descriptor Definitions (PD.FST Section)
PD.SMF $0A 1 State flag:
Bit 0 = current buffer is altered
Bit 1 = current sector is in the buffer
Bit 2 = descriptor sector is in the buffer
PD.CP $0B 4 Current logical file position (byte address)
PD.SIZ $0F 4 File size
PD.SBL $13 3 Segment beginning logical sector number (LSN)
PD.SBP $16 3 Segment beginning physical sector number (PSN)
PD.SSZ $19 3 Segment size
PD.DSK $1C 2 Disk ID (for internal use only)
PD.DTB $1E 2 Address of drive table
The RBF manager Option Section Definitions (PD.OPT Section)(Copied from the device descriptor)
PD.DTP $20 1 Device class
0 = SCF
1 = RBF
2 = PIPE
3 = SBF
PD.DRV $21 1 Drive number (0..n)
PD.STP $22 1 Step rate
PD.TYP $23 1 Device type
PD.DNS $24 1 Density capability
PD.CYL $25 2 Number of cylinders (tracks)
PD.SID $27 1 Number of sides (surfaces)
PD.VFY $28 1 0 = verify disk writes
PD.SCT $29 2 Default number of sectors per track
PD.T0S $2B 2 Default number of sectors per track (Track 0)
PD.ILV $2D 1 Sector interleave factor
PD.SAS $2E 1 Segment allocation size
PD.TFM $2F 1 DMA transfer mode
PD.EXTEN $30 2 Path extension for record locking
PD.STOFF $32 1 Sector/track offsets
(Not copied from the device descriptor)
PD.ATT $33 1 File attributes (D S PE PW PR E W R)
PD.FD $34 3 File descriptor PSN
PD.DFD $37 3 Directory file descriptor PSN
PD.DCP $3A 4 File’s directory entry pointer
PD.DVT $3E 2 Address of the device table entry

Any values not determined by this table default to zero.

RBF-Type Device Descriptor Modules

This section describes the use of the initialization table contained in the device descriptor modules for RBF-type devices. The following values are those the I/O manager copies from the device descriptor to the path descriptor.

Name Relative Address Size (Bytes) Use
  $00-$11   Standard device descriptor module header
IT.DTP $12 1 Device type:
0 = SCF
1 = RBF
2 = PIPE
3 = SBF
IT.DRV $13 1 Drive number
IT.STP $14 1 Step rate
IT.TYP $15 1 Device type (see RBF path descriptor)
IT.DNS $16 1 Media density: Always 1 (double)(see following information)
IT.CYL $17 2 Number of cylinders (tracks)
IT.SID $19 1 Number of sides
IT.VFY $1A 1 0 = Verify disk writes
1 = no verify
IT.SCT $1B 2 Default number of sectors per track
IT.T0S $1D 2 Default number of sectors per track (Track 0)
IT.ILV $1F 1 Sector interleave factor
IT.SAS $20 1 Minimum size of segment allocation (number of sectors to be allocated at one time)

IT.DRV is used to associate a 1-byte integer with each drive that a controller handles. Number the drives for each controller as 0 to n-1, where n is the maximum number of drives the controller can handle.

IT.TYP specifies the device type (all types):

Bit 0 0 = 5¼-inch floppy diskette
1 = 3½-inch floppy diskette
Bit 5 0 = Non-Color Computer format
1 = Color Computer format
Bit 6 0 = Standard NitrOS-9 format
1 = Non-standard format
Bit 7 0 = Floppy diskette
1 = Hard disk

IT.DNS specifies the density capabilities (floppy diskette only):

Bit 0 0 = Single-bit density (FM)
1 = Double-bit density (MFM)
Bit 1 0 = Single-track density (5¼-inch, 48 tracks per inch or 3½-inch)
1 = Double-track density (5¼-inch, 96 tracks per inch)

IT.SAS specifies the minimum number of sectors allowed at one time.

SuperDesc - Super Driver Device Descriptor

IT.STP (offset $14):

Bit Meaning
7-0 HDB-DOS Drive Number (useful only if HDB-DOS bit set it IT.DNS)

IT.TYP (offset $15):

Bit Meaning
7 Hard Disk: 1 = hard disk
6 Fudge LSN0: 0 = OS-9 disk, 1 = non-OS-9 disk
5 Undefined
4 Drive Size Query (1 = yes, 0 = no)
2-3 Undefined
0-1 Sector Size (0 = 256, 1 = 512, 2 = 1024, 3 = 2048)

IT.DNS (offset $16) for SCSI Low Level Driver:

Bit Meaning
5-7 SCSI Logical Unit Number of drive (0-7) (ignored if bit 3 is 1)
4 Turbo Mode: 1 = use accelerated handshaking, 0 = standard
3 HDB-DOS Partition Flag
0-2 SCSI ID of the drive or controller (0-7)

IT.DNS (offset $16) for IDE Low Level Driver:

Bit Meaning
4-7 Undefined
3 HDB-DOS Partition Flag
1-2 Undefined
0 IDE ID (0 = master, 1 = slave)

RBF Record Locking

Record locking is a general term that refers to methods designed to preserve the integrity of files that can be accessed by more than one user or process. The NitrOS-9 implementation of record locking is designed to be as invisible as possible. This means that existing programs do not have to be rewritten to take advantage of record locking facilities. You can usually write new programs without special concern for multi-user activity.

Record locking involves detecting and preventing conflicts during record access. Whenever a process modifies a record, the system locks out other procedures from accessing the file. It defers access to other procedures until it is safe for them to write to the record. The system does not lock records during reads; so, multiple processes can read the records at the same time.

Record Locking and Unlocking

To detect conflicts, NitrOS-9 must recognize when a record is being updated. The RBF manager provides true record locking on a byte basis. A typical record update sequence is:

  • OS9 I$Read program reads record
  • Record is locked
  • ...
  • program updates record
  • ...
  • OS9 I$Seek reposition to record
  • OS9 I$Write record is rewritten
  • Record is released

When a file is opened in update mode, any read causes locking of the record being accessed. This happens because the RBF manager cannot determine in advance if the record is to be updated. The record stays locked until the next read, write, or close.

However, when a file is opened in the read or execute modes, the system does not lock accessed records because the records cannot be updated in these two modes.

A subtle but important problem exists for programs that interrogate a data base and occasionally update its data. If you neglect to release a record after accessing it, the record might be locked indefinitely. This problem is characteristic of record locking systems and you can avoid it with careful programming.

Only one potion of a file can be locked at a time. If an application requires more than one record to be locked, open multiple paths to the same file and lock the record accessed by each path. RBF notices that the same process owns both paths and keeps them from locking each other.

Non-Shareable Files

Sometimes (although rarely), you must create a file that can never be accessed by more than one user at a time. To lock the file, you set the single-user bit in the file’s attribute byte. You can do this by using the proper option when the file is created, or later using the NitrOS-9 ATTR command. Once the single-user bit is set, only one use can open the file at a time. If other users attempt to open the file, Error 253 is returned. Note, however, that non-shareable means only one path can be opened to a file at one time. Do not allow two processes to concurrently access a non-shareable file through the same path.

More commonly, you need to declare a file as single-user only during the execution of a specific program. You can do this by opening the file with the single-user bit set. For example, suppose a process is sorting a file. With the file’s single-user bit set, NitrOS-9 treats the file exactly as though it had a single-user attribute. If another process attempts to open the file, NitrOS-9 returns Error 253.

You can duplicate non-shareable files by using the I$Dup system call. This means that it can be inherited and therefore accessible to more than one process at a time. Single-user means only that the file can be opened only once.

End-of-File Lock

A special case of record locking occurs when a user reads or writes data at the end of a file, creating an EOF Lock. An EOF Lock keeps the end of the file locked until a process performs a read or write that it is not at the end of the file. It prevents problems that might otherwise occur when two users want to simultaneously extend a file. The EOF Lock is the only case in which a write call automatically causes portions of a file to be locked. An interesting and useful side effect of the EOF Lock function occurs if a program creates a file for sequential output. As soon as the program creates the file, EOF Lock is set and no other process can pass the writer in processing the file. For example, if an assembler redirects a listing to a disk file, and a spooler utility tries to print a line from the file it is written, record locking makes the spooler wait and stay at least one step behind the assembler.

Deadlock Detection

A deadly embrace, or deadlock, typically occurs when two processes attempt to gain control of two or more disk areas at the same time. If each process gets one area (locking the other process), both processes become permanently stuck. Each waits for a segment that can never become free. This situation is not restricted to any particular record locking scheme or operating system.

When a deadly embrace occurs, RBF returns a deadlock error (Error 254) to the process that caused NitrOS-9 to detect the deadlock. To avoid deadlocks, make sure that processes always access records of shared files in the same sequence.

When a deadlock error occurs, it is not sufficient for a program to retry the operation that caused the error. If all processes use this strategy, none can ever succeed. For any process to proceed, at least one must cancel operation to release control over a requesting segment.

RBF-Type Device Driver Modules

An RBF-type device driver module contains a package of subroutines that perform sector-oriented I/O to or from a specific hardware controller. Such a module is usually re-entrant. Because of this, one copy of one device driver module can simultaneously run several devices that use identical I/O controllers.

The I/O manager allocates a permanent memory area for each device driver. The size of the memory area is given in the device driver module header. The I/O manager and the RBF manager use some of this area. The device driver can use the rest in any manner. This area is used as follows:

The RBF Device Memory Area Definitions

Name Relative Address Size (Bytes) Use
V.PAGE $00 1 Port extended address bits A20-A16
V.PORT $01 2 Device base address (defined by the I/O manager)
V.LPRC $03 1 ID of the last active process (not used by RBF device drivers)
V.BUSY $04 1 ID of the current process using driver (defined by RBF)0 = no current process
V.WAKE $05 1 ID of the process waiting for I/O completion (defined by the device driver)
V.USER $06 0 Beginning of file manager specific storage
V.NDRV $06 1 Maximum number of drives the controller can use (defined by the device driver)
  $07 8 Reserved
DRVBEG $0F 0 Beginning of the drive tables
TABLES $0F DRVMEM*N Space for number of tables reserved (n)
FREE   0 Beginning of space available for driver

These values are defined in files in the DEFS directory on the Development Package disk.

TABLES. This area contains one table for each drive that the controller handles. (The RBF manager assumes that there are as many tables as indicated by V.NDRV.) Some time after the driver Init routine is called, the RBF manager issues a request for the driver to read LSN 0 from a drive table by copying the first part of LSN 0 (up to DD.SIZ) into the table. Following is the format of each drive table:

Name Relative Address Size (Bytes) Use
DD.TOT $00 3 Number of sectors
DD.TKS $03 1 Track size (in sectors)
DD.MAP $04 2 Number of bytes in the allocation bit map
DD.BIT $06 2 Number of sectors per bit (cluster size)
DD.DIR $08 3 Address (LSN) of the root directory
DD.OWN $0B 2 Owner’s user number
DD.ATT $0D 1 Disk access attributes (D S PE PW PR E W R)
DD.DSK $0F 2 Disk ID (a pseudo-random number used to detect diskette swaps)
DD.FMT $10 1 Media format
DD.SPT $11 2 Number of sectors per track. (Track 0 can use a different value specified by IT.T0S in the device descriptor.)
DD.RES $13 2 Reserved for future use
DD.SIZ $15 0 Minimum size of device descriptor
V.TRAK $15 2 Number of the current track (the track that the head is on, and the track updated by the driver)
V.BMB $17 1 Bit-map use flag:0 = Bit map is not in use (Disk driver routines must not alter V.BMB)
V.FILEHD $18 2 Open file list for this drive
V.DISKID $1A 2 Disk ID
V.BMAPSZ $1C 1 Size of bitmap
V.MAPSCT $1D 1 Lowest reasonable bitmap sector
V.RESBIT $1E 1 Reserved bitmap sector
V.SCTKOF $1F 1 Sector/track byte
V.SCOFST $20 1 Sector offset split from byte above
V.TKOFST $22 4 Reserved for future use
DRVMEM $26 . Size of each drive table

The format attributes (DD.FMT) are these:

Bit 0 Number of sides
0 Single-sided
1 Double-sided
Bit 1 Density
0 Single-density
1 Double-density
Bit 2 Track density
0 Single (5¼-inch, 48 tracks per inch or 3½-inch)
1 Double (5¼-inch, 96 tracks per inch)

RBF Device Driver Subroutines

Like all device driver modules, RBF device drivers use a standard executable memory module format.

The execution offset address in the module header points to a branch table that has six 3-byte entries. Each entry is typically a long branch (LBRA) to the corresponding subroutine. The branch table is defined as follows:

ENTRY LBRA  INIT    Initialize drive
      LBRA  READ    Read sector
      LBRA  WRITE   Write sector
      LBRA  GETSTA  Get status
      LBRA  SETSTA  Set status
      LBRA  TERM    Terminate device

Ensure that each subroutine exits with the C bit of the condition code register cleared if no error occurred. If an error occurs, set the C bit and return an appropriate error code in Register B.

The rest of this chapter describes the RBF device driver subroutines and their entry and exit conditions.

Init Initializes a device and the device’s memory area.

Entry Conditions

Y address of the device descriptor
U address of the device memory area

Exit Conditions

CC carry set on error
B error code (if any)

Additional Information

  • If you want NitrOS-9 to verify disk writes, use the Request Memory system call (F$SRqMem) to allocate a 256-byte buffer area in which a sector can be read back and verified after a write.
  • You must initialize the device memory area. For floppy diskette controllers, initialization typically consists of:
  1. Initializing V.NDRV to the number of drives with which the controller works
  2. Initializing DD.TOT (in the drive table) to a non-zero value so that Sector 0 can be read or written
  3. Initializing V.TRAK to $FF so that the first seek finds Track 0
  4. Placing the IRQ service routing on the IRQ polling list, using the Set IRQ system call (F$IRQ)
  5. Initializing the device control registers (enabling interrupts if necessary)
  • Prior to being called, the device memory area is cleared (set to zero), except for V.PAGE and V.PORT. (These areas contain the 24-bit device address.) Ensure the driver initializes each drive table appropriately for the type of diskette that the driver expects to be used on the corresponding drive.

Read Reads a 256-byte sector from a disk and places it in a 256-byte sector buffer.

Entry Conditions

B MSB of the disk’s LSN
X LSB of the disk’s LSN
Y address of the path descriptor
U address of the device memory area

Exit Conditions

CC carry set on error
B error code (if any)

Additional Information

The following is a typical routine for using Read:

  1. Get the sector buffer address from PD.BUF in the path descriptor.
  2. Get the drive number from PD.DRV in the path descriptor.
  3. Compute the physical disk address from the logical sector number.
  4. Initiate the Read operation
  5. Copy V.BUSY to V.WAKE. The driver goes to sleep and waits for the I/O to complete. (The IRQ service routine is responsible for sending a wakeup signal.) After awakening, the driver tests V.WAKE to see if it is clear. If it is not clear, the driver goes back to sleep.
  • Whenever you read LSN 0, you must copy the first part of this sector into the proper drive table. (Get the drive number from PD.DRV in the path descriptor.) The number of bytes to copy is in DD.SIZ. Use the drive number (PD.DRV) to compute the offset for the corresponding drive table as follows:
          LDA   PD.DRV,Y  Get the drive number
          LDB   #DRVMEM   Get the size of a drive table
          MUL
          LEAX  DRVBEG,U  Get the address of the first table
          LEAX  D,X       Compute the address of the table

Write Writes a 256-byte sector buffer to a disk.

Entry Conditions

B MSB of the disk LSN
X LSB of the disk LSN
Y address of the path descriptor
U address of the device memory area

Exit Conditions

CC carry set on error
B error code (if any)

Additional Information

Following is a typical routine for using Write:

  1. Get the sector buffer address from PD.BUF in the path descriptor.
  2. Get the drive number from PD.DRV in the path descriptor.
  3. Compute the physical disk address from the logical sector number.
  4. Initiate the Write operation.
  5. Copy V.BUSY to V.WAKE. The driver then goes to sleep and waits for the I/O to complete. (The IRQ service routine sends the wakeup signal.) After awakening, the driver tests V.WAKE to see if it is clear. If it is not, the driver goes back to sleep. If the disk controller cannot be interrupt-driven, it is necessary to perform a programmed I/O transfer.
  6. If PF.VFY in the path descriptor is equal to zero, read the sector back in and verify that it is written correctly. Verification usually does not involve a comparison of all of the data bytes.
  • If disk writes are to be verified, the Init routine must request the buffer in which to place the sector when it is read back. Do not copy LSN 0 into the drive table when reading it back for verification.
  • Use the drive number (PD.DRV) to compute the offset to the corresponding drive table as shown for the Read routine.

GetStats and SetStats

Reads or changes device’s operating parameters.

Entry Conditions

U address of the device memory area
Y address of the path descriptor>
A status code

Exit Conditions

CC carry set on error
B error code (if any)

Additional Information

  • Get/set the device’s operating parameters (status) as specified for the Get Status and Set Status system calls. GetStat and SetStat are wild card calls.
  • It might be necessary to examine or change the register stack that contains the values of the 6809 registers at the time of the call. The address of the register stack is in PD.RGS, which is located in the path descriptor. You can use the following offsets to access any value in the register stack:
Reg. Relative Address Size 6809 Register
R$CC $00 1 Condition code register
R$D $01 2 Register D
R$A $01 1 Register A
R$B $02 1 Register B
R$DP $03 1 Register DP
R$X $04 2 Register X
R$Y $06 2 Register Y
R$U $08 2 Register U
R$PC $0A 2 Program counter

Register D overlays Registers A and B.

Term Terminate a device.

Entry Conditions

U address of the device memory area

Exit Conditions

CC carry set on error
B error code (if any)

Additional Information

  • This routine is called when a device is no longer in use in the system (when the link count of its device descriptor module becomes zero).
  • Following is a typical routine for using Term:
  1. Wait until any pending I/O is completed.
  2. Disable the device interrupts.
  3. Remove the device from the IRQ polling list.
  4. If the Init routine reserved a 256-byte buffer for verifying disk writes, return the memory with the Return System Memory system call (F$SRtMem).

IRQ Service Routine

Services device interrupts

Additional Information

  • The IRQ Service routine sends a wakeup signal to the process indicated by the process ID in V.WAKE when the I/O is complete. It then clears V.WAKE as a flag to indicate to the main program that the IRQ has indeed occurred.
  • When the IRQ Service routine finishes servicing an interrupt, it must clear the carry and exit with an RTS instruction.
  • Although this routine is not included in the device driver module branch table and is not called directly by the RBF manager, it is a key routine in interrupt-driven drivers. Its function is to:
    1. Service the device interrupts (receive data from device or send data to it). The IRQ Service routine puts its data into and gets its data from buffers that are defined in the device memory area.
    2. Wake up a process that is waiting for I/O to be completed. To do this, the routine checks to see if there is a process ID in V.WAKE (if the bit is non-zero); if so, it sends a wakeup signal to that process.
    3. If the device is ready to send more data, and the out buffer is empty, disable the device’s ready to transmit interrupts.

Boot (Bootstrap Module)

Loads the boot file into RAM.

Entry Conditions

None

Exit Conditions

D size of the boot file (in bytes)
X address at which the boot file was loaded into memory
CC carry set on error
B error code (if any)

Additional Information

  • The Boot module is not part of the disk driver. It is a separate module that is stored on the boot track of the system disk with OS9P1 and REL.
  • The bootstrap module contains one subroutine that loads the bootstrap file and related information into memory. It uses the standard executable module format with a module type of $C. The execution offset in the module header contains the offset to the entry point of this subroutine.
  • The module gets the starting sector number and size of the OS9Boot file from LSN 0. NitrOS-9 allocates a memory area large enough for the Boot file. Then, it loads the Boot file into this memory area.
  • Following is a typical routine for using Boot:
    1. Read LSN 0 from the disk into a buffer area. The Boot module must pick its own buffer area. LSN 0 contains the values for DD.BT (the 24-bit LSN of the bootstrap file), and DD.BSZ (the size of the bootstrap file in bytes).
    2. Get the 24-bit LSN of the bootstrap file from DD.BT.
    3. Get the size of the bootstrap file from DD.BSZ. The Boot module is contained in one logically contiguous block beginning at the logical sector specified in DD.BT and extending for DD.BSZ/256+1 sectors.
    4. Use the NitrOS-9 Request System Memory system call (F$SRqMem) to request the memory area in which the Boot file is loaded.
    5. Read the Boot file into this memory area.
    6. Return the size of the Boot file and its location. Boot file is loaded.