7.2 Asynchronous Functions


Asynchronous functions are so named because their actual processing is performed by a different thread (leo manager) than that which called the function, and it is thus performed in asynchrony with the calling thread. To notify the calling function when processing is completed, a message queue called the post queue is usually specified. When a function is called, this post queue notifies the calling function of termination. Specific asynchronous functions are as follows.

The following syntax is generally used for asynchronous functions.

Calling asynchronous functions

#include <PR/leo.h>

s32 Leo******( LEOCmd *cmdBlock, ***, ...,OSMesgQueue *mq);

cmdBlock   pointer to the command block
mq   post queue

A value of 0 is returned if the leo manager is running and -1 is returned if it is not running. Consequently, checking the return value is usually not necessary.

cmdBlock allows a function to send commands to the leo manager. The members of this structure are assigned values by each function as appropriate. Thus, the programmer must simply create the variables and pass their addresses to the functions. For mq, a message queue can both be specified or not specified, and the operation of the function differs with each case.

Program with the message queue for mq specified

LEOCmd cmdBlock;

u32 error;

.....

Leo******(&cmdBlock, ***, ..., &diskQ);

osRecvMesg(&diskQ, (OSMesg *)&error, OS_MESG_BLOCK);

.....

In this case, the message is placed in the specified queue (diskQ in above example) if the function processing terminates. The content of the message is an error code. Before the function is called, the message queue must be initialized using the osCreateMesgQueue() function.

Program with the message queue for mq not specified

volatile LEOCmd cmdBlock;

u32 error;

.....

Leo******(&cmdBlock, ***, ..., (OSMesgQ *)NULL);

while(cmdBlock.header.status == LEO_STATUS_BUSY)

;

error = GET_ERROR(cmdBlock);

.....

This case is very inefficient because the thread that calls this function remains in the executable state until function processing ends, and threads with a lower priority sequence than this thread are not passed CPU execution rights. The error code in the command block must be accessed directly, but this can be done easily using GET_ERROR() macro provided for this purpose.

In general, please avoid procedures such as directly accessing members of cmdBlock. Cases in which it must be directly accessed are described in the sections concerned with those particular functions.

The following describes each function.


7.2.1 Forced Mode Changes

LeoSpdlMotor( )function

#include <PR/leo.h>

typedef u8 LEOSpdlMode;

s32 LeoSpdlMotor(LEOCmd *cmdBlock, LEOSpdlMode mode,

OSMesgQueue *mq);

mode LEO_MOTOR_ACTIVE   active mode
LEO_MOTOR_STANDBY   standby mode
LEO_MOTOR_SLEEP   sleep mode
LEO_MOTOR_BRAKE   sleep mode(sudden stop)

The 64DD state is changed to the specified state using mode.

64DD has the following 3 modes (states)

Active mode

An active state in which the motor is turning and reading and writing can quickly be performed.

Standby mode

The motor is turning but the head is retracted. If a read or write command is issued in this state, 64DD is changed to active mode before processing.

Sleep mode

The motor is halted and the head is retracted. If reading or writing is performed in this state, the motor is started and the head is positioned over the magnetic portion, requiring extra time.

When 64DD receives a read command, it automatically switches to active mode. When execution of the command is completed, it switches to standby mode and then sleep mode at fixed time intervals. Although these changes normally occur automatically, the LeoSpdlMotor() function allows the mode to be changed forcibly.

Calling LeoSpdlMotor() with LEO_MOTOR_ACTIVE substituted for mode puts 64DD in active mode. Calling this function with LEO_MOTOR_STANDBY substituted for mode puts 64DD in standby mode. (However if LeoSpdlMotor() is called with this argument while 64DD is in sleep mode, 64DD does not switch to standby mode but remains in sleep mode: 64DD does not switch directly from sleep mode to standby mode.) When LeoSpdlMotor() is called with LEO_MOTOR_SLEEP substituted for mode, 64DD waits until the disk stops before going into sleep mode. When LEO_MOTOR_BRAKE is specified for mode, 64DD goes into sleep mode following rapid halting of the disk. The differences between interrupting by specifying LEO_MOTOR_SLEEP or LEO_MOTOR_BRAKE in LeoSpdlMotor are as follows.

