home *** CD-ROM | disk | FTP | other *** search
/ hackzapple.com / www.hackzapple.com.tar / www.hackzapple.com / THEMAS / M4 / GUILLARD / lwlv-src.txt < prev    next >
Text File  |  2007-03-08  |  10KB  |  506 lines

  1.             ;Prototype driver for IDE/ATA interface board
  2.             ;65C02 assembly (using Procode)
  3.             ;ATA PIO mode 1 protocol
  4.             ;(c) 2001 stephane.guillard@steria.com
  5.             ;Release 0.0.2 May-03-2001
  6.  
  7.             ;############## Constant values
  8. base    equ    $C0F0    ;Base address for slot I/O 16 bytes (slot 7)
  9. datmsb    equ    base+0    ;Read / write latch MSB
  10. altern    equ    base+6    ;Alternate status byte (R)
  11. devctrl    equ    base+6    ;Device control reg (W)
  12. drivad    equ    base+7    ;Device selection (Master / Slave)
  13. datlsb    equ    base+8    
  14. error    equ    base+9    ;Error code
  15. feature    equ    base+9    
  16. seccnt    equ    base+10    
  17. secnr    equ    base+11    
  18. cyllow    equ    base+12    
  19. cylhig    equ    base+13    
  20. drhead    equ    base+14    
  21. status    equ    base+15    ;Status (R)
  22. command    equ    base+15    ;Commande (W)
  23.  
  24.             ;############## Screen holes used as RAM parameters for syscalls
  25. ph    equ    $47E    ;Head parameter
  26. ps    equ    $4FE    ; Sector parameter
  27. pcl    equ    $57E    ;Cyl (lsb) parameter
  28. pch    equ    $5FE    ;Cyl (msb) parameter
  29.  
  30.             ;############## Apple ROM useful routines
  31. home    equ    $FC58    ;Clear screen
  32. crout    equ    $FD8B    ;Outputs a CR/LF
  33. cout    equ    $FDED    ;Outputs reg. A as char
  34. strout    equ    $DB3A    ;Outputs AY-pointed null-terminated string
  35. prax    equ    $F941    ;Outputs AX as 4 hex digits
  36. pra    equ    $FDDA    ;Outputs A as 2 hex digits
  37. prspc    equ    $DB57    ;Outputs 1 space char
  38.  
  39.             ;############## Macros
  40.     do    0    ;No code generation
  41.  
  42. pr    mac        ;Outputs string without CR/LF
  43.     phy        
  44.     pha        
  45.     ldy    #>.0    
  46.     lda    #<.0    
  47.     jsr    strout    
  48.     pla        
  49.     ply        
  50.     eom        
  51.  
  52. prln    mac        ;Outputs string with CR/LF
  53.     pr    .0    
  54.     jsr    crout    
  55.     eom        
  56.  
  57.     fin        ;Revert to normal code generation
  58.  
  59.             ;############## Start of code
  60.     org    $4000    
  61.  
  62. init0    jmp    init    
  63.             ;############## Text messages
  64. secbuf    ds    512    ;RAM sector buffer (1 sector = 512 bytes in ATA world)
  65. m_hello    asc    "A2IDE 2001 stephane.guillard@steria.com"
  66.     dfb    0
  67. m_done    asc    "ok"
  68.     dfb    0
  69. m_yes    asc    "yes"
  70.     dfb    0
  71. m_no    asc    "no"
  72.     dfb    0
  73. m_hd    asc    "Non-packet IDE HD signature..."
  74.     dfb    0
  75. m_reset    asc    "Init HDà "
  76.     dfb    0
  77. m_qry    asc    "Get HD info..."
  78.     dfb    0
  79. m_name    asc    "Name.....:"
  80.     dfb    0
  81. m_firm    asc    "Firmware.:"
  82.     dfb    0
  83. m_ser    asc    "Serial #.:"
  84.     dfb    0
  85. m_cyl    asc    "Cylinders:&H"
  86.     dfb    0
  87. m_head    asc    "Heads....:&H"
  88.     dfb    0
  89. m_sec    asc    "Sectors..:&H"
  90.     dfb    0
  91. m_lba    asc    "Lba......:"
  92.     dfb    0
  93. m_mbr    asc    "Read MBR..."
  94.     dfb    0
  95. m_chk    asc    "MBR signature..."
  96.     dfb    0
  97. m_part    asc    "Partition #"
  98.     dfb    0
  99. m_undef    asc    "undef'd"
  100.     dfb    0
  101. m_act    asc    ">Active:"
  102.     dfb    0
  103. m_start    asc    ">CHS start:"
  104.     dfb    0
  105. m_end    asc    ", end :"
  106.     dfb    0
  107. m_type    asc    ", type "
  108.     dfb    0
  109. m_res    asc    ">Resvd secs:"
  110.     dfb    0
  111. m_seccnt    asc    ">Total secs:"
  112.     dfb    0
  113. m_rdy    asc    "Boot sector in secbuf at $"    
  114.     dfb    0    
  115. m_rdsect    asc    "RDSect() syscall at $"    
  116.     dfb    0    
  117.  
  118.             ;############## init() : main init routine
  119. init    jsr    home    ;Clear screen
  120.     prln    m_hello    
  121.     jsr    hdinit    ;Reset HD
  122.     bcs    done    
  123.     jsr    hdqry    ;Query and display HD info
  124.     bcs    done    
  125.     jsr    hdmbr    ;Analyze MBR and find 1st partition boot sector (leave CHS in RAM parameters)
  126.     bcs    done    
  127.     jsr    rdsect    ;Read 1st partition boot sector into RAM sector D42buffer
  128.     bcs    done    
  129.     pr    m_rdy    ;Print sector buffer address (for later use in other sw)
  130.     ldx    #<secbuf    
  131.     lda    #>secbuf    
  132.     jsr    prax    
  133.     jsr    crout    
  134.     pr    m_rdsect    ;Print RDSect() syscall address (for later use in other sw)
  135.     ldx    #<rdsect    
  136.     lda    #>rdsect    
  137.     jsr    prax    
  138.     jsr    crout    
  139. done    clc        
  140.     rts        ;End
  141.  
  142.             ;############## hdinit() : check IDE HDD signature and reset disk
  143. signok    prln    m_no    
  144.     sec        
  145.     rts        
  146. hdinit    pha        ;Init master IDE peripheral
  147.     stz    datmsb    ;Clear interface MSB register (we are going to make a few 8 bit transfers)
  148.     stz    drhead    ;Select master
  149.  
  150.     pr    m_hd    ;Check IDE non packet signature : seccnt=secnr=1,
  151.     lda    #$1    ;cyllow=cylhig=0
  152.     cmp    seccnt    ;If signature is different then peripheral may be an ATAPI (ATA w/packet
  153.     bne    signok    ;interface, like CD) or nothing
  154.     cmp    secnr    
  155.     bne    signok    
  156.     lda    #$0    
  157.     cmp    cyllow    
  158.     bne    signok    
  159.     cmp    cylhig    
  160.     bne    signok    
  161.     prln    m_yes    
  162.  
  163.     pr    m_reset    
  164.     lda    #$06    ;Start reset, no interrupts
  165.     sta    devctrl    
  166.     lda    #$02    ;Stop reset, no interrupts
  167.     sta    devctrl    
  168.     jsr    waitBSY    ;Wait for BUSY bit to go away
  169.     prln    m_done    
  170.     pla        
  171.     clc        
  172.     rts        
  173.  
  174.             ;############## hdmbr() ; read disk Master Boot Record, check it and analyze partition entries
  175. hdmbr    pha        ;Analyze MBR and find 1st partition boot sector (leave CHS in RAM parameters)
  176.     phx        
  177.     phy        
  178.  
  179.     pr    m_mbr    ;MBR = sector C=0, H=0, S=1
  180.     lda    #$1    
  181.     sta    ps    
  182.     stz    ph    
  183.     stz    pcl    
  184.     stz    pch    
  185.     jsr    rdsect    ;Read sector
  186.     prln    m_done    
  187.  
  188.     pr    m_chk    ;Check signature MBR : offset 1FE=$55AA
  189.     lda    secbuf+$1FE    
  190.     cmp    #$55    
  191.     beq    ]55ok    
  192.     jmp    ]signok    
  193. ]55ok    lda    secbuf+$1FF    
  194.     cmp    #$AA    
  195.     beq    ]AAok    
  196. ]signok    prln    m_no    
  197.     sec        
  198.     rts        
  199. ]AAok    prln    m_done    
  200.  
  201.             ;Scan the 4 partition entries of MBR (starts at secbuf+446)
  202.     ldy    #$0    ;Y=offset beginning part from (secbuf + 446) (Y may be 0, 16, 32, 48)
  203. ]nextprt    pr    m_part    ;Loop for 4 partition entries
  204.     tya        ;Store A in Y, and then A <- D272A/16
  205.     phy        
  206.     lsr        
  207.     lsr        
  208.     lsr        
  209.     lsr        
  210.     jsr    pra    ;Output current partition number (may be 0, 1, 2, 3)
  211.  
  212.     pr    m_type    ;Output partition type (as hex)
  213.     ply        
  214.     phy        
  215.     lda    secbuf+446+4,y    
  216.     bne    ]defined    ;If partition type is null then partition is not defined
  217.     prln    m_undef    
  218.     jmp    ]undef    
  219. ]defined    jsr    pra    
  220.     jsr    crout    
  221.  
  222.     pr    m_act    ;Output partition active flag Y/N
  223.     ply        
  224.     phy        
  225.     lda    secbuf+446+0,y    
  226.     cmp    #$80    
  227.     beq    ]active    
  228.     prln    m_no    
  229.     jmp    ]chs    
  230. ]active    prln    m_yes    
  231.  
  232. ]chs    pr    m_start    ;Output start / End CHS (note that start CHS is the boot sector of the partition)
  233.     ply        
  234.     phy        
  235.     lda    secbuf+446+2+1,y    ;A - Extract cyl# (10 bit) into AX
  236.     and    #$C0    ;A1 - Extract cyl# MSB which is in the 2 upper bits of sector#, into A
  237.     lsr        
  238.     lsr        
  239.     lsr        
  240.     lsr        
  241.     lsr        
  242.     lsr        
  243.     ldx    secbuf+446+2,y    ;A2 - Extract cyl# LSB into X
  244.     sta    pch    ;Store cyl# in RAM parameters for later RDSect() call by init() (to read in boot sector)
  245.     stx    pcl    
  246.     jsr    prax    
  247.     jsr    prspc    
  248.     ply        
  249.     phy        
  250.     lda    secbuf+446+1,y    ;B - Extract head#
  251.     sta    ph    ;Store head# in RAM parameters for later RDSect() call by init() (to read in boot sector)
  252.     jsr    pra    
  253.     jsr    prspc    
  254.     ply        
  255.     phy        
  256.     lda    secbuf+446+2+1,y    ;C - Extract sector# (and mask out the 2 upper bits which are part of cyl#, see A above)
  257.     and    #$3F    
  258.     sta    ps    ;Store sector# in RAM parameters for later RDSect() call by init() (to read in boot sector)
  259.     jsr    pra    
  260.     pr    m_end    ;Do the same for partition end CHS
  261.     ply        
  262.     phy        
  263.     lda    secbuf+446+6+1,y    ;MSB C
  264.     and    #$C0    
  265.     lsr        
  266.     lsr        
  267.     lsr        
  268.     lsr        
  269.     lsr        
  270.     lsr        
  271.     ldx    secbuf+446+6,y    ;LSB C
  272.     jsr    prax    
  273.     jsr    prspc    
  274.     ply        
  275.     phy        
  276.     lda    secbuf+446+5,y    ;H
  277.     jsr    pra    
  278.     jsr    prspc    
  279.     ply        
  280.     phy        
  281.     lda    secbuf+446+6+1,y    ;S
  282.     and    #$3F    
  283.     jsr    pra    
  284.     jsr    crout    
  285.  
  286.     pr    m_res    ;Reserved sectors (not implemented yet)
  287.     jsr    crout    
  288.  
  289.     pr    m_seccnt    ;Total sectors (not implemented yet)
  290.     jsr    crout    
  291.  
  292. ]undef    ply        ;Next partition : Y <- Y + 16
  293.     tya        
  294.     clc        
  295.     adc    #16    
  296.     tay        
  297.     cmp    #64    
  298.     beq    ]done    
  299.     jmp    ]nextprt    
  300.  
  301. ]done    ply        
  302.     plx        
  303.     pla        
  304.     clc        
  305.     rts        
  306.  
  307.             ;############## hdqry() : inquiry disk properties and display them
  308. hdqry    pha        
  309.     phx        
  310.     pr    m_qry    
  311.     stz    datmsb    
  312.     lda    #$EC    ;Send ATA Inquiry command
  313.     sta    command    
  314.     jsr    waitBSY    
  315.     jsr    waitDATA    
  316.     jsr    rd512byt    
  317.     prln    m_done    
  318.     pr    m_name    ;Output disk name
  319.     ldx    #54    
  320. ]nextc    lda    secbuf,x    
  321.     jsr    cout    
  322.     inx        
  323.     cpx    #94    
  324.     bne    ]nextc    
  325.     jsr    crout    
  326.     pr    m_firm    ;Output disk firmware rev.
  327.     ldx    #46    
  328. ]nextf    lda    secbuf,x    
  329.     jsr    cout    
  330.     inx        
  331.     cpx    #54    
  332.     bne    ]nextf    
  333.     jsr    crout    
  334.     pr    m_ser    ;Output disk serial #
  335.     ldx    #20    
  336. ]nexts    lda    secbuf,x    
  337.     jsr    cout    
  338.     inx        
  339.     cpx    #40    
  340.     bne    ]nexts    
  341.     jsr    crout    
  342.     pr    m_cyl    ;Output cylinder count
  343.     lda    secbuf+2    
  344.     ldx    secbuf+3    
  345.     jsr    prax    
  346.     jsr    crout    
  347.     pr    m_head    ;Output head count
  348.     lda    secbuf+6    
  349.     ldx    secbuf+7    
  350.     jsr    prax    
  351.     jsr    crout    
  352.     pr    m_sec    ;Output sector per track count
  353.     lda    secbuf+12    
  354.     ldx    secbuf+13    
  355.     jsr    prax    
  356.     jsr    crout    
  357.     pr    m_lba    ;Output LBA accepted flag (yes / no)
  358.     lda    secbuf+98    
  359.     bit    #8    
  360.     beq    ]nolba    
  361.     prln    m_yes    
  362.     jmp    ]done    
  363. ]nolba    prln    m_no    
  364. ]done    plx        
  365.     pla        
  366.     clc        
  367.     rts        
  368.  
  369.             ;############## rdsect() : read a sector pointed by pch/pcl, ph, ps into secbuf
  370. rdsect    pha        
  371.     lda    #$1    
  372.     sta    seccnt    ;We want to read 1 sector (multiple sector transfer is also possible)
  373.     lda    ps    
  374.     sta    secnr    ;Sector # in track
  375.     lda    pcl    
  376.     sta    cyllow    ;Cylinder # LSB
  377.     lda    pch    
  378.     sta    cylhig    ;Cylinder # MSB
  379.     lda    ph    
  380.     sta    drhead    ;Head #
  381.     stz    datmsb    
  382.     lda    #$20    
  383.     sta    command    ;Send ATA Read Sector command
  384.     jsr    waitBSY    ;Wait for BUSY to go away
  385.     jsr    waitDATA    ;Wait for DRQ to come (DRQ is Data ReQuest)
  386.     jsr    rd256wrd    ;Read 256 16 bit words into RAM sector buffer
  387.     pla        
  388.     clc        
  389.     rts        
  390.  
  391.             ;############## rd256wrd() : read 256 16 bit words into RAM sector buffer
  392. rd256wrd    phx        ;The trick is simple : we read the interface LSB first.
  393.     pha        ;This latches the drive's MSB at the same time into the interface MSB latch.
  394.     ldx    #$0    ;Then we read the interface's MSB latch and we have read the full 16 bits from the drive.
  395. ]next1    lda    datlsb    
  396.     sta    secbuf,X    
  397.     lda    datmsb    
  398.     sta    secbuf+1,X    
  399.     inx        
  400.     inx        
  401.     bne    ]next1    
  402. ]next2    lda    datlsb    
  403.     sta    secbuf+$100,X    
  404.     lda    datmsb    
  405.     sta    secbuf+$101,X    
  406.     inx        
  407.     inx        
  408.     bne    ]next2    
  409.     pla        
  410.     plx        
  411.     rts        
  412.  
  413.             ;############## rd512byt() : read 512 8 bit words into RAM sector buffer
  414. rd512byt    phx        ;Same as above. But as this is a 8 bit transfer, the order of the bytes come reversed.
  415.     pha        
  416.     ldx    #$0    
  417. ]next1    lda    datlsb
  418.     sta    secbuf+1,X
  419.     lda    datmsb
  420.     sta    secbuf,X
  421.     inx    
  422.     inx    
  423.     bne    ]next1
  424. ]next2    lda    datlsb
  425.     sta    secbuf+$101,X
  426.     lda    datmsb
  427.     sta    secbuf+$100,X
  428.     inx    
  429.     inx    
  430.     bne    ]next2
  431.     pla    
  432.     plx    
  433.     rts        
  434.  
  435.             ;############## waitDATA() : wait for DRQ bit to come
  436. waitDATA    pha        
  437. ]wait    lda    status    
  438.     bit    #$8    ;Loop until DRQ == 1
  439.     beq    ]wait    
  440.     pla        
  441.     rts        
  442.  
  443.             ;############## waitBSY() : wait for BUSY bit to go
  444. waitBSY    pha        
  445. ]wait    lda    status    
  446.     bit    #$80    ;Loop until BUSY == 0
  447.     bne    ]wait    
  448.     pla        
  449.     rts        
  450.  
  451.             ;############## dumpsec() : dump current sector in secbuf to screen (first as chars then as hex)
  452. dumpsec    pha        
  453.     phx        
  454.     phy        
  455.  
  456.     ldx    #$0    
  457. ]next1    lda    secbuf,x    
  458.     cmp    #$20    
  459.     bmi    ]notasc1    
  460.     cmp    #$7E    
  461.     bmi    ]done1    
  462. ]notasc1    lda    #32    
  463. ]done1    jsr    cout    
  464.     inx        
  465.     bne    ]next1
  466.  
  467. ]next2    lda    secbuf+$100,x
  468.     cmp    #$20
  469.     bmi    ]notasc2
  470.     cmp    #$7E
  471.     bmi    ]done2
  472. ]notasc2    lda    #32
  473. ]done2    jsr    cout
  474.     inx    
  475.     bne    ]next2
  476.  
  477.     jsr    crout
  478.  
  479.     ldy    #0
  480. ]next3    lda    secbuf+1,y
  481.     tax    
  482.     lda    secbuf,y
  483.     phy    
  484.     jsr    prax
  485.     ply    
  486.     iny    
  487.     iny    
  488.     bne    ]next3
  489.  
  490. ]next4    lda    secbuf+$101,y
  491.     tax    
  492.     lda    secbuf+$100,y
  493.     phy    
  494.     jsr    prax
  495.     ply    
  496.     iny    
  497.     iny    
  498.     bne    ]next4
  499.  
  500.     jsr    crout
  501.  
  502.     ply    
  503.     plx    
  504.     pla    
  505.     rts    
  506.