258 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			258 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
	;; File: ata.inc
 | 
						|
	;;
 | 
						|
	;; Usefull links:
 | 
						|
	;; - <ATA PIO Mode at https://wiki.osdev.org/ATA_PIO_Mode>
 | 
						|
	;; - <IDE spec at https://www.cpcwiki.eu/imgs/a/a2/IDE_SPEC.PDF>
 | 
						|
 | 
						|
ATA_PRIMARY_IO        = 0x1F0
 | 
						|
ATA_PRIMARY_IO_CTRL   = 0x3F6
 | 
						|
ATA_SECONDARY_IO      = 0x170
 | 
						|
ATA_SECONDARY_IO_CTRL = 0x376
 | 
						|
 | 
						|
ATA_CHAN0_IO = 0x1F0
 | 
						|
ATA_CHAN1_IO = 0x170
 | 
						|
ATA_CHAN2_IO = 0x1E8
 | 
						|
ATA_CHAN3_IO = 0x168
 | 
						|
 | 
						|
	;; Constant:  ATA_DATA
 | 
						|
	;; Read/Write data
 | 
						|
ATA_DATA     = 0x0
 | 
						|
 | 
						|
	;; Constant: ATA_ERROR
 | 
						|
	;;
 | 
						|
	;; > ┌────┬─────┬────┬───┬────┬──┬───┬───┐
 | 
						|
    ;; > │AMNF│TKZNF│ABRT│MCR│IDNF│MC│UNC│BBK│
 | 
						|
    ;; > └────┴─────┴────┴───┴────┴──┴───┴───┘
 | 
						|
    ;; >      7     6    5   4    3  2   1   0
 | 
						|
	;;
 | 
						|
	;; AMNF  - Address mark not found.
 | 
						|
	;; TKZNF - Track zero not found.
 | 
						|
	;; ABRT  - Aborted command.
 | 
						|
	;; MCR   - Media change request.
 | 
						|
	;; IDNF  - ID not found.
 | 
						|
	;; MC    - Media changed
 | 
						|
	;; UNC   - Uncorrectable data error.
 | 
						|
	;; BBK   - Bad Block detected.
 | 
						|
	;;
 | 
						|
ATA_ERROR    = 0x1
 | 
						|
ATA_ERROR_AMNF  = 0x01
 | 
						|
ATA_ERROR_TKZNF = 0x02
 | 
						|
ATA_ERROR_ABRT  = 0x04
 | 
						|
ATA_ERROR_MCR   = 0x08
 | 
						|
ATA_ERROR_IDNF  = 0x10
 | 
						|
ATA_ERROR_MC    = 0x20
 | 
						|
ATA_ERROR_UNC   = 0x40
 | 
						|
ATA_ERROR_BBK   = 0x80
 | 
						|
 | 
						|
	;; Constant: ATA_FEATURES
 | 
						|
ATA_FEATURES = 0x1
 | 
						|
 | 
						|
	;; Constant: ATA_SECCOUNT
 | 
						|
ATA_SECCOUNT = 0x2
 | 
						|
 | 
						|
	;; Constant: ATA_SECNUM
 | 
						|
ATA_SECNUM   = 0x3
 | 
						|
 | 
						|
	;; Constant: ATA_CYLLO
 | 
						|
ATA_CYLLO    = 0x4
 | 
						|
 | 
						|
	;; Constant: ATA_CYLHI
 | 
						|
ATA_CYLHI    = 0x5
 | 
						|
 | 
						|
	;; Constant: ATA_DRVHEAD
 | 
						|
	;; Drive/Head register
 | 
						|
	;;
 | 
						|
ATA_DRVHEAD  = 0x6
 | 
						|
ATA_DRVHEAD_DRV = 0x10
 | 
						|
ATA_DRVHEAD_LBA = 0x40
 | 
						|
 | 
						|
	;; Constant: ATA_COMMAND
 | 
						|
