Porting device drivers from VAX to Alpha DECUS Atlanta; June 1993 Gerard K. Newman, TGV, Inc. 603 Mission St. Santa Cruz, CA 95060 gkn@tgv.com | 619.591.4717 (voice+fax) | 800.TGV.3440 | 408.427.4366 Not covered: - Real hardware (e.g., access via CRAMs) - Kernel processes Documents you'll need: - IDSM for both VAX and Alpha - Alpha listings - MACRO porting guide - Device driver porting guide Source code changes: - Standard MACRO32 porting stuff, including adding .JSB_ENTRYs, Fixing calls between routines, atomicity issues, use of condition codes as part of the output from a subroutine, etc. - Stricter PSECT ordering requirements: use DRIVER_DATA and DRIVER_CODE macros. - System data structure changes: mostly field size promotions (to a longword or quadword) (UCB and IRP especially) - DPT changes: - DPTAB must include STEP=1, which will produce whining from the MACRO compiler. - Controller/Unit init routines pointers move from DPT to DDT. Use new DDTAB {CTRL,UNIT}INIT keywords. - Unit init and controller init routines must now return status in R0. - QIO parameters in IRP instead via AP. - Useful data cells in the exec: MMG$GL_VPN_TO_VA Number of bits to turn a virtual page # to a virtual address MMG$GL_PAGE_SIZE Page size in bytes Fork processes: - FORK macro now takes a routine address to fork to, and optionally a continue address. This takes the place of: VAX: PUSHAB Continue ;Cause EXE$FORK to return here PUSHAB Fork ;Fork to here JSB G^EXE$FORK ;Create a fork Continue: ;Continue here: Alpha: FORK Routine=FORK,Continue=Continue ;Fork to Fork: Continue: ;Continue here: - Can also call EXE$QUEUE_FORK if PC already set in fork block. Registers in fork block are also 64 bits for the Alpha. - Same for FORK_WAIT and IOFORK. - Mechanics of WFIKPCH have changed -- timeout argument now gets loaded into R1, and they return the caller, not the caller's caller. Architecture dependencies: - Obviously, the page tables are different. Here's some example code loading PTEs on the VAX and on the Alpha: VAX: ; R0 - Number of pages to map ; R2 - SVAPTE of source buffer ; R5 - SVAPTE of destination buffer ; R6 - System virtual address of destination buffer 10$: MOVL (R2)+,R3 ;Get next PTE BBS #PTE$V_VALID,R3,20$ ;Branch if it's valid JSB G^IOC$PTETOPFN ;Else get VMS to fetch the proper PTE 20$: BICL3 #^c,R3,(R5) ;Isolate the PFN and store it BISL #,(R5)+ ;Valid, kernel write. MTPR R6,#PR$_TBIS ;Invalidate the TLB MOVAB 512(R6),R6 ;Next page in destination, please SOBGTR R0,10$ ;Loop. Alpha: ; R0 - Number of pages to map ; R2 - SVAPTE of source buffer ; R5 - SVAPTE of destination buffer ; R6 - System virtual address of destination buffer 10$: EVAX_LDQ R3,(R2)+ ;Grab the entire (quad) PTE ASSUME PTE$V_VALID EQ 0 BLBS R0,20$ ;Branch if it's valid JSB G^IOC$PTETOPFN ;Else get VMS to fetch the proper PTE EVAX_SLL R3,#PTE$V_PFN,R3 ;Shift the PFN over 20$: EVAX_ZAP R3,#^xF,R3 ;Lose the flags longword. EVAX_OR R3,#,R3 ;Kernel write EVAX_STQ R3,(R5)+ ;Store the PTE MTPR R6,#PR$_TBIS ;Invalidate the TLB ADDL MMG$GL_PAGE_SIZE,R6 ;Next page in the destination buffer SOBGTR R0,10$ ;Loop Unusual gymnastics with the PSL: - On the VAX, it's fairly common to do an REI to change the PSL (e.g., current or previous mode). Harder to do on the Alpha. VAX: PUSHL New_PSL ;New PSL BSBW DO_REI ;Go do an REI Alpha: PUSHAB 10$ ;Continue address PUSHL #New_Mode ;Not a PSL CALLS #2,G^EXE$REI_INIT_STACK ;Get a new stack in a new mode 10$: .JSB_Entry - If you were simply changing PSL to use a PROBEx instruction, the Alpha IFRD/IFWRT/IFNORD/IFNOWRT macros let you specify the previous mode to check against (the PS on the alpha is user-writable). Linking: - Ugly on the Alpha because drivers are execlets and get sliced. - Must use complicated options file and linker command. VAX: $ Link/System=0/Header FOODRIVER+SYS$SYSTEM:SYS.STB/Selective Alpha: $ Link/Native/BPage=14/Section/NoTrace/NoDemand/NoSysShr/SysExe=Select- /Share=FOODRIVER FOODRIVER/Options Generic options file: CLUSTER=FOODRIVER,,,- FOODRIVER,- SYS$LIBRARY:STARLET/INCLUDE:(- SYS$DOINIT,- SYS$DRIVER_INIT) PSECT_ATTR=_AMAC$CODE,PIC,USR,CON,REL,GBL,NOSHR,EXE,RD,NOWRT,NOVEC PSECT_ATTR=_AMAC$LINKAGE,PIC,USR,CON,REL,GBL,NOSHR,NOEXE,RD,WRT,NOVEC PSECT_ATTR=$CODE$,PIC,USR,CON,REL,GBL,NOSHR,EXE,RD,NOWRT,NOVEC PSECT_ATTR=$LINK$,PIC,USR,CON,REL,GBL,NOSHR,NOEXE,RD,WRT,NOVEC PSECT_ATTR=$PLIT$,PIC,USR,CON,REL,GBL,NOSHR,NOEXE,RD,WRT,NOVEC PSECT_ATTR=$OWN$,PIC,USR,CON,REL,GBL,NOSHR,NOEXE,RD,WRT,NOVEC PSECT_ATTR=$GLOBAL$,PIC,USR,CON,REL,GBL,NOSHR,NOEXE,RD,WRT,NOVEC PSECT_ATTR=EXEC$INIT_CODE,NOSHR PSECT_ATTR=EXEC$INIT_LINKAGE,PIC,USR,CON,REL,GBL,NOSHR,EXE,RD,WRT,NOVEC PSECT_ATTR=$$$115_LINKAGE,PIC,USR,CON,REL,GBL,NOSHR,NOEXE,RD,WRT,NOVEC COLLECT=NONPAGED_READONLY_PSECTS/ATTRIBUTES=RESIDENT,- _AMAC$CODE,- EXEC$NONPAGED_CODE,- $$$115_DRIVER,- $CODE$ COLLECT=NONPAGED_READWRITE_PSECTS/ATTRIBUTES=RESIDENT,- _AMAC$LINKAGE,- EXEC$NONPAGED_DATA,- EXEC$NONPAGED_LINKAGE,- $$$105_PROLOGUE,- $$$110_DATA,- $$$115_LINKAGE,- $PLIT$,- $GLOBAL$,- $OWN$,- $LINK$ COLLECT=INITIALIZATION_PSECTS/ATTRIBUTES=INITIALIZATION_CODE,- EXEC$INIT_LINKAGE,- EXEC$INIT_CODE,- EXEC$INIT_000,- EXEC$INIT_001,- EXEC$INIT_002,- EXEC$INIT_SSTBL_000,- EXEC$INIT_SSTBL_001,- EXEC$INIT_SSTBL_002 Load a device driver: - On VAX, use SYSGEN - On Alpha, use SYSMAN IO commands