HP OpenVMS Systems Documentation

Content starts here

OpenVMS I/O User's Reference Manual


Previous Contents Index

3.4.5.1 Logical End-of-Volume (EOV) Detection

A skip file or skip record operation that uses the standardspace-by-records algorithm is terminated when two consecutive tapemarks are encountered when the tape moves in the forward direction.After the operation terminates, the tape remains positioned between thetwo tape marks that were detected. The I/O status block (IOSB) returnsthe status SS$_ENDOFVOLUME and the actual number of files (or records)skipped during the operation prior to the detection of the second tapemark. The skip count is returned in the high-order word of the firstlongword of the IOSB.

An optimized skip file that uses the IO$M_ALLOWFAST modifier isterminated when the end-of-data position is encountered. If twoconsecutive tape marks immediately precede the end-of-data position onthe tape, the tape is positioned between these two tape marks. TheSS$_ENDOFVOLUME status and the skip count are returned in the IOSB.

Subsequent skip record (or skip file) requests terminate immediatelywhen the tape is positioned between the two tape marks, producing nonet tape movement and returning the SS$_ENDOFVOLUME status with a skipcount of zero.

To move the tape beyond the second tape mark, you must employ anotherI/O function. For example, the IO$_READLBLK function, if issued afterreceipt of the SS$_ENDOFVOLUME status return, terminates with anSS$_ENDOFFILE status and with the tape positioned just past the secondtape mark. From this new position, other skip functions could be issuedto produce forward tape motion (assuming there is additional data onthe tape).

If three consecutive tape marks are encountered during a skip filefunction, you must issue two IO$_READLBLK functions, the first to getthe SS$_ENDOFFILE return and the second to position the tape past thethird tape mark.

3.4.6 Write End-of-File

The write end-of-file (EOF) function writes an extended interrecord gap(of approximately 3 inches for non-return-to-zero-inverted (NRZI)recording and 1.5 inches for phase-encoded (PE) recording) followed bya tape mark. No device- or function-dependent arguments are used withIO$_WRITEOF.

An end-of-tape (EOT) status is returned in the I/O status block ifeither ofthe following conditions is present and no other error conditions occur:

  • A write EOF function is executed while the tapeis positioned past the EOT marker.
  • A write EOF function causes the tape position to enter the EOT region.

3.4.7 Rewind Offline

The rewind offline function rewinds and unloads the tapeon the selected drive.

The I/O operation is completed as soon as the tape movement isinitiated. The actual finish of the mechanical rewind or unloadoperation may occur long after the I/O operation completes.

If the IO$M_RETENSION function modifier is specified and the devicesupports the retension operation, the rewind offline function positionsthe tape to the physical end-of-tape (EOT) marker and rewinds the tapeto the beginning-of-tape (BOT) marker. If the tape does not support theIO$M_RETENSION modifer, a SS$_ILLIOFUNC error is returned.

No device- or function-dependent arguments are used with IO$_REWINDOFF.

3.4.8 Unload

The unload function rewinds and unloads the tapeon the selected drive. The unload function is functionally the same asthe rewind offline function. If the IO$M_NOWAIT function modifier isspecified, the I/O operation is completed as soon as the rewindoperation is initiated. No device- or function-dependent arguments areused with IO$_UNLOAD.

3.4.9 Sense Tape Mode

The sense tape mode function senses the current device-dependent andextended device characteristics (see Tables 3-2 and3-3).

The operating system provides the following function codes:

  • IO$_SENSEMODE---Sense mode
  • IO$_SENSECHAR---Sense characteristics

Sense mode requires logical I/O privilege. Sense characteristicsrequires physical I/O privilege. For TMSCP drives, the sense modefunction returns magnetic tape information in a user-supplied buffer,which is specified by the following function-dependent arguments:

  • P1---Optional. Address of a user-supplied buffer.
  • P2---Optional. Length of a user-supplied buffer.

If P1 is not zero, the sense mode buffer returns the tapecharacteristics. (If P2=8, the second longword of the buffer containsthe device-dependent characteristics. If P2=12, the second longwordcontains the device-dependent characteristics and the third longwordcontains the tape densities that the drive supports and the extendedtape characteristics.) The extended characteristics are identical tothe information returned by DVI$_DEVDEPEND2 (see Table 3-3).Figure 3-3 shows the contents of the P1 buffer.