ATA_COMMAND  = 0x7
 | 
						|
 | 
						|
	;; Constant: ATA_CMD_RESTORE
 | 
						|
	;; Recalibrate
 | 
						|
ATA_CMD_RESTORE    = 0x10
 | 
						|
	;; Constant: ATA_CMD_DIAGNOSTIC
 | 
						|
	;; Execute device diagnostic
 | 
						|
ATA_CMD_DIAGNOSTIC = 0x90
 | 
						|
	;; Constant: ATA_CMD_IDENTIFY
 | 
						|
ATA_CMD_IDENTIFY   = 0xA0
 | 
						|
 | 
						|
	;; Constant: ATA_STATUS
 | 
						|
	;; 
 | 
						|
ATA_STATUS   = 0x7
 | 
						|
ATA_STATUS_ERR  = 0x01
 | 
						|
ATA_STATUS_IDX  = 0x02
 | 
						|
ATA_STATUS_CORR = 0x04
 | 
						|
ATA_STATUS_DRQ  = 0x08
 | 
						|
ATA_STATUS_SRV  = 0x10
 | 
						|
ATA_STATUS_DF   = 0x20
 | 
						|
ATA_STATUS_RDY  = 0x40
 | 
						|
ATA_STATUS_BSY  = 0x80
 | 
						|
 | 
						|
	;; Constant: ATA_CTRL
 | 
						|
	;; Device control register (Control base + 0)
 | 
						|
ATA_CTRL = 0x0
 | 
						|
ATA_CTRL_nIEN = 0x02
 | 
						|
ATA_CTRL_SRST = 0x04
 | 
						|
ATA_CTRL_HOB  = 0x80
 | 
						|
 | 
						|
	;; Constant: ATA_DRVADDR
 | 
						|
	;; 
 | 
						|
ATA_DRVADDR = 0x1
 | 
						|
ATA_DRVADDR_DS0 = 0x01
 | 
						|
ATA_DRVADDR_DS1 = 0x02
 | 
						|
ATA_DRVADDR_WTG = 0x40
 | 
						|
 | 
						|
 | 
						|
	;; Function: ata_wait
 | 
						|
	;;
 | 
						|
	;; In:
 | 
						|
	;;    AX - IO port
 | 
						|
	;;
 | 
						|
ata_wait:
 | 
						|
	mov dx, ax
 | 
						|
	add dx, ATA_STATUS
 | 
						|
	xor ecx, ecx
 | 
						|
@@:
 | 
						|
	inc ecx
 | 
						|
	cmp ecx, 5000
 | 
						|
	jg @f
 | 
						|
	in al, dx
 | 
						|
	and al, ATA_STATUS_BSY
 | 
						|
	jnz @b
 | 
						|
@@:
 | 
						|
	ret
 | 
						|
 | 
						|
	;; Function: ata_select
 | 
						|
ata_select:
 | 
						|
	ret
 | 
						|
 | 
						|
ata_cmd:
 | 
						|
	ret
 | 
						|
 | 
						|
	;; Function: ata_probe
 | 
						|
	;; In:
 | 
						|
	;;    AX - IO port
 | 
						|
	;;
 | 
						|
ata_probe:
 | 
						|
	push bx
 | 
						|
	mov bx, ax
 | 
						|
	xor ecx, ecx
 | 
						|
