IOP SSBUSC Sub-System Bus Controller of the IOP documentation compiled by Wisi rev. 2018.01.06 This document is compiled from multiple sources and tests. Sources and people who helped in creating this document: - ps2sdk - information from various sources and developers - SP193 who guided me when I still had no idea what hardware the IOP was comprised of - psx-spx documents and all their sources, where a lot of the following information came from - many others I may have forgotten over the time while writing and testing The IOP uses an on-chip (external) peripheral bus controller (the SSBUSC) to communicate with external peripheral devices. The SSBUS is (in PIO mode) a non-Address-Data-multiplexed 8-bit or 16-bit parallel bus with per-device configurable address range and timing. It supports DMA, both as a pseudo-PIO (that can appear as PIO access to the peripheral device) mode and fast and/or wide (32-bit) DMA mode, through which the maximal bandwidth of the bus can be attained. The SSBUSC interfaces the IOP internal system bus to the external SSBUS. The SSBUSC in the PS2 IOP is extended upon the SSBUSC of PS1 CPU, with complete backward compatibility. It is possible that the IOP even supports connecting the PS1 GPU to the IOP SBUS (untested) (see PGIF document). Glossary: Dev SSBUSC channel (usually) used for that device number, but also refers to the device itself. Dev# Unofficial sequential numbering given to the channels, based on the numbering in the SSBUSC IRX. All channels (and even a few non-existing) are listed through this numbering. This is deprecated in favour of "Sbc" i.e. "Sbc4" is Dev4, "Sbc8" is Extr, "Sbc9" is SPU2, "Sbc10" is Dev9M. Sbc SsBusc Channel sequential number according to the SSBUSC IRX. This is a new, unofficial naming, based on the official numbering from SSBUSC IRX. /CS Chip Select line of the an SSBUSC channel, that corresponds to the given device number. DREQ DMA Request line of the an SSBUSC channel, that corresponds to the given device number. DACK DMA Acknowledge line of the an SSBUSC channel, that corresponds to the given device number. /INT Interrupt request line, usually used by the given device number. Dev9C The Dev9 Controller chip. Also known as SSBUS Interface, SSBUS Controller, HDD Controler, etc. It interfaces the SSBUS with the Expansion Bay Expansion bus. When referring to early versions of it that supported PCMCIA cards, it is called "the PCMCIA Dev9C" or "the PCIC Dev9C". Its /CS signal is also called /CS9C and its SSBUSC channel is called Dev9C / Dev9_1. PCIC PC Card Interfcae Controller - the PCMCIA Dev9C is called this way. Address space and device memory-range mapping The limits of the SSBUSC address space are 0x10000000 - 0x1FFFFFFF. However recent tests showed that Dev4 can be remapped all the way down to 0x00000000, so the prior statement is not entirely true. However there are several IOP-internal devices with fixed-mapping that are not connected through the SSBUS and thus those ranges (should) fall outside the SSBUSC address range. Such devices are: - SBUS control registers at 0x1D000000 - 0x1DFFFFFF(?) - All the IOP devices not accessed through the SSBUS in the range 0x1F800000 - 0x1F900000. Note that there are devices internal to the CPU core that are not accessible through the internal IOP bus. Such are the cache (scratchpad) (0x1F7FFC00 - 0x1F8007FF) and its configuration registers (around 0xFFFE130). See Cache_Scratchpad document). Because they are internal to the IOP Core, and because in accessing the IOP system bus from the EE, the EE "goes in the place of" the IOP Core, the EE cannot access memory (mapped registers) internal to the IOP Core. It is unknown what are the effects of remapping over an internal device. Mapping different SSBUSC devices over each-other is not thoroughly tested (maybe it causes bus error, but sometimes seems to cause more serious unrecoverable errors). Accesses to internal IOP devices are not forwarded to the SSBUS, so its /SRD, /SWR, /RT, address, data, ... lines do not change state to reflect the accessed register. Access to unmapped registers (including PS2-mode-specific registers (0xBF8014xx) 0xBF801460 for example in PS1 mode) does not cause access on the SSBUS (/SRD /SWR /RT). The SSBUSC consists of several mostly identically-functioning channels. Each channel is referred to as "Dev", however for some channels, there is no correlation between the Dev and the number in the /CS, /INT and DMA lines. This document uses a numbering scheme (Sbc), based on the numbering in the SSBUSC IRX module, and extended with PPC-IOP SSBUSC devices (numbering there is unofficial). The INTC uses a separate channel numbering, and because it is not connected to the SSBUSC there is no direct relation between an interrupt and an SSBUSC channel (other than that defined by the external connections and software). The DMAC channels are connected to (some of) the SSBUSC channels. The SSBUSC "delay" registers are used to set the timing and bus-width parameters of both the SSBUSC channel in PIO mode and its DMAC counterpart in DMA mode. There is no correlation between DMAC channel numbering and SSBUSC channel numbering. It is unknown if the PS1 SSBUSC supports Wide DMA mode, but registers' bit-fields maximum values show that it does not. SSBUSC signals signal direction A26:A16 IOP-> High address bus. States are usually latched (unconfirmed) or floats low when not in bus access cycle (untested). A15:A0 IOP<-> Low address bus. As above. In Wide (32-bit) DMA mode it is used as the high 16-bits of the data bus, when it become bi-directional. D15:D0 IOP<-> Data bus. Floats high (week pull-ups) when not in bus cycle. See /RT for direction. SYSCLK0 IOP-> PS1 mode bus clock. ~33MHz. SYSCLK1 IOP-> PS2 mode bus clock. ~36MHz. Peripheral devices that support both PS1 and PS2 mode have both clock inputs. /SRD IOP-> Read strobe signal. Goes active low when reading from peripheral. With default settings, data is output on the falling edge and latched (by the IOP) on the rising edge. /SWR IOP-> Write strobe signal. Goes active low when writing to peripheral. With default settings, data is output on the falling edge and latched (by the peripheral) on the rising edge. /CS IOP-> Chip Select signal (one for each SSBUSC channel). For channels lacking a /CS signal, such should be generated from the address bus externally, matching the set address range in SSBUSC registers. While in DMA transfer (DACK active high) /CS is also kept active low. Because of this, one can do pseudo-DMA transfers in PIO mode of the peripheral (without DMA lines connected). Note however that the state of the address lines in DMA is not guaranteed (untested). DREQ ->IOP DMA Request. A peripheral device asserts this high to request (signal that it is ready for) a DMA transfer. Once the transfer is acknowledged (DACK) this is usually deasserted and DMA is started. This has no direct relation in time to the start of the DMA bus cycles. DACK IOP-> DMA Acknowledge. Once the IOP has received a DREQ and a DMA channel is enabled for transfer or a DMA channel is forced to start transfer (see IOP DMAC document), this is asserted high and a DMA transfer is started. This line marks the exact beginning and end of a DMA transfer and while active the bus (and the IOP) is DMA mode. /RT IOP-> Read-Time Active low only when the SSBUS controller lets a device output data on the data bus. Assume that in all other cases a device should not output data. Stays active low on 4 consecutive 8-bit accesses (32-bit read) and jumps high for shorter period than the inactive period, only between every 4 accesses. Connects to SSB_SSAT at the SPEED chip, after being buffered by the Dev9C. Signifies a single read access cycle (only reads). Basically a copy of any /CS, but only for reads. Works just the same in Programmed I/O and DMA modes. Example: reading an 8-bit device as 32-bit: __ __ ___ /CS \_______A_______/ \_______A_______/ __ __ ___ /RT \_______A_______/ \_______A_______/ ___ _ _ _ _ _ _ _ ____ _ _ _ _ _ _ _ ____ /SRD _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ This is for controlling the bus direction of external buffers. The line would go low, when the CPU lets a device output data on its bus. The Dev9Controller ('SSBUS Interface'), surely uses this line to set the bus drivers (buffers) direction. /UBE IOP-> Upper Byte Enable. Goes active low, when the upper byte of the 16-bit data bus has valid data. The state of this line is latched - once it changes state it keeps it up to the next change. For 8-bit devices (SSBUSC channels set to 8-bit width), this is always inactive high, while for 16-bit devices it always goes active low. /UBE is always inactive high in PS1 mode, even for devices configured for 16-bit wide bus. /IOIS16 ->IOP Used by a peripheral device to signal to the IOP that the accessed register is 16-bit (rather than 8-bit) (when asserted low). It is unknown how this should affect the load/store operation - perhaps overrides the set bus-width in the SSBUSC delay/config register. It is only available for the Dev9 (Dev9M, Dev9I) channel (untested), but tests couldn't determine its exact function. The Dev9C drives it always, regardless of its configuration registers. The SPEED buffer of the Dev9C has to be enabled (1460.0 = 1) for the state of the /CIOIS16 line (->Dev9C) to appear on the /IOIS16 line. This is most likely a left-over from some early PCMCIA interface. On Network Adapters /CIOIS16 is unconnected; the SPEED chip has no pin for such signal (as far as it is known). See Dev9C and Dev9C PCMCIA documents for more information. /WAIT ->IOP When asserted by a peripheral device low, and the /WAIT signal is enabled for that SSBUSC channel, when reading from the device, the IOP stalls before reading the data until /WAIT is deasserted, and the data transfer takes place. The drivers of this seem to should be open-collector or open-drain, or tri-state, gated on /CS. /SSRST IOP-> Sub-System bus Reset. On power-up ramps slowly high (with power supply perhaps. On power-down first drops from 3.44V to 2.28V and stays at 2.28V for 80ms. Then drops at 0V and stays at 0V for 28ms. Then goes back to 2.28V and stays so for 18ms, until finally slowly ramping down to 0V. __3.44V_____ |<--80ms--->|<28ms>|18ms| |___2.28V___ ____ | | \\ | | \\ | | \\... |__0V__| ****---______640mV_(PS2_sandby_off)______ On power-up (from standby): from 640mV goes quickly to 0V then ramps-up for 40ms to 3.44V. On reset to PS1 mode it is pulsed low. /SSRST is kept low while /SRST (EE->SBUS->IOP) is low (while reg. F240.19 = 1), but only if IOP reset is enabled by 1450.5 (=1), otherwise it keeps high. When driving input lines, older PS2 models require stronger drivers. For sinking some lines, a resistor of ~330 ohm may be necessary. For finished devices, use resistors according to the correct line termination specifications (usually 22-33ohm). Very simplified IOP block diagram: The SIF interface logic includes PS1 GPU registers and DMA emulation in PS1 mode. When EE takes control over IOP memory, the EE does that through the SIF interface logic in the IOP, and controls the IOP System Bus, but not the IOP core internal bus. The IOP Core, through its internal bus, controls the IOP System Bus just the same way as the EE controls it, when it has taken control over the controllable IOP memory, through the SBUS, with the SIF acting as a controller. ______________________________________________ | IOP (ASIC) | | ___________________________________ | | |IOP Core | | | | | | | | I| | | | | n| ________________ | | | | t|-------|Cache/Scratchpad| | | | | e| |________________| | | | | r| | | | | n| _________________ | | | | a|-------|InternalRegisters| | | | | l| |_________________| | | | | B| | | | | u| | | | | s| | | | |_____|_____________________________| | | | | | | IOP SystemBus _____________ | SBUS | ------+---+---------------+-|SIF interface|---------- EE | | | |_____________| | | _______|_____________ | _________ | SSBUS | |Internal IOP Devices | | | SSBUSC |-------------- IOP peripheral devices | |SIO2, USB, iLink, ...| +-|_________| | | |_____________________| | | | | _________ | ____|____ | | |EDO DRAMC|-----+-| DMAC | | | |_________| |_________| | | | \-------------/ | | | | |_______________|______________________________| | EDO DRAM SSBUSC Channels The channels on the PS2 IOP include the channels already available on the PS1 CPU and a few PS2-specific channels. Later, on PPC-IOP (DECKARD) -models, a few more channels are added and a few of the already-existing ones are left unused and possibly unfunctioning. The SSBUSC is configured through two sets of registers - at 0x1F801000 (legacy channels from the PS1 CPU) and at 0x1F801400 (added for the PS2). Channel Dev Default DMA INTC ------lines----- Sbc name device channel channel /CS DMA /INT --- PS1 Mode of the PS2 IOP: --- Sbc0 Dev0 Dev0 ROM Exp1 - - ExGe - - Sbc1 Dev1 Dev1 DVD ROM Exp3 - - 1 - - Sbc2 Dev2 Dev2 BOOT ROM - - 2 - - Sbc3 Not known to have ever existed. Sbc4 Dev4 SPU1 4 9 4 4 4 Sbc5 Dev5 CDVD 3 2 5 5 5 Sbc6 Not known to have ever existed. Sbc7 Dev7? PS1 GPU (SIF2?) 2 1 7 2 1 Sbc8 Extr? PIF/MRP(TOOL) Exp2 5 23 /EXTR *EX *EX --- Added on the MIPS-IOP for the PS2: --- Sbc9 Dev8? SPU2 7 12 8 8 8 Sbc10 Dev9_2 Expansion Bus Mem 8 13 9 9 9 Sbc11 Dev9_3 Expansion Bus I/O 8 13 9 9 9 Sbc12 Dev9_1 Dev9ControllerCfg - - 9C - - --- Added on the PPC-IOP on DECKARD-models: --- Sbc13 PPC? PPC BOOT ROM - - PPC - - Sbc14 ? Dev9_2 new channel 8 26 InternalDevice ExGe = Externally Generated /CS signal from the address bus. N/A = Not Available - = Not Available *Each category above includes those preceding it. There are strange stuff in interrupt emulation code of DECKARD, which suggest that there may be differences in other devices' interrupt mappings. Unlike on the PS2 in PS1 mode, on the PS1 Dev0 has uses the /CS0 signal, while Sbc8 doesn't have a /CS signal (it is formed from the address lines). Dev0 is unusable in PS2 mode. Sbc7 above is only added for completeness. Sbc3, Sbc6, Sbc7 do not exist as SSBUSC channels, even if devices under those names (still) exist. On PS2 IOP /CS7 and the other signals of Dev7 which is assumed to be the PS1 GPU are not present, but in PS1 mode should be available at the SBUS signals. One can suspect that in PS1 mode the SBUS signals are identical to those of the System Bus in the PS1 between the CPU and the GPU. For more information see SIF/SBUS and PGIF documents. Dev7 is not an SSBUSC channel, as it isn't connected through the SSBUSC. (see SCPH-9000 SM) Speculation: Channels Sbc 3 and 6 might have been for SIO0, SIO1 and MDEC before they were integrated in the PS1 CPU ASIC in an early prototype. On the PPC-IOP the /CS, DMA and /INT signals of the following devices are not available, because they are integrated in the IOP/PS2-on-chip ASIC: Sbc: 4, 5, 9, 10, 11, 12, 14. The /CSPPC (/CS13) is added for the BOOT ROM of the PPC-IOP (a part of the PS2 BOOT ROM). All PS2 Mode-specific devices are unusable in PS1 mode and access to their control registers results in a bus error. This is only true for non-PPC MIPS-IOPs. In PS1 mode for Sbc8, interrupt 23 - /INTEX is not available and the equivalent is the PIO 10 interrupt caused by the controllers /HTR0 and /HTR1 lines (as on a real PS1). See INTC document for more info. The Dev9_2 Sbc10 PIO timing is valid for PIO mode of the actual Dev9 at 0x10000000, while DMA timing of the Dev9_3 (Sbc11) is valid for Dev9 DMA timing. This is most likely due to Dev9_2 being Dev9M - the memory range part of the complete Dev9 range and Dev9_3 Dev9I being the I/O range - as DMA should be tied to the I/O range. This separation is most likely a leftover from some early method of directly connecting a PCMCIA card to the SSBUS (with a very simple Dev9C PCIC). The above is further supported by the fact that early SPEED chips are known to have been connected directly to the SSBUS (source TOOL / PA TOOL MIF, SMAP, SPEED diagnostic programs on HDD). Another fact in support of this is the presence of SSBUS signals /IOIS16 and /WAIT (/IOIS16 - only supported on the Dev9M / Dev9I channel). It is unknown what the DMA timing setting of Dev9_2 Sbc10 controls. It may very well be a dummy bit-field or be put into use by some unknown bit-field of the Dev9 DMA registers or the Dev9 SSBUSC registers, or it may only be used for one particular DMA mode (slice/burst)(unlikely). Sbc10 Dev9M and Sbc11 Dev9I activate the same /CS9 signal. The peripheral (Dev9Controller) tells them apart by A26. This is possible because Dev9M is "locked" at 0x10000000 - 0x13FFFFFF (A26=0) and Dev9I (abeit its start address is changeable) it limited within 0x14000000 - 0x17FFFFFF (A26=1). Using A26, A25, A24, a total of 8 sub-ranges can be selected under the common channel Dev9. The ExpansionBay version of the Dev9C has inputs for A26 A25, A24, which define where in memory the SPEED chip and the I2C interface will be mapped. Notice that by sequential numbering Dev9C takes number 12 = 0xC - one more reason to be abbreviated as "Dev9C". For some unknown hardware called "njig", the Dev9M range was used for a Flash memory device. (source: TOOL romflash utility) "njig" might stand for Namco jig and this memory might have been used by the Namco PS2 arcades. This is only a speculation (quite possibly incorrect). On the Namco System 246 / 256 the Dev9 channel is used for arcade-specific hardware, including memory devices. It is unknown if this is related to the separation of Dev9 to Dev9M and Dev9I, but most likely it is not. Register map Any (32 / 16 / 8 -bit) access should be supported. 32 and 16 -bit wide accesses are known to be used. Base addresses: 0x1F801000 - 0x1F80103F - PS1 and PS2 devices 0x1F801400 - 0x1F80144F - PS2 devices Addr Ch# Type Device 1000 0 addr Dev0 Exp1 1004 8 addr Extr Exp2 PIO/EXTR/... 1008 0 del Dev0 Exp1 100C 1 del Dev1 ROM-DVD Exp3 1010 2 del Dev2 ROM-BOOT 1014 4 del Dev4 SPU1 1018 5 del Dev5 CDVD 101C 8 del Extr Exp2 PIO/EXTR/... 1020 common delay cfg - 1400 1 addr Dev1 ROM-DVD Exp3 1404 4 addr Dev4 SPU1 1408 5 addr Dev5 CDVD 140C 9 addr Dev8 SPU2 1410 11 addr Dev9_3 I/O 1414 9 del Dev8 SPU2 1418 10 del Dev9_2 Mem 141C 11 del Dev9_3 I/O 1420 12 del Dev9_1 Cfg 1424 13 addr PPC BOOT ROM 1428 13 del PPC BOOT ROM 142C 14 addr PPC Dev9/SPEED 1430 14 del PPC Dev9/SPEED ch# -registers- delay addr 0 1008 1000 1 100C 1400 2 1010 (0x1FC00000) 3 - - 4 1014 1404 5 1018 1408 6 - - 7 - - 8 101C 1004 9 1414 140C A 1418 (0x10000000) B 141C 1410 C 1420 (0x1F801460) D 1428 1424 E 1430 142C *Address values in brackets mean that no register for setting the address exists and it is hard-wired to that value. In PS2 mode (SCPH-30003) the registers of Dev0 and Sbc11 mirror each other on both read and write. Dev0 is basically unusable, because it *is* Dev9I in PS2 mode. This is most likely because the channel of Dev0 was (mis-)used for Dev9I once Dev0 was deemed unused in PS2 mode. Dev0 behaves differently (the available address range) between PS1 and PS2 modes. Limits of registers configurability PS1 mode (SCPH-30003 GH-006) ch# ------ address ------- ----- delay/cfg ------ /WAIT - Notes min max min max capable 0 0x1F000000 0x1FFFFFFF 0x00000000 0xAF1FFFFF selectable 1 (0x1FA00000) 0x00000000 0x2F1FFFFF no, hardwired 2 (0x1FC00000) 0x00000000 0x2F1FFFFF no, hardwired 3 - - 4 (0x1F801C00) 0x00000000 0x2F1FFFFF yes, hardwired Fixed sz=0x4000 5 (0x1F801800) 0x00000000 0x2F1FFFFF no, hardwired Fixed sz=0x4 6 - - 7 - - 8 0x1F000000 0x1FFFFFFF 0x00000000 0x2F1FFFFF yes, hardwired Accessing any PS2-specific SSBUSC register (0x1F801400 - 144F) results in a bus error. Dev0 can in fact have the /WAIT signal (bit 31 = 1) enabled and it is fully-functional - when asserted low, accessing in the Dev0 range causes IOP to stall until /WAIT is deasserted. For Dev4 and Dev5 the range-sizes are fixed to the specified values regardless of the settings. When the size of a memory range is fixed, this affects where the /CS signal goes active, as well as where bus error occurs. PS2 mode (SCPH-30003 GH-006) ch# ------ address ------- ----- delay/cfg ------ min max min max 0 Mirrors channel 11. 1 0x1E000000 0x1FFFFFFF 0x00000000 0xEF1FFFFF 2 (0x1FC00000) 0x00000000 0xEF1FFFFF 3 - - 4 0x00000000* 0x1FFFFFFF 0x00000000 0xEF1FFFFF 5 0x1E000000 0x1FFFFFFF 0x00000000 0xEF1FFFFF 6 - - 7 - - 8 0x1E000000 0x1FFFFFFF 0x00000000 0xEF1FFFFF 9 0x1E000000 0x1FFFFFFF 0x00000000 0xEF1FFFFF A (0x10000000) 0x00000000 0xEF1FFFFF B 0x14000000 0x17FFFFFF 0x00000000 0xEF1FFFFF C (0x1F801460) 0x00000000 0xEF1FFFFF It is curious that in PS2 mode channel 4 can be remapped below 0x1F000000 and even below 0x10000000 -all the way down to 0x00000000 (tested with 0x00200000 and 0x00800000), which defies MIPS logic, where anything below 0x10000000 is RAM (and not memory-mapped hardware). Test was done from EE - accessing IOP RAM at 0xBC200000 works too (0x00200000 for Dev4 base addr), but DMAC seems to see this as unmapped RAM and doesn't increment MADR - maybe doesn't do any transfer. It can also be mapped over RAM (below 0x00200000), but it doesn't activate /CS there. The DMA channel for Extr was used. It is untested whether any channel is locked by size or address regardless of its settings (which is observed for some channels in PS1 mode), but the way they are used in different cases (the PSX DVR, etc.) suggests that channels should be directly affected by all their settings (bit-fields). Given that all channels have DMA timing settings' bit-fields even though it is certain that ROM channels do not have counterpart DMA channels, suggests that the registers logic was just copied for all regardless whether those bit-fields were connected to anything. To prevent IOP from crashing by channels' ranges overlapping, set first the start address of the range to either one with a lot of free space after it, or the highest address possible (0x1FFFFFFF) which will make the range span for only a single byte regardless of the set size. Default configuration values In PS2 mode, the SSBUSC configuration registers are first initialized by RESET. The IRX SSBUSC provides functions for setting them, while some modules write to them directly (DEV9, ...). PS1 mode ch# address delay/cfg 0 0x1F000000 0x00142455 1MB, 8bit 1 (0x1FA00000) 0x00153044 2MB, 16bit 2 (0x1FC00000) 0x0015243F 2MB, 8bit 3 - - 4 (0x1F801C00) 0x200931E1 512B, 16bit 5 (0x1F801800) 0x00020943 4B, 8bit 6 - - 7 - - 8 0x1F802000 0x000D2077 8kB, 8bit PS2 mode TODO: Add values in PS2 mode and those used by drivers. ch# address delay/cfg 0 0x14000000 0xEF1A3043 64MB, 16bit 1 0x1E000000 0x00183444 16MB, 16bit 2 (0x1FC00000) 0x0016244F 4MB, 8bit 3 - - 4 0x1F801DA8 0x200B31E1 2kB, 16bit 5 0x1F402000 0x6F060011 64B, 8bit 6 - - 7 - - 8 0x1F802000 0x000D2077 8kB, 8bit 9 0x1F400010 0x200931E1 512B, 16bit A (0x10000000) 0xE01A3043 64MB, 16bit B 0x14000000 0xEF1A3043 64MB, 16bit C (0x1F801460) 0x00051011 32B, 16bit PS2 mode on DECKARD-models ch# address delay/cfg 0 0x1F000000 0x800026FF 1B, 8bit 1 0x1E000000 0x00183444 16MB, 16bit 2 (0x1FC00000) 0x0016244F 4MB, 8bit 3 - - 4 0x1F801DA8 0x300B31E1 2kB, 16bit 5 0x1F402000 0x6F060011 64B, 8bit 6 - - 7 - - 8 0x1F802000 0x000D3655 8kB, 16bit 9 0x1F400010 0x200931E1 512B, 16bit A (0x10000000) 0xE0183043 16MB, 16bit B 0x14000000 0xEF1A3043 64MB, 16bit C (0x1F801460) 0x00051011 32B, 16bit D 0x1FC00000 0x0018244F 16MB, 8bit E 0x11000000 0xE0183043 16MB, 16bit TODO: On PPC-IOP in the above test, Dev4 returned Address Error =1 => find what cause that and what sets this flag. Perhaps the unaligned (to the size of the range -i.e. the range's size wil be reduced due to start address being unaligned) start address? Base address registers: All base address registers are similar, only differing by memory limits. 3 3 2 2 2 2 2 2 0 1 0 9 8 5 6 4 3 0 ----------------------- | | R | S | | - | L T | | | I A | | | M | D | ----------------------- 28:0 r/w STAD Base (start) physical address of the memory range to which this SSBUSC channel is mapped (its /CS goes active and its timing and other setting are applied to the SSBUSC). Accessing any unmapped memory results in a bus error, thus mapping a channel in a certain memory range makes accesses to that range not result in bus error. RLIM Range Limits: The highest bits 28:24 / 28:25 / 28:26 are fixed to different values (0x1F / 0x1E / 0x14) for the different channels (see Limits of registers configurability), which limits the address range they can be mapped in. When the start address is on an unaligned boundary of the size of the range, then the memory made available to this channel spans from the start address to the first boundary aligned to the size of the memory range (untested). If is possible that this is not so, but rather the available memory range is the whole region of the chosen size, starting from the first boundary, divisible by the size of the range, before (or on) the start address to the next one. I.e. if the size of the range is 0x20 and the start address is 0x15, the range will either span 0x15 - 0x1F, or 0x10 - 0x1F (untested, but assume the former). 31:29 r/o, always 0. Delay / Configuration channel registers: All bit-fields are r/w unless otherwise noted. 3 3 2 2 2 2 2 2 2 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 9 8 7 4 3 1 0 6 5 4 3 2 1 0 9 8 7 4 3 0 -------------------------------------------------- |W|W|D|A| D | | D |E|I|A|A|S|F|H|R| R | W | |A|D|M|D| M | - | E |X|O|I|T|T|L|O|E| D | R | |I|M|A|E| A | | C |D|I|N|Y|R|O|L|C| D | D | |T|A|F|R| T | | R |L|S|C|P|B|T|D|V| L | L | -------------------------------------------------- 3:0 WRDL Write delay: /SWR active low period: 0-15 [cycles+1] 7:4 RDDL Read delay: /SRD active low period: 0-15 [cycles+1] 8 RECV Recovery period: 0= off / 1= use commonDelay.3:0 9 HOLD Hold period: 0= off / 1= use commonDelay.7:4 10 FLOT Floating period: 0= off / 1= use commonDelay.11:8 11 STRB Pre-Strobe period: 0= off / 1= use commonDelay.15:12 12 ATYP Access type: 0= 8bit / 1= 16bit. Also affects DMA bus width, when not using Wide DMA mode. 13 AINC Increment address when accessing a register shorter than the access instruction: 0= off / 1= increment. Example: when reading a word from a byte-wide bus, this option sets whether the address on each consecutive 8-bit access would increment or not. If disabled the byte at the base address of the word would be read 4 times, otherwise the bytes at +0, +1, +2, +3 will be read in that order. This is useful (to be disabled) for devices like ATA interfaces, where some ATA registers are written twice for extended LBA (which can be done with a single word-access). 14 IOIS16 I/O is 16-bit: /IOIS16 signal: 0= don't use it / 1= regard it. Supported by only(?) DEV9 (but which Dev9M or Dev9I(more likely) or both?). Most likely overrides the Access Type (8/16 -bit) setting (tested, but doesn't seem to have any effect). /IOIS16 should be an input to the IOP, but is marked as output. A peripheral signals by this signal that the register accessed is 16-bit (when low). See Dev9C document for more info. From PCMCIA specs (volume 2 / r7.0, february 1999). ----- The IOIS16# output signal is asserted when the address at the socket corresponds to an I/O address to which the card responds, and the I/O port addressed is capable of 16-bit access. When this signal is not asserted during a 16-bit I/O access, the system will generate 8-bit references to the even and odd byte of the 16-bit port being accessed. ----- 15 EXDL Extended delay: MSb of /SRD active low period. Not found to have any effect (regardless of reg. 1020). 20:16 DECR Decoding range = 2^n bytes. Values: 0 - 27 = 1B - 128MB. 23:21 r/o Unused, 0. 27:24 DMAT DMA timing: /SRD /SWR active.low period: 0-14 [cycles+1]. The inactive period is always 1cycle. 0=1cycle, 1=2cycles, ..., 14=15cy 15(0xF)= '0.5cycles' Each word still remains on the bus for 1cy, but there are no inactive pauses between the words. - 'fastest' DMA mode: /SRD/SWR is kept active low over the whole transfer and the SSCLK clocks the data words. On some devices (PS2 mode only?) the /SRD active low period cannot be 1 cycle, thus with DMAT = 0 or 1, the resulting period is 2cy. It is unknown if this is caused by some setting. The /SWR period is unaffected. 28 ADER r/o Address error flag (when =1). When the an address error within the memory range of this channel occurs this bit becomes set. Writing 1 clears it. Unknown what Address Error means. This doesn't become set by unaligned access. It might be for the DMAC accessing RAM past its end when doing DMA through this SSBUSC channel, but it doesn't activate on that either. 29 DMAF DMA select timing source flag: 0= use PIO timing / 1= use DMA timing bit-field 28:24 for DMA. 30 WDMA Wide DMA mode. When = 1 this overrides the Access Type (8/16 bit) setting, and causes 32 bits to be transferred in one go. The low 16bits are mapped to the SD15:SD0 data lines, and the high 16bits - to the low address lines SA15:SA0, which become inputs, if the transfer is done 'to RAM'. This is why most devices get all the low 16 address bits, even though their address space is much smaller than 64kbyte. The SPU2 doesn't get all 16 low address lines, so this is disabled for it, while it is enabled for the CDVD and Dev9_2, Dev9_3. 31 WAIT /WAIT signal. When = 1 enables the IOP waiting on the /WAIT (input to IOP) signal, when accessing the range of the given device. Slow devices can make the IOP wait (indefinitely) before transferring data, by asserting the /WAIT line low while a PIO access is being done (after the device detected assertion of /CS and decoded the address). On read, once /WAIT is deasserted, IOP loads the data (it was made to wait for) from the device/bus (on read) and continues execution. On write the write operation completes even if /WAIT is asserted low and the IOP can continue executing. This is true for any device. However if /WAIT is kept asserted low and another write (or a read) access is done (to any device - even such with /WAIT hardwired to disabled state), then the IOP will stall before (or after?) transferring any data, until /WAIT is deasserted. This can be used as a hack to use /WAIT even of devices that have it disabled (like the BOOT ROM for example): write a device that has it enabled (while /WAIT is low) then access (r/w) the BOOT ROM and the IOP will stall until /WAIT is deasserted. /WAIT should be driven most likely by OC/OD drivers (or a tri-state output enabled on /CS). The output of the Dev9C seems to be just such. There are two main modes of transfer: PIO and DMA. The timing parameters of the PIO mode can be set in detail, while for the DMA mode a symmetric clock is assumed only with period configurable. PIO timing configuration can be used for DMA transfers too. For DMA on read (->IOP) both for 0 and 1 DMA periods 1 cycle is added, which results in 2 cycle transfer - reason unknown. On write, 0->1cycle, 1->2cycles (reason unknown). Besides the /SRD /SWR active.low periods that can be set individually for each channel, the following parameters exist, that can only be enabled for the individual channels, but the value is common for all. Their values are set by the Common Delay register. 1020 Common delay register r/w: 3:0 Recovery period 0 - 15 cycles. 7:4 Hold period 0 - 15 cycles. 11:8 Floating release delay 0 - 15 cycles. 15:12 Strobe active-going edge delay 0 - 15 cycles. 16 r/w ? 0 by default. 17 r/w ? 0 by default. 31:18 r/o, = 0 unused. No effect was observed from any combination of the comDelay high bits 16 and 17. Maybe they set relations between some delays or sampling edges. Maybe the high bits in the common register are for Wide DMA or outputing/latching adds or outputing addess while in DMA or something related to DMA, or some of the dysfuinctional bits in the individual delay registers? Recovery period: Elongates with commonDelay.3:0 cycles the period after the data bus is released by the IOP (write) (after the added hold period, if any) or after /SRD goes inact.high, to the next active /SRD/SWR pulse or /CS going inactive transition, to give the device more time to release the bus on read or give more bus turnaround time to the next access on write. Hold period: The period after /SWR goes inact.high when the data bus keeps its data valid, necessary for signal propagation and correct latching. The /SWR active.low inter-pulse period will be elongated with commonDelay.7:4 cycles in which after /SWR goes inactive.high the data output from the IOP would still be kept valid. This setting has no effect on /SRD read timing. Floating period: Elongate the /CS (active low) and the inter-/SRD pulses periods after /SRD goes inactive to give the device more time to leave the bus floating after driving it (for slow devices that release the bus slowly). Give the device commonDelay.11:8 cycles more after /SRD goes inactive to the next /SRD pulse or the end of the cycle (/CS -> inact.high), to leave the bus floating. When set to 0, the period /SRD inact.high-going edge to /CS inact.high -going edge is 1/2 cycle and is 1cy between /SRD pulses act.low pulses. This setting has no effect on /SWR write timing. Pre-Strobe period: Delay from the start of data output (and /CS going active.low) to the active.low -going edge of /SRD or /SWR: Shifts the active-going edge of /SWR the commonDelay.15:12 cycles later than it would usually come, so data can be read on the active-going falling edge. If the active period of the act.low pulse is less than this strobe delay, then the inactive periods between pulses are elongated to account for that. The active pulse is shrunk to a minimum of 1cy in this case. /CS act.low-going edge to /SRD or /SWR act-low going edge is of this number of cycles (otherwise = 0). While delayReg./SRD/SWR_act.low_period <= strobePeriod, no change in the total period is done. Pulse active.low period = max((delayReg.act.low_period - strobePer), 1). - at least 1 cy. This has the same effect on both /SRD and /SWR. The two 8-bit accesses in a common /CS access are just an example - they could also be two 16-bit accesses in a 32-bit /CS access, or 4 8-bit accesses in a 32-bit access. _______ _______________ _ _______________ __________ Data from IOP X_______________X X_______________X | valid data | | valid data | |F| |G|J|H| |I| |<----C---->|<-D->|<----C---->| _________| |_____| |____________ /SWR(/SRD) \___________/ \___________/ | 8bit 8bit | _______|A| access access |B|__________ /CS \_________________________________/ | 16-bit access | |<---------------E--------------->| * The period J (old_DATA_valid to new_DATA_valid in a single access) may always be 0, because the IOP switches from the old to the new data immediately (however that still requires some time for data to become certainly valid). D = G+J+H E = A+C+D+C+B The above periods (A-J) are sometimes different for /SRD and /SWR. In case they don't match, they are marked as _R (read) and _W (write). The following periods are also defined: M = /CS inactive pause between RD->RD (two reads) N = /CS inactive pause between RD->WR (a write following a read) O = /CS inactive pause between WR->RD (a read following a write) P = /CS inactive pause between WR->WR (two writes) (Almost) no test were done to determine exactly when the IOP latches input data and whether the settings have any effect on that, as that is too difficult to determine. It is assumed that the IOP latches input data on the rising (inactive.high-going) edge of /SRD. The measurements (in us) below are somewhat inaccurate. The measurements were done in PS2 mode with ~36MHz clock, but the specified values in [cycles] ([cy]) are valid for PS1 mode at ~33MHz as well. The followng measurements were done with example commonDelay register values (0x00001225), but from them one can understand the behavior of the bus for any setting. ########################################### No added delays (strobe, float, hold, recovery): Delay register = 0x000D2077 : /CS inact pause RD->RD M = 3cy 81ns /CS inact pause RD->WR N = 3cy 81ns /CS inact pause WR->RD O = 1cy /CS inact pause WR->WR P = 1cy /CS active Read E_R = 18cy 486ns /CS active Write E_W = 18cy 486ns /SRD active period C_R = (delay+1)cy /SWR active period C_W = (delay+1)cy /SRD inact between 2x8bit D_R = 1cy /SWR inact between 2x8bit D_W = 1cy /CS ->act to /SRD ->act A_R = 0.5cy 12ns /CS ->act to /SWR ->act A_W = 0.5cy 12ns /SRD ->inact to /CS ->inact B_R = 0.5cy 16ns /SWR ->inact to /CS ->inact B_W = 0.5cy 16ns DATA_valid to /SWR_act F = 0 /SWR_inact to DATA_inval. ITM* G = 1cy Bus free over /SWR inact. ITM* J = 0 DATA_valid to /SWR_act ITM* H = 0 /SWR_inact to DATA_inval. I = 2cy 54ns *ITM = Intermediate timing between the two 8-bit accesses in an 16-bit access of a 8-bit device. 32-bit access of 8-bit or 16-bit device should have the same internal timing. The above is usually the case, however some configurations use the ITM for all consecutive writes (not only 16<-8 and 32<-16). It is better to consider the F and G periods relative to ever 'first' access, while the H and I periods - to all the next consecutive accesses in a single CPU read/write. Note that 12ns + 16ns = 28ns - exactly one period. 12ns one half-period of the master clock, while 16ns is the other. The measurements may not be correct - so both can equal 13.5ns. ########################################### Recovery delay enabled Delay register = 0x000D2177 Increases all RECOVERY periods (between every access) to (commonDelay.3:0) 5cy, for devices, which need more time to release the bus or process written data. /CS inact pause RD->RD M = 5cy 135ns /CS inact pause RD->WR N = 5cy 135ns /CS inact pause WR->RD O = 5cy 135us /CS inact pause WR->WR P = 5cy 135us /CS active Read E_R = 22cy 594ns /CS active Write E_W = 22cy 594ns /SRD active period C_R = (delay+1)cy /SWR active period C_W = (delay+1)cy /SRD inact between 2x8bit D_R = 5cy 135us /SWR inact between 2x8bit D_W = 5cy 135us /CS ->act to /SRD ->act A_R = 0.5cy 12ns /CS ->act to /SWR ->act A_W = 0.5cy 12ns /SRD ->inact to /CS ->inact B_R = 0.5cy 16ns /SWR ->inact to /CS ->inact B_W = 0.5cy 16ns DATA_valid to /SWR_act F = 2cy(4cy) 54us(108ns) * /SWR_inact to DATA_inval. ITM* G = 1cy Bus free over /SWR inact. ITM* J = 0 DATA_valid to /SWR_act ITM* H = 4cy 108ns /SWR_inact to DATA_inval. I = 2cy 54ns *Because the minimum inactive period has to equal or be more than 5, on consecutive writes, the 'DATA_valid to /SWR_act' period will be 4cy(rather than 2cy), making the total /SWR inactive period 6cy, and the /CS inactive period - 5cy. *ITM = Intermediate timing between the two 8-bit accesses in an 16-bit access of a 8-bit device. 32-bit access of 8-bit or 16-bit device should have the same internal timing. In this mode, subsequent Write accesses to the one and the same device have the same intermediate timing. This mode is an exception in that subsequent writes to the same device have the intermediate delay(G,H), rather that the end delay(I,F). ########################################### Hold delay enabled Delay register = 0x000D2277 Hold the data on the bus for (commonDelay.7:4) 2cy more, after /SWR goes inactive to make certain that a slow device will latch it correctly. /CS inact pause RD->RD M = 3cy 81ns /CS inact pause RD->WR N = 3cy 81ns /CS inact pause WR->RD O = 1cy /CS inact pause WR->WR P = 1cy /CS active Read E_R = 18cy 486ns /CS active Write E_W = 22cy 594ns /SRD active period C_R = (delay+1)cy /SWR active period C_W = (delay+1)cy /SRD inact between 2x8bit D_R = 1cy 27ns /SWR inact between 2x8bit D_W = 3cy 81ns /CS ->act to /SRD ->act A_R = 0.5cy 12ns /CS ->act to /SWR ->act A_W = 0.5cy 12ns /SRD ->inact to /CS ->inact B_R = 0.5cy 16ns /SWR ->inact to /CS ->inact B_W = 2.5cy 67ns DATA_valid to /SWR_act F = 0.5cy(2cy) 12ns(54ns) * /SWR_inact to DATA_inval. ITM* G = 3cy 81ns Bus free over /SWR inact. ITM* J = 0 DATA_valid to /SWR_act ITM* H = 0 /SWR_inact to DATA_inval. I = 2cy 54ns *On consecutive writes, F will equal 2cy, rather than 0.5cy, making the /SWR inactive period there - 4cy. ########################################### uncertain Floating bus delay enabled Delay register = 0x000D2477 Elongate the /CS or /SRD inactive period after each /SRD goes inactive (commonDelay.11:8) +2cy to give the device more time to release the bus floating. /CS inact pause RD->RD M = 1cy /CS inact pause RD->WR N = 1cy /CS inact pause WR->RD O = 1cy /CS inact pause WR->WR P = 1cy /CS active Read E_R = 22cy 594ns /CS active Write E_W = 18cy 486ns /SRD active period C_R = (delay+1)cy /SWR active period C_W = (delay+1)cy /SRD inact between 2x8bit D_R = 3cy 81ns /SWR inact between 2x8bit D_W = 1cy 27ns /CS ->act to /SRD ->act A_R = 0.5cy 12ns /CS ->act to /SWR ->act A_W = 0.5cy 12ns /SRD ->inact to /CS ->inact B_R = 2.5cy 67ns /SWR ->inact to /CS ->inact B_W = 0.5cy 16ns DATA_valid to /SWR_act F = 0 /SWR_inact to DATA_inval. ITM* G = 1cy Bus free over /SWR inact. ITM* J = 0 DATA_valid to /SWR_act ITM* H = 0 /SWR_inact to DATA_inval. I = 2cy 54ns ########################################### Pre-Strobe delay at the expense of the /SRD /SWR active low pulse (delays only the active-going edge) Delay register = 0x000D2877 Moves the active-going transitions of /SRD /SWR (commonDelay.15:12) 1 cycle later. That way there is an extra cycle of valid data before the active-going strobe edge. Shifts the active-going (H->L) /SRD /SWR edge commonDelay.15:12 cycles later - for devices which latch the data on the inactive-to-active /SWR transition. The /SWR active period is decreased that way, so commonDelay.15:12 cannot be more than (the_write_delay (bits 3:0) + 1). I.e. the A, F and H periods are increased by commonDelay.15:12 and the C periods are decreased with commonDelay.15:12. All other signals remain the same. /CS inact pause RD->RD M = 3cy 81ns /CS inact pause RD->WR N = 3cy 81ns /CS inact pause WR->RD O = 1cy /CS inact pause WR->WR P = 1cy /CS active Read E_R = 18cy 486ns /CS active Write E_W = 18cy 486ns /SRD active period C_R = (delay)cy * /SWR active period C_W = (delay)cy * /SRD inact between 2x8bit D_R = 2cy 54ns /SWR inact between 2x8bit D_W = 2cy 54ns /CS ->act to /SRD ->act A_R = 1.5cy 43ns * /CS ->act to /SWR ->act A_W = 1.5cy 43ns * /SRD ->inact to /CS ->inact B_R = 0.5cy 12ns /SWR ->inact to /CS ->inact B_W = 0.5cy 12ns DATA_valid to /SWR_act F = 1cy /SWR_inact to DATA_inval. ITM G = 1cy Bus free over /SWR inact. ITM J = 0 DATA_valid to /SWR_act ITM H = 1cy /SWR_inact to DATA_inval. I = 2cy 54us *Enables /SRD/SWR commonDelay.15:12 cycles later (strobe-like mode). So 43ns = 16ns (as it usualy is) + 27ns (the cycle taken from the strobe period). Timing diagrams of the SSBUS and relations to the EDO DRAM bus and the ExpansionBay bus. ------------------------------------------------------------------------------- The inactive spike, that appears sometimes in 'the fastest' DMA mode is the /RAS refresh, that needs to be done every 1-2ms per row address combination. The DRAM controller issues it. Transfer (read) from RAM: Data on SSBUS changes while SSCLK_1 is high (on the /CAS H->L transition). While data output from RAM changes on /CAS L->H transition. Data stays on the bus 1cycle. Data that RAM has output on its bus, appears on the SSBUS 1.5cycles later! But, that corresponds to 2cy after the /CAS that triggered the data. The same 'delay' is probably valid for writes to RAM as well. All the timing for a write to RAM is the same for read too. Transfer (write) to RAM: /MWE is held constantly active (low) when writing to RAM in 'the fastest' DMA mode. In write to RAM mode: the first active /CAS (H->L) occurs 81ns (3cy) after DACK and 67ns (2.5cy) after /SRD. /MWE goes active 2cycles (54ns) after /SRD and 2.5cy after DACK. DACK's transition to low occurs while SSCLK_1 is high (not on its transition). /CAS is 90 degrees offset from the SSCLK_1 too - it goes active low on SSCLK_1 high. /CAS goes back high, when (while) SSCLK_1 is low. /SRD goes active, low while SSCLK_1 is low. ------------------------------------------------------------------------------ The following diagrams are 'to-scale' - each character equals 1/4 cycle. This is not true for most of the other diagrams in this document. DRAM and DMA timings: *A /RAS DRAM refresh can occur over a DMA transfer. In that case the transfer is interrupted (DACK, /SRD/SWR), while the refresh takes place. IOP DMA Read from SSBUS device - SSBUS and DRAM timings in the 'fastest' (DMA Timing = 15) DMA mode. _ /RAS \______Goes_inactive_when_it's_time_to_refresh_DRAM ________________________________________________ DACK ___/ _____ /SRD \______________________________________________ _ _ _ _ _ _ _ _ _ _ _ _ _ SSCLK \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ _____________ /MWE \______________________________________ _______________ _ _ _ _ _ _ _ _ _ /CAS \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \ _____________ ___ _______ ___ ___ RAM DATA IN \___/ \___/ \___/ \___/ \___ _________ ___ _______ ___ ___ SSBUS DATA IN \___/ \___/ \___/ \___/ \_______ _______ ___ _______ ___ ___ Exp.Bay.Con. \___/ \___/ \___/ \___/ \_________ |A| B | A Expansion Bay Connector data change to SSBUS data change = 1/2cy B SSBUS data change to DRAM bus data change = 1cy The above seems to be correct, but I really am not sure about anything now, after recording it all.... SSBUS data arrives at DRAM DATA bus 1 cycle later. Dev9 (on SSBUS) outputs data either on SSCLK H->low and it gets delayed so we see it on the very beginning of l->h or it outputs on l->h very fast. IOP DMA Write to SSBUS device - SSBUS and DRAM timings in the 'fastest' (DMA Timing = 15) DMA mode. _ /RAS \______Goes_inactive_when_it's_time_to_refresh_DRAM ________________________________________________ DACK ___/ _____________ /SWR \______________________________________ _ _ _ _ _ _ _ _ _ _ _ _ _ SSCLK \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ _______ _ _ _ _ _ _ _ _ _ _ _ /CAS \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \ ____________ ___ _______ ___ ___ RAM DATA OUT \___/ \___/ \___/ \___/ \___ ___________________ ___ _______ ___ SSBUS DATA OUT \___/ \___/ \___/ \___/ >|\< | |A | |<--B-->| A /CAS active to DRAM DATA out ~1/4cy - depends on DRAM. B /CAS active to SSBUS DATA out = 2cycles. Note that the SSCLK actually precedes all signals by about 1/8-1/4cycles. This delay, introduced by the logic gates, can make measuring the signal offsets very tricky. Data out from IOP SSBUS appears in the end of the L->H SSCLK transition, and /CAS goes low at the same point. RAM output data changes over the SSCLK high, because that is what follows /CAS going active low. IOP data out - write to device: DMA Timing = 0 (Fastest DMA mode that still uses /SRD/SWR as a strobe.) Example data = 0101... ________________________________ DACK ____/ _ _ _ _ _ _ _ _ _ _ SSCLK \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ ______ ___ ___ ___ __ /SWR \___/ \___/ \___/ \___/ ______ _______ ______ IOP DATA \_______/ \_______/ device samples ^ ^ ^ ^ IOP data in - read from device: DMA Timing = 0 (Fastest DMA mode that still uses /SRD/SWR as a strobe.) Example data = 0101... ________________________________ DACK ____/ _ _ _ _ _ _ _ _ _ _ SSCLK \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ ______ ___ ___ ___ __ /SRD \___/ \___/ \___/ \___/ ______ _______ ______ DEV DATA \_______/ \_______/ IOP samples ^ ^ ^ ^