;       SCCSID = @(#)dskinit.asm        6.6 92/03/06
        page    78,132
        title   Dskinit - Initialize Disk Device Driver Data Structures

SCCSID  equ     "@(#)dskinit.asm        6.6 92/03/06"

; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;/********************** START OF SPECIFICATIONS **********************/
;/*                                                                   */
;/* SOURCE FILE NAME: Dskinit                                         */
;/*                                                                   */
;/* DESCRIPTIVE NAME: Initialize disk device driver data structures   */
;/*                                                                   */
;/* FUNCTION: To build the disk/diskette configuration data table     */
;/*           needed for the Disk/Diskette Device Driver              */
;/*                                                                   */
;/* NOTES:                                                            */
;/*   DEPENDENCIES: None                                              */
;/*   RESTRICTIONS: None                                              */
;/*                                                                   */
;/* ENTRY POINTS: InitDisk                                            */
;/*               InitDiskTable                                       */
;/*                                                                   */
;/* EXTERNAL REFERENCES:                                              */
;/*               Int 13h        - Disk/Diskette BIOS                 */
;/*                                                                   */
;/*********************** END OF SPECIFICATIONS ***********************/

        subttl  Data Structures
        page
        .sall
        .xlist
        .xcref
        include dosseg.inc              ; CP/DOS segment setup
        include basemaca.inc            ; CP/DOS macros
        include fnoinit.inc
        include osmaca.inc              ; CP/DOS macros
        include abint13.inc             ; Disk/diskette BIOS data structures
        include config.inc              ; Device configuration table
        include dconfig.inc             ; Disk configuration table
        include struc.inc               ; Structured assembler macros
        include dskinit.inc             ; dskinit structures
        include doshlp.inc              ; DosHlp macros and definitions
        .cref
        .list

        ModName , FNO_DSKINIT_ASM


;       External data structures

        ReferGlobal     DevConfigTbl,BYTE
        ReferGlobal     ABIOS_Revision,BYTE
        ReferGlobal     _CpuType,BYTE
        ReferInitGlobal OEM_config,WORD
        ReferGlobal     RealInitDS,WORD
        ReferGlobal     DHF,dword

;       Local Data structures

INITDATA segment

        extrn   HardDriveCount:byte

        IRQ_TABLE_SIZE  equ     4 * 10H

;       Parameter list passed to the Disk/Diskette Device Driver

        public  Disk_DD_Parameter_List
        Disk_DD_Parameter_List  DDD_Parm_List <InitCache_Parameter_List, disk_configuration_table, IRQ_Vector_Table,,Machine_Config_Pkt>

;       Format of CL register returned by Int 13H function 8

sector_parm record max_track_hi:2,max_sector:6

;       Characteristics of PC/AT diskette drives

cylinders_1_2M       equ  80          ; cylinders - 1.2M drive
sect_per_track_1_2M  equ  15          ; sectors per track - 1.2M drive
heads_1_2M           equ  2           ; heads - 1.2M drive

cylinders_360K       equ  40          ; cylinders - 360K drive
sect_per_track_360K  equ  9           ; sectors per track - 360K drive
heads_360K           equ  2           ; heads - 360K drive

INITDATA ends


INITBSS segment

        public  InitCache_Parameter_List
InitCache_Parameter_List Cacheinit_Input <>     ; Cache Initalization Parms

;       Disk/diskette configuration data table
IRQ_Vector_Table equ $
        db      IRQ_TABLE_SIZE  dup(0h)
disk_configuration_table equ $
        db      (MAX_DRIVE_NUMBER * size ROMcfg) dup(0) ; space for 10 entries

Machine_Config_Pkt   Machine_Config_Info <>

INITBSS ends


;       Structure of a double word

doubleword struc
lsw        dw   ?                     ; least significant word
msw        dw   ?                     ; most significant word
doubleword ends

;       Equates used to modify the contents of the registers pushed
;       by a PUSHA instruction

restore_bx equ  word ptr [bp+8]
restore_cx equ  word ptr [bp+12]
restore_di equ  word ptr [bp+0]

        FARCODE INIT
INITCODE segment


;/********************** START OF SPECIFICATIONS **********************/
;/*                                                                   */
;/* SUBROUTINE NAME: InitDiskTable                                    */
;/*                                                                   */
;/* DESCRIPTIVE NAME: Initialize disk configuration data table        */
;/*                                                                   */
;/* FUNCTION: To build the disk/diskette configuration data table     */
;/*           needed for the Disk/Diskette Device Driver              */
;/*                                                                   */
;/* NOTES: This routine assumes that the disk/diskette configuration  */
;/*        table is large enough to hold the data for all the         */
;/*        attached diskette and fixed disk drives (currently 4)      */
;/*                                                                   */
;/*        This routine is called in real mode                        */
;/*                                                                   */
;/* ENTRY POINT: InitDisk                                             */
;/*    LINKAGE:  Call near                                            */
;/*                                                                   */
;/* INPUT: None                                                       */
;/*                                                                   */
;/* EXIT-NORMAL: Return to caller (no values returned)                */
;/*                                                                   */
;/* EXIT-ERROR: None                                                  */
;/*                                                                   */
;/* EFFECTS: All other registers preserved                            */
;/*                                                                   */
;/* INTERNAL REFERENCES:                                              */
;/*    ROUTINES: Get_Disk_Data     - get data for fixed disks         */
;/*              Get_Diskette_Data - get data for diskettes           */
;/*                                                                   */
;/* EXTERNAL REFERENCES:                                              */
;/*              disk_configuration_table - disk/diskette             */
;/*                                  configuration data table         */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/*********************** END OF SPECIFICATIONS ***********************/
;
; Procedure InitDiskTable
;
;   Call Get_IRQs to get all of the initial IRQ addresses.
;   Call Get_Diskette_Data to get the configuration data for each
;       diskette drive attached to the system
;   Call Get_Disk_Data to get the configuration data for each fixed
;       disk drive attached to the system
;
;   Return to caller
;
; End InitDiskTable

Procedure InitDiskTable
        assume ds:nothing, es:nothing, ss:nothing
        pusha
        SaveReg <ds>

;       Get the configuration data for each diskette drive and fixed
;       disk drive attached to the system

        DosContext <es>
        mov     ds,[RealInitDS]         ; (DS) = DOSINITDATA paragraph address
        assume  ds:DOSINITDATA

        call    Get_IRQs                ; get the IRQ addresses
        lea     di,disk_configuration_table ; point to start of table
        call    Get_Diskette_Data       ; get diskette data
        call    Get_Disk_Data           ; get fixed disk data

;       Remove forward link from last table entry

        sub     di,Size ROMcfg
        mov     [di].ROMlink,0

        call    Get_Machine_Info        ;

;       Return to caller

        RestoreReg <ds>
        popa
        ret

EndProc InitDiskTable


;/********************** START OF SPECIFICATIONS **********************/
;/*                                                                   */
;/* SUBROUTINE NAME: Get_Diskette_Data                                */
;/*                                                                   */
;/* DESCRIPTIVE NAME: Get diskette configuration data                 */
;/*                                                                   */
;/* FUNCTION: To fill in the configuration data table data for the    */
;/*           attached diskette drives                                */
;/*                                                                   */
;/* NOTES: This is an internal subroutine within InitDisk             */
;/*                                                                   */
;/* ENTRY POINT: Get_Diskette_Data                                    */
;/*    LINKAGE:  Call near                                            */
;/*                                                                   */
;/* Input:       DI = address of next available slot in the           */
;/*                   configuration data table                        */
;/*              DevConfigTbl contains the number of diskette drives  */
;/*                                                                   */
;/* EXIT-NORMAL: DI = address of next available slot in the           */
;/*                   configuration data table                        */
;/*                                                                   */
;/* EXIT-ERROR: None                                                  */
;/*                                                                   */
;/* EFFECTS: All other registers preserved                            */
;/*          configuration data table updated                         */
;/*                                                                   */
;/* INTERNAL REFERENCES:                                              */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/* EXTERNAL REFERENCES:                                              */
;/*    ROUTINES: DHF:DosHlpGetDriveParms                              */
;/*                                                                   */
;/*********************** END OF SPECIFICATIONS ***********************/
;
; Procedure Get_Diskette_Data(configuration table pointer)
;
; For device = 0 to number of diskettes-1
;
;   put common information into configuration table entry:
;       device number
;       flags (diskette)
;       forward link
;
;   call DosHlpGetDriveParms to determine whether or not this drive
;       supports the change line - put this information into the
;       configuration table entry
;
;   put device specific information into configuration table entry:
;       number of tracks
;       number of sectors per track
;       number of heads
;
;   point to next configuration table entry
;
; Next device
;
; Return to caller
;
; End Get_Diskette_Data

Procedure Get_Diskette_Data
        assume ds:DOSINITDATA, es:DOSGROUP, ss:nothing

        SaveReg <ds,es>
        pusha
        cli                     ;ensure interrupts disabled!!!!

;       Get the parameters for each diskette drive in the system

        mov     dh,DevConfigTbl.Config_diskettes ; Pick up number of
        dec     dh                               ; diskette drives
        .for    dl = 0 to dh
          SaveReg <es,ds,dx>

          mov   [di].ROMdevnbr,dl     ; diskette device number
          mov   [di].ROMflags,0       ; clear the flags
          lea   ax,[di + Size ROMcfg] ; set up link field
          mov   [di].ROMlink,ax

;        Get the diskette drive parameters

          push ds
        call    es:DHF.DosHlpGetDriveParms   ;get device specific data
                                             ; es <= DosGroup
          pop  es
        assume ds:nothing,es:DOSINITDATA

;         Put parameters into configuration data table
;       (DS:SI -> drive parameter save area,  where;
;
;       DS:[SI]         ->      number of cylinders
;       DS:[SI+2]       ->      number of sectors per track
;       DS:[SI+4]       ->      number of heads
;       DS:[SI+6]       ->      Hard disk precomp cylinder
;       DS:[SI+8]       ->      Flags, where:
;                                   xxxxxxx1 = Non-removable media
;                                   xxxxxx1x = Change line supported
          mov   ax,ds:[si]
          mov   es:[di].ROMcyls,ax            ; number of tracks
          mov   ax,ds:[si+2]
          mov   es:[di].ROMsecptrk,ax    ; sectors/track
          mov   ax,ds:[si+4]
          mov   es:[di].ROMheads,ax      ; number of heads
          mov   ax,ds:[si+8]
          mov   es:[di].ROMflags,ax

          add   di,Size ROMcfg        ; point to next table entry
          RestoreReg <dx,ds,es>
        .next   dl                    ; loop through all drives

;       Return to caller
        cli                           ; redisable interrupts
        mov     bp,sp                 ; update DI on stack
        mov     restore_di,di
        popa
        RestoreReg <es,ds>
        ret

EndProc Get_Diskette_Data


;/********************** START OF SPECIFICATIONS **********************/
;/*                                                                   */
;/* SUBROUTINE NAME: Get_Disk_Data                                    */
;/*                                                                   */
;/* DESCRIPTIVE NAME: Get fixed disk configuration data               */
;/*                                                                   */
;/* FUNCTION: To fill in the configuration data table data for the    */
;/*           attached fixed disk drives                              */
;/*                                                                   */
;/* NOTES: This is an internal subroutine within InitDisk             */
;/*                                                                   */
;/* ENTRY POINT: Get_Disk_Data                                        */
;/*    LINKAGE:  Call near                                            */
;/*                                                                   */
;/* Input:       DI = address of next available slot in the           */
;/*                   configuration data table                        */
;/*                                                                   */
;/* EXIT-NORMAL: DI = address of next available slot in the           */
;/*                   configuration data table                        */
;/*                                                                   */
;/* EXIT-ERROR: None                                                  */
;/*                                                                   */
;/* EFFECTS: All other registers preserved                            */
;/*          configuration data table updated                         */
;/*                                                                   */
;/* INTERNAL REFERENCES:                                              */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/* EXTERNAL REFERENCES:                                              */
;/*    ROUTINES: DHF:DosHlpGetDriveParms                              */
;/*                                                                   */
;/*********************** END OF SPECIFICATIONS ***********************/
;
; Procedure Get_Disk_Data(configuration table pointer)
;
; number of fixed disks attached already passed for DosHlpConfig
;
; For device = 0 to number of fixed disks-1
;
;   put common information into configuration table entry:
;       device number
;       flags (fixed disk)
;       forward link
;
;   call DosHlpGetDriveParms to get the disk drive parameters
;
;   put device specific information into configuration table entry:
;       number of tracks
;       number of sectors per track
;       number of heads
;       write precompensation factor
;
;   point to next configuration table entry
;
; Next device
;
; Return to caller
;
; End Get_Disk_Data

Procedure Get_Disk_Data
        assume ds:DOSINITDATA, es:nothing, ss:nothing

        SaveReg <ds,es>
        pusha
        cli                           ; make sure interrupts are off

;       Find out the number of fixed disks attached to the system

        mov     dh,HardDriveCount

;       If DH is 0, there are no fixed
;       disks attached to the system

        .if     <nonzero dh>
          dec   dh

;         Get the parameters for each fixed disk drive in the system

          .for  dl = 0 to dh

            test OEM_config, CFG_MCA    ; 161976 is this a microchannel system?
            jz   short gdd10            ; 161976 yes, perform following test

              .leave <dl ge 2>          ; have to leave if disk # greater than
                                        ; 2, causes serious problems on PS/2
                                        ; with >2 hardfiles. Zero based count.
gdd10:
            SaveReg <es,ds,dx>
            or  dl,80h                  ; convert to BIOS device number
            mov [di].ROMdevnbr,dl       ; disk device number
            mov [di].ROMflags,ROMfixed  ; indicate fixed disk
            lea ax,[di + Size ROMcfg]   ; set up link field
            mov [di].ROMlink,ax

;           Get the fixed disk drive parameters

            push        ds
            call        es:DHF.DosHlpGetDriveParms
            pop es
        assume ds:nothing,es:DOSINITDATA

;           Put parameters into configuration data table
;       DS:SI -> drive parameter save area,  where;
;
;       DS:[SI]         ->      number of cylinders
;       DS:[SI+2]       ->      number of sectors per track
;       DS:[SI+4]       ->      number of heads
;       DS:[SI+6]       ->      Hard disk precomp cylinder
;       DS:[SI+8]       ->      Flags, where:
;                                   xxxxxxx1 = Non-removable media
;                                   xxxxxx1x = Change line supported

            mov ax,ds:[si]
            mov es:[di].ROMcyls,ax            ; number of tracks
            mov ax,ds:[si+2]
            mov es:[di].ROMsecptrk,ax    ; sectors/track
            mov ax,ds:[si+4]
            mov es:[di].ROMheads,ax      ; number of heads
            mov ax,ds:[si+6]
            mov es:[di].ROMwpf,ax             ; fixed disk write precomp factor
            mov ax,ds:[si+8]
            mov es:[di].ROMflags,ax
            add di,Size ROMcfg        ; point to next table entry
            RestoreReg <dx,ds,es>
          .next dl                    ; loop through all drives
        .endif

;       Return to caller

        cli                             ; redisable interrupts
        mov     bp,sp                 ; update DI on stack
        mov     restore_di,di
        popa
        RestoreReg <es,ds>
        ret

EndProc Get_Disk_Data


;/********************** START OF SPECIFICATIONS **********************/
;/*                                                                   */
;/* SUBROUTINE NAME: InitDisk                                         */
;/*                                                                   */
;/* DESCRIPTIVE NAME: Initialize disk device driver data              */
;/*                                                                   */
;/* FUNCTION: To return the address of the Disk/Diskette Device       */
;/*           Driver initialization data structure                    */
;/*                                                                   */
;/* NOTES: This routine is called in protected mode                   */
;/*                                                                   */
;/* ENTRY POINT: InitDisk                                             */
;/*    LINKAGE:  Call near                                            */
;/*                                                                   */
;/* INPUT: None                                                       */
;/*                                                                   */
;/* EXIT-NORMAL: BX:CX = address of parameter list to be passed to    */
;/*                      the Disk Device Driver in the initialization */
;/*                      packet                                       */
;/*                                                                   */
;/* EXIT-ERROR: None                                                  */
;/*                                                                   */
;/* EFFECTS: All other registers preserved                            */
;/*                                                                   */
;/* INTERNAL REFERENCES:                                              */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/* EXTERNAL REFERENCES:                                              */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/*********************** END OF SPECIFICATIONS ***********************/
;
; Procedure InitDisk
;
; Return (address of parameter list)
;
; End InitDisk

Procedure InitDisk
        assume ds:nothing, es:nothing, ss:nothing
;
;       Return address of parameter list to caller
        push    ds                             ;save DS
        DosInitContext ds,bx
        lea     bx,Disk_DD_Parameter_List      ;set BX (value for CX)
        mov     ds:[bx].cmd_line_args,cx       ;store offset to command line
        DosInitContext ,cx                     ;set CX (value for BX)
        xchg    bx,cx                          ;put right value in right reg
        pop     ds                             ;restore DS
        ret

EndProc InitDisk



;/********************** START OF SPECIFICATIONS **********************/
;/*                                                                   */
;/* SUBROUTINE NAME: Get_IRQs                                         */
;/*                                                                   */
;/* DESCRIPTIVE NAME: Get_IRQs                                        */
;/*                                                                   */
;/* FUNCTION: Fill in the initialization packet with                  */
;/*           all of the IRQ handler addresses.                       */
;/*                                                                   */
;/* NOTES:                                                            */
;/*                                                                   */
;/* ENTRY POINT: Get_IRQs                                             */
;/*    LINKAGE:  Call near                                            */
;/*                                                                   */
;/* INPUT: None                                                       */
;/*                                                                   */
;/* EXIT-NORMAL: none                                                 */
;/*                                                                   */
;/* EXIT-ERROR: None                                                  */
;/*                                                                   */
;/* EFFECTS: All other registers preserved                            */
;/*                                                                   */
;/* INTERNAL REFERENCES:                                              */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/* EXTERNAL REFERENCES:                                              */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/*********************** END OF SPECIFICATIONS ***********************/
;
; Procedure Get_IRQs
;
; fill in the initialization packet with all of the IRQ handler addresses
;
; End Get_IRQs

Procedure Get_IRQs,,local
        assume  ds:DOSINITDATA, es:nothing, ss:nothing
        pusha
        SaveReg  <es, ds>

        push ds
        pop es
        assume  es:DOSINITDATA
        push    0                               ; location of vectors is 0:0
        pop     ds
        assume  ds:nothing

        mov     cx, IRQ_TABLE_SIZE              ; fill up 1/2 the table
        shr     cx, 1                           ; size of 8 of 16 vectors
                                                ; (16 devided by 2)
        mov     di, OFFSET IRQ_Vector_Table     ; destination
        mov     si, 0+8*4                       ; IRQs 0-7 are stored at
                                                ; location 0:8*4
rep     movsb                                   ; get IRQ vectors 0-7

        mov     cx, IRQ_TABLE_SIZE              ; fill up 1/2 the table
        shr     cx, 1                           ;

        mov     di, OFFSET IRQ_Vector_Table     ; destination
        add     di, cx                          ; size of 8 vectors
        mov     si, 0+70H*4                     ; IRQs 0-7 are stored at
                                                ; location 0:8*4
rep     movsb                                   ; get IRQ vectors 8-15

        RestoreReg  <ds, es>
        popa
        ret
EndProc Get_IRQs

;/********************** START OF SPECIFICATIONS **********************/
;/*                                                                   */
;/* SUBROUTINE NAME: Get_Machine_Info                                 */
;/*                                                                   */
;/* DESCRIPTIVE NAME:                                                 */
;/*                                                                   */
;/* FUNCTION: Fill in the initialization packet with                  */
;/*           all of the IRQ handler addresses.                       */
;/*                                                                   */
;/* NOTES:                                                            */
;/*                                                                   */
;/* ENTRY POINT: Get_IRQs                                             */
;/*    LINKAGE:  Call near                                            */
;/*                                                                   */
;/* INPUT: None                                                       */
;/*                                                                   */
;/* EXIT-NORMAL: none                                                 */
;/*                                                                   */
;/* EXIT-ERROR: None                                                  */
;/*                                                                   */
;/* EFFECTS: All other registers preserved                            */
;/*                                                                   */
;/* INTERNAL REFERENCES:                                              */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/* EXTERNAL REFERENCES:                                              */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/*********************** END OF SPECIFICATIONS ***********************/
;

Procedure Get_Machine_Info,near

        assume ds:DOSINITDATA, es:DOSGROUP, ss:nothing

        .386p

        SaveReg <ax>

        mov     Machine_Config_Pkt.MCH_Length, MCH_Reserved1

        mov     ax, OEM_config
        mov     Machine_Config_Pkt.MCH_BusInfo, ax

        movzx   ax, HardDriveCount
        mov     Machine_Config_Pkt.MCH_HardDriveCount, ax

        movzx   ax, _CpuType
        mov     Machine_Config_Pkt.MCH_CpuInfo, ax

        mov     ah, DevConfigTbl.Config_model
        mov     al, DevConfigTbl.Config_type
        mov     word ptr Machine_Config_Pkt.MCH_SubModel, ax

        movzx   ax, ABIOS_Revision
        mov     Machine_Config_Pkt.MCH_ABIOSRevision, ax

        .286p

        RestoreReg <ax>
        ret

EndProc Get_Machine_Info


INITCODE ends

        end