.loop:
 | 
						|
	push ecx
 | 
						|
	call ata_wait
 | 
						|
	pop ecx
 | 
						|
 | 
						|
	; select drive
 | 
						|
	mov dx, bx
 | 
						|
	add dx, ATA_DRVHEAD
 | 
						|
	mov al, cl
 | 
						|
	shl al, 4
 | 
						|
	or al, 0xa0
 | 
						|
	out dx, al
 | 
						|
 | 
						|
	mov ax, bx
 | 
						|
	push ecx
 | 
						|
	call ata_wait
 | 
						|
	pop ecx
 | 
						|
 | 
						|
	mov dx, bx
 | 
						|
	add dx, ATA_COMMAND
 | 
						|
	mov al, ATA_CMD_DIAGNOSTIC
 | 
						|
	out dx, al
 | 
						|
 | 
						|
	mov ax, bx
 | 
						|
	push ecx
 | 
						|
	call ata_wait
 | 
						|
	pop ecx
 | 
						|
 | 
						|
	mov dx, bx
 | 
						|
	add dx, ATA_STATUS
 | 
						|
	in al, dx
 | 
						|
	and al, ATA_STATUS_ERR or ATA_STATUS_DRQ
 | 
						|
	jnz .skip
 | 
						|
 | 
						|
	mov ax, bx
 | 
						|
	push ecx
 | 
						|
	call ata_wait
 | 
						|
	pop ecx
 | 
						|
 | 
						|
	mov dx, bx
 | 
						|
	add dx, ATA_COMMAND
 | 
						|
	mov al, ATA_CMD_RESTORE
 | 
						|
	out dx, al
 | 
						|
 | 
						|
	mov ax, bx
 | 
						|
	push ecx
 | 
						|
	call ata_wait
 | 
						|
	pop ecx
 | 
						|
 | 
						|
	mov dx, bx
 | 
						|
	add dx, ATA_STATUS
 | 
						|
	in al, dx
 | 
						|
	and al, ATA_STATUS_ERR or ATA_STATUS_DRQ
 | 
						|
	jnz .skip
 | 
						|
 | 
						|
	push ecx
 | 
						|
	cmp bx, ATA_CHAN1_IO
 | 
						|
	jne @f
 | 
						|
	add ecx, 2
 | 
						|
	jmp .drive_found
 | 
						|
@@:
 | 
						|
	cmp bx, ATA_CHAN2_IO
 | 
						|
	jne @f
 | 
						|
	add ecx, 4
 | 
						|
	jmp .drive_found
 | 
						|
@@:
 | 
						|
	cmp bx, ATA_CHAN3_IO
 | 
						|
	jne @f
 | 
						|
	add ecx, 8
 | 
						|
	jmp .drive_found
 | 
						|
@@:
 | 
						|
.drive_found:
 | 
						|
	push ecx
 | 
						|
	mov esi, szMsgAtaFound
 | 
						|
	call klog
 | 
						|
	pop ecx
 | 
						|
.skip:
 | 
						|
	inc cl
 | 
						|
	cmp cl, 2
 | 
						|
	jb .loop
 | 
						|
	pop bx
 | 
						|
	ret
 | 
						|
 | 
						|
	;; Function: ata_init
 | 
						|
ata_init:
 | 
						|
	mov ecx, aAtaChans
 | 
						|
@@:
 | 
						|
	push ecx
 | 
						|
	mov ax, word [ecx]
 | 
						|
	call ata_probe
 | 
						|
	pop ecx
 | 
						|
	add ecx, 2
 | 
						|
	cmp ecx, aAtaChans.end
 | 
						|
	jb @b
 | 
						|
	ret
 | 
						|
 | 
						|
ata_primary_irq:
 | 
						|
	iret
 | 
						|
 | 
						|
ata_secondary_irq:
 | 
						|
	iret
 | 
						|
 | 
						|
ata_device:
 | 
						|
	db "ata", 0, 0, 0, 0, 0
 | 
						|
	dd ata_init
 | 
						|
 | 
						|
aAtaChans:
 | 
						|
	dw ATA_CHAN0_IO
 | 
						|
	dw ATA_CHAN1_IO
 | 
						|
	dw ATA_CHAN2_IO
 | 
						|
	dw ATA_CHAN3_IO
 | 
						|
.end:
 | 
						|
 | 
						|
ata_bdevsw:
 | 
						|
	dd 0
 | 
						|
 | 
						|
szMsgAtaFound db "ATA: hd%u found", 0
 |