.* To print this document on the 3800, say SCRIPT86 ICATS .* To print this document on the 6670, say 6670C ICATS .im myprof .hy off .dh 1 noj npa :gdoc sec='IBM Internal Use Only' :frontm :titlep :TITLE.ICATS Functional Specification :title.*** Final Version *** :date.September 26, 1983 :author.Rick Jasper :address :aline.A68-861 :aline.San Jose, CA :eaddress :etitlep :toc :body :h1.Scope .sk .il 5 This is the fourth draft of the "ICATS Functional Specifications" and is an expansion of, and obsoletes, the first three drafts. The ICATS project is complete (unless Jeff dreams up something else he wants added like reading in files from the reader) and, as with most projects, has developed and changed quite a bit since its original conception. Included in this revision are :ul :li.explanation of the virtual terminal support to the UTS, :li.available console commands. :li.source code format for files to and from the UTS, :li.other minor technical errors corrected. :eul .* .sk .il 5 The ICATS virtual machine is a service machine, servicing the users of a UTS machine from a 370 VM system. This document will explain how to maintain and use the ICATS virtual machine. The intent of this paper is threefold, to explain ICATS's purpose and capabilities, to detail each function and its use, and to show how to manage the ICATS configuration. As of this writing, both the software and hardware development are done and ICATS has been operational and stable for a few months. This paper is the authoritative source regarding function details and data format. .* :H1.ICATS VIRTUAL MACHINE OVERVIEW .* .sk .il 5 The ICATS virtual machine (hereafter referred to as simply ICATS) is a virtual machine running under the VM operating system on a 370 computer. It is written in 370 assembler language and runs under CMS as a normal user program. Its purpose is to serve requests from users of one or more UTS machine, like :ul :li.take this data I'm sending you and write it to a file on my CMS minidisk, :li.send me a file I've got stored on my CMS minidisk, :li.allow me to log on to the UTS machine from this VM terminal, :li.or what time is it? :eul .* .sk .il 5 ICATS is automatically logged on when VM is originally IPL'ed on the 370 computer. Once logged on, ICATS starts itself and waits until it receives an interrupt from a DIALable terminal or a request. A request can be received in any one of three different ways; :ul :li.from an ATTENTION interrupt from any of the UTS machines it it servicing, :li.from somebody logged onto the ICATS virtual machine under VM and entering something from its console, :li.or from a special message (SMSG) from another virtual machine under VM. :eul When a terminal interrupt comes in, ICATS passes that interrupt on to whichever UTS that terminal is "plugged into." Likewise, once a request is received, ICATS awakens and services that request. When ICATS finishes with its current task, it looks to see if any other task came in while it was busy servicing this one. If so, it services the new request. Otherwise, it waits again for a new request. .* :h2.Multitasking, or Lack Thereof .* .sk .il 5 ICATS is a relatively simple-minded program. Although ICATS can service multiple terminals and multiple UTS machines, it can only handle one request from any source at a time. There is no multitasking of service requests. In other words, ICATS does not start servicing another request until the current request is completely finished. However, if ICATS is busy with one request and receives another, it "remembers" it, and services the second request when it finishes with the first. This isn't a serious restriction however, because all of ICATS's requests are short. They either work quickly or fail quicker, so this lack of multitasking should not be missed. Also, there cannot be multiple requests from the same UTS machine. One UTS machine must not initiate another request until any previous request it has made, is completely serviced. This requirement is to just keep things simple, and its fulfillment is dependent upon the UTS software. .* :h2.Configuration .* .sk .il 5 There's a CMS file on the ICATS 191 disk that is used to configure the ICATS virtual machine upon start up.:fnref refid=foot1.:fn id=foot1 I also considered having a command that rereads this configuration file and dynamically reconfigures, but I never implemented it. It wouldn't be that difficult to add, but I don't feel it's really necessary. It's so easy right now to shut ICATS down, update the ICATS CONFIG file, and restart ICATS. Total down time is a couple of minutes. :efn .* This configuration file specifies things like :ul :li.how many UTS machines ICATS is to service,:fnref refid=foot2.:fn id=foot2 Currently, ICATS is servicing only one UTS. The program however, is designed to handle multiple UTS machines. Although it's never been tested, I believe any realistic number of UTS machines could be put on the same system and serviced by the same ICATS virtual machine. :efn :li.what their addresses are, :li.the number of DIALable terminals ICATS is to handle, :li.the UTS users for each UTS machine, :li.the CMS minidisks for each user, :li.and the passwords for each minidisk. :eul See the next chapter for an example ICATS configuration. This CONFIG file is a simple EBCDIC CMS file that is easy to maintain and change. All one needs to do to change the ICATS configuration in some way is to LOGON to ICATS, stop the ICATS program if it's running, make the changes to the ICATS CONFIG file with some editor, and restart the ICATS program. .* :h2.ICATS Functions .* .* --- QUIT TRACE TEST FAKIT RESTART STATUS .* --- CAT READ TIME WRITE TERMIO .sk .il 5 Each request, regardless of where it comes from, invokes some function of ICATS. Not all functions are valid from every source, though. For example, QUIT is only allowed from the console. Currently, the ICATS functions are QUIT, TRACE, TEST, FAKIT, RESTART, STATUS, CAT, READ, TIME, WRITE, and TERMIO. I have thought of more that would be nice to have (like SEND, PRINT, or RECONFIG) and people will undoubtedly dream up of more yet. ICATS is designed with this probable expansion in mind. New ICATS functions are fairly easy to create, integrate into the software, debug, and modify. See the chapter on the ICATS functions for details on each function. .* :h2.Protocol For UTS-Initiated Requests Between ICATS and the UTS Machine .* .sk .il 5 Requests from the console or from SMSG's are straightforward enough. From the console, one merely types in a command and gets a response using normal CMS macros. From another virtual machine, one uses the CP command SMSG, and receives a message back from the ICATS virtual machine. Communication between the UTS machines and ICATS however, is a little more complex. Refer to figure 2.1. To initiate a request, the UTS machine causes an interrupt to the 370 CPU with the Attention bit on in the CSW. ICATS sees this attention interrupt and knows there is a UTS that needs servicing. .* .sk .il 5 When ICATS gets around to servicing the request, he issues a START I/O with a CCW op code of X'06' (Read Modified), length of 128 (8-bit) bytes:fnref refid=foot3.:fn id=foot3 .* Throughout this paper, when I use the term "byte", I'm referring to an 8-bit quantity. The term "word" refers to 4 bytes (32 bits). There might be some confusion because each address in a UTS main memory holds 16 bits, so one might be tempted to call a byte, 16 bits, or a word, 16 bits. I'm not. My byte is 8 bits, my word is 32 bits. :efn to the requesting UTS machine. The UTS then ships over a 128-byte request control block. This request control block contains the UTS user's ID, the function desired, and whatever other information is required for that function. If that function requires further I/O to the UTS machine (for example, a WRITE request would need another SIO to get the data to write to the CMS file), the CCW op code used is X'02' (Read). .* .sk .il 5 When ICATS finishes with the request, another SIO is done to the UTS machine, with a CCW op code of X'01' (Write) and a length of 128 bytes or more, depending on whether or not there is any data following the reply control block (the byte count of the data following the reply control block if any, is imbedded in the reply control block). .* .sk .il 5 Figure 2.1 shows this sequence graphically. A request is initiated by a UTS. ICATS gets the request control block and interprets it. If need be, ICATS does another SIO to get some data, then he services the request. Afterwards, ICATS sends a reply control block and again waits until another request comes in. .* :line65 .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | UTS MACHINE ICATS/370 %------------------------------@------------------------------ | | | | | | . | | | | . | | | | . | | | | WAIT | | | | . | | | | . | | | | . | | | Attention | Interrupt . | | #----------------+---------------> | | WAIT (I want some | work done) | | | . | | | | . | | | | . SIO | X'06' | | | %<---------------+----------------$ | | | Send | Request WAIT | | #----------------+---------------> | | WAIT (What do | you want ?) | Interpret | | . | | Request | | . | | | | . Optional | SIO X'02' | | | %<---------------+----------------$ | | | Send File | Data WAIT | | #----------------+---------------> | | WAIT | | Service | | . | | Request | | . | | | | . | | | | . | | | | . | | | | . | | | | . SIO | X'01' | | .TR & EC | .<---------------+----------------& | .TR & & | . Send Reply | and Data | | | %<---------------+----------------$ | | | (Here's what | I did) WAIT | | | | . | | | | . | | | | . | | | | . | | | | . | | | | . | | | | . | | | | #------------------------------*------------------------------$ .* .TR - -;.TR % %;.TR * *;.TR ;.TR > >;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sk 2 :hp2. Figure 2.1. Communication Protocol between the UTS machine and ICATS. :ehp2. Time is shown vertically. .kp off :line6 .* :h2.Logging On To The UTS Machine Through ICATS .* .sk .il 5 The UTS machine supports 327X terminals as console devices. Since the communication link to the UTS was there and VM of course, supports 327X terminals, we decided to use VM terminals to log on to the UTS machine. Modeled after VM's PASS-THROUGH (a.k.a. PVM), "virtual terminals" came into being. After clearing away the VM logo from the screen, you can enter "DIAL ICATS" and get a menu similar to PVM's menu. All you do is move your cursor to the UTS you wish to log on to and hit enter, and from then on, it's as if your terminal is "plugged into" that UTS. There's even a facility similar to PVM's four pound signs ("####") to get back to the menu by entering four dollar signs ("$$$$"). The "virtual terminal" facility has probably been the most tangible and impressive function for showing off the ICATS project. .* .sk .il 5 Once a terminal gets "plugged into" a UTS, further interrupts from that terminal get passed on to that UTS. The communication sequence for this, since it's initiated by ICATS and not by the UTS, is different than that for normal ICATS requests. For real terminals, a typical interaction would be an interrupt comes in from the terminal, its buffer is read, and a new screen is written. The way this is accomplished for virtual terminals is :ol :li.To pass the interrupt on to the UTS, ICATS does a SIO with a CCW op code of X'05' (write modified) for 128 bytes. Those 128 bytes, which are similar to the request and reply control blocks, specify which terminal is causing the interrupt and its CSW status. The UTS knows that since this is a write modified, it represents an interrupt from a terminal and not any of the other I/O sequences, like read request control block, send file data, or write reply control block. .* :li.Sometime later, in a normal ICATS request sequence, the UTS requests a SIO to be done to that terminal (via the TERMIO function). This SIO might be to do a read modified, a read buffer, or whatever. The data from the 327X gets transferred, and :li.sometime later still, the UTS would come back with another terminal I/O request to write an updated screen. :eol Terminal I/O, of course, doesn't have to follow this sequence, this is just an illustrative example. This terminal interaction took three distinct steps, the first of which was initiated by ICATS. The actual terminal I/O (if any) is initiated by the UTS in the normal fashion. .* :h1.ICATS Example Configuration .* .sk .il 5 This section will go through an example configuration of UTS machines, ICATS minidisks, UTS users, DIALable terminals, and the configuration file required to define it. This configuration file is a normal CMS file residing on ICATS's 191 minidisk which, as are all files on ICATS's A-disk, should not be made generally available to UTS users for transfer or manipulation. The configuration file contains records defining the physical hardware configuration of the UTS machines and the 370 computer, the user community under each UTS machine, and the accessible minidisks for each user. This file is read once upon initial bring up of the ICATS virtual machine and from then on, ICATS is guided by the information that was in the file at that time. .* :h2.What's Out There Imagine, for our example, this hypothetical configuration (see figure 3.1). On SJEVM2, we have two UTS machines, let's name them UTS#1 and UTS#2 (such original names). Both UTS machines are on channel 0, UTS#1 has device address 020 and UTS#2 is 080.:fnref refid=foot4.:fn id=foot4 .* It's no coincidence that both UTS addresses end with zero. The current implementation of the Dobbox (Jeff Dobbek's control unit) only works for the lowest address in its address range. The box takes up eight addresses on the channel, but only responds correctly to the first address. Jeff says this will be fixed in the next version. The ICATS software doesn't care, it'll work with any address. :efn Let's also say that there's one project group using UTS#1, code named ENTERPRISE, and there's two projects using UTS#2, code named CAPTAIN and JLA. For our purposes, these three projects are completely independent and, except for CAPTAIN and JLA sharing the same UTS, have nothing at all to do with one another. We also want ICATS to service up to 3 DIALable terminals. .* .sk .il 5 Let's further suppose that besides the system programmer, SPOCK, there are two users on the ENTERPRISE project, KIRK and SULU. Each user will need access to their own private disk, the common project disk, and to the UTS system source disk. KIRK, being the project leader, will have control over the common project disk. .* .sk .il 5 Our second UTS machine, UTS#2, has two projects using it, CAPTAIN and JLA. The CAPTAIN project has two users, AHAB and KIRK. Notice that the user named KIRK under the CAPTAIN project is completely separate from the user with the same name under the ENTERPRISE project. Even though they have the same user ID, they are distinguishable because they are on different UTS machines. The JLA project has three users, FLASH, BATMAN, and ROBIN. SPOCK, of course, needs a user id on this system as well. .* .sk .il 5 Let's see what the configuration file for our example looks like. See figure 3.2. Afterwards, I'll go through each type of statement in the file and explain the different options. .* :line65 .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR > EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | TERMINALS 370 COMPUTER (SJEVM2) ICATS' MINIDISKS %--- %-------------------------------- %--- %--- %--- %--- |100| | VM | |190| |191| |19E| |200| #---$ | | #---$ #---$ #---$ #---$ %--- | %-------------- | %--- %--- %--- %--- |101| | | ICATS | | |201| |202| |203| |210| #---$ | | | | #---$ #---$ #---$ #---$ %--- | #------%------$ | %--- %--- %--- %--- |102| | || | |220| |221| |222| |223| #---$ | || | #---$ #---$ #---$ #---$ #---------------><---------------$ %--- %--- %--- || |230| |238| |5FF| .TR > > 370 CHANNEL 0 --------->|| #---$ #---$ #---$ .TR > EC || ---------------------------><---------------------------------------------- UTS MACHINES || %--------------------$#-------------------- |%----------------------------------------| || || || || %-----$#----- %-----$#----- .TR # # | UTS#1 | | UTS#2 | .TR # AB | | | | #------------$ #------------$ ENTERPRISE: CAPTAIN: KIRK AHAB SULU KIRK JLA: FLASH BATMAN ROBIN .* .TR - -;.TR % %;.TR * *;.TR ;.TR > >;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sp 2 :hp2. Figure 3.1. Example UTS Configuration: :ehp2. Figure shows the ICATS virtual machine under VM, its DIALable terminals, its associated minidisks, and the two UTS machines it is servicing. Also shows the code names of the projects using each UTS and the user ID's for each project. .kp off .* :line6 .* .* :line65 .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR > EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | %----------------------------------------------------------------------- .TR # # .TR * * |* ICATS CONFIGURATION FILE FOR SJEVM2 (1-28-83) | |TERM 100 | |TERM 101 | |TERM 102 | |UTS UTS#1 020 020 ENTERPRISE PROJECT | | USER SPOCK 33 SYSTEMS PROGRAMMER | | DISK B 210 POINTY EARS PERSONAL DISK | | DISK H 200 ALL 3DCHESS ICATS#1 SYSTEM DISK| | DISK I 220 ALL LOGICAL ICATS#2 SYSTEM DISK| | USER KIRK 26 PROJECT LEADER | | DISK B 201 BEAM DOWN PERSONAL DISK | | DISK C 202 PHASOR KLINGON SHARED PROJECT DISK| | DISK H 200 ALL NONE ICATS#1 SYSTEM DISK| | USER SULU B5 | | DISK B 203 KARATE WATCHOUT PERSONAL DISK | | DISK C 202 PHASOR NONE SHARED PROJECT DISK| | DISK H 200 ALL NONE ICATS#1 SYSTEM DISK| |* | |UTS UTS#2 080 080 CAPTAIN AND JLA PROJECTS | | USER SPOCK 33 SYSTEMS PROGRAMMER | | DISK B 210 POINTY EARS PERSONAL DISK | | DISK H 220 ALL LOGICAL ICATS#2 SYSTEM DISK| | DISK I 200 ALL 3DCHESS ICATS#1 SYSTEM DISK| | USER AHAB 60 CAPTAIN PROJECT LEADER| | DISK B 221 WHITE WHALE PERSONAL DISK | | DISK C 222 BOSSES PEGLEG SHARED PROJECT DISK| | DISK H 220 ALL NONE ICATS#2 SYSTEM DISK| | USER KIRK 4A | | DISK B 223 ESL PROJECT PERSONAL DISK | | DISK C 222 BOSSES NONE SHARED PROJECT DISK| | DISK H 220 ALL NONE ICATS#2 SYSTEM DISK| |* | | USER FLASH 21 JLA PROJECT LEADER | | DISK B 230 SPEEDY KEN PERSONAL DISK | | DISK H 220 ALL NONE ICATS#2 SYSTEM DISK| | USER BATMAN 9 | | DISK B 238 BATCAVE BRUCE PERSONAL DISK | | DISK H 220 ALL NONE ICATS#2 SYSTEM DISK| | USER ROBIN 69 | | DISK B 238 BATCAVE DICK PERSONAL DISK | | DISK H 220 ALL NONE ICATS#2 SYSTEM DISK| .TR # AB .TR * CB #-----------------------------------------------------------------------$ .* .TR - -;.TR % %;.TR * *;.TR ;.TR > >;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sp 2 :hp2. Figure 3.2. Sample ICATS Configuration File: :ehp2. Figure shows the ICATS configuration file for the example UTS configuration described in this section. This file exists on ICATS' 191 minidisk (its A-disk) and is in fixed length, 80-character format. .kp off :line6 .* :h2.The ICATS Configuration File .* .cp 9 :h3.Comment Statements .* .sk .il 5 Any line in the configuration file starting with an asterisk in column one is considered to be a comment statement and is ignored. This is handy for documenting the configuration file or to delete statements be simply "commenting" them out. Also, you can add comments on any of the other statements after the required fields. .* .cp 8 :h3.The TERM Statement .* .sk .il 5 The TERM statements in the configuration file are used to identify the number and addresses of the DIALable terminals ICATS is to handle. In our example, we want ICATS to handle up to three terminals, so there are three TERM statements. The fields in the TERM statements are :ul :li.the keyword "TERM". This defines this line to be a TERM statement. :li.terminal virtual address. This is not the terminal's real address of course, since it could be any terminal under VM. Rather, it's this terminal's address as it will be known by the ICATS virtual machine and later, to the UTS machine it will be "plugged into." These addresses should be on channel 1 (1XX). This is because that's how the UTS software distinguishes between a real terminal and one that's coming through ICATS. :eul .* .cp 8 :h3.The UTS Statement .* .sk .il 5 The UTS statements in the configuration file are used to identify the various UTS machines the ICATS virtual machine is to handle. In our example, there are two UTS machines so there are two UTS statements. The fields in the UTS statements are :ul :li.the keyword "UTS". This defines this line to be a UTS statement. :li.UTS unique identifier. This field is used to distinguish this UTS from other UTS machines ICATS is servicing. :li.Real device address of this UTS machine. :li.Virtual device address of this UTS machine. This is in case of a UTS machine occupying say, real address 01F, the virtual address of ICATS' virtual printer. This field tells ICATS to attach the UTS machine to himself as this address. Since there are no address conflicts in our example, each UTS machine is defined as its real address. :eul .* .cp 8 :h3.The USER Statement .* .sk .il 5 The USER statement simply identifies the UTS user ID of each user on this particular UTS. It also serves to group the following DISK statements together and associate them to this UTS user. Again, notice that the user KIRK on UTS#1 is completely different than the user KIRK on UTS#2. One has nothing to do with the other and is not even aware of the other's existence. You cannot, however, have two users identically named on the same UTS machine. For example, you cannot have a KIRK on the CAPTAIN project on UTS#2 and a different KIRK on the JLA project on the same UTS. One of them must be renamed. The fields of the USER statement are :ul :li.the keyword "USER". This defines this line to be a USER statement. :li.User id. Each user id can be up to 8 characters long. :li.User's encoded machine type. This is a hexadecimal number that is this user's encoded machine type down at the UTS. Don't ask me what an "encoded machine type" is. If you don't know either, ask Jeff Dobbek. :eul .* .cp 8 :h3.The DISK Statement .* .sk .il 5 The DISK statements are the backbone of the configuration file. It is in these statements that the view a UTS user perceives of the minidisks available to him is defined. Referring back to Figure 3.1, we see that even though the ICATS virtual machine has 15 minidisks defined, each UTS user sees, and has access to, only those that are defined for him in the configuration file. For example, the user KIRK on UTS#1 has access to 3 of ICATS's minidisks, 200, 201, and 202. KIRK does not have access to the other 12 minidisks (191, 208, 210, etc) and doesn't even know that they exist. The password fields of this statement are to provide some security among UTS users. These passwords are not to be confused with other CP passwords like LOGON passwords, or minidisk passwords. The passwords in these DISK statements are completely separate from CP and are seen only by the ICATS software. The fields of the DISK statement are :ul :li.the keyword "DISK". This defines this line to be a DISK statement. :li.UTS user's virtual disk identifier. This is what the UTS user uses to refer to this particular disk. When doing anything with this disk, ICATS will access it with this access mode, then do the read or write. For this reason, don't use the letters 'A', 'S', 'U', or 'Z'. ICATS has his own minidisks at these addresses that he needs. :li.ICATS real minidisk address. :li.Read password. A password of "ALL" means that password checking is not done so no password need be supplied. A password of "NONE" means that no password is valid. "NONE" probably wouldn't be used as a read password unless you wanted the disk to be write-only (kind of like write-only memory). :li.Write password. "ALL" or "NONE" could be specified here as well and "NONE" makes more sense as a write password, effectively making this a read-only disk. :eul .* .sk .il 5 Here is how disk accesses are made. When KIRK on UTS#1 says to read a file from his B-disk, a quick table look up is done to determine that the ICATS 201 minidisk is the disk he is referring to. When SPOCK refers to his B-disk, the ICATS 210 minidisk is used. When the other KIRK on UTS#2 refers to his B-disk, the ICATS' 223 minidisk is used. Thus, everybody can have their own personal B-disk or even share a B-disk as in the case of BATMAN and ROBIN. Notice that disks can be shared in a variety of ways. Group disks might be shared on a read-only basis to some users in a group, and kept read/write to group leaders (refer to the ICATS 202 and 222 disks). Or, a disk containing source code might want to be shared by all users on a UTS-wide basis as in the case of ICATS's 200 and 220 minidisks. Also notice that minidisks can be shared across systems as in the case of SPOCK on UTS#1 and UTS#2. This might be the system programmer in charge of all the UTS source, and so has access to multiple UTS systems and would need read/write access to all the system disks. This scheme allows for the greatest flexibility in allocating disk space for UTS machines and UTS users. .* :h1.Generic Request Control Block and Reply Control Block Formats .* .sk .il 5 The request control blocks for each ICATS function all share a common format (see figure 4.1). There are 16 8-byte fields for a total of 128 bytes. The first ten of these 8-byte fields have a meaning common for all functions, the other six fields are for parameters peculiar to the particular function. Not all functions use each of the first 10 fields (TIME, for example, only uses the second field). The unused fields can have anything in them but should be left blank in case that field becomes meaningful at a later date. All fields in the request control block are in EBCDIC, even the all-numeric fields like the number of bytes to transfer (the only exception is the TERMIO request control block). All fields are left justified, padded with blanks on the right. See the next chapter on how the request control block is used for each function. .* .sk .il 5 The fields of the request control block are described below. :ul :li.The "UTS User ID" is the field that must match a USER statement in the configuration file, else this request is rejected with a return code of X'4004'. The only exceptions are those functions that aren't user oriented, like TERMIO or TIME. :li.The "ICATS Function" field defines the service being requested (WRITE, READ, TIME, CAT, etc.). ICATS functions are described in chapter 5. If this field (with the required trailing blanks) does not match one of the known ICATS functions, this request is rejected with a return code of X'1000'. :li.The "ICATS Subfunction" is an optional field depending upon the function selected. Currently, only the WRITE function uses this field. :li.The "Number of Bytes to Transfer" is either the CCW byte count in the X'02' CCW ICATS gives the UTS to get the data (as in a WRITE request), or the maximum number of data bytes the UTS can handle (as in a Read request - i.e. don't send more than this many bytes). :li.The "File Name", "File Type", and "File Mode" fields are the standard CMS file identifiers. The File Mode is one character long, and must be in the first byte of the seventh field. :li.The last byte of the seventh field is a pad character. The pad character is used to pad a small record that must be converted to a larger sized fixed length, or to pad an odd length CMS record that is to be shipped down to the UTS in variable-length format (since variable-length UTS record lengths must be even). Most of the times the user will want his records padded with blanks but if he wants them padded with X'00' for example, he has the facility to change the pad character. :li.The "Write or Read Password" is the password required when writing to or reading from one of ICATS' minidisks. :eul .* :line65 .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR & EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | %------------------------------- %------------------------------- | UTS User ID | ----> | UTS User ID | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | ICATS Function | ----> | ICATS Function | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | ICATS Subfunction | | Next ICATS Subfunction | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Number of Bytes to Transfer | ----> | Number of Bytes to Transfer | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | File Name | | Actual File Name Used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | File Type | ----> | File Type | <---+---*---*---*---*---*---+---& <---+---*---*---*---*---*---+---& | FM| not used |Pad| ----> | FM| not used |Pad| <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Write or Read Password | ----> | Write or Read Password | <---+---*---*---*---*---*---*---& <---+---*---*---*---*---*---*---& |URF| not used | ----> |URF| not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | UTS LRECL if Fixed Length | ----> | UTS LRECL if Fixed Length | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Starting Record Number | | Next Starting Record Number | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | Free | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Day of Week in MM/DD/YY Format| <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& .tr & : | not used | | Time in HH&MM&SS Format | .tr & EC <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Free | <---*---*---*---*---*---*---*---& <---*---+---*---*---*---*---*---& .TR # # | not used | |RetCode| # Data Bytes Following| .TR # AB #---*---*---*---*---*---*---*---$ #---*---*---*---*---*---*---*---$ .* .TR - -;.TR % %;.TR * *;.TR ;.TR & &;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sp 2 :hp2. Figure 4.1. Standard Generic Request Control Block and Reply Control Block Format: :ehp2. Each line represents 8 bytes. The arrows between the two control blocks mean that this parameter is copied over to the reply control block unchanged. Most of the time this is the case, but sometimes fields are changed. See the next chapter for details. .kp off :line6 .* :ul :li.The "UTS Record Format" is the format the UTS user sees the data in, either "F" for fixed-length records, "V" for variable-length records, or "S" for source records. For example, if this is a read request, the output is in the format specified in this field regardless of whether the CMS file is in that format or not. If this is a write request, the data the UTS is shipping up is in that format, and the resulting CMS file, if it's a new file, will also be in that format. See the discussion on each of the three formats in the next chapter under the write command. :li.If the UTS Data Format specifies fixed-length records, this field contains the logical record length (LRECL) or the record blocking factor. This blocking factor does not necessarily have to be equal to the CMS file's LRECL. If, for example, the UTS user wants to read a fixed, 60-byte CMS file and wants it in fixed 80-byte format, each record will be padded with 20 of the pad characters. :li.The "Starting Record Number" field is used for read requests and direct access write requests only. Blanks, zeros, or a one here will all start with the first record. A two will skip the first record and start with the second. :eul .* .sk .il 5 The reply control block is, for the most part, an unchanged copy of the request control block. Depending on the function however, some fields may be modified. The twelfth and thirteenth 8-byte fields are used by some functions to return the current date and time in the same format as the TIME function. The fourteenth field in the reply control block is used by some functions to return some informational data not directly requested. See the READ and WRITE functions for details. The last field will .us always be changed to show the return code (used to determine what, if anything, went wrong) and the number of bytes of data that follow this reply control block (which could be zero). The data in these last two fields, unlike everything else in the request and reply control blocks, is in hexadecimal, not EBCDIC. So, when I say the return code is zero, it will be two bytes of hex zeros (X'0000'), not two bytes of EBCDIC zeros (X'F0F0'). .* .sk .il 5 The function of the reply control block is twofold. One, to tell the UTS machine the result of the function he requested, and two, to use as the next request control block. For example, assume a user on a UTS machine has a big file he wants written on his CMS minidisk. Since the file is so big, it must be written in two steps. The first request control block might request the WRITE and Replace function. The reply control block coming back from this WRITE request will have the subfunction field changed to APPEND since, if the UTS user is going to continue to write to this file, he will probably want to append the new data, not write over the data he just got through writing. This reply control block can be examined to insure that the first write went O.K. and then used as the request control block for the second write. Likewise, if he's now reading that big file, the first request control block would say READ, starting with the first record. Let's say he read the first 250 records, the reply control block would have 251 for the starting record number since, if he's going to continue reading, that's where he would want to start the next read from. .* .sk .il 5 The return code in the reply control block will be a 16-bit hexadecimal number. Return codes are uniform throughout the ICATS system, regardless of which ICATS function is used. That means that return codes will always have the same meaning. For example, a return code of X'1000' always means that this is an invalid ICATS function and X'1010' always means you supplied the wrong password. The first 8 bits will give the class of error that occurred, the last 8, the particular error inside that class. The different error classes which are arranged in order of severity, are :ul :li.X'0000' - X'0FFF' = None, expected, or only a minor error occurred. :li.X'1000' - X'1FFF' = Invalid parameter found in request control block. :li.X'2000' - X'2FFF' = Miscellaneous error. :li.X'3000' - X'3FFF' = UTS or terminal I/O error. :li.X'4000' - X'4FFF' = Configuration file error. :li.X'5000' - X'5FFF' = CMS detected error. :li.X'6000' - X'6FFF' = "Should never happen" errors. Logically impossible. :li.X'7000' - X'5FFF' = Program detected error. Should also never happen. :li.X'8000' - X'FFFF' = Unused. :eul .* .sk .il 5 Any data shipped down to the UTS machine will be prefixed by a reply control block. Inside this reply control block will be a count field telling the UTS machine how many (8-bit) bytes of data were shipped over in this I/O operation. The data, if any, will directly follow the reply control block. The last 6 bytes in the reply control block is this count. The count will be a hexadecimal number and will .us not include the 128 bytes for the reply control block itself. So, if there is no data following the reply control block, the count will be zero. If there's 1000 bytes of data following the reply control block (1128 bytes transferred in all), the count will be 1000 (X'0000000003E8'). .* :h1.ICATS Functions - Detailed Description .* .* --- QUIT TRACE TEST FAKIT RESTART STATUS .* --- CAT READ TIME WRITE TERMIO .sk .il 5 The eleven ICATS functions (QUIT, TRACE, TEST, FAKIT, RESTART, STATUS, CAT, READ, TIME, WRITE, and TERMIO) are described below, along with a functional description of what happens when each is invoked, the input specifications, the output description, and the possible return codes for each function. .* :h2.QUIT .* .sk .il 5 The QUIT command is only valid from the console. It is used to shut ICATS down and return to CMS. One should use the STATUS command before shutting down to see if anybody is using ICATS. The format for the QUIT command is simply, .fo off QUIT .fo on There are no parameters and Q is the abbreviation for QUIT. .* :h2.TRACE .* .sk .il 5 ICATS keeps an internal trace table that records various events in the ICATS virtual machine. The TRACE command turns this tracing on or off, and is only valid from the console or from an SMSG. The format for the TRACE command is .fo off TRACE | T <? | ON | OFF> .fo on The abbreviation for TRACE is T. TRACE ? will tell you whether tracing is being done right now or not and, if entered from the console, will tell you the addresses of the beginning, next entry, and end of the trace table. Use the command #CP D Txxxxx.xxx to see the trace table entries. The trace table entries are prefixed by an 8-byte hex time stamp, but the rest is in EBCDIC to make for easy reading. TRACE ? is the default if you just say TRACE. Normally, ICATS comes up with tracing off. .* :h2.TEST .* .sk .il 5 The TEST command is only valid from the console. The ICATS program has 96 test flags available that produce messages under various circumstances. The TEST command queries these flags or turns them on or off. The messages produced by the test flags are useful for program debugging and are not for general use. The format for the TEST command is .fo off TEST <nn | ALL> <? | ON | OFF> .fo on There is no abbreviation for TEST. NN is a number from 1 to 96. TEST ALL ? is assumed if you just enter TEST. Normally, ICATS comes up with all the test flags off. As of this writing, the test flags get you the following messages from the following modules; :ol :li.READ - BYTE COUNT THUS FAR IS nnn, NUMWANTS IS STILL nnn. :li.READ - RECORD NUMBER nnn IS nnn BYTES BIG. . :li.WRITE - MVCL TO aaaaaa, LENGTH = nnnn. FROM aaaaaa, LENGTH = nnnn. :li.WRITE - I'M GOING TO WRITE nnnn BYTES STARTING AT aaaaaa. :li.WRITE - THE FILE JUST WRITTEN WAS fn ft fm. :li.WRITE - AFTER nn RECORDS, THE RETURN CODE IS nn. :li.READ - DONE FOR NOW. RETURN CODE = nn, # BYTES TRANSFERRED = nnnn. n. # COMPLETED RECORDS = nnnn, # COMPLETED BYTES = nnnn. # BYTES YOU WANTED = nnnn, UTS LRECL = nnn, STARTING RECORD # = nn. THE PAD CHAR WAS HEX xx AND THE BIGGEST RECORD I FOUND WAS nn. BUFFER ENDS AT aaaaaa. END OF FILE WAS <NOT> HIT. LAST RECORD IS <NOT> INCOMPLETE. :li.WRITE - THIS IS RECORD # nn IN THIS BLOCK AND THERE'S nnn BYTES LEFT TO DO. :li.UTSIOIH - IGNORING THIS UTS INTERRUPT. CSW STATUS = xxxx. :li.TERMIOIH - GOT A TERMINAL INTERRUPT FROM aaa, CSW STATUS = xxxx. :eol The rest of the test flags are not assigned. .* :h2.FAKIT .* .sk .il 5 The FAKIT command is only valid from the console or via an SMSG. Out of necessity, since the software was developed before the hardware was available, I developed a means of testing the software be faking an attention interrupt from the UTS. Once the attention interrupt got faked, the program would go through it's normal code for whatever function got requested. All I/O for the duration of this request however, is also faked. The request control block is read from the file ICATS REQUEST A. Any data "read" from the UTS is read from ICATS INDATA A. Any data "written" to the UTS is written to ICATS OUTDATA A. The format for the FAKIT command is .fo off FAKIT <xxx> .fo on XXX is a optional hex address of which UTS address to fake the attention interrupt from (the default is the first UTS). The abbreviation for FAKIT is F. Generally, this setup works quite well for testing new functions or for seeing what gets sent to the UTS for a given input. .* :h2.STATUS .* .sk .il 5 The STATUS command is valid from the console or from a SMSG. It's used to see what's been going on in the ICATS virtual machine. The format for the STATUS command is .fo off STATUS .fo on There is no abbreviation for STATUS. The STATUS command tells you which terminals are being used, which UTS they're "plugged into" or that they're looking at a menu right now, and the time of their last interrupt. It will also tell you which UTS machines are offline or the time of their last interrupt. The STATUS command was intended to be used just prior to shutting down ICATS to see whether or not it is being used. .* :h2.RESTART .* .sk .il 5 The RESTART command is used to bring online those UTS machines that are currently offline. When ICATS first starts up, it tries to vary on and attach each UTS machine. If the UTS machine doesn't respond, it's considered to be offline. The RESTART command instructs ICATS to try again to get those offline UTS machines. The RESTART command is valid from either an SMSG, the console, an online UTS, or from a DIALed terminal. The format for the RESTART command from the console or an SMSG, is simply, .fo off RESTART .fo on There are no parameters and there is no abbreviation. .* .sk .il 5 From the menu on a DIALed terminal, position the cursor under an offline UTS and hit the enter key. ICATS will know that that UTS is offline and try to get it online. If it succeeds, you will be "plugged in" to that UTS. If not, you'll be told that ICATS failed to get it online. .* .sk .il 5 From a UTS machine, the request control block needs only the ICATS function field (the second 8-byte field) to specify RESTART. The return code in the reply control block will always be zero, as will the Number of Data Bytes Following. .* :line65 :h3.RESTART Request and Reply Control Blocks .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR & EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | %------------------------------- %------------------------------- | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | R E S T A R T | ----> | R E S T A R T | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---+---*---*---*---*---*---+---& <---+---*---*---*---*---*---+---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---+---*---*---*---*---*---*---& <---+---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---+---*---+---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---+---*---*---*---*---*---& .TR # # | not used | |RetCode| # Data Bytes Following| .TR # AB #---*---*---*---*---*---*---*---$ #---*---*---*---*---*---*---*---$ .* .TR - -;.TR % %;.TR * *;.TR ;.TR & &;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sp 2 :hp2. Figure 5.3.RESTART Request and Reply Control Blocks :ehp2. The return code and the number of data bytes following in the reply control block will always be hex zeros. .kp off :line6 .* :h2.WRITE .* .sk .il 5 Write requests can come from another user via an SMSG (what I'll call SMSG writes) or from a UTS machine (UTS writes). All write requests write data to a CMS file onto one of ICATS' minidisks. For SMSG writes, the file is copied from one of the requestor's minidisks. For UTS writes, the data comes from a separate SIO operation (that is, separate from the SIO's for the request and reply control blocks). This separate SIO will have one CCW with an op code of X'02' (Read). The data length for this one CCW will be specified by the "Number of Bytes to Transfer" field in the request control block. .* .sk .il 5 Write is a very powerful function. An SMSG write only works one way - it copies a whole file from the requestor's minidisk onto one of ICATS's disks, overlaying the old copy if there was one. For UTS writes though, there are five different ways to write to the CMS file and three different formats the input data can be in. You can write the whole file, rewrite any one record or a block of records, or append records to the CMS file. If a file already exists with this file name, you can choose to abort this write request, rewrite the file, or write the data to a new file with a different file name. The data can be fixed-length, variable-length, or in UTS source code format. The five different kinds of writes are, .* :ol :li.:hp2.Create.:ehp2. If you say to write the file TEST DATA B and a file already exists with that name, then this Write request is aborted. The original TEST DATA B file is left undisturbed. .* :li.:hp2.Replace.:ehp2. If you say to write the file TEST DATA B, and a file already exists with that name, that file is first erased and a new TEST DATA B file is then written with the transferred data. If the file TEST DATA B does not already exist, then the file TEST DATA B is created. .* :li.:hp2.Increment the Version Level.:ehp2. If you say to write the file TEST DATA B and the file TEST DATA B already exists, then ICATS will change the file name to TEST000 and create the file TEST000 DATA B with the new data. If the files TEST DATA B and TEST000 DATA B both exist, then the data will be written to the file TEST001 DATA B. If TEST, TEST000, and TEST001 all exist, TEST002 will be used; et cetera, until an unused file name is found. This gives the UTS user 1001 file names (TEST, TEST000-TEST999) to go through until this write request cannot be serviced. The reply control block I send back to the UTS machine will inform the UTS user of the actual file name used. See the paragraph on the next page for more details on the file name search order. This method of writing was designed for those times where you want this data saved and you cannot stand to resend it if there's an error. For example, if some test is collecting data every hour and sending it up to VM, you would probably want to do the write by this method. Besides avoiding the conflict of duplicate file names, the data will be in separate files. So if anything should go wrong, it only affects one hours' testing. .* :li.:hp2.Append.:ehp2. The data that gets transferred is appended to the already existing CMS file. If the file does not already exist, the request is treated as a create and a new file is created. .* :li.:hp2.Direct Access.:ehp2. The file is presumed to already exist, and the data is to replace the records starting at the specified record number. For example, if the file TEST DATA B is 75 80-byte records large, and you say to write 240 bytes starting at record 49, then record numbers 49, 50, and 51 get replaced with the new data. The starting record number must be less than the total number of records in the file plus one. The CMS file must be a fixed-length file, else the Write request will be rejected. Writing in the middle of variable-length CMS files is not supported. :eol .* .sk .il 5 The search order ICATS goes through to find an unused file name for the increment the version level write is first, try the original file ID. If the original file ID is being used by another file, then change the file name by appending three zeros and see if that file ID is being used. If so, then continue to increment the three zeros in the file name until either a free file ID is found or it goes past 999. The reason I chose to use three zeros instead of some other number is because file names on the UTS are only five characters long. That leaves three positions to get up to CMS's eight character limit. So a file can have identical file names on the UTS machine and on VM, with just the last three characters being a version level number. If the original file name is shorter than five characters, the three zeros are appended after the last character. If longer, they overlay the sixth through eighth characters. Here are some examples; .sk;.fo off;.cp 16 Original .ti ^ 05;.tb 14 .usFile Name^File Name Search Order .sk .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR & EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB A A, A000, A001, .... A999 TEST TEST, TEST000, TEST001, .... TEST999 ATEST ATEST, ATEST000, ATEST001, .... ATEST999 TESTDATA TESTDATA, TESTD000, TESTD001, .... TESTD999 ||| ||| #**-------***- The "ATA" gets overlayed. TEST000 TEST000, TEST0000, TEST0001, .... TEST0999 | | #--------*- This '0' does not get incremented. ATEST000 ATEST000, ATEST000, ATEST001, .... ATEST999 | | #--------*- Yes, ATEST000 is checked twice. No biggy. ATEST123 ATEST123, ATEST000, ATEST001, .... ATEST999 | | #------------------------*- Yes, ATEST123 is checked twice. .TR - -;.TR % %;.TR * *;.TR ;.TR & &;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .* .sk .il 5 The first three types of writes will always create a new CMS file. Append writes may, if the file does not already exist, create a new file. Direct access writes will never create a new file. If the CMS file already exists, its file characteristics (record format and logical record length) are already fixed, they cannot be changed. If the CMS file is going to be created, then its file characteristics will have to be specified. The file characteristics for new CMS files shall be determined by the characteristics of the input data. If the input data is in either variable-length or source code format, then the new CMS file will be variable-length. If it's in fixed length format, then the CMS file will also be fixed length and have the same LRECL as the input data. .* .sk .il 5 File names on the UTS may start with a cent sign (), but the CMS file system does not like cent signs. Therefore, if a WRITE request ever specifies a cent sign as the first character of the file name, ICATS will substitute a pound sign. For example, if you say to create a file with a file name of 'TEST', then ICATS will write a file with a file name of '#TEST'. Likewise, if you say to read 'TEST', ICATS will read '#TEST'. .* :h3.SMSG Write Request Format .sk .il 5 To write a file from your VM signon, to one of ICATS's minidisks, enter the CP command .fo off SMSG ICATS WRITE fn ft yda ydrp utsid userid ud udwp .fo on where :ul :li."SMSG ICATS WRITE" tells ICATS that you want to copy a file from your disk to one of his. :li.fn ft is the file name and file type as the file sits on your disk now. This will also be the file name and file type when the file gets copied onto ICATS's disk. :li.yda is your disk address. This is .us not the file mode of your minidisk (i.e. 'A'). Rather, this is its address (e.g. '191'). :li.ydrp is the read password for your minidisk. This is the password CP needs when ICATS links to your disk to read the file. :li.utsid is the UTS unique identifier that distinguishes this UTS from other UTS machines ICATS is servicing. This is the second parameter on the UTS statement in the ICATS CONFIG file. :li.userid is the UTS user id to identify which disk you wish to write on. This is the second parameter on the USER statement in the ICATS CONFIG file. :li.ud specifies which of this user's disks you want to write on. This is the second parameter on the DISK statement in the ICATS CONFIG file. :li.udwp is the write password for this user's disk. This is the fifth parameter on the DISK statement in the ICATS CONFIG file. :eul .* .sk .il 5 Basically, what ICATS does when doing an SMSG write, are these three commands. .fo off CP LINK vmuserid yda 5FF RR ydrp ACCESS 5FF Z COPYFILE fn ft Z = = ud ( REPLACE .fo on You can see why 'yda' must be your disk address ('191'), not your disk access mode ('A'), because ICATS has to LINK to your minidisk. This also explains why ICATS needs your disk read password ('ydrp') and why 5FF is a reserved ICATS minidisk address (see figure 3.1). As you can also see from this method of writing, you can only write from a disk that your virtual machine owns. For example, if I'm logged on to VM as JASPER and link to another disk by saying, .fo off CP LINK DOBBEK 191 222 ACCESS 222 B .fo on then I won't be able to write to an ICATS disk from what is now my 222 disk, because ICATS will try to do the link to JASPER's 222 disk and JASPER doesn't have a 222 disk defined in his directory entry. What I would have to do is to copy the file over to my A-disk and then do the SMSG write from my 191 disk. .* :line65 :h3.WRITE Request and Reply Control Blocks .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR & EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | %------------------------------- %------------------------------- | UTS User ID | ----> | UTS User ID | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | W R I T E | ----> | W R I T E | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | subfunction | | next subfunction | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Number of Bytes to Transfer | ----> | Number of Bytes to Transfer | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | File Name | | Actual File Name Used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | File Type | ----> | File Type | <---+---*---*---*---*---*---+---& <---+---*---*---*---*---*---+---& | FM| not used |Pad| ----> | FM| not used |Pad| <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Write Password | ----> | Write Password | <---+---*---*---*---*---*---*---& <---+---*---*---*---*---*---*---& | Input Format | ----> | Input Format | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | LRECL if Fixed-Length Input | ----> | LRECL if Fixed-Length Input | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Starting Record Number if DA | | Next Starting Record Number | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Day of Week in MM/DD/YY Format| <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& .tr & : | not used | | Time in HH&MM&SS Format | .tr & EC <---*---*---*---*---*---*---*---& <---+---+---*---+---*---+---*---& .TR # # .TR " | | not used | |F"V| | LRECL |# RCDS |Biggest| <---*---*---*---*---*---*---*---& <---*---+---*---*---*---*---*---& | not used | |RetCode| # Data Bytes Following| .TR # AB .TR " " #---*---*---*---*---*---*---*---$ #---*---*---*---*---*---*---*---$ .* .TR - -;.TR % %;.TR * *;.TR ;.TR & &;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sp 2 :hp2. Figure 5.1.WRITE Request and Reply Control Blocks :ehp2. .kp off :line6 .* .cp 8 :h3.Input Specification .* .sk .il 5 The request control block has these required fields; :ul :li.UTS User ID. :li.ICATS Function ('WRITE'). :li.ICATS Subfunction. This will be 'CREATE', 'REPLACE', 'INCRVL', 'APPEND', 'DA', or blank (defaults to 'CREATE'). :li.Number of Bytes to Transfer. This number is the number of bytes the UTS user is going to send to ICATS to write to the CMS file. :li.File Name, File Type, and File Mode. :li.Pad Character. If input records must be expanded to a larger fixed-length LRECL, this character will be used to pad the trailing portion of the record. :li.Write Password. This is the write password for this UTS user for this minidisk. :li.Input Format. The input data can be in one of three formats, fixed-length, variable-length, or source code format. See the next paragraph for details on the format of each. This field designates which format the input will be in. Only the first letter of this field is checked and must be the letter 'F', 'V', or 'S'. :li.LRECL if Fixed-Length Input. If the input is going to be fixed-length, ICATS will need to know the blocking factor, or LRECL, of the input. This field will be that LRECL. :li.Starting Record Number. If this is a Direct Access Write request, this field tells ICATS which record number in the CMS file to start writing at. A zero or one will start writing at the start of the CMS file, a two will start at the second record, etc. If this field specifies a number that is larger than the number of records plus one, an error is recognized and the write operation is aborted. Specifying a starting record number equal to the number of records currently in that CMS file plus one, appends the data to the end of that file. :eul .* .sk .il 5 Input data from the UTS:fnref refid=foot5.:fn id=foot5 .* This discussion applies as well to data sent to the UTS from a READ request. If the UTS user specifies the data to be shipped in variable-length format, the CMS file data will be converted to the variable-length format described here. If source code format is requested, then ICATS packages the CMS file data into the required 1740-byte blocks. :efn can be in one of three different formats, fixed-length, variable-length, or source code format. Fixed-length format is simply each record blocked back-to-back. The input is solid data and the blocking factor (also known as record length or LRECL) is given in the request control block. .* .sk .il 5 Each record in variable-length format however, is prefixed by a 2-byte length field. This length field specifies the length of this record divided by two. In other words, if a record is 10 characters long, its length field will be X'0005'. As you can see, all record in UTS variable-length format will have an even length. There are three anomalies with the length field. :ul :li.The high order bit of the length field is used to indicate a "tabbed" record. The tab is six blank characters. For example, if the length field of a record is X'8005', its true length is .fo off 6 + (2*5) = 16 bytes .fo on and it has six leading spaces. When this record is written to a CMS file, those six leading spaces will be placed in the record. However, when this record is read by the UTS user, ICATS does .us not take out those six spaces, they are left in. Data shipped to the UTS user in variable-length format will never have the "tabbed" bit on. :li.X'0000'. A length field of all zeros is an end-of-file marker. There's no more data belonging to this file. If X'0000' is encountered in the middle of variable-length input data, the rest of the data is ignored. An end-of-file marker is put in variable-length output if the end of the CMS file is encountered. :li.X'FFFF'. A length field of all ones is an end-of-block marker. There's no more data in this data transmission. If X'FFFF' is encountered in the middle of input data, the rest of the data is ignored. An end-of-block marker is put in variable-length output if the last record in the CMS file was not read. :eul .* .sk .il 5 UTS source code format is how source code is kept on the UTS. A UTS source code file consists of one or more 1740-byte blocks. Each 1740-byte block consists of a 10-byte header of 4 fields, 1710 bytes of variable-length data as described above, and a 20-byte trailer consisting of 5 fields and 10 bytes of hex zeros. When writing to a CMS file, ICATS takes the data from each 1740-byte block, ignores the header and trailer (except for the "number of data bytes in this block" field), and writes the records to the CMS file. When reading, ICATS takes the records from the CMS file, packs them into 1710-byte blocks of variable-length data, appends the header, and tacks on the trailer. The fields inside each 1740-byte block are as follows, .fo off .cp 11 Number Bytes Field Name Field Description 1 Encoded Machine This single hexadecimal digit is the same Type field as on the USER statement in the ICATS CONFIG file. It is ignored on a write and filled in with the value on the USER state- ment for this user on a read. 5 File Name This five-byte EBCDIC field is the file name this file is known as, on the UTS. It is ignored during a write (since the file name is given in the request control block) and is filled in with the first five characters of the CMS file name during a read. 2 ?????? This two-byte field is x'F900'. I don't know what its purpose is, so it's ignored on a write and filled in with x'F900' on a read. 2 Number of Data This two-byte hexadecimal number is a count Bytes In This of the number of bytes of data in the records Block in this block, including lengths, divided by two. For example, if there were only three 20-byte records in this block, then this field would contain x'0021' (3*(2+20)/2). This field is used during a write to get only valid record data, and is properly filled in during a read. 1710 Record Lengths As many complete records that can fit are put and Data in these bytes, in variable-length format. Each record is prefixed by a 2-byte length field as described above. The rest of this field is padded with hex zeros. 2 Block Sequence This hexadecimal field specifies the sequence Number number of this block in this file. It will be x'0001' for the first block of the file, x'0002' for the second, x'0003' for the third, etc. This field is ignored on a write operation and filled in on a read. The only time this field would need to be corrected by the UTS software, is after a read starting from the middle of the CMS file. 2 Number of Records This field gives the number of records that In This Block are in the 1710-byte data area in this block. 2 Number of Data This field is a duplicate of the fourth field Bytes In This in this block by the same name. Block 2 Next Block This hexadecimal field is the sequence number Sequence Number of the :hp1.next:ehp1. block. It will simply be one plus this block's sequence number. This field is ignored on a write operation, and correctly filled in on a read (except as described above, after a read from the middle of the CMS file). 2 Number of Lines This hexadecimal field is the count of the Before This Block number of records :hp1.before:ehp1. this block. Since there are no records before the first block, this field in the first block will be x'0000'. This field in the second block will be the number of records in the first block. This field in the third block will be the sum of the number of records in the first two blocks. This field is ignored during a write operation and correctly filled in during a read. 10 Unused This field is unused and ignored during a write. It is set to all hex zeros during a read operation. .fo on .* .cp 5 :h3.Output Specification .* .sk .il 5 The reply control block is a duplicate of the request control block except for the subfunction, the file name, the starting record number, and the last 32 bytes. The modified fields in the reply control block are; :ul :li.Subfunction. ICATS makes an educated guess at what the next request, if any, will be. Assuming the UTS user will continue to write to this CMS file, the next subfunction will probably be APPEND. That is what is put in the subfunction field of the reply control block. The one exception is if this was a Direct Access Write. Then the next request will probably be another Direct Access Write, so the subfunction field is left unchanged. .* :li.File Name. This field is modified only if this was a Write and Increment the Version Level and ICATS had to increment the version level in the file name to write the file. This field notifies the UTS user of the actual file name ICATS used to write the CMS file. .* :li.Starting Record Number. In keeping with the philosophy of making the reply control block usable as the next request control block, this field is changed (Direct Access Write only) to point to the record following the last record that was written this time. .* :li.Today's date and Time of Day. This is the current date and time in the same format as in the TIME function. .* :li.CMS File Record Format. The next 8 bytes contain information on the CMS file just written. This one-byte field will be the character 'F' or 'V' depending on whether the CMS file has fixed or variable length records. This is the only field of the last 16 bytes to be in EBCDIC, all the rest are in hexadecimal. .* :li.CMS File LRECL. This field will be the logical record length if the CMS file is fixed length, else it's variable length and this field is the longest record now in the file. .* :li.Number of Records in the CMS File. .* :li.Biggest Record Found in the Input Data. If an input record gets truncated to fit into a fixed-length CMS file, that fact will not be reflected in the return code. The return code will still be zero. Instead, the UTS user can compare the CMS File LRECL with this field. If this field is larger than the CMS File LRECL, then he knows that truncation has occurred. .* :li.Return Code. See the next section for possible return codes. .* :li.Number of Data Bytes Following. There is never any data following the reply control block of a Write request, so this will always be zero. :eul .* .cp 8 :h3.WRITE Return Codes .* Return Code :dl tsize='11' :dt.X'0000' :dd.All went O.K. There were no detected errors. The input data ended exactly at the end of a record, an end-of-block marker (X'FFFF'), or an end-of-file marker (X'0000'). .* :dt.X'0004' :dd.An end-of-block marker (X'FFFF') or an end-of-file marker (X'0000') was found in the input data before the end of the input data was reached. Only data up to this point in the input data was written to the CMS file, the rest was ignored. Other than that, everything went O.K. .* :dt.X'0008' :dd.The last input record was incomplete and padded. This would happen when we've run out of input data before completing the last record. You didn't send enough data. The record .us was written to the CMS file, but ICATS is just warning you that maybe something went wrong at your end. .* :dt.X'1000' :dd.Invalid ICATS function. The second field of the request Control block is not a known ICATS command. Possibly you don't have it left-justified, or padded with blanks, or not all in upper case. .* :dt.X'1004' :dd.Invalid "Number of Bytes to Transfer". The third field of the request control block is not a valid EBCDIC decimal number, or it's zero. .* :dt.X'1008' :dd.Invalid File ID. Either the file name or file type (or both) violates the rules for a valid CMS file ID. File names and file types must be 1-8 characters. Valid characters are A-Z, 0-9, $, #, and @. .* :dt.X'100C' :dd.Invalid File Mode. There is no such disk for this user defined in the configuration file. Verify the file mode in the request control block. .* :dt.X'1010' :dd.Incorrect Write password given. .* :dt.X'1014' :dd.Invalid Starting Record Number. The starting record number in the request control block is not a valid EBCDIC, decimal number. This can only happen with a Direct Access Write. See also Return Code X'200C'. .* :dt.X'1018' :dd.Invalid LRECL. The logical record length in the request control block for this fixed-length input data is not a valid EBCDIC, decimal number or it is zero. .* :dt.X'101C' :dd.Invalid Subfunction specified. The third field in the request control block is not a valid Write subfunction. Possibly you don't have it left-justified, or padded with blanks, or not all in upper case. .* :dt.X'2004' :dd.You do not have write access to this disk. The write password for this user for this disk is 'NONE', meaning it is a Read only disk. .* :dt.X'2008' :dd.The CMS file does not exist. This can only happen with the Direct Access Write. .* :dt.X'200C' :dd.The Starting Record Number is too big. It is bigger than the number of records in this CMS file plus one. This can only happen with the Direct Access Write. See also Return Code X'1014'. .* :dt.X'2010' :dd.This variable-length input data ended right in the middle of the length field for the last record. Nothing was written for the last record. .* :dt.X'2014' :dd.You tried to do a Direct Access Write into a variable-length CMS file. Direct Access Writes are only supported with fixed-length CMS files. The CMS file is left unchanged. .* :dt.X'2018' :dd.All file names used. You tried to do a Write and Increment the Version Level, and ICATS could not find an unused file name. For example, you said to write the file TEST DATA, and the files TEST DATA, TEST000 DATA, TEST001 DATA, TEST002 DATA, ..... TEST999 DATA already exist on that minidisk. .* :dt.X'201C' :dd.File already exists. You said to Write and Create, and a CMS file already exists with that file name and file type. .* :dt.X'4004' :dd.No such UTS user for this UTS. Possibly you don't have it left-justified, or padded with blanks, or not all in upper case. If that's not it, then check to insure that that user is in the configuration file for that UTS. .* :dt.X'4008' :dd.No minidisk exists at that address. The address specified in the configuration file for this disk for this user does not exist or is not a CMS minidisk. Check the ICATS virtual machine configuration. .* :dt.X'400C' :dd.You tried to do a Write to a minidisk that is a Read only minidisk for the ICATS virtual machine. Either the configuration file is in error or the ICATS virtual machine is not getting set up correctly. .* :dt.X'5004' :dd.Unexpected error with the CMS command ACCESS. :dt.X'5008' :dd.Unexpected error with the CMS macro FSSTATE. :dt.X'500C' :dd.Unexpected error with the CMS macro FSOPEN. :dt.X'501C' :dd.Unexpected error with the CMS macro FSERASE. :dt.X'5020' :dd.Unexpected error with the CMS macro FSWRITE. .* :dt.X'5024' :dd.This minidisk is full. As much of the data as we could was written to the CMS file, but some data (maybe all of it) was lost. .* :dt.X'6004' :dd.UTS was not found in UTSCB chain. :dt.X'600C' :dd.Unexpected error with the CMS macro FSPOINT. :dt.X'7004' :dd.Unexpected return code from the ACCESS routine in the ICATS mainline program. :edl. .* End of Write Return Code list .* :h2.READ .* .sk .il 5 Fortunately, the read function is a whole lot simpler than the write. The read function is used to read data from a CMS file and ship it to the UTS machine. Read requests can only come from a UTS machine. The UTS user specifies the CMS file id, the maximum number of bytes he wants, and the format he wants it in, and the file is shipped down to him. If the end of the CMS file is reached before the maximum number of bytes is reached, then only that number of bytes are shipped to the UTS and the byte count is given in the reply control block. The UTS user should ask for as much of the file as he can handle at a time, which would probably be the whole file. But if the file is really huge or his buffer space really small, then he could ask for the file n bytes at a time. .* :line65 :h3.READ Request and Reply Control Blocks .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR & EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | %------------------------------- %------------------------------- | UTS User ID | ----> | UTS User ID | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | R E A D | ----> | R E A D | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Number of Bytes to Transfer | ----> | Number of Bytes to Transfer | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | File Name | ----> | File Name | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | File Type | ----> | File Type | <---+---*---*---*---*---*---+---& <---+---*---*---*---*---*---+---& | FM| not used |Pad| ----> | FM| not used |Pad| <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Read Password | ----> | Read Password | <---+---*---*---*---*---*---*---& <---+---*---*---*---*---*---*---& | Output Format | ----> | Output Format | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | LRECL if Fixed-Length Output | ----> | LRECL if Fixed-Length Output | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Starting Record Number | | Next Starting Record Number | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Day of Week in MM/DD/YY Format| <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& .tr & : | not used | | Time in HH&MM&SS Format | .tr & EC <---*---*---*---*---*---*---*---& <---*---*---*---+---*---+---*---& .TR # # .TR " | | not used | |#Complete Bytes|# RCDS |Biggest| <---*---*---*---*---*---*---*---& <---*---+---*---*---*---*---*---& | not used | |RetCode| # Data Bytes Following| .TR # AB .TR " " #---*---*---*---*---*---*---*---$ #---*---*---*---*---*---*---*---$ .* .TR - -;.TR % %;.TR * *;.TR ;.TR & &;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sp 2 :hp2. Figure 5.2.READ Request and Reply Control Blocks :ehp2. .kp off :line6 .* .cp 7 :h3.Input Specification .* .sk .il 5 The request control block has these required fields; :ul :li.UTS User ID. This identifies the CMS disk the file is to be read from by correlating it to the ICATS CONFIG file. :li.ICATS Function ('READ'). :li.Number of Bytes to Transfer. This number should be the maximum number of bytes the UTS user can handle at one time. :li.File Name, File Type, and File Mode. The CMS standard file id, left-justified and padded with blanks. :li.Pad Character. If a CMS record needs to be expanded to fit a larger size fixed-length output, or if an odd-sized record must have one character added to make the output record's length even (since UTS variable-length records have even lengths), then this character will be used to pad the trailing portion of the record. Normally, I should think this character should be a blank, but if the UTS user wants a different pad character, he has control over it. :li.Read Password. This should be the read password for this UTS user for this minidisk. :li.Output Format. The format the output will be in is independent of the CMS file's record format. The input data can be put in either of the three formats, fixed-length, variable-length, or source code format, whichever is desired by the UTS user. See the discussion in the previous section on the format of each. This field will be the single character 'F', 'V', or 'S' and will determine which of the three formats the output data will be in. :li.LRECL if Fixed-Length Output. If the output is going to be in fixed-length format, ICATS will need to know the blocking factor, or logical record length (LRECL), of the output. This field will be that LRECL. :li.Starting Record Number. This field determines which record number to start reading at. The starting record number can range from zero to the number of records in this file. It will generally be zero or one, meaning to start with the first record in the CMS file. :eul .* .cp 12 :h3.Output Specification .* .sk .il 5 The reply control block is a duplicate of the request control block except for the the starting record number, and the last 32 bytes. The modified fields in the reply control block are; :ul :li.Next Starting Record Number. In keeping with the philosophy of making the reply control block usable as the next request control block, this field is changed to point to the record following the last record that was read this time. For example, if the first 25 records were read this time, this field will contain an EBCDIC 26 ('00000026'). .* :li.Day of Week and Time of Day. This is the current date and time in the same format as in the TIME function. .* :li.Number of Bytes in the Completed Records. If the output is in fixed length format, this is the number of complete records times the LRECL. If it's in variable length format, this field includes all the length fields as well as the data in the completed records. If in source code format, this will be the number of complete blocks times 1740, and so will always be a multiple of 1740. See the discussion in the next two paragraphs for a more detailed explanation of this field. .* :li.Number of Complete Records or Blocks. If the output is in fixed- or variable-length format, this field tells the UTS user how many complete records there are in the output data. If it's in source code format, this field gives the number of complete 1740-byte blocks in the output. See the discussion in the next two paragraphs for a more detailed explanation of this field. .* :li.Biggest Record Found in the CMS file. This field is the size of the biggest record ICATS found in the CMS file. .* :li.Return Code. See the next section for possible return codes. .* :li.Number of Data Bytes Following. This will be the Number of Bytes to Transfer specified in the request control block, or the Number of Bytes in the Completed Records given in the reply control block, whichever is smaller. :eul .* .sk .il 5 When a UTS user makes a read request, he probably doesn't know the size of the CMS file, and so doesn't know how many bytes to ask to be transferred. Typically, the read request should be for the maximum number of bytes the UTS can handle which would probably be enough to contain the whole CMS file. But if there's more data in the CMS file than he asked to be transferred, then only a portion of the file will be sent and the rest will have to be sent in a second read request. If this is the case, the UTS user can find out how much data he got in this read by examining the two reply control block fields, "Number of Bytes in the Completed Records" and "Number of Complete Records or Blocks". To illustrate, let's suppose a UTS user makes a read request for the ridiculously small amount of 1024 bytes. The CMS file he's reading from has 30 records in it and he wants the output blocked in 50-byte fixed-length records. Since only 20 of the 30 records will fit in the 1024 bytes, he will not get the whole file. He will have read the first 20 records, part of the 21st, and missed the last 9. The number of complete records will be 20, the number of bytes in the completed records will be 1000 (20*50), and the next starting record number will be 21. Even though the last record has only 24 of its 50 bytes in it and is incomplete, it is still transferred (the UTS user said he wanted 1024 bytes, ICATS is going to give him 1024 bytes of data if possible). In this example, the number of bytes in the completed records was simply the number of completed records times the output LRECL. But if the UTS user wanted variable-length output, then the number of bytes in the completed records would include the length fields for each record and the trailing end-of-block marker (x'FFFF'), or the end-of-file marker (x'0000') if end-of-file was hit, and would be more useful. .* .sk .il 5 If the output is in source code format, the "Number of Completed Records or Blocks" field gives the number of complete 1740-byte blocks given to the UTS, :hp1.not:ehp1. the the number of records in those complete blocks. Since normally, the UTS will ask for some large multiple of 1740 number of bytes, this field will indicate the number of blocks needed to contain the whole CMS file. But for illustrative purposes, let's assume the UTS user asks for only 2000 bytes. The CMS file contains 30 records, and let's say that the first 23 records plus their length fields fit into 1707 bytes and the 24th record is 10 bytes long, so that it doesn't fit in the first block. Then it would take two 1740-byte blocks to ship this file to the UTS. But since the UTS user only asked for 2000 bytes, only one complete block can be shipped in this read request. The number of complete blocks will be 1, the number of bytes in the completed records will be 1740, and the next starting record number will be 24. Note that 2000 bytes of data will be shipped (the "Number of Data Bytes Following" field will be 2000), but the last 260 will only be the beginning of the second block. .* .sk .il 5 If, during reading, a record gets truncated to fit into a smaller size fixed-length output, this fact will not be reflected in the return code. The return code will still be zero. Instead, the UTS user must compare the output LRECL he specified with the "Biggest Record Found" field of the reply control block. If the biggest record found in the CMS File is larger than his output LRECL, then he knows that data truncation has occurred. That field might also come in handy if the UTS user tries something stupid like reading a file in source code format, that contains a record larger than 1708 bytes, so that it won't fit in a 1740-byte block. In that case, the return code would be x'2020' and that field will show the size of the record that didn't fit. .* .cp 8 :h3.READ Return Codes .* Return Code :dl tsize='11' :dt.X'0000' :dd.All went O.K. There were no detected errors and we did .us not hit the end of file of the CMS file. In other words, there's still more data yet to read in this CMS file. .* :dt.X'0004' :dd.All went O.K. There were no detected errors and we .us did hit the end of file of the CMS file. In other words, there's no more data to read in this CMS file. .* :dt.X'1000' :dd.Invalid ICATS function. The second field of the request Control block is not a known ICATS command. Possibly you don't have it left-justified, or padded with blanks, or not all in upper case. .* :dt.X'1004' :dd.Invalid "Number of Bytes to Transfer". The third field of the request control block is not a valid EBCDIC decimal number. .* :dt.X'1008' :dd.Invalid File ID. Either the file name or file type (or both) violates the rules for a valid CMS file ID. See the CMS User's Guide for a description of valid File ID's. .* :dt.X'100C' :dd.Invalid File Mode. There is no such disk for this user defined in the configuration file. Verify the file mode in the request control block. .* :dt.X'1010' :dd.Incorrect Read password given. .* :dt.X'1014' :dd.Invalid Starting Record Number. The starting record number in the request control block is not a valid EBCDIC, decimal number. .* :dt.X'1018' :dd.Invalid LRECL. The logical record length in the request control block is not a valid EBCDIC, decimal number or it's zero. .* :dt.X'2004' :dd.You do not have read access to this disk. The read password in the configuration file for this user for this disk is 'NONE'. .* :dt.X'2008' :dd.The CMS file does not exist. .* :dt.X'200C' :dd.The Starting Record Number is too big. It is bigger than the number of records in this CMS file. .* :dt.X'2020' :dd.The CMS file you wanted read, contains a record larger than 1708 bytes. This record will not fit in UTS source code format block. This file cannot be read in source code format. .* :dt.X'4004' :dd.No such UTS user for this UTS. Possibly you don't have it left-justified, or padded with blanks, or not all in upper case. If that's not it, then check to insure that that user is in the configuration file for that UTS. .* :dt.X'4008' :dd.No minidisk exists at that address. The address specified in the configuration file for this disk for this user does not exist or is not a CMS minidisk. Check the ICATS virtual machine configuration. .* :dt.X'5004' :dd.Unexpected error with the CMS command ACCESS. :dt.X'5008' :dd.Unexpected error with the CMS macro FSSTATE. :dt.X'500C' :dd.Unexpected error with the CMS macro FSOPEN. :dt.X'5010' :dd.I/O error while reading from the CMS minidisk. :dt.X'5014' :dd.Ran out of buffer space inside the ICATS program while reading the CMS file. Currently, I'm allocating 192K for buffer space, and you've just exceeded that. :dt.X'5018' :dd.Unexpected error with the CMS macro FSREAD. :dt.X'6004' :dd.UTS was not found in UTSCB chain. :dt.X'600C' :dd.Unexpected error with the CMS macro FSPOINT. :dt.X'7004' :dd.Unexpected return code from the ACCESS routine in the ICATS mainline program. :edl. .* End of Read Return Code list .* :h2.TIME .* .sk .il 5 Since the UTS machines do not have a time of day clock, the Time function delivers the time and date to the UTS machine in a variety of formats. The different formats ICATS gives are, :ul :li.Date in script format (i.e. January 22, 1983), :li.Date in Julian format (i.e. 83.022), :li.Date in month, day, year format (i.e. 01/22/83), :li.Time in hours, minutes, seconds (i.e. 14:22:59), :li.And a 64-bit binary counter. :eul Time is also valid from the console or an SMSG and returns a line similar to this. .fo off TODAY IS MONDAY, OCTOBER 10, 1983 - THE TIME IS 14:22:41. .fo on .* :line65 :h3.TIME Request and Reply Control Blocks .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR & EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | %------------------------------- %------------------------------- | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | T I M E | ----> | T I M E | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---+---*---*---*---*---*---+---& <---+---*---*---*---*---*---+---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Date | <---+---*---*---*---*---*---*---& <---+---*---*---*---*---*---*---& | not used | | in | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Script | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Format | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Julian Date in YY.DDD Format | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Day of Week in MM/DD/YY Format| <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& .tr & : | not used | | Time in HH&MM&SS Format | .tr & EC <---*---*---*---*---*---*---*---& <---*---*---*---+---*---+---*---& | not used | | 64-Bit Binary Clock Counter | <---*---*---*---*---*---*---*---& <---*---+---*---*---*---*---*---& .TR # # | not used | |RetCode| # Data Bytes Following| .TR # AB #---*---*---*---*---*---*---*---$ #---*---*---*---*---*---*---*---$ .* .TR - -;.TR % %;.TR * *;.TR ;.TR & &;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sp 2 :hp2. Figure 5.3.TIME Request and Reply Control Blocks :ehp2. .kp off :line6 .* .cp 8 :h3.Input Specification .* .sk .il 5 The request control block has only one required field, the function field. The function field must contain the eight EBCDIC characters 'TIME '. The rest of the request control block is ignored. .* .cp 13 :h3.Output Specification .* .sk .il 5 The reply control block is a duplicate of the request control block except for the last 9 fields. The first 7 fields contain EBCDIC data and the last 2, hexadecimal data. The last 9 fields are; :ul :li.Date in Script Format. This field will be variable in length and will be padded as necessary to fill the 32 bytes allotted for it. .fo off The minimum length is 19 characters ('Monday, May 1, 1983') plus 13 blanks. The maximum length is 29 characters ('Wednesday, September 22, 1983') plus 3 blanks. .fo on :li.Julian Date. The format for the Julian date is YY.DDD. .fo off For example, January 1, 1983 would be '83.001', December 31, 1983 would be '83.365', and December 31, 1982 would be '82.366' (1982 was a leap year). .fo on :li.Date in month, day, year format. Leading zeros are not suppressed. For example, January 1, 1983 would be '01/01/83'. :li.Time in hours, minutes, seconds format. Leading zeros are not suppressed. Also, it's a 24-hour clock. .fo off For example, 1:05 a.m. and 3 seconds would be '01:05:03', 11:59 p.m. and 59 seconds would be '23:59:59', and midnight would be '00:00:00'. .fo on :li.64-Bit Binary Clock. This is the result of the 370 instruction, Store Clock. Bit 51 (bit 0 is on the far left) is calibrated in microseconds. From my observations, this also seems to be the resolution of the clock. I've never seen any of the bits past bit 51 (bits 52-63) be anything but zero, but don't take my word on it. The resolution of the CPU's clock depends on which model CPU it is. See the 370 Principles of Operation manual for more details. :li.Return Code. This will always be zero. :li.Number of Data Bytes Following. This will also always be zero. :eul .* .cp 5 :h3.TIME Return Codes .* .sk .il 5 This is easy. Nothing can go wrong with the TIME function (famous last words), so the only return code possible is zero. .* :h2.CAT .* .sk .il 5 The CAT function is only valid from a UTS. It's similar to the CMS command, LISTFILE. All the files on any minidisks this user has access to can be listed. As the CMS LISTFILE command allows partial names to be specified (e.g. LIST TEST* * A), this function also allows the same feature. However, since the user must specify a read password and read passwords may be different for different minidisks, the CAT function will not allow an asterisk for the file mode. Only the catalog of one minidisk may by queried at a time. The data returned by this function includes all the details of each file the CMS command LISTFILE gives with the DATE option. This includes file name, file type, file mode, record format, logical record length (LRECL), the number of records in each file, and probably,:fnref refid=foot6.:fn id=foot6 .* The reason I say probably, is because there is a quirk about CMS files that occasionally the date and time get fouled up. If this happens, there's nothing ICATS can do to get them back again. The CAT function will pass on whatever CMS gives it, but be forewarned that there can be no guarantees on the validity of the date and time. :efn the date and time the file was last modified. .* :line65 :h3.CAT Request and Reply Control Blocks .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR & EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | %------------------------------- %------------------------------- | UTS User ID | ----> | UTS User ID | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | C A T | ----> | C A T | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Number of Bytes to Transfer | ----> | Number of Bytes to Transfer | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | File Name | ----> | File Name | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | File Type | ----> | File Type | <---+---*---*---*---*---*---+---& <---+---*---*---*---*---*---+---& | FM| not used | ----> | FM| not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Read Password | ----> | Read Password | <---+---*---*---*---*---*---*---& <---+---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | | Day of Week in MM/DD/YY Format| <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& .tr & : | not used | | Time in HH&MM&SS Format | .tr & EC <---*---*---*---*---*---*---*---& <---*---*---*---+---*---+---*---& .TR # # | not used | |# compltd bytes|# lines|# files| <---*---*---*---*---*---*---*---& <---*---+---*---*---*---*---*---& | not used | |RetCode| # Data Bytes Following| .TR # AB #---*---*---*---*---*---*---*---$ #---*---*---*---*---*---*---*---$ .* .TR - -;.TR % %;.TR * *;.TR ;.TR & &;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sp 2 :hp2. Figure 5.4.CAT Request and Reply Control Blocks :ehp2. .kp off :line6 .* .cp 6 :h3.Input Specification .* .sk .il 5 The request control block has these required fields; :ul :li.UTS User ID. :li.ICATS Function ('CAT'). :li.Number of Bytes to Transfer. This number should be the maximum number of bytes the UTS user can handle. Since each CMS file found generates 64 bytes of output data, this number should be a multiple of 64. :li.File Name and File Type. These fields comprise the search criteria for this CAT command. Only CMS files on this user's minidisk that satisfy this search criteria will be returned to the UTS user. They can contain any number of asterisks ('*') with their normal CMS meaning of representing any number of characters. :li.File Mode. Unlike the CMS command LISTFILE, this field cannot contain an asterisk. The minidisk must be explicitly specified. :li.Read Password. This should be the read password for this UTS user for this minidisk. :eul .* .cp 16 :h3.Output Specification .* .sk .il 5 The reply control block is a duplicate of the request control block except for the last 16 bytes. The last 16 bytes contain hexadecimal data in this format; :ul :li.Number of Bytes in Completed Lines. This will be 64 times the next field, the Number of Complete Lines. :li.Number of Complete Lines. This is the number of CMS files satisfying the search criteria specified in the request control block that would fit in the Number of Bytes to Transfer. This would normally be the same as the next field, the Number of Files Found, but if all the data wouldn't fit in the Number of Bytes to Transfer, then this field would represent the number of files that actually did fit. :li.Number of Files Found. This is a count of the number of CMS files on this user's minidisk that satisfied the search criteria, whether or not they all fit in the Number of Bytes to Transfer. :li.Return Code. See the next section for possible return codes. :li.Number of Data Bytes Following. This will be the smallest of the Number of Bytes to Transfer or the Number of Bytes in Completed Lines. :eul .* .sk .il 5 Following the reply control block will be the CMS file data. As always, the amount of file data given will be reflected in the last field of the reply control block. The file data will be alphabetically ordered by file name and file type. The data will have 8 fields of 8 bytes each (64 bytes) for each file found satisfying the search criteria. The 8 fields, all EBCDIC, left-justified, and padded with blanks, will be; .kp on;.fo off;.sk .ti ^ 05;.tb 8 17 38 .us^Offset^What It Is^Additional Comments .sk;.in 7 0 - 7 File Name 8 - 15 File Type 16 - 23 File Mode 2 characters (e.g. 'A1') 24 - 31 Record Format The character 'F' for fixed-length or 'V' for variable-length files. 32 - 39 LRECL No leading zeros. The Logical Record Length if fixed-length or the longest record in the file if variable-length. 41 - 47 # Records in File No leading zeros. 48 - 55 Date Last Modified Date is in the format 'MM/DD/YY'. No leading zeros (e.g. '1/03/83 '). .tr & : 56 - 63 Time Last Modified Time is in the format 'HH&MM '. .tr & & No leading zeros (e.g. '1:07 '). 24-hour clock (e.g. '14:59 '). .kp off;.fo on;.in 0 .* .cp 7 :h3.CAT Return Codes .* Return Code :dl tsize='11' :dt.X'0000' :dd.All went O.K. All the data on all the files that satisfied the search criteria fit in the number of bytes you wanted. .* :dt.X'0004' :dd.All the data on all the files that satisfied the search criteria did .us not fit in the number of bytes you wanted. You didn't ask for enough bytes. .* :dt.X'1004' :dd.Invalid "Number of Bytes to Transfer". The third field of the request control block is not a valid EBCDIC decimal number. .* :dt.X'100C' :dd.Invalid File Mode. There is no such disk for this user. Verify the file mode in the request control block. .* :dt.X'1010' :dd.Incorrect Read password given. .* :dt.X'2004' :dd.You do not have read access to this disk. The read password in the configuration file for this user for this disk is 'NONE'. .* :dt.X'2008' :dd.No files were found that satisfied the search criteria. .* :dt.X'4004' :dd.No such UTS user for this UTS. Possibly you don't have it left-justified, or padded with blanks, or not all in upper case. If that's not it, then check to insure that that user is in the configuration file for that UTS. .* :dt.X'4008' :dd.No minidisk exists at that address. The address specified in the configuration file for this disk for this user does not exist or is not a CMS minidisk. Check the ICATS virtual machine configuration. .* :dt.X'5004' :dd.Unexpected error with the CMS command ACCESS. :dt.X'5014' :dd.Ran out of buffer space inside the ICATS program while reading the CMS file. Currently, I'm allocating 192K for buffer space, and you've just exceeded that. :dt.X'6004' :dd.UTS was not found in UTSCB chain. :dt.X'6010' :dd.Unexpected error with the CMS command LISTFILE. :dt.X'7004' :dd.Unexpected return code from the ACCESS routine in the ICATS mainline program. :edl. .* End of CAT Return Code list .* :h2.TERMIO .* .sk .il 5 To do an I/O operation to a DIALed and "plugged in" terminal, the UTS requests a TERMIO function. This function performs the I/O operation, waits around for ending status, and then presents ending status to the UTS machine. TERMIO is a peculiar function in that it could be a read or a write operation. If the channel command word (CCW) specified in the request control block indicates a read, then the terminal's buffer is read and data is sent to the UTS. If the CCW specifies a write operation, ICATS does another I/O operation to the UTS to get the data to write to the terminal. The sequence of I/O operations to the UTS are similar to the sequence for the read and write functions. .* .sk .il 5 If the CCW specifies a READ MODIFIED operation, ICATS may not actually do another read to the terminal. You see, this READ MODIFIED is probably in response to an attention interrupt provided by the terminal. When ICATS saw that attention interrupt and before he passed the interrupt on to the UTS, he did a READ MODIFIED of his own to check for this terminal's session terminate string (usually four dollar signs, '$$$$'). At that time, ICATS saved the data he got from his READ MODIFIED (if it's 100 bytes or less), then passed the interrupt on to the UTS. Now, when the UTS comes around with a READ MODIFIED of its own, ICATS can save an I/O operation and simply give the UTS the data from the previous READ MODIFIED. As always, the data from the read, regardless of when it occurred, follows the reply control block. .* :line65 :h3.TERMIO Request and Reply Control Blocks .kp on;.fo off .TR - BF;.TR % AC;.TR * CB;.TR BC;.TR & EC;.TR + 8F .TR | FA;.TR # AB;.TR @ CC;.TR $ BB;.TR < EB .* | .* %--*-- |--|--| .* > + < ==> -| + |- .* #--@--$ |--|--| .* | %------------------------------- %------------------------------- | Terminal Address | ----> | Terminal Address | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | T E R M I O | ----> | T E R M I O | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | Channel Command Word (CCW) | | Actual CCW Used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---+---*---*---*---*---*---+---& <---+---*---*---*---*---*---+---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---+---*---*---*---*---*---*---& <---+---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---*---*---*---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---*---*---+---*---+---*---& | not used | ----> | not used | <---*---*---*---*---*---*---*---& <---*---+---*---*---*---*---*---& .TR # # | not used | |RetCode|x00|Sns|USt|CSt|# Bytes| .TR # AB #---*---*---*---*---*---*---*---$ #---*---*---*---*---*---*---*---$ .* .TR - -;.TR % %;.TR * *;.TR ;.TR & &;.TR + + .TR | |;.TR # #;.TR @ @;.TR $ $;.TR < < .fo on .sp 2 :hp2. Figure 5.3.TERMIO Request and Reply Control Blocks :ehp2. .kp off :line6 .* .cp 8 :h3.Input Specification .* .sk .il 5 Only the first three fields of the request control block are required, the terminal address, the function field, and the CCW field. The rest of the request control block is ignored. The terminal address must be three left-justified, EBCDIC characters (i.e. '100 '). The function field must contain the eight EBCDIC characters 'TERMIO '. The CCW field contains the single CCW to use in this I/O to this terminal. Only CCW chains of one CCW long are supported. Only the command code (the first byte) and the byte count (the last two bytes) of the CCW field are used, the rest are filled in by ICATS. This field is different from other fields in the request control blocks for every other function in that this field is given in hexadecimal, :hp1.not:ehp1 in EBCDIC. .* .cp 11 :h3.Output Specification .* .sk .il 5 The reply control block is a duplicate of the request control block except for the CCW field and the last field. The CCW field is modified to the actual CCW used (CCW bytes 2-6 are filled in). This should be transparent to the UTS software since those fields in the request control block are ignored anyway. The last eight bytes contain, :ul :li.Return Code. This is another unique feature of the TERMIO function, these two bytes will always be zero. Any error indication will be reflected in the two CSW status bytes and the sense byte. :li.Free byte. This byte is unused and will always be hex zero (x'00'). :li.Sense Byte. If the terminal gives a unit check in response to this I/O operation, this will be the sense byte. Normally, there is no unit check, and this byte will be zero. However, if the terminal address is invalid, that terminal isn't "plugged into" that UTS, or the terminal was turned off, the sense byte will show intervention required (x'40'). :li.CSW Unit Status. :li.CSW Channel Status. :li.Number of Bytes Following Reply Control Block. As always, if any data is following the reply control block, this field tells the UTS how many bytes of data there are. For a write operation, this will always be zero, but for a read operation, this will give the number of bytes of data read. :eul .* .cp 12 :h3.TERMIO Error Conditions .* .sk .il 5 As stated above, the return code in the reply control block will always be zero. Any error indications will be posted in the CSW status fields and the sense byte. We decided it was better this way because the error handling on the UTS side would be identical as with a direct terminal. The errors that occur because of some error with the request control block will respond as if the terminal is not there, i.e. unit check in the CSW unit status and intervention required in the sense byte. Real I/O errors caused by an invalid CCW op code, invalid data, or the terminal being powered off will result in whatever CSW status and sense byte the real terminal provides to ICATS. .* :egdoc.