DASD I/O Programming

Now we can look specifically at CCW programming to access DASD devices.  For this discussion I will work with the 3350 device.  The concepts here can be applied to other types of DASD devices.  The reason I am using the 3350 is because this device is natively supported in MVS 3.8 and does not require any additional usermod support.  It is also the device I have used the most over the years.

In programming for DASD devices we have to think about how the devices were originally constructed.  There were a series of round platters stacked on about the other.  There was an access arm the contained read/write heads with one head for each platter.  The arm could move inward and outward from the center of the platter to the outer edge in specific increments.  Each of these increments defined a circular track at some offset on the platter.  The collection of tracks (one for each platter) made up a cylinder.  If you are not familiar with this concept there are sevearl sources of documents that explain it better using pictures.

With a basic understanding of the structure of the DASD device we can understand how a specific location (data record) is referenced.  Each track has a unique address that consists of a two byte cylinder address and a two byte head address.  These addresses are fixed by the physical layout and construction of the device.  Each track may contain a variable number of data records based on the size of the records and the size of the track.  Therefore to identify a specific record we have an address in the form CCHHR (2 byte cylinder address, 2 byte head address, 1 byte record address).

Each track contains some special records that are created when the device is formatted and normally there is no need to accees them.  These include the Home Address (HA) and Record Zero.  Data records begin with record number one.

The 3350 has 555 cylinders.  Each cylinder has 19 tracks (heads).  Each track has a maximum capacity of 19,069 bytes.  This infomation will be needed when writing CCWs to access the device.  This will be different for different types of DASD devices.

To read a specific record we have to first position the heads to the correct cylinder this is done with the SEEK command.  The command code for SEEK is X’07’ and it expects six bytes of data containing the seek address in the format 00CCHH where 00 is two bytes of binary zeros, CC is the two byte cylinder address and HH is the two byte head address.

SEEKCCW  DC    X'07',AL3(SEEKADDR),X'40',x'00',AL2(6)
            :
            :
*                  C C H H 
SEEKADDR DC    X'0001000001'    Cyl=256, H=1

This CCW command would cause the heads to be positioned at cylinder 256 and select the head for track one.  Notice that the X’40’ flag bit is set indicating Command Chaining.  Simply seeking to a specific cylinder would not accomplish much so we need to follow up with additional CCW commands to actually do something useful.  Setting the Command Chain bit tells the channel that another CCW immediately follows this one.

When using EXCP to access a DASD device we don’t issue a SEEK command.  In fact MVS will prevent us from issuing a SEEK command.  This is because there are usually multiple datasets contained on a DASD volume.  MVS keeps us from reading or writing to areas of the device we are not authorized to access.  We will quickly review how this is accomplished.

Each dataset is made up of one or more extents.  An extent is a set of contiguous tracks or cylinders.  The VTOC is a special file on each volume that keeps track of where datasets are located.  This information is maintained in a Dataset Control Block (DSCB).  The DSCB has a list of the extents that make up the dataset.  Open processing reads the DSCB and uses the extent information to build the DEB.  The DEB is contained in protected storage and can not be modified by a non-authorized user.

When an EXCP request is submitted for a DASD device MVS gets the seek address from the IOB, validates it against the DEB to verify it is contained within an extent of the dataset.  If the seek address is not contained within a valid dataset extent the request is rejected.  If the seek address is valid then MVS builds a SEEK CCW using the IOB seek address.  A SET FILE MASK CCW is then chained on to the SEEK CCW.  The SET FILE MASK specifies what types of CCW commands may follow.

         DC    X'1F',AL3(FILEMASK),X'40',x'00',AL2(1)         --- Set File Mask CCW
             :
             :
FIELMASK DC  X'file-mask-bits'

File Mask
00......  - Do not allow Write Home Address and Write Record Zero
01......  - Do not allow any write commands
10......  - Do not allow Write Format commands
11......  - Allow all write commands
...00...  - Allow all Seek commands
...01...  - Allow Seek Cylinder and Seek Head commands 
...10...  - Allow Seek Head commands
...11...  - Do not allow Seek commands or head switching
......0.  - Do not allow Diagnostic Write commands
......1.  - Allow Diagnostic Write commands
.......0  - Not PCI Fetch mode
.......1  - PCI Fetch mode
..0..0..  - Must always be Zero

There may only be one SET FILE MASK command in a CCW sequence. This keeps the user CCW program from accessing tracks outside the dataset extents. It also enforces read-only for datasets opened for input.  The users CCWs follow the SET FILE MASK command.

Once the correct cylinder and head have been selected by the SEEK command we need to position for the record we wish to read or write.  This is done with a SEARCH command.  To understand how to use SEARCH we have to understand the physical layout of the track.

As we said earlier the track always begins with two special records, the Home Address and Record Zero.  Data records are made up of three components, the count, the key, and the data area.  The key is optional an may be omitted.  The count is always required.  It is made up of 8 bytes in the format CCHHRKDL.  CC is the cylinder number, HH is the head, R is the record number, K is the length of the key area, and DL is two-byte length of the data area.  If the key length is zero then there is no key area for the record.  If the key length and data length of the block are both zero the record is an end of file indicator.

+---+---+---+---+---+---+---+---+ 
| C   C | H   H | R | K |  DL   |
+---+---+---+---+---+---+---+---+