Regardless of whether the P1 buffer is specified, the I/O status blockreturns the device-dependent characteristics in the second longword(see Figure 3-6). These characteristics are identical to theinformation returned by DVI$_DEVDEPEND (see Table 3-2 inSection 3.3).

Figure 3-3 Sense Mode P1 Buffer


3.4.10 Set Mode

Set mode operations affect the operation and characteristics of theassociated magnetic tape device. The operating system defines two typesof set mode functions: set mode and set characteristics.

Set mode requires logical I/O privilege. Set characteristics requiresphysical I/O privilege. The following function codes are provided:

  • IO$_SETMODE---Set mode
  • IO$_SETCHAR---Set characteristics

These functions take the following device- or function-dependentarguments (other arguments are ignored):

  • P1---The address of a characteristics buffer.
  • P2---Optional. The length of the characteristics buffer. The default is 8 bytes. If a length of 12 bytes is specified, the third longword (which is for TMSCP drives only) specifies the extended tape characteristics.

Figure 3-4 shows the P1 characteristics buffer for IO$_SETMODE.Figure 3-5 shows the same buffer for IO$_SETCHAR.

Figure 3-4 Set Mode Characteristics Buffer forIO$_SETMODE


Figure 3-5 Set Mode Characteristics Buffer forIO$_SETCHAR


The first longword of the P1 buffer for the set characteristicsfunction contains information on device class and type, and the buffersize. The device class for tapes is DC$_TAPE.

The $DCDEF macro defines the device type and class names. The buffersize is the default to be used for tape transfers (this default isnormally 2048 bytes).

The second longword of the P1 buffer for both the set mode and setcharacteristics functions contains the tape characteristics.Table 3-5 lists the tape characteristics and their meanings. The$MTDEF macro defines the symbols listed. If P2=12, the third longwordcontains the extended tape characteristics for TMSCP drives, which arelisted in Table 3-6. The extended tape characteristics are definedby the $MT2DEF macro and are identical to the information returned byDVI$_DEVDEPEND2.

Table 3-5 Set Mode and Set Characteristics Magnetic Tape Characteristics
Characteristic1 Meaning
MT$M_PARITY If set, all data transfers are performed with even parity. If clear (normal case), all data transfers are performed with odd parity. Even parity can be selected only for non-return-to-zero-inverted recording at 800 bits/inch. Even parity cannot be selected for phase-encoded recording (tape density is MT$K_PE_1600) or group-coded recording (tape density is MT$K_GCR_6250) and is ignored.
MT$V_DENSITY
MT$S_DENSITY
Specifies the density at which all data transfers are performed. Tape density can be set only when the selected drive's tape position is at the BOT marker. Possible density values are as follows:
MT$K_DEFAULT Default system density.
MT$K_GCR_6250 Group-coded recording, 6250 bits/inch.
MT$K_PE_1600 Phase-encoded recording, 1600 bits/inch.
MT$K_NRZI_800 Non-return-to-zero-inverted recording, 800 bits/inch.
MT$K_BLK_833 Cartridge block mode recording 2.
MT$V_FORMAT
MT$S_FORMAT
Specifies the format in which all data transfers are performed. Possible format values are as follows:
MT$K_DEFAULT Default system format.
MT$K_NORMAL11 Normal PDP-11 format. Data bytes are recorded sequentially on tape with each byte occupying exactly one frame.

1Defined by the $MTDEF macro.
2Only for the TK50 and TZ30.

Table 3-6 Extended Device Characteristics for Tape Devices
Characteristic1 Meaning
MT2$V_WBC_ENABLE Enable write-back caching on a per-unit basis.
MT2$V_RDC_DISABLE Disable read caching on a per-unit basis.

1Defined by the $MT2DEF macro. Only for TU81-Plus drives.

Application programs that change specific magnetic tape characteristics should perform the following steps, as shown in Example 3-2 in Section 3.6:

  1. Use the IO$_SENSEMODE function to read the current characteristics.
  2. Modify the characteristics.
  3. Use the set mode function to write back the results.

Failure to follow this sequence will result in clearing any previously set characteristic.

3.4.11 Multiple Tape Density Support (Alpha Only)