LEO_MOTOR_SLEEP

Halting of the disk takes a certain amount of time (average: 3 sec; maximum: 6 sec).

Because the disk stops spontaneously, almost no sound is produced when it stops.

LEO_MOTOR_BRAKE

The disk is halted rapidly (average: 1.5 sec; maximum: 3 sec.)

In almost all cases, a slight click occurs as a result of the disk's being halted.

For example, when a disk must be replaced during a game, it may be necessary to rapidly stop the rotating disk. LEO_MOTOR_BRAKE is effective in such cases.

In previous versions of the development drive used before 1997, LEO_MOTOR_BRAKE was not a valid specification; when it was specified, it had the same effect as specifying LEO_MOTOR_SLEEP. The new and previous versions of the drive can be identified by the value of the drive argument to the LeoInquiry function. This value is 0x14 with the new drive and 0x4 with the previous version of the drive.

For information on return values cmdBlock, mq, see the description in section 7.2Asynchronous Functions.

Note: Because the motor is a mechanical component, it has a notably shorter life than electrical components. The time required for reading and writing can be reduced by running the motor continously, but this shortens the life of the user's 64DD hardware. Therefore, continuously running the motor by calling LeoSpdlMotor() function numerous times when no data are being read should be prohibited. Whenever it is possible to anticipate a need for data slightly in advance (such as when moving a map, a player's character comes closer just before data are needed), please implement measures such as initiating a seek at that time (use the LeoSeek()function, section 7.2.3).


7.2.2 Reading and Writing

LeoReadWrite( ) Function

#include <PR/leo.h>

s32 LeoReadWrite( LEOCmd *cmdBlock, s32 direction,

u32 startLBA, void *vaddr, u32 nLBAs,

OSMesgQueue *mq);

direction OS_READ read
OS_WRITE write
startLBA read/write initiation LBA
vaddr RDRAM virtual address
nLBAs number of transfer blocks

Data are transferred between disk blocks, beginning from startLBA and extending nLBAs number of blocks, and RDRAM, starting from vaddr. The data are transferred in the read direction(from 64DD to RDRAM) if direction is OS_READ and in the write direction (from RDRAM to 64DD) if it is OS_WRITE.

For information on return values, cmdBlock, or mq, see the description in section 7.2, Asynchronous Functions.


7.2.3 Seek

LeoSeek( )function

#include<PR/leo.h>

s32 LeoSeek(LEOCmd *cmdBlock, u32 lba, OSMesgQueue *mq);

lba

Seeking moves the drive head to the desired block. The LeoSeek()function causes the head to seek the block specified by lba. When the 64DD is in sleep or standby mode before the command is issued, it automatically switches to active mode, and subsequent read or write commands are processed quickly. (However, if a short time is passed in active mode, the 64DD automatically returns to the standby and sleep modes.)

For information on return values, cmdBlock, or mq, see the description in section 7.2, Asynchronous Functions.

Note: Unlike electrical components, the motor has a limited life. Please give adequate consideration to the note in section 12.6.


7.2.4 Reading the Disk ID

LeoReadDiskID( )function

#include<PR/leo.h>

s32 LeoReadDiskID(LEOCmd *cmdBlock, LEODiskID *vaddr,

OSMesgQueue *mq);

vaddr RDRAMvirtual address

Reads the disk ID to the specified address vaddr.

For information on the format and usage of the ID, please see Chapter 6: Disk ID.

For information on return values, cmdBlock, or mq, see the description in section 7.2, Asynchronous Functions.


7.2.5 Reading and Setting the RTC

LeoReadRTC( ),LeoSetRTC( )functions

#include <PR/leo.h>

s32 LeoReadRTC(LEOCmd *cmdBlock, OSMesgQueue *mq);

s32 LeoSetRTC(LEOCmd *cmdBlock, LEODiskTime *RTCdata,

OSMesgQueue *mq);

RTCdata time setting

For information on return values, cmdBlock, or mq, see the description in section 7.2, Asynchronous Functions.

Details related to these RTC functions are discussed in Chapter 8: Reading and Setting RTC