psx.wiki
Log in
Main page
Hardware
Hardware tests
System software
SDKs
File formats
Games
Tools
History
All pages
page
view source
history
View source for BIOS Events
← BIOS Events
You do not have permission to edit this page.
Log in
to edit.
--- title: BIOS Events type: component summary: Event management service that reports interrupts, exceptions and device completion. category: System software info: Control block = EvCB, 0x1C bytes info: Default count = 16 (EVENT = 10) --- ## Overview An event is either a CPU exception or an interrupt from an external device. Because events occur asynchronously with the main program, there are two ways of dealing with them: polling to see whether an event has occurred, or installing an event handler that the kernel executes automatically when the event occurs.[^lo209] The event management service of the [PS-X OS](/system/ps-x-os/) controls program execution triggered by these events.[^os33] The kernel and the libraries also deliver events of their own for file I/O and device completion.[^lo210][^spxsum] An event is specified by two 32-bit integers called the cause descriptor and the event type. OpenEvent() takes the cause descriptor, the event type, the event mode and the address of the handler function, and returns a 32-bit event descriptor that identifies the event to the other functions.[^lo210] psx-spx calls the cause descriptor the class and the event type the spec.[^spxev] The event is triggered only when both values match.[^spxev] Event handlers execute in interrupt context on a 4K interrupt stack in the kernel's reserved memory. When a handler completes its processing it calls ReturnFromException(), which restores the registers and returns to the previous context.[^lo209][^lo210] A handler may instead enable interrupts with ExitCriticalSection() and continue as the main flow. In this case the user must provide a stack allocated before the interrupt, and the stack is changed with SetSp().[^lo210] ## Event Status An event has one of four statuses.[^lo211] Before it is opened its status is EvStUNUSED. OpenEvent() makes it EvStWAIT, and EnableEvent() makes it EvStACTIVE, in which the event may occur. DisableEvent() returns an EvStACTIVE or EvStALREADY event to EvStWAIT, and the previous state is not saved.[^lo211] Table: Event conditions | Macro | Contents | Generation | EvCB status value | | --- | --- | --- | --- | | EvStUNUSED | Not opened | Prohibited | 0x0000 | | EvStWAIT | Event generation prohibited | Prohibited | 0x1000 | | EvStACTIVE | Event not yet generated | Possible | 0x2000 | | EvStALREADY | Event already generated | Prohibited | 0x4000 | The macros and their meanings are from the Run-Time Library Overview.[^lo211] psx-spx gives the EvCB status values as 0x0000 free, 0x1000 disabled, 0x2000 enabled and busy, and 0x4000 enabled and ready, which correspond in meaning to the four Sony statuses.[^spxcb] ## Event Modes An event has one of two modes, chosen when it is opened.[^lo211] With EvMdINTR the handler function is called when the event occurs and the event stays EvStACTIVE. With EvMdNOINTR no handler is called, the event becomes EvStALREADY, and the program must test for it.[^lo211] Table: Event modes | Macro | Value | Status after generation | Handler function | | --- | --- | --- | --- | | EvMdINTR | 0x1000 | EvStACTIVE | Active | | EvMdNOINTR | 0x2000 | EvStALREADY | Not active | psx-spx gives mode 0x1000 as "execute function and stay busy" and mode 0x2000 as "no function and mark ready", which correspond to EvMdINTR and EvMdNOINTR.[^spxmode] Because an EvMdINTR event never becomes EvStALREADY, WaitEvent() on such an event never returns.[^spxev] ## Generating and Clearing Events DeliverEvent() switches every enabled event with the given cause descriptor and event type to EvStALREADY. Events in EvMdINTR mode have their handler called inside DeliverEvent().[^lo211] Clearing an event switches it from EvStALREADY back to EvStACTIVE. UnDeliverEvent() takes a cause descriptor and an event type and clears all matching events, while TestEvent() and WaitEvent() clear the one event they are given.[^lo211][^lr173][^lr176] An event must be cleared with UnDeliverEvent() before it is issued again.[^lo211] DeliverEvent() scans every EvCB, even when all events are disabled. A larger EVENT value in SYSTEM.CNF therefore slows down every event delivery.[^spxev] OpenEvent(), CloseEvent(), DeliverEvent() and UnDeliverEvent() must be executed in a critical section.[^lr154][^lr115][^lr117][^lr175] A program may define its own events with the DescUEV macro. The calls take the forms DeliverEvent(DescUEV|my_event_num, my_event_spec) and OpenEvent(DescUEV|my_event_num, my_event_spec, EvMdNOINTR, NULL).[^lo211] ## Event Functions Table: Event functions | Function | BIOS | Explanation | | --- | --- | --- | | OpenEvent(desc, spec, mode, func) | B(08h) | Secures an EvCB and returns the event descriptor (0xF1000000 and up), or -1[^lr154][^spxev] | | CloseEvent(event) | B(09h) | Releases the EvCB[^lr115] | | EnableEvent(event) | B(0Ch) | Changes the status to EvStACTIVE[^lr120] | | DisableEvent(event) | B(0Dh) | Changes the status to EvStWAIT[^lr118] | | WaitEvent(event) | B(0Ah) | Waits for the event, then restores EvStACTIVE; returns 0 if the event is disabled[^lr176][^spxev] | | TestEvent(event) | B(0Bh) | Returns 1 and restores EvStACTIVE if the event has occurred, 0 otherwise[^lr173] | | DeliverEvent(ev1, ev2) | B(07h) | Generates an event[^lr117] | | UnDeliverEvent(ev1, ev2) | B(20h) | Returns matching EvMdNOINTR events from EvStALREADY to EvStACTIVE[^lr175] | Sony documents CloseEvent(), EnableEvent() and DisableEvent() as returning 1 on success and 0 on failure.[^lr115][^lr120][^lr118] psx-spx finds that the BIOS functions always return 1 and do so even for an unused or invalid descriptor.[^spxev] The return value of WaitEvent() is also unreliable: it may return 0 when the event becomes ready shortly after the call.[^spxev] In a program with several threads, a loop that calls TestEvent() and ChangeTh() lets other threads run, whereas WaitEvent() holds the CPU until the event occurs.[^spxev] ## Event Control Block The kernel keeps the information about an event in an event control block. The EvCB array is reached through ToT entry 4 at address 0x00000120.[^lo204][^lo210] ``` struct EvCB { /* event control block */ unsigned long desc; /* cause descriptor */ long status; /* status */ long spec; /* event type */ long mode; /* mode */ long (*FHandler)(); /* function format handler */ long system[2]; /* system reserved */ }; ``` Table: EvCB layout | Offset | Size | Field | Contents | | --- | --- | --- | --- | | 0x00 | 4 | desc | Cause descriptor (class) | | 0x04 | 4 | status | 0x0000, 0x1000, 0x2000 or 0x4000 | | 0x08 | 4 | spec | Event type | | 0x0C | 4 | mode | 0x1000 or 0x2000 | | 0x10 | 4 | FHandler | Handler function, or 0 | | 0x14 | 8 | system | Not used | The structure is from the Run-Time Library Reference, and the offsets and values are from psx-spx.[^lr104][^spxcb] An event descriptor converts to its EvCB as [0x120] + (event AND 0xFFFF) * 0x1C.[^spxtot] ## Cause Descriptors The cause descriptors related to the kernel library are shown below. Other events are described in the individual libraries.[^lo210] Table: Cause descriptors (kernel library) | Cause descriptor | Contents | Event type | | --- | --- | --- | | RCntCNT0 to RCntCNT3 | Root counter interrupt | EvSpINT | | File descriptor | File input/output | EvSpEIO | | File descriptor | File close | EvSpCLOSE | | HwCdRom | CD-ROM decoder interrupt | EvSpUNKNOWN | | HwSPU | SPU interrupt | EvSpTRAP | | HwGPU | GPU interrupt | EvSpTRAP | | HwPIO | Extension parallel port interrupt | EvSpTRAP | | HwSIO | Extension serial port interrupt | EvSpTRAP | | HwCPU | Exceptions | EvSpTRAP | | DescUEV, m | User-defined event (m = 0 to 0xFFFF) | Optional | The numeric classes used by the BIOS are shown below.[^spxclass] Table: Event classes | Class | Source | | --- | --- | | 0x0000000x | Memory Card file, for file descriptor x | | 0xF0000001 | IRQ0, vertical blank | | 0xF0000002 | IRQ1, GPU | | 0xF0000003 | IRQ2, CD-ROM decoder | | 0xF0000004 | IRQ3, DMA controller | | 0xF0000005 | IRQ4, timer 0 | | 0xF0000006 | IRQ5 and IRQ6, timer 1 and timer 2 | | 0xF0000008 | IRQ7, controller and Memory Card | | 0xF0000009 | IRQ9, SPU | | 0xF000000A | IRQ10, PIO | | 0xF000000B | IRQ8, SIO | | 0xF0000010 | Exception (break, bad syscall, overflow, memory error) | | 0xF0000011 | Memory Card, lower level BIOS functions | | 0xF2000000 | Root counter 0 (dot clock) | | 0xF2000001 | Root counter 1 (horizontal retrace) | | 0xF2000002 | Root counter 2 (one-eighth of the system clock) | | 0xF2000003 | Root counter 3 (vertical retrace, a software counter) | | 0xF4000001 | Memory Card, higher level BIOS functions | | 0xF4000002 | libmath | psx-spx also reports classes 0xF1xxxxxx for events, 0xF3xxxxxx for user events and 0xFFxxxxxx for threads, which the BIOS does not use.[^spxclass] ## Event Types The numeric event types are shown below.[^spxspec] Table: Event types | Spec | Meaning | | --- | --- | | 0x0001 | Counter becomes zero | | 0x0002 | Interrupted | | 0x0004 | End of I/O | | 0x0008 | File was closed | | 0x0010 | Command acknowledged | | 0x0020 | Command completed | | 0x0040 | Data ready | | 0x0080 | Data end | | 0x0100 | Time out | | 0x0200 | Unknown command | | 0x0400 | End of read buffer | | 0x0800 | End of write buffer | | 0x1000 | General interrupt | | 0x2000 | New device | | 0x4000 | System call instruction | | 0x8000 | Error happened | | 0x8001 | Previous write error happened | | 0x0301 | Domain error in libmath | | 0x0302 | Range error in libmath | ## Events Delivered by the BIOS The BIOS opens five CD-ROM events for itself, with class 0xF0000003 and types 0x10, 0x20, 0x40, 0x80 and 0x8000. The other events below are delivered by the BIOS for a game to open.[^spxsum] Table: Events delivered by the BIOS | Class | Spec | Meaning | | --- | --- | --- | | 0xF0000003 | 0x0010 | CD-ROM DMA finished (all sectors) | | 0xF0000003 | 0x0080 | CD-ROM INT4, end of disc reached | | 0x0000000x | 0x0004 | Memory Card file x done | | 0xF4000001 | 0x0004 | Memory Card done | | 0xF4000001 | 0x0100 | Memory Card busy error | | 0xF4000001 | 0x2000 | Memory Card ejected or unformatted | | 0xF4000001 | 0x8000 | Memory Card write or general error | | 0xF0000011 | 0x0004 | Memory Card hardware I/O finished | | 0xF0000011 | 0x0100 | Memory Card hardware busy error | | 0xF0000011 | 0x2000, 0x8000, 0x8001 | Memory Card hardware errors | | 0xF2000000 | 0x0002 | Timer 0 (IRQ4) | | 0xF2000001 | 0x0002 | Timer 1 (IRQ5) | | 0xF2000002 | 0x0002 | Timer 2 (IRQ6) | | 0xF2000003 | 0x0002 | Vertical blank (IRQ0) | | 0xF0000010 | 0x1000 | Unknown exception | | 0xF0000010 | 0x4000 | Unknown syscall | The default interrupt handler also delivers class 0xF0000001 to 0xF000000B with type 0x1000. psx-spx advises against using these events, because the handler does not record which interrupt occurred and may deliver them at random.[^spxsum][^spxexc] It also reports timer 2 with the same class as timer 1.[^spxsum] ## Interrupt Handling When an interrupt or exception occurs, the kernel saves the registers in the execution TCB as the main flow context. Processing begins at address 0x00000080, which jumps to the kernel interrupt dispatcher, and the dispatcher calls the routine for the interrupt. When processing is complete, the main flow registers are restored and the main flow resumes.[^lo206] The dispatcher keeps four priority chains of interrupt handlers and calls every handler in order. The first handler called is the first element of chain 0. Each handler checks the interrupt status register at 0x1F801070 for its own source.[^spxexc] A handler that has processed and acknowledged its interrupt may call ReturnFromException() to skip the handlers of lower priority.[^spxexc] The default chains are shown below.[^spxexc] Table: Default interrupt priority chains | Priority | Handlers | | --- | --- | | 0 | CdromDmaIrq, CdromIoIrq, SyscallException | | 1 | CardSpecificIrq, VblankIrq, Timer2Irq, Timer1Irq, Timer0Irq | | 2 | PadCardIrq | | 3 | DefInt | Because the dispatcher does not record the incoming interrupt flags, a high priority handler may reject an interrupt that has not yet been flagged while a lower priority handler later processes or acknowledges it. psx-spx therefore recommends only one handler for each interrupt source.[^spxexc] The kernel does not support nested exceptions: the registers are saved in the current TCB and the exception stack has a fixed start address, so a nested exception overwrites both.[^spxexc] HookEntryInt() installs a function that runs after the handler chains have been fully processed. It takes a structure in the setjmp() format, and the hook is called with R2 = 1 and should end with ReturnFromException(). ResetEntryInt() restores the default structure, whose RA is ReturnFromException().[^spxexc] The cautions and prohibitions for code in interrupt context are on the [PS-X OS](/system/ps-x-os/) page. ## References [^os33]: Sony Computer Entertainment Inc. PlayStation Operating System. August 1998. Page 3-3. [^lo204]: Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-4. [^lo206]: Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-6. [^lo209]: Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-9. [^lo210]: Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-10, Table 2-12. [^lo211]: Sony Computer Entertainment Inc. Run-Time Library Overview. January 1999. Page 2-11, Table 2-13, Table 2-14. [^lr104]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-4, EvCB. [^lr115]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-15, CloseEvent. [^lr117]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-17, DeliverEvent. [^lr118]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-18, DisableEvent. [^lr120]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-20, EnableEvent. [^lr154]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-54, OpenEvent. [^lr173]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-73, TestEvent. [^lr175]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-75, UnDeliverEvent. [^lr176]: Sony Computer Entertainment Inc. Run-Time Library Reference. January 1999. Page 1-76, WaitEvent. [^spxev]: psx-spx. Kernel (BIOS), BIOS Event Functions. https://psx-spx.consoledev.net/kernelbios/ [^spxmode]: psx-spx. Kernel (BIOS), BIOS Event Functions, Event modes. https://psx-spx.consoledev.net/kernelbios/ [^spxclass]: psx-spx. Kernel (BIOS), BIOS Event Functions, Event Classes. https://psx-spx.consoledev.net/kernelbios/ [^spxspec]: psx-spx. Kernel (BIOS), BIOS Event Functions, Event Specs. https://psx-spx.consoledev.net/kernelbios/ [^spxsum]: psx-spx. Kernel (BIOS), BIOS Event Summary. https://psx-spx.consoledev.net/kernelbios/ [^spxcb]: psx-spx. Kernel (BIOS), BIOS Control Blocks, Event Control Blocks. https://psx-spx.consoledev.net/kernelbios/ [^spxtot]: psx-spx. Kernel (BIOS), Table of Tables. https://psx-spx.consoledev.net/kernelbios/ [^spxexc]: psx-spx. Kernel (BIOS), BIOS Interrupt/Exception Handling. https://psx-spx.consoledev.net/kernelbios/