INCLUDE Equates.s ORG Code_Start JSR CS_Init JSR Sys_INIT JSR UART_INIT JSR TimerINIT JSR I2C_Init CLR.L D0 MOVE.W #0x2500,D0 MOVE.W D0,0x10000036 ; Interrupt Mask Register MOVE.W #0x2000,SR CLR.L D0 CLR.L D1 CLR.L D2 CLR.L D4 CLR.L D6 MOVE.B D0,Eight_LEDs MOVE.B #0x00,D0 MOVE.B D0,0x100001C9 JSR Wait MOVE.L #STA_Conf,A6 BCLR.B #6,(A0) MOVE.B #0x86,D0 JSR I2C_Start MOVE.B D0,0x100001F0 ; BRA IDLE_LOOP MOVE.L #Init_LCD,A0 JSR StartTime CLR.L D0 ; JSR Wait_4ATA ; BRA Query_ATA IDLE_LOOP: NOP NOP BRA IDLE_LOOP Clr_Timer: CLR.L D0 ; 40uS = 0x64 Prescale MOVE.W #0xF919,D0 ; Stops the clock MOVE.W D0,0x10000100 MOVE.W #0xF901,D0 ; Resets the clock MOVE.W D0,0x1000010C RTS StartTime: CLR.L D0 MOVE.W #0xF91B,D0 ; Starts the clock MOVE.W D0,0x10000100 RTS UART1_INT: MOVE.B 0x1000014C,D1 ;UART Recieve Buffer CMP.L #0x1B,D1 BEQ Exit_Prog CMP.L #0x33,D1 BEQ Get_Stat CMP.L #0x34,D1 BEQ Get_Error CMP.L #0x36,D1 BEQ CLR_LCD CMP.L #0x37,D1 BEQ Send_1 CMP.L #0x38,D1 BEQ Send_2 CMP.L #0x39,D1 BEQ Send_3 CMP.L #0x30,D1 BEQ Send_4 RTE Exit_Prog: CLR.L D0 TRAP #15 BRA IDLE_LOOP Send_1: BCLR.B #6,(A0) MOVE.B #0x86,D0 JSR I2C_Start MOVE.B D0,0x100001F0 RTE Send_2: MOVE.B #0x01,D0 MOVE.B D0,0x100001F0 RTE Send_3: JSR I2C_2Strt NOP NOP MOVE.B #0x87,D0 MOVE.B D0,0x100001F0 NOP NOP NOP NOP BCLR.B #4,(A0) RTE Send_4: JSR I2C_Stop MOVE.B 0x100001F0,D7 MOVE.B 0x100001EC,D6 RTE Get_Stat: CLR.L D0 MOVE.W 0x70000038,D0 MOVE.B D0,0x80000007 RTE Get_Error: CLR.L D0 MOVE.W 0x70000008,D0 MOVE.B D0,Eight_LEDs RTE Get_BPB: JSR Wait_4ATA CLR.L D0 MOVE.W D0,0x70000020 JSR Wait_4ATA CLR.L D0 MOVE.W D0,0x70000028 JSR Wait_4ATA MOVE.W #0xE0,D0 MOVE.W D0,0x70000030 JSR Wait_4ATA MOVE.W #0x3F,D0 MOVE.W D0,0x70000018 JSR Wait_4ATA CLR.L D0 MOVE.W #0x03,D0 MOVE.W D0,0x70000010 JSR Wait_4ATA CLR.L D0 MOVE.W #0x20,D0 MOVE.W D0,0x70000038 JSR Get_Data JSR Store_BPB RTE CLR_LCD: MOVE.L #ClearLCD,A0 JSR StartTime RTE StartSpin: MOVE.L #Spinner,A0 JSR StartTime RTE Get_Data: CLR.L D1 MOVE.L #HDD_Buffer,A5 JSR Wait_4ATA MOVE.W 0x70000038,D0 AND.L #0x88,D0 CMP.L #0x08,D0 BNE End_L7 Loop_7: MOVE.W 0x70000000,D0 JSR End_Flip MOVE.W D0,(A5)+ NOP NOP NOP NOP MOVE.W 0x70000010,D0 MOVE.B D0,Eight_LEDs NOP NOP NOP NOP MOVE.W 0x70000038,D0 AND.L #0x88,D0 CMP.L #0x08,D0 BEQ Loop_7 End_L7: CLR.L D0 CLR.L D1 RTS End_Flip: MOVE.W D0,Temp_Word1 MOVE.L #Temp_Word1,A2 MOVE.L #Temp_Word2,A3 MOVE.B (A2)+,(A3)+ MOVE.B (A2),(A3) MOVE.L #Temp_Word1,A2 MOVE.B (A3),(A2)+ MOVE.B -(A3),(A2) MOVE.W Temp_Word1,D0 RTS Reset_IDE: CLR.L D0 MOVE.W #0x0C,D0 MOVE.W D0,0x70000032 NOP NOP NOP NOP MOVE.W #0x08,D0 MOVE.W D0,0x70000032 RTE Query_ATA: MOVE.B #0xEC,D0 MOVE.B D0,0x70000038 CLR.L D1 MOVE.L #LCD_Buffer,A1 MOVE.L #0x04010700,D0 ; Clear LCD MOVE.L D0,(A1)+ MOVE.L #0x10070004,D0 MOVE.L D0,(A1)+ CLR.L D0 MOVE.L #HDD_Buffer,A5 Loop_1: MOVE.W 0x70000000,D0 MOVE.W D0,(A5)+ NOP NOP NOP NOP MOVE.W 0x70000038,D0 AND.L #0x88,D0 CMP.L #0x08,D0 BEQ Loop_1 CLR.L D0 CLR.L D1 JSR Disp_DID JMP IDLE_LOOP Disp_DID: MOVE.L #HDD_Buffer,D0 ; Use HHD_Buffer + Offset of 54 ADD.L #54,D0 MOVE.L D0,A0 CLR.L D1 CLR.L D0 MOVE.L #Message_1,A2 JSR MSG_Copy1 Loop_2: MOVE.B #0x01,(A1)+ ; This loop adds the drive model MOVE.B (A0)+,D0 ; number (28 characters) to the LCD MOVE.B D0,(A1)+ ; buffer for the next update. ADDQ.L #0x01,D1 CMP.L #28,D1 BNE Loop_2 MOVE.L #Message_2,A2 JSR MSG_Copy1 MOVE.L #HDD_Buffer,D0 ; Use HHD_Buffer + Offset of 2 ADD.L #2,D0 MOVE.L D0,A0 CLR.L D1 ; The following (messy) code looks CLR.L D0 ; at the DriveID info, picks the MOVE.W (A0)+,D0 ; cyl/head/sec info out, multiplies MOVE.W (A0)+,D1 ; all of it together, and then MOVE.W (A0)+,D1 ; multiplies the result by 512. It MULU.L D0,D1 ; then sends this to Bin_ASCII to be CLR.L D0 ; put into a displayable format. For MOVE.W (A0)+,D0 ; a 1.6GB HDD: MOVE.W (A0)+,D0 ; Heads x Cylinders x Sectors per track MOVE.W (A0)+,D0 ; 16 x 3148 x 63 = 3173184 MULU.L D1,D0 ; 3173184 x 512 (512 bytes in a sector) MOVE.L #512,D1 ; = 1624670208 Bytes (0x60D68000 Bytes) MULU.L D1,D0 ; = 1.62467 GB JSR Bin_Hex MOVE.L #Message_3,A2 JSR MSG_Copy2 MOVE.L #HDD_Buffer,D0 ; Use HHD_Buffer + Offset of 98 ADD.L #98,D0 MOVE.L D0,A0 CLR.L D0 ; This segment uses the drive MOVE.W (A0),D0 ; capabilities information to AND.L #0x200,D0 ; determine wether or not the CMP.L #0x200,D0 ; drive can use logical block BEQ LBA_Here1 ; addressing and reports it's LBA_Here0: MOVE.L #Message_5,A2 ; findings to the LCD buffer. BRA Mess_Ret LBA_Here1: MOVE.L #Message_4,A2 Mess_Ret: CLR.L D0 JSR MSG_Copy2 MOVE.W #0x02C0,D0 MOVE.W D0,(A1)+ MOVE.L #Message_6,A2 CLR.L D0 JSR MSG_Copy2 CLR.L D0 MOVE.B 0x70000008,D0 ; Checks the error register for the CMP.L #0x01,D0 ; drives diagnostic code. If it = 1 BEQ Err_Here1 ; then everything is cool. If = to Err_Here1: MOVE.L #Message_5,A2 ; anything but 1, there's a problem BRA Error_Ret Err_Here0: MOVE.L #Message_4,A2 Error_Ret: CLR.L D0 JSR MSG_Copy2 MOVE.B #0x06,(A1)+ MOVE.L #LCD_Buffer,A0 JSR StartTime RTS MSG_Copy1: MOVE.B (A2)+,D0 ; Message copy and parsing sub for the CMP.L #0x06,D0 ; top half of the LCD. BEQ End_Copy1 MOVE.B #0x01,(A1)+ MOVE.B D0,(A1)+ BRA MSG_Copy1 End_Copy1: RTS MSG_Copy2: MOVE.B (A2)+,D0 ; Message copy and parsing sub for the CMP.L #0x06,D0 ; bottom half of the LCD. BEQ End_Copy2 MOVE.B #0x03,(A1)+ MOVE.B D0,(A1)+ BRA MSG_Copy2 End_Copy2: RTS Bin_Hex: CLR.L D1 ; Converts a 32-bit binary number in D0 CLR.L D2 ; into eight ASCII coded digits CLR.L D3 ; representitive of the hexadecimal Loop_4: ADDQ.L #0x01,D3 ; equivilent of the binary number. Loop_3: ADDQ.L #0x01,D1 LSL.L #1,D0 BCC No_Bit ADDQ.L #0x01,D2 No_Bit: LSL.L #1,D2 CMP.L #0x04,D1 BNE Loop_3 MOVE.B #0x01,(A1)+ JSR CMP_Nibbl CLR.L D2 CLR.L D1 CMP.L #0x08,D3 BNE Loop_4 RTS CMP_Nibbl: LSR.L #1,D2 CMP.L #0x00,D2 BNE Next_Nib0 MOVE.B #0x30,(A1)+ RTS Next_Nib0: CMP.L #0x01,D2 BNE Next_Nib1 MOVE.B #0x31,(A1)+ RTS Next_Nib1: CMP.L #0x02,D2 BNE Next_Nib2 MOVE.B #0x32,(A1)+ RTS Next_Nib2: CMP.L #0x03,D2 BNE Next_Nib3 MOVE.B #0x33,(A1)+ RTS Next_Nib3: CMP.L #0x04,D2 BNE Next_Nib4 MOVE.B #0x34,(A1)+ RTS Next_Nib4: CMP.L #0x05,D2 BNE Next_Nib5 MOVE.B #0x35,(A1)+ RTS Next_Nib5: CMP.L #0x06,D2 BNE Next_Nib6 MOVE.B #0x36,(A1)+ RTS Next_Nib6: CMP.L #0x07,D2 BNE Next_Nib7 MOVE.B #0x37,(A1)+ RTS Next_Nib7: CMP.L #0x08,D2 BNE Next_Nib8 MOVE.B #0x38,(A1)+ RTS Next_Nib8: CMP.L #0x09,D2 BNE Next_Nib9 MOVE.B #0x39,(A1)+ RTS Next_Nib9: CMP.L #0x0A,D2 BNE Next_NibA MOVE.B #0x41,(A1)+ RTS Next_NibA: CMP.L #0x0B,D2 BNE Next_NibB MOVE.B #0x42,(A1)+ RTS Next_NibB: CMP.L #0x0C,D2 BNE Next_NibC MOVE.B #0x43,(A1)+ RTS Next_NibC: CMP.L #0x0D,D2 BNE Next_NibD MOVE.B #0x44,(A1)+ RTS Next_NibD: CMP.L #0x0E,D2 BNE Next_NibE MOVE.B #0x45,(A1)+ RTS Next_NibE: MOVE.B #0x46,(A1)+ RTS Store_BPB: MOVE.L #HDD_Buffer,D0 ADD.L #0x0D,D0 MOVE.L D0,A0 MOVE.W (A0)+,D0 JSR End_Flip MOVE.W D0,Bytes_Per_Sec MOVE.B (A0)+,Sect_Per_Clus MOVE.W (A0)+,Rsvd_Sect_Cnt MOVE.B (A0)+,FAT_Table_Cnt MOVE.L #HDD_Buffer,D0 ADD.L #0x20,D0 MOVE.L D0,A0 MOVE.L (A0)+,D0 SWAP D0 MOVE.L D0,Total_Sectors MOVE.L (A0)+,D0 SWAP D0 MOVE.L D0,FAT_Size RTS Timer_INT: PUSH D0 CLR.L D0 MOVE.B #0x02,D0 MOVE.B D0,0x10000111 ; This clears the interrupts. Get_Point: MOVE.B (A0)+,D0 CMP.L #0x01,D0 ; High data BEQ High_Data CMP.L #0x03,D0 ; Low data BEQ Low_Data CMP.L #0x06,D0 ; End LCD BEQ End_LCD CMP.L #0x00,D0 BEQ High_Comm CMP.L #0x02,D0 BEQ Low_Comm CMP.L #0x04,D0 BEQ Dual_Comm CMP.L #0x05,D0 BEQ Dual_Data CMP.L #0x07,D0 BEQ New_Perio CMP.L #0x08,D0 BEQ Repeater BRA End_LCD1 Dual_Data: MOVE.B (A0)+,D0 MOVE.B D0,0x80000001 MOVE.B D0,0x80000003 BRA End_LCD1 High_Data: MOVE.B (A0)+,D0 MOVE.B D0,0x80000001 BRA End_LCD1 High_Comm: MOVE.B (A0)+,D0 MOVE.B D0,0x80000000 BRA End_LCD1 Low_Data: MOVE.B (A0)+,D0 MOVE.B D0,0x80000003 BRA End_LCD1 Low_Comm: MOVE.B (A0)+,D0 MOVE.B D0,0x80000002 BRA End_LCD1 Dual_Comm: MOVE.B (A0)+,D0 MOVE.B D0,0x80000000 MOVE.B D0,0x80000002 BRA End_LCD1 New_Perio: MOVE.W (A0)+,D0 MOVE.W D0,0x10000104 CLR.L D0 BRA End_LCD1 Repeater: MOVE.L A0,D0 SUB.L #17,D0 MOVE.L D0,A0 CLR.L D0 BRA Get_Point End_LCD: JSR Clr_Timer MOVE.L #0x00,A0 End_LCD1: PULL D0 RTE I2C_Int: PUSH D0 PUSH A0 PUSH A1 CLR.L D0 MOVE.L #0x100001E8,A0 MOVE.L #STA_End,A1 MOVE.B D0,0x100001EC ; Clears the interrupt. BSET.B #4,(A0) CMPA.L A1,A6 BEQ End_I2C MOVE.B (A6)+,D0 MOVE.B D0,0x100001F0 MOVE.B 0x100001EC,D5 PULL A1 PULL A0 PULL D0 RTE End_I2C: BCLR.B #5,(A0) ; Generate a STOP condition. PULL A1 PULL A0 PULL D0 RTE I2C_Stop: PUSH A0 MOVE.L #0x100001E8,A0 BCLR.B #5,(A0) PULL A0 RTS I2C_Start: PUSH A0 MOVE.L #0x100001E8,A0 BSET.B #5,(A0) PULL A0 RTS I2C_2Strt: PUSH A0 MOVE.L #0x100001E8,A0 BSET.B #2,(A0) PULL A0 RTS Wait_4ATA: MOVE.W 0x70000038,D0 MOVE.B D0,Eight_LEDs AND.L #0xF0,D0 CMP.L #0x50,D0 BNE Wait_4ATA RTS Wait: NOP ; This wait loop is only here to wait for ADDQ.L #0x01,D0 ; the hard drive to assert the busy bit CMP.L #0x01FF,D0 ; in the status register before the BEQ Wait_Next ; program goes to check it. BRA Wait Wait_Next: NOP RTS INCLUDE INIT.S INCLUDE MESSAGES.S