As of Version 7.2, OpenVMS Alpha permits the selection of any densityand any compression supported by a tape drive. You can write to tapesusing any density and any compression algorithm supported by the tapedrive. Exchanging tapes among tape drives with different defaultsettings for density or compression is much easier with thisenhancement.

Mutiple tape density support is provided by changes in the QIOinterface. These changes are guided by device/density tables in systemlibraries and the corresponding class drivers. This enhancementfunctions with tape drives that support multiple tape density switchingvia the standard MODE_SENSE and MODE_SELECT mechanisms. All density andcompression options available for a given drive will be accessible bythe system. The QIO interface uses MT3DEF to identify the drives, andto match them with their density and compression code options. Somenewer drives may not be included in the module.

Note

After the media has been initialized to a specific density, it willremain that density until the media is initialized to a differentdensity. For example, if a COMPAC III media has been initialized withTK86 density, the DCL command MOUNT/DENSITY=TK85 will have no effectsince the media is initialized at TK86 density. Likewise,BACKUP/DENSITY=TK85 will have no effect if the media is initialzed atTK86 density. However, BACKUP/DENS=TK85/INITIALIZE will initialize themedia to TK85 density.

These enhancements allow IO$_SETMODE and IO$_SENSEMODE to function with most density values and a wider variety of drives. The system management utilities BACKUP and MOUNT take advantage of this added functionality. For more information about multiple tape density support with these utilities, refer to the OpenVMS System Management Utilities Reference Manual. For more information about enchancements in INITIALIZE, refer to the OpenVMS DCL Dictionary.

3.4.12 Data Security Erase

The data security erase function erases all data from the currentposition of the volume to 10 feet beyond the EOT reflective strip, andthen rewinds the tape to the BOT marker. It is a physical I/O functionand requires the access privilege necessary to perform physical I/Ofunctions. The following function code is provided:

IO$_DSE

If the function is issued when a tape is positioned at the BOT marker,all data on the tape will be erased.

IO$_DSE takes no device- or function-dependent arguments.

3.4.13 Modify

Specifying the ATR$C_USERLABEL or ATR$C_ENDLBLAST attributes with IO$_MODIFY results in a bad attribute error. If any other attributes are specified, the IO$_MODIFY function is treated as a no-operation; that is, the function returns success, but no action is performed.

3.4.14 Pack Acknowledge

The pack acknowledge function sets the volume valid bit for allmagnetic tape devices. It is a physical I/O function and requires theaccess privilege to perform physical I/O. The following function codeis provided:

IO$_PACKACK

This function code takes no function-dependent arguments.

IO$_PACKACK must be the first function issued when a volume is placedin a magnetic tape drive. IO$_PACKACK is issued automatically when theDCL commands INITIALIZE or MOUNT are issued.

3.4.15 Available

The available function clears the volume valid bit for all magnetictape drives, that is, it reverses the function performed by the packacknowledge function (see Section 3.4.14). A rewind of the tape isperformed (applicable to all tape drives). No unload function is issuedto the drive. The following function code is provided:

IO$_AVAILABLE

This function takes no function-dependent arguments.

3.4.16 Flush

The flush function is used to ensure that all previously issued cachedcommands have fully completed. Normally, hosts use this function toestablish or maintain synchronization with write-back cached commandsissued to the specified tape unit. The I/O request does not completeuntil all cached data is written successfully to the media in the exactorder that the user specified.

IO$_FLUSH

This function code takes no function-dependent arguments.

3.5 I/O Status Block

The I/O status block (IOSB) for QIO functions on magnetic tape devicesis shown in Figure 3-6. Appendix A lists the status returns forthese functions. (The OpenVMS system messages documentation providesexplanations and suggested user actions for these returns.)Table 3-2 (in Section 3.3) lists the device-dependent datareturned in the second longword. The IO$_SENSEMODE function can be usedto return that data.

Figure 3-6 IOSB Contents


