================================================================================ Note 10.0 MicroVAX I I/O Programming No replies JAWS::KAISER 229 lines 25-MAR-1985 09:18 -------------------------------------------------------------------------------- +---------------+ +-----------------+ | d i g i t a l | | uNOTE # 010 | +---------------+ +-----------------+ +----------------------------------------------------+-----------------+ | Title: MicroVAX I/O Programming | Date: 27-JUL-84 | +----------------------------------------------------+-----------------+ | Originator: Peter Jonhson | Page 1 of 5 | +----------------------------------------------------+-----------------+ The Qbus MicroVax implements the full Vax memory management, so virtual addresses are translated to physical addresses - just as they are for the Vax minicomputers. When memory management is enabled, system and process space virtual addresses are translated into physical addresses and sent onto the Qbus. Normally, the programmmer need not concern himself with this translation as this is completely handled by the operating system; however, when accessing locations in the I/O space directly the programmer must concern himself with the mapping since specific information must be supplied by the programmer to MicroVMS in order for it to successfully map the user's virtual addresses into the I/O space. The process of mapping a virtual address to a physical address must start by determining the physical address that you wish to access. In our case this means that we must calculate a Qbus MicroVax physical address given that we know the address that the Qbus board is configured to. In order to do this we must know a few key facts about the Qbus MicroVax architecture. 1) The Qbus MicroVax I/O space begins at physical 20000000 (hex) 2) The I/O space of a Qbus MicroVax is largely empty containing only Q22 bus I/O space which is 8K bytes long Given these two pieces of information we now know that the I/O space for the Qbus MicroVax starts at physical 20000000 (hex) and extends to 20001FFF (hex). This I/O space directly corresponds to the configurable addresses on Qbus option boards 160000-177777 (oct). In order to convert any Qbus option address to a Qbus MicroVax address one simply subtracts 160000 from the boards configured address to get its offset into the I/O space and then add this value to the base of the Qbus MicroVax I/O space. For example, let us consider a board which has been configured to 166540. In order to calculate its equivalent Qbus MicroVax address we would do the following: Page 2 1) Subtract off the I/O base address for this board (160000) 166540 (oct) - 160000 (oct) --------- 6540 (oct) --> D60 (hex) 2) Add the board's address offset to the Qbus MicroVax I/O space base address 20000000 (hex) + D60 (hex) ---------- 20000D60 (hex) This addition results in the physical address on the Qbus MicroVax system that this board would answer to. Now we have calculated the physical address for the board in the Qbus MicroVax environment. This value, however, is in the raw state and is still not usable by the uVMS software to perform virtual to physical address translation. In order for this address to be useful to the software it must now be converted from a physical address to a page frame number. The page is the basic unit of memory mapping and protection. A page is 512 contiguous byte locations. A page frame number (PFN) is the address of the first byte of a page in physical memory. This means that the lsb of a PFN has the resolution of 1 page or 512 bytes. It is a simple matter now to convert a physical address to a PFN. Since the lsb of a PFN is 1 page to convert a physical address to PFN just shift right the physical address 9 bits, i.e. shift off the 9 least significant bits. physcial 20000D60 (hex) shift right 9 --> PFN 100006 (hex) The PFN value which we have calculated is sufficient to allow the system to map a physcial page of addresses into your virtual address space. The address of the Qbus option resides somewhere in the page which we have mapped. It is the responsibility of the programmer to correctly offset from the beginning of the page in order to access the board i.e. the programmer must displace from the base of the mapped page with the correct virtual address offset. To determine the offset from the beginning of the mapped page look to bits 0-9 of the configured address of the Qbus option board - this is the offset. In our example the offset would be: Page 3 166540 (oct) | | \ / | -------- 540 bits 9-0 are the offset This offset would be used by the programmer to access the device registers on the board. Failure to use the offset will usually result in an attempt to access non-esxistent locations (analagous to memory time-outs) which will result in an access violation error being returned to the user. A sample program follows which illustrates the principles which have been discussed. It uses the same board address discussed earlier so that one can see the code needed to acutally implement the previous example. The following program illustrates, in a raw fashion, how one might actually access the I/O space with software. It is not meant to illustrate good or recommended programming practice but rather to show the mechanics of accessing the I/O space of a Qbus on MicroVax I. Page 4 .title map_io_space ;This program will allow a user with suitable privilege to access ;device registers in the I/O space of a uVax. This example shows ;code which is used to extract data from a DRV11 - a general purpose ;parallel interface which resides in I/O space. It is sufficiently ;general to allow the concept to be used in other situations where ;access to the I/O space from a user process is desireable. ;This portion of the program is responsible for creating the ;virtual to physical mapping required to access registers in ;the I/O space. For this example the device registers are assumed to ;start at 166540. In order for virtual to physical mapping to occur ;the user must calculate the physcial page frame that the device ;registers overlap into. (See accompanying text for how to do this) ;Create and map section directive does the actual work of mapping. ;In order for this system service to work correctly the ;use must have PFNMAP privilege .entry start,^m<> $crmpsc_s - inadr = maprange, - ;Input virtual address range retadr = actadr, - ;Virtual address range acutally ;mapped pagcnt = #1, - ;Non zero required for page frame ;section flags =#, - vbn = pfn_number ;Actual page frame of I/O space ;page which contains device registers blbs r0,continue ;check the return status of create ;and map - if successful branch pushl r0 ;put status onto stack calls #1,g^lib$stop ;tell him what happened and ;stop program Page 5 ;At this point one page of virtual addresses in the user's process ;space is now mapped into one page of the I/O space. Now the user ;can access device registers by using move instructions. ;...... ** Please note that only certain instructions are allowed when ;doing physical I/O to the bus. For example a MOVL instruction is ;NOT legal to the I/O space. continue: movl actadr, r6 ;Get starting virtual address from ;system service and put into R6 addl #^x160, r6 ;Add the displacement into this page ;to access the device registers ;Access data from the parallel interface tstb (r6) ;Test for data transfer request bgew 10$ ;If no data exit movw 4(r6), data_in_buffer ;Data is present - store it 10$: $exit_s - ;exit gracefully code = #1 ;data for program ...... maprange: .long ^x400 .long ^x800 control_status .word 0 data_in_buffer .word 0 actadr: .blkl 2 ;holds returned virtual ; address range pfn_number: .long ^x100006 ;actual pfn of I/O page to ;be mapped .end start