Command SubSystem

From OSDev Wiki
Jump to navigation Jump to search

The command subsystem is responsible of handling command programs and routing programs and actions to specific devices. It works as if it was a big device which has DMA.

The CSS uses chains of commands instead of a sequential execution: it uses multiple commands at once instead of only one command at a time (ex. in x86, I/O bound instructions can only output 1 element at a time).

The execution of CSS commands is sequential. The commands are executed in the order they appear.

CSS addresses are real, this means that all addresses are physical and are not bound to the current virtual space.

Command words

There are 2 types of command words, the first is used by S360 for SIO/TIO set of instructions, these can be considered mostly obsolete. The second format is more modern and is actively used in most Z11 and z/Arch machines.

// Format 0 Control Command Word
struct css_ccw0 {
  uint8_t cmd;
  uint16_t lo_addr;
  uint8_t hi_addr;
  uint8_t flags;
  uint8_t reserved;
  uint16_t count;
} __attribute__((packed));

// Format 1 Control Command Word
struct css_ccw1 {
  uint8_t cmd;
  uint8_t flags;
  uint16_t count;
  uint32_t addr;
} __attribute__((packed));

Command types

SEEK (0x07)

Address points to a BBCCHH field (that is, 1 unused halfword, 1 halfword denoting cylinders and another halfword denoting heads). The count should be the size of the BBCCHH (6)

SEARCH (0x31)

This will perform a search on the disk (something akin to a seek, but done on the track); Address points to a CCHHR field (that is, 1 halfword denoting cylinders, 1 halfword denoting heads and a character denoting record number). The coount should be the size of the CCHHR (5)

Transfer In Channel (0x08)

Jumps to the address field if an error occurs during a SEARCH on the DASD - when the operation is sucessful this command is skipped. TIC will loop infinitely when SEARCH fails, when the DASD detects that it has read the entire track it will abnormally exit the channel program.

Read key and Data (0x0E)

Address is used to point to the destination buffer and length is used to denote the length of data to read.

Enable (0x27)

Used mostly by telnet terminals to request them to be enabled (start listening/activate send mode).

Examples

Start Channel

Starts the execution of an ORB which will be executed on the given device.

// cc=0 - operational
// cc=3 - not available/device was taken off
int css_start_channel(
    struct css_schid schid,
    struct css_orb *schib)
{
    register struct css_schid r1 __asm__("1") = schid;
    int cc = -1;
    __asm__ __volatile__(
        "ssch 0(%1)\n"
        "ipm %0\n"
        : "+d"(cc)
        : "a"(schib), "d"(r1), "m"(schib)
        : "cc", "memory");
    return cc >> 28;
}

Store Channel

// cc=0 - operational
// cc=3 - not available/device was taken off
int css_store_channel(
    struct css_schid schid,
    void *schib)
{
    register struct css_schid r1 __asm__("1") = schid;
    int cc = -1;
    __asm__ __volatile__(
        "stsch 0(%2)\n"
        "ipm %0"
        : "+d"(cc), "=m"(*schib)
        : "a"(schib), "d"(r1)
        : "cc", "memory");
    return cc >> 28;
}

Modify Channel

Modify channel parameters.

// cc=0 - operational
// cc=3 - not available/device was taken off
int css_modify_channel(
    struct css_schid schid,
    struct css_schib *schib)
{
    register struct css_schid r1 __asm__("1") = schid;
    int cc = -1;
    __asm__ __volatile__(
        "msch 0(%2)\n"
        "ipm %0"
        : "+d"(cc), "=m"(*schib)
        : "a"(schib), "d"(r1)
        : "cc", "memory");
    return cc >> 28;
}

Test Channel

Usually used to obtain the status of a device after an execution/action.

// cc=0 - operational
// cc=3 - not available/device was taken off
int css_test_channel(
    struct css_schid schid,
    struct css_irb *schib)
{
    register struct css_schid r1 __asm__("1") = schid;
    int cc = -1;
    __asm__ __volatile__(
        "tsch 0(%2)\n"
        "ipm %0"
        : "+d"(cc), "=m"(*schib)
        : "a"(schib), "d"(r1)
        : "cc", "memory");
    return cc >> 28;
}