Below is the layout of a track. The track begins at the Index Point which physically identifies the beginning of every track. Immediately following the index point is the Homa Address (HA).  The Home Address contains track information and is used to indicate if an alternate track is in use.  Alternate tracks are special reserved tracks used to replace a defective track.  A special record called Record Zero (R0) is always present immediately following the Home Address.  R0 does not contain any user data but is part of the standard track formatting.  It is necessary to allow track positioning using the SEARCH CCW command.  The HA and R0 are written using special CCW commands when the volume is formatted.  There is not normally any reason to read or write these special records.  User data begins with Record One (R1) and may be followed by additional user records.  An empty track contains only the HA and R0.

[IX] [HA] [R0-CKD] [R1-CKD] [R2-CKD] ... [Rn-CKD]

When setting our position around a track (a position to a specific record) we use the SEARCH CCW command.  The SERACH command compares the serach value (specified by the SRARCH CCW) against the next record that passes the read heads.  If there is not a match the CCW completes normally.  If the values to match the CCW completes but also sets the Status Modifier bit in the CSW.  This tells the channel that a match has occured and causes the channel to skip over the next CCW immediately following the SEARCH.  This allows us to set up a loop in our channel program to locate the desired record:

        CCW   SEARCH
        CCW   TIC,*-8
        CCW   READ

In this example we have three CCW commands. The first is a SEARCH followed by a Transfer In Channel (TIC) CCW. A TIC is an unconditional branch in a channel program. The address portion of the TIC CCW points to the next CCW to be executed by the channel. In this case the TIC will branch back to the SEARCH (*-8 refers to the previous CCW since each is eight bytes in length). When we start this channel program the first CCW executed is the SEARCH. If the search does not match then the channel will fall through to the next command, a TIC that branches back to the SEARCH. This will be repeated until the SERACH matches a record on the track at which point the channel will skip the command immediately following the SEARCH (in this case the TIC) and the READ CCW will be executed by the channel to read the selected record.

We do have to deal with the situation where the SEARCH never matches. In this case the Status Modifier bit will never be set and it would appar that we would be in a infinite loop that never ends. The loop is broken when the dasd device detects two Index Points during an uninterrupted search CCW sequence. By the time the Index Point has passed the read heads twice the deivce knows that every record on the track has been checked at least once. When this happens the CCW is terminated abnormally and the Unit Check bit is set in the CSW. This causes the channel to end the current program.

There are two types of SERACH commands, one searches by ID which is the CCHHR in the count area.  The othter type searches by key data contents.  Both of the types search for either an equal condition, high condition, or a equal or high condition.  The following table shows the results of various combinations of the SEARCH ID CCW in relation to a record.  The values are in the format CC-HH-R. (The SEARCH ID command may search for R0).


Search CCW Value | Count Area for Record | ID Equal | ID High | ID Equal or High
--------------------------------------------------------------------------------
   01-01-3       |      01-01-1          |  False   |  False  |      False
   01-01-3       |      01-01-3          |  True    |  False  |      False
   01-01-3       |      01-01-4          |  False   |  True   |      True

There are also three SEARCH KEY commands (key equal, key high, key high or equal) that compare the search contents of the CCW against the data in the key area of the record.

When we indicated what happens when two Index Points are encountered is true for the normal SEARCH commands but there is a second type of each of the SEARCH commands that are Multi-Track commands.  If the SEARCH is a multi-track request and the end of the track is reached (two Index Points encountered) the device will switch to the next head and continue the search.  This allows an entire cylinder to be searched using one CCW program and an single I/O request.  If the end of the last trrack of a cylinder is detected and the search has not been satsified the CCW terminates with the Unit Check bit set in the CSW.  It is important to note that the multi-track CCWs can only be used if allowed by the settings in the SET MASK instruction that preceeded the SEARCH.  MVS sets the authorization in the SET MASK based on how the dataset was allocated.  If it was allocated in cylinders then MVS will allow SEEK HEAD and Multi-Track operations.  If the dataset was allocated in tracks then SEEK HEAD and Multi-Track operations are not allowed so that the user program can never access tracks not belonging to the data set.

Below are the various CCW command codes for the SEARCH commands:


   CCW Command     Normal  Multi-Track
Search ID Equal      31         B1
Search ID High       51         D1
Search ID Eq/High    71         F1

Search Key Equal     29         A9
Search KEY High      49         C9
Search KEY Eq/High   69         E9

Now one thing we do have to consider is which record to search for.  If we want to read or write the Key  or Data area of a record we search for the ID of the record we want to access.  If we want to read or write the Count area we must position based on the ID of the previous record.  This is because once the device has read the count area for a Search ID equal the count area for that record is now past the read/write heads.  So if we want to read the Count, Key and Data area for record number two we would have to do a search ID for record number one.  If we just want to read the Data area for record number two we would do a search for record number two.  This can get a little confusing but it does make great sense when you consider what is physically happening on a dasd device.  Using Hercules we need to think in terms of how an actual 3350 device was constructed and how it operated since that behaviour is emulated.

Here are additional CCW Command Codes for accessing dasd devices:


   CCW Command     Normal  Multi-Track
Read Count           12         91
Read R0              16         96
Read Data            06         86
Read Key & Data      0E         8E
Read CKD             1E         9E
Read Multiple CKD    5E

Write CKD            1D         -
Write Data           05         -
Write Key & Data     0D         -

Erase                11         -