纯DOS下无需加载MSCDEX,直接弹出或关闭CD-ROM舱
   作者:jim.yu 于2004-7-19上传 

    ;=====================================================
  ;
  ; Program: Detect ATAPI device exist or not
  ;        If exist, change status.
  ;        If now exist, do nothing.
  ;        Not affect ATA device.
  ; Environment: Pure DOS.
  ; Author: Jim Yu (Yu Ling)
  ; Data:   2004.07.15
  ; Version: 1.0.0
  ; Mail: Jim.Yu@Mic.Com.Tw
  ;
  .MODEL SMALL
  .586P
  .STACK 1024
  .DATA
      BSY    EQU    80h
      DRQ    EQU    8
      START_STOP_UNIT    EQU    1Bh
      EJECT_TRAY    EQU    2
      CLOSE_TRAY    EQU    3
      MODE_SENCE    EQU    5Ah
      STATUS_PAGE    EQU    2Ah
      SIZE_OF_CHANNEL_ITEM    EQU    15h
      SHOW_DOOR_OPEN    DB 'Door Opened.',0dh, 0ah, '$'
      SHOW_DOOR_CLOSE    DB 'Door Closed.',0dh, 0ah, '$'
      NOT_EXIST    DB 'Not Exist.',0dh, 0ah, '$'
      SS_CHANNEL    DB '4.Secondary Slave   $'
      SM_CHANNEL    DB '3.Secondary Master  $'
      PS_CHANNEL    DB '2.Primany Slave     $'
      PM_CHANNEL    DB '1.Primany Master    $'
      PACKET_COMMAND    DB 12 DUP(0)
  .CODE
  START:
      MOV    AX, @code
      MOV    DSAX
      PUSH    DS
  
  ;Code start
      push    seg PACKET_COMMAND
      pop    ds
      mov    cx, 4
  next_device:
      call    show_channel
  
      call    detect_atapi
  
      jne    not_atapi
  
      call    detect_device
  
      jc    @f
      call    open_device
      call    open_device             Some ATAPI (e.g. DVD-ROM)
      call    open_device             Need send command 3 times.
      mov    dxoffset SHOW_DOOR_OPEN
      jmp    show_and_reset_device
  @@:
      call    close_device
      call    close_device             Some ATAPI (e.g. DVD-ROM)
      call    close_device             Need send command 3 times.
      mov    dxoffset SHOW_DOOR_CLOSE
  show_and_reset_device:
      mov    ah, 9
      int    21h
      call    reset_device
      jmp    check_device_finish
  not_atapi:
      mov    dxoffset NOT_EXIST
      mov    ah, 9
      int    21h
  check_device_finish:
      loop    next_device
  
  ;Code end
  
      POP    DS
      MOV    AX, 4C00h
      INT    21h
  
  ;=====================================================
  ;    procedure:    show_channel
  ;    in:    cx
  ;    out:    none
  ;    destroy:none
  show_channel    proc
      push    cx
      push    seg SS_CHANNEL
      pop    ds
      mov    dlcl
      dec    dl
      mov    ax, SIZE_OF_CHANNEL_ITEM
      mul    dl
      mov    dxax
      add    dxoffset SS_CHANNEL
      mov    ah, 9
      int    21h
      pop    cx
      ret
  show_channel    endp
  
  ;=====================================================
  ;    procedure:    waid_idle
  ;    in:    dx
  ;    out:    CY = time out
  ;        NC = device idle
  ;    destroy:none
  wait_idle    proc
      push    cx
      push    dx
      push    ax
      
      or    dl, 7
      mov    cx, 0ffffh
  @@:
      call    in_al_dx
      test    al, BSY
      jz    @f
      loop    @b
  @@:
      pop    ax
      pop    dx
      pop    cx
      ret
  wait_idle    endp
  
  ;=====================================================
  ;    procedure:    req_data
  ;    in:    dx
  ;    out:    CY = time out
  ;        NC = device request data
  ;    destroy:none
  req_data    proc
      push    cx
      push    dx
      push    ax
  
      or    dl, 7
      mov    cx, 0ffffh
  @@:
      call    in_al_dx
      test    al, DRQ
      jnz    @f
      loop    @b
  @@:
      pop    ax
      pop    dx
      pop    cx
      ret
  req_data    endp
  
  ;=====================================================
  ;    procedure:    set_feature
  ;    in:    ax
  ;    out:    none
  ;    destroy:ax
  ;    Set 1X1 = 0
  ;    Set 1X4 = AL
  ;    Set 1X5 = AH
  ;    Send 1X7 0A0h
  set_feature    proc
      push    dx
      push    ax
  
      inc    dl
      xor    alal
      call    out_dx_al
  
      pop    ax
  
      add    dl, 3
      call    out_dx_al
  
      inc    dl
      xchg    ahal
      call    out_dx_al
  
      add    dl, 2
      mov    al, 0a0h
      call    out_dx_al
  
      pop    dx
      ret
  set_feature    endp
  
  ;=====================================================
  ;    procedure:    send_packet_command
  ;    in:    dx, si
  ;    out:    none
  ;    destroy:ax, si
  send_packet_command    proc
      push    cx
  
      mov    cx, 6
  @@:
      mov    axds:[si]
      call    out_dx_ax
      xor    axax
      mov    ds:[si], ax
      add    si, 2
      loop    @b
  
      call    wait_idle
  
      pop    cx
      ret
  send_packet_command    endp
  
  ;=====================================================
  ;    procedure:    detect_device
  ;    in:    cx
  ;    out:    CY = Tray Open
  ;        NC = Tray Close
  ;    destroy:dx, ax, si
  ;    Detect atapi device tray
  detect_device    proc
  
      call    set_device
  
      mov    ax, 090h
      call    set_feature
  
      call    wait_idle
  
  @@:
      mov    sioffset PACKET_COMMAND
  
      mov    ax, (STATUS_PAGE * 100h) + MODE_SENCE
      mov    ds:[si], al
      mov    ds:[si+2], ah
      mov    al, 90h
      mov    ds:[si+8], al
  
      call    send_packet_command
  
      call    req_data
  
      call    in_al_dx
      call    in_al_dx
      cmp    al, 70h
      je    door_close
      stc
      ret
  door_close:
      clc
      ret
  detect_device    endp
  
  ;=====================================================
  ;    procedure:    reset_device
  ;    in:    cx
  ;    out:    none
  ;        none
  ;    destroy:dx, ax, si
  ;    Open atapi device tray
  reset_device    proc
  
      call    set_device
  
      mov    ax, 0ffffh
      call    set_feature
  
      call    wait_idle
  
      call    req_data
  
      mov    sioffset PACKET_COMMAND
  
      xor    axax
      call    send_packet_command
  
      ret
  reset_device    endp
  
  ;=====================================================
  ;    procedure:    open_device
  ;    in:    cx
  ;    out:    none
  ;        none
  ;    destroy:dx, ax, si
  ;    Open atapi device tray
  open_device    proc
  
      call    set_device
  
      mov    ax, 0fffeh
      call    set_feature
  
      call    wait_idle
  
      call    req_data
  
      mov    sioffset PACKET_COMMAND
  
      mov    ax, (EJECT_TRAY * 100h) + START_STOP_UNIT
      mov    ds:[si], al
      mov    ds:[si+4], ah
  
      call    send_packet_command
  
      ret
  open_device    endp
  
  ;=====================================================
  ;    procedure:    close_device
  ;    in:    cx
  ;    out:    none
  ;        none
  ;    destroy:dx, ax, si
  ;    Close atapi device tray
  close_device    proc
  
      call    set_device
  
      xor    axax
      call    set_feature
  
      call    wait_idle
  
      call    req_data
  
      mov    sioffset PACKET_COMMAND
  
      mov    ax, (CLOSE_TRAY * 100h) + START_STOP_UNIT
      mov    ds:[si], al
      mov    ds:[si+4], ah
  
      call    send_packet_command
  
      ret
  close_device    endp
  
  ;=====================================================
  ;    procedure:    detect_atapi
  ;    in:    cx
  ;    out:    PO = not atapi device
  ;        PE = is atapi device
  ;    destroy:none
  detect_atapi    proc
      push    cx
      call    set_device
  
      call    wait_idle
  
      add    dl, 7
      mov    al, 0ech
      call    out_dx_al
  
      call    wait_idle
  
      sub    dx, 3
      call    in_al_dx
      xchg    ahal
      inc    dx
      call    in_al_dx
  
      cmp    ax, 014ebh
  
      pop    cx
      ret
  detect_atapi    endp
  
  ;=====================================================
  ;    procedure:    set_device
  ;    in:    cx
  ;    out:    none
  ;    
  ;    destroy:dx, ax
  ;
  ;    Out 1X6 = 0A0h or 0B0h
  ;    Set DX = 1X0
  ;    Set AL = 0A0h or 0B0h
  set_device    proc
      mov    dxcx
      cmp    dx, 2
      mov    dx, 1f6h
      ja    @f
      mov    dx, 176h
  @@:
  
      mov    axcx
      and    al, 1
      shl    al, 4
      or    al, 0a0h
  
      call    out_dx_al
  
      and    dl, 0F0h
      ret
  set_device    endp
  
  in_al_dx    proc
      in    aldx
      out    0edh, al
      ret
  in_al_dx    endp
  
  in_ax_dx    proc
      in    axdx
      out    0edh, al
      ret
  in_ax_dx    endp
  
  out_dx_al    proc
      out    dxal
      out    0edh, al
      ret
  out_dx_al    endp
  
  out_dx_ax    proc
      out    dxax
      out    0edh, al
      ret
  out_dx_ax    endp
  END START 


欢迎访问AoGo汇编小站:http://www.aogosoft.com