The byte count is the actual number of bytes transferred to or from theprocess buffer or the number of files or blocks skipped. (If aIO$_SKIPRECORD function is terminated by the detection of a tape mark,the count returned in the IOSB is an unsigned number reflecting thenumber of blocks skipped, plus 1.

3.6 Magnetic Tape Driver Programming Examples

This section presents magnetic tape driver VAX MACRO programmingexamples.

Example 3-2 shows the recommended sequence for changing a devicecharacteristic. It retrieves the current characteristics using anIO$_SENSEMODE request, sets the new characteristics bits, and then usesIO$_SETMODE to set the new characteristics.

Example 3-3 shows ways of specifying sense mode and set mode, bothwith and without a user buffer specified, and with user buffers ofdifferent lengths.

In addition, Example 3-4 shows how data is written to and read from magnetic tape through the magnetic tape ACP.

Example 3-2 Device Characteristic Program Example

$QIOW_S -                                ; Get current characteristics.        FUNC      = #IO$_SENSEMODE,-     ; - Sensemode        CHAN      = CHANNEL,-            ; - Channel        IOSB      = IO_STATUS,-          ; - IOSB        P1        = BUFFER,-             ; - User buffer supplied        P2        = #12                  ; - Buffer length = 12        .        .        .(Check for errors)        .        .        .(Set desired characteristics bits)        .        .        .$QIOW_S -                                ; Set new characteristics.        FUNC      = #IO$_SETMODE,-       ; - Set Mode        CHAN      = CHANNEL,-            ; - Channel        IOSB      = IO_STATUS,-          ; - IOSB        P1        = BUFFER,-             ; - User buffer address        P2        = #12                  ; - Buffer length = 12        .        .        .(Check for errors)        .        .        .

Example 3-3 Set Mode and Sense Mode Program Example

        .PSECT        IMPURE, NOEXE, NOSHR        $IODEFDEVICE_NAME:                                  ; Name of device        .ASCID        /MUA0/                  ;CHANNEL:                                      ; Channel to device        .WORD        0                        ;BUFFER: .BLKL        3                        ; Set/Sense characteristics                                              ;  bufferIO_STATUS:                                    ; Final I/O status        .QUAD        0                        ;        .PSECT        CODE, RD, NOWRT, EXE        .ENTRY        MAIN,^M<>        $ASSIGN_S -                           ; Assign a channel to device                DEVNAM      = DEVICE_NAME,-   ;                CHAN        = CHANNEL         ;        BSBW    ERR_CHECK2                    ; Check for errors        $QIOW_S -                             ; Get current characteristics                FUNC        = #IO$_SENSEMODE,-; No user buffer supplied                CHAN        = CHANNEL,-       ;                IOSB        = IO_STATUS       ;        BSBW    ERR_CHECK                     ; Check for errors        $QIOW_S -                             ; Get current characteristics                FUNC        = #IO$_SENSEMODE,-; User buffer supplied, length                CHAN        = CHANNEL,-       ;  defaulted                IOSB        = IO_STATUS,-     ;                P1          = BUFFER          ;        BSBW    ERR_CHECK                     ; Check for errors        $QIOW_S -                             ; Get current characteristics                FUNC        = #IO$_SENSEMODE,-; User buffer supplied, length                CHAN        = CHANNEL,-       ;  = 8                IOSB        = IO_STATUS,-     ;                P1          = BUFFER,-        ;                P2          = #8              ;        BSBW    ERR_CHECK                     ; Check for errors        $QIOW_S -                             ; Get extended characteristics                FUNC        = #IO$_SENSEMODE,-; User buffer supplied, length                CHAN        = CHANNEL,-       ;  = 12                IOSB        = IO_STATUS,-     ;                P1        = BUFFER,-          ;                P2        = #12               ;        BSBW    ERR_CHECK                     ; Check for errors        $QIOW_S -                             ; Set new characteristics                FUNC        = #IO$_SETMODE,-  ; Length defaulted                CHAN        = CHANNEL,-       ;                IOSB        = IO_STATUS,-     ;                P1          = BUFFER          ;        BSBW    ERR_CHECK                     ; Check for errors        $QIOW_S -                             ; Set new characteristics                FUNC        = #IO$_SETMODE,-  ; Length = 8                CHAN        = CHANNEL,-       ;                IOSB        = IO_STATUS,-     ;                P1          = BUFFER,-        ;                P2          = #8              ;        BSBW    ERR_CHECK                     ; Check for errors        $QIOW_S -                             ; Set extended characteristics                FUNC        = #IO$_SETMODE,-  ; Length = 12                CHAN        = CHANNEL,-       ;                IOSB        = IO_STATUS,-     ;                P1        = BUFFER,-          ;                P2        = #12               ;        BSBW    ERR_CHECK                     ; Check for errors        RET        .ENABLE LSBERR_CHECK:        BLBS    IO_STATUS,ERR_CHECK2          ; Continue if good IOSB        MOVZWL  IO_STATUS,-(SP)               ; Otherwise, set up for stop        BRB     10$                           ; Branch to common codeERR_CHECK2:        BLBS    R0,20$                        ; Continue if good status        PUSHL   R0                            ; Otherwise, set up for stop10$:    CALLS        #1,G^LIB$STOP            ; Stop execution20$:    RSB        .DISABLE LSB        .END        MAIN

Example 3-4 MAGNETIC_TAPE.MAR Device Characteristic Program Example

; *********************************************************************;        .TITLE  MAGTAPE PROGRAMMING EXAMPLE        .IDENT  /01/;; Define necessary symbols.;        $FIBDEF                         ;Define file information block                                        ;symbols        $IODEF                          ;Define I/O function codes;; Allocate storage for the necessary data structures.;;; Allocate magtape device name string and descriptor.;TAPENAME:                               ;        .LONG   20$-10$                 ;Length of name string        .LONG   10$                     ;Address of name string10$:    .ASCII  /TAPE/                  ;Name string20$:                                    ;Reference label;; Allocate space to store assigned channel number.;TAPECHAN:                               ;        .BLKW   1                       ;Tape channel number;; Allocate space for the I/O status quadword.;IOSTATUS:                               ;        .BLKQ   1                       ;I/O status quadword;; Allocate storage for the input/output buffer.;BUFFER:                                 ;        .REPT   256                     ;Initialize buffer to        .ASCII  /A/                     ;contain 'A'        .ENDR                           ;;; Now define the file information block (FIB), which the ACP uses; in accessing and deaccessing the file.  Both the user and the ACP; supply the information required in the FIB to perform these; functions.;FIB_DESCR:                              ;Start of FIB        .LONG   ENDFIB-FIB              ;Length of FIB        .LONG   FIB                     ;Address of FIBFIB:    .LONG   FIB$M_WRITE!FIB$M_NOWRITE ;Read/write access allowed        .WORD   0,0,0                   ;File ID        .WORD   0,0,0                   ;Directory ID        .LONG   0                       ;Context        .WORD   0                       ;Name flags        .WORD   0                       ;Extend controlENDFIB:                                 ;Reference label;; Now define the file name string and descriptor.;NAME_DESCR:                             ;        .LONG   END_NAME-NAME           ;File name descriptor        .LONG   NAME                    ;Address of name stringNAME:   .ASCII  "MYDATA.DAT;1"          ;File name stringEND_NAME:                               ;Reference label;; *********************************************************************;;                        Start Program;; *********************************************************************;; The program first assigns a channel to the magnetic tape unit and; then performs an access function to create and access a file called; MYDATA.DAT.  Next, the program writes 26 blocks of data (the letters; of the alphabet) to the tape.  The first block contains all A's, the; next, all B's, and so forth.  The program starts by writing a block of; 256 bytes, that is, the block of A's.  Each subsequent block is reduced; in size by two bytes so that by the time the block of Z's is written,; the size is only 206 bytes.  The magtape ACP does not allow the reading; of a file that has been written until one of three events occurs:;       1. The file is deaccessed.;       2. The file is rewound.;       3. The file is backspaced.; In this example the file is backspaced zero blocks and then read in; reverse (incrementing the block size every block); the data is; checked against the data that is supposed to be there.  If no data; errors are detected, the file is deaccessed and the program exits.;        .ENTRY  MAGTAPE_EXAMPLE,^M<R3,R4,R5,R6,R7,R8>;; First, assign a channel to the tape unit.;        $ASSIGN_S TAPENAME,TAPECHAN     ;Assign tape unit        CMPW    #SS$_NORMAL,R0          ;Success?        BSBW    ERRCHECK                ;Find out;; Now create and access the file MYDATA.DAT.;        $QIOW_S CHAN=TAPECHAN,-         ;Channel is magtape                FUNC=#IO$_CREATE!IO$M_ACCESS!IO$M_CREATE,-;Function                -                       ;is create                IOSB=IOSTATUS,-         ;Address of I/O status                -                       ;word                P1=FIB_DESCR,-          ;FIB descriptor                P2=#NAME_DESCR          ;Name descriptor        CMPW    #SS$_NORMAL,R0          ;Success?        BSBW    ERRCHECK                ;Find out;; LOOP1 consists of writing the alphabet to the tape (see previous; description).;        MOVL    #26,R5                  ;Set up loop count        MOVL    #256,R3                 ;Set up initial byte count                                        ;in R3LOOP1:                                  ;Start of loop        $QIOW_S CHAN=TAPECHAN,-         ;Perform QIOW to tape channel                FUNC=#IO$_WRITEVBLK,-   ;Function is write virtual                -                       ;block                P1=BUFFER,-             ;Buffer address                P2=R3                   ;Byte count        CMPW    #SS$_NORMAL,R0          ;Success?        BSBW    ERRCHECK                ;Find out;; Now decrement the byte count in preparation for the next write; operation and set up a loop count for updating the character; written; LOOP2 performs the update.        SUBL2   #2,R3                   ;Decrement byte count for                                        ;next write        MOVL    R3,R8                   ;Copy byte count to R8 for                                        ;LOOP2 count        MOVAL   BUFFER,R7               ;Get buffer address in R7LOOP2:  INCB    (R7)+                   ;Increment character        SOBGTR  R8,LOOP2                ;Until finished        SOBGTR  R5,LOOP1                ;Repeat LOOP1 until alphabet                                        ;complete;; The alphabet is now complete.  Fall through LOOP1 and update the; byte count so that it reflects the actual size of the last block; written to tape.;        ADDL2   #2,R3                   ;Update byte count;; The tape is now read, but first the program must perform one of; the three functions described previously before the ACP allows; read access.  The program performs an ACP control function,; specifying skip zero blocks.  This is a special case of skip reverse; and causes the ACP to allow read access.;        CLRL    FIB+FIB$L_CNTRLVAL      ;Set up to space zero blocks        MOVW    #FIB$C_SPACE,FIB+FIB$W_CNTRLFUNC ;Set up for space                                        ;function        $QIOW_S CHAN=TAPECHAN,-         ;Perform QIOW to tape channel                FUNC=#IO$_ACPCONTROL,-  ;Perform an ACP control                -                       ;function                P1=FIB_DESCR            ;Define the FIB        CMPW    #SS$_NORMAL,R0          ;Success?        BSBW    ERRCHECK                ;Find out;; Read the file in reverse.;        MOVL    #26,R5                  ;Set up loop count        MOVB    #^A/Z/,R6               ;Get first character in R6LOOP3:                                  ;        MOVAL   BUFFER,R7               ;And buffer address to R7        $QIOW_S CHAN=TAPECHAN,-         ;Channel is magtape                FUNC=#IO$_READVBLK!IO$M_REVERSE,- ;Function is read                -                       ;reverse                IOSB=IOSTATUS,-         ;Define I/O status quadword                P1=BUFFER,-             ;And buffer address                P2=R3                   ;R3 bytes        CMPW    #SS$_NORMAL,R0          ;Success?        BSBW    ERRCHECK                ;Find out;; Check the data read to verify that it matches the data written.;        MOVL    R3,R4                   ;Copy R3 to R4 for loop countCHECKDATA:                              ;        CMPB    (R7)+,R6                ;Check each character        BNEQ    MISMATCH                ;If error, print message        SOBGTR  R4,CHECKDATA            ;Continue until finished        DECB    R6                      ;Go through alphabet in reverse        ADDL2   #2,R3                   ;Update byte count by 2 for                                        ;next block        SOBGTR  R5,LOOP3                ;Read next block;; Now deaccess the file.;        $QIOW_S CHAN=TAPECHAN,-         ;Channel is magtape                FUNC=#IO$_DEACCESS,-    ;Deaccess function                P1=FIB_DESCR,-          ;File information block (required)                IOSB=IOSTATUS           ;I/O status;; Deassign the channel and exit.;EXIT:   $DASSGN_S CHAN=TAPECHAN         ;Deassign channel        RET                             ;Exit;; If an error had been detected, a program would normally; generate an error message here.  But for this example the; program simply exits.;MISMATCH:                               ;        BRB     EXIT                    ;ExitERRCHECK:                               ;        BNEQ    EXIT                    ;If not success, exit        RSB                             ;Otherwise, return        .END    MAGTAPE_EXAMPLE


Previous Next Contents Index