All pastes #1815152 Raw Edit

richard

public text v1 · immutable
#1815152 ·published 2010-02-28 01:31 UTC
rendered paste body
; base port register%define BASE_IO_PORT 0x1f0%define BASE_CMD_PORT 0x3f4%define ATA_SR_BSY     0x80%define ATA_SR_DRDY    0x40%define ATA_SR_DF      0x20%define ATA_SR_DSC     0x10%define ATA_SR_DRQ     0x08%define ATA_SR_CORR    0x04%define ATA_SR_IDX     0x02%define ATA_SR_ERR     0x01%define ATA_ER_BBK      0x80%define ATA_ER_UNC      0x40%define ATA_ER_MC       0x20%define ATA_ER_IDNF     0x10%define ATA_ER_MCR      0x08%define ATA_ER_ABRT     0x04%define ATA_ER_TK0NF    0x02%define ATA_ER_AMNF     0x01%define ATA_CMD_READ_PIO          0x20%define ATA_CMD_READ_PIO_EXT      0x24%define ATA_CMD_READ_DMA          0xC8%define ATA_CMD_READ_DMA_EXT      0x25%define ATA_CMD_WRITE_PIO         0x30%define ATA_CMD_WRITE_PIO_EXT     0x34%define ATA_CMD_WRITE_DMA         0xCA%define ATA_CMD_WRITE_DMA_EXT     0x35%define ATA_CMD_CACHE_FLUSH       0xE7%define ATA_CMD_CACHE_FLUSH_EXT   0xEA%define ATA_CMD_PACKET            0xA0%define ATA_CMD_IDENTIFY_PACKET   0xA1%define ATA_CMD_IDENTIFY          0xEC%define ATA_MODE 0xe;     *  Data Register: BAR0 + 0; // Read-Write;     * Error Register: BAR0 + 1; // Read Only;     * Features Register: BAR0 + 1; // Write Only;     * SECCOUNT0: BAR0 + 2; // Read-Write;     * LBA0: BAR0 + 3; // Read-Write;     * LBA1: BAR0 + 4; // Read-Write;     * LBA2: BAR0 + 5; // Read-Write;     * HDDEVSEL: BAR0 + 6; // Read-Write, used to select a drive in the channel.;     * Command Register: BAR0 + 7; // Write Only.;     * Status Register: BAR0 + 7; // Read Only.;     * Alternate Status Register: BAR1 + 2; // Read Only.;     * Control Register: BAR1 + 2; // Write Only.;     * DEVADDRESS: BAR1 + 2; // I don't know what is the benefit from this register.%define ATA_REG_DATA       BASE_IO_PORT+0x00%define ATA_REG_ERROR      BASE_IO_PORT+0x01%define ATA_REG_FEATURES   BASE_IO_PORT+0x01%define ATA_REG_SECCOUNT0  BASE_IO_PORT+0x02%define ATA_REG_LBA0       BASE_IO_PORT+0x03%define ATA_REG_LBA1       BASE_IO_PORT+0x04%define ATA_REG_LBA2       BASE_IO_PORT+0x05%define ATA_REG_HDDEVSEL   BASE_IO_PORT+0x06%define ATA_REG_COMMAND    BASE_IO_PORT+0x07%define ATA_REG_STATUS     BASE_IO_PORT+0x07; %define ATA_REG_SECCOUNT1  BASE_IO_PORT+0x08; %define ATA_REG_LBA3       BASE_IO_PORT+0x09; %define ATA_REG_LBA4       BASE_IO_PORT+0x0A; %define ATA_REG_LBA5       BASE_IO_PORT+0x0B%define ATA_REG_CONTROL    BASE_CMD_PORT+0x02%define ATA_REG_ALTSTATUS  BASE_CMD_PORT+0x02; %define ATA_REG_DEVADDRESS BASE_CMD_PORT+0x02%define high_io [ebx+4]%define low_io [ebx]cursor: dd 0xc00b8040putch:push ebxand ax,0x00ffor ax,0x7000mov ebx,[cursor]add bx,2mov [ebx],axmov [cursor],ebxpop ebxret%macro GETSTATUS 0xor eax,eax; mov edx,high_io ; mov dx,ATA_REG_ALTSTATUS; add dx,2mov edx,[ebx]add dx,7in al,dx%endmacro%macro PRINTSTATUS 0GETSTATUSpush eaxcall printstatuspop eax%endmacrowait_for_busy:GETSTATUStest ax,ATA_SR_BSYjz .endinc word [0xc00b8002]jmp wait_for_busy.end:retwait_for_drq:GETSTATUS; push eax; call printstatus; pop eaxtest ax,ATA_SR_DRQjnz .endinc word [0xc00b8012]jmp wait_for_drq.end:retwait_for_ready:GETSTATUStest ax,ATA_SR_DRDYjnz .endinc word [0xc00b8004]jmp wait_for_ready.end:ret; %macro GETADDRESSglobal ata_issue_identifyglobal ata_read_bufferglobal ata_28bit_operationglobal ata_read_testextern printstatus; param 1, drive no.; param 2, buffer; param 3, low io port; param 4, high io port; return 1 if not present, 0 otherwiseata_issue_identify:push ebpmov ebp,esppush ebxmov ebx,ebpadd ebx,16; select drivemov edx,[ebx]   ; mov dx,ATA_REG_HDDEVSELadd edx, 6mov eax, [ebp+8]and al,1	; do the bit twiddlingshl al,4or al,ATA_MODEout dx,al; PRINTSTATUSGETSTATUS ; pause a bitGETSTATUSGETSTATUScall wait_for_busy; wait for rdy; PRINTSTATUS; GETSTATUS; test al,ATA_SR_ERR; jz .noerror; xor eax,eax; ret; .noerror:GETSTATUStest al,ATA_SR_DRDYjnz .noerror2xor eax,eaxpop ebxpop ebpret.noerror2:; call wait_for_ready; now issue the identify command.mov ax, ATA_CMD_IDENTIFYmov edx,low_io ; mov dx,ATA_REG_COMMANDadd dx,7out dx,al; wait a few ticksGETSTATUSGETSTATUSGETSTATUSGETSTATUS; wait for !bsy and drqcall wait_for_busycall wait_for_drq; param 1, buffer (fixed at 512b len); param 2, low io port; param 3, high io portpush dword [ebx+4]push dword [ebx]mov eax,[ebp+12]push eax ; buffer ad.call ata_read_bufferadd esp,12; read into the buffer; it's possible a string instruction is incorrect though... it works///; mov edx,[ebx]	; data reg, no offset; mov edi, [ebp+12]	; destination buf; mov ecx,128 ; count (128 dwords = 512b); cld; rep insd; ;pop ebxpop ebpret; param 1, buffer (fixed at 512b len); param 2, low io port; param 3, high io portata_read_buffer:push ebxmov ebx,espadd ebx,12push ediGETSTATUStest al,ATA_SR_BSY|ATA_SR_ERRjnz .endtest al,ATA_SR_DRQjz .end; read into the buffer; it's possible a string instruction is incorrect though... it works///mov edx,[ebx]	; data reg, no offsetmov edi, [ebx-4]	; destination bufmov ecx,128 ; count (128 dwords = 512b)cldrep insd;.end:pop edipop ebxretextern ide_buf; param 1 low io; param 2 highata_read_test:push ebpmov ebp,esppush ebxmov ebx,ebpadd ebx,8push dword 0	; loop counterpush dword 0	; read itpush dword 1 ; sectorpush dword [ebx+4] ; high iopush dword [ebx] ; low iopush dword ide_buf ; bufferpush dword 0	; drive number.loop1:mov [ide_buf],dword 0mov eax,[esp+24]and eax,0xfshl eax,18mov [esp+16],eaxinc word [0xc00b8024]call ata_28bit_operationcall wait_for_busycall wait_for_drqGETSTATUStest eax,ATA_SR_ERRjz .noerrorPRINTSTATUS.noerror:push dword [ebx+4] ; high iopush dword [ebx] ; low iopush dword ide_buf ; buffercall ata_read_bufferadd esp,12mov al, [ide_buf]call putchmov al, [ide_buf+1]call putchmov al, [ide_buf+2]call putch; mov [0xc00b8040],eaxinc dword [esp+24]mov eax,[esp+24]cmp eax,1<<16; jle .loop1add esp,28pop ebxpop ebpret; param 1, drive no.; param 2, buffer; param 3, low io port; param 4, high io port; param 5, sector number; param 6, direction 1=write,0=read; return 1 if not present, 0 otherwiseata_28bit_operation:push ebpmov ebp,esppush ebxmov ebx,ebpadd ebx,16 ; param blocksub esp,4mov eax,[ebx+8]mov [esp],al ; lba_0shr eax,8mov [esp+1],al ; lba 1shr eax,8mov [esp+2],al ; lba 2shr eax,8; eax=head addressand al,0xf ; should be unnecessarymov [esp+3],alcall wait_for_busy; PRINTSTATUS; select drivemov edx,[ebx]   ; mov dx,ATA_REG_HDDEVSELadd edx, 6mov eax, [ebp+8]and al,1	; do the bit twiddlingshl al,4or al,0xe0or al,[esp+3]	; head countout dx,almov edx,[ebx]add dx,2mov al,1out dx,al	; sector countinc dxmov al,[esp]out dx,al	; lba0inc dxmov al,[esp+1]out dx,al	; lba1inc dxmov al,[esp+2]out dx,al	; lba2; mov eax,[ebx+8]; test eax,eax; jnz .writecmdmov al,ATA_CMD_READ_PIO; jmp .afterdecision; .writecmd:; mov al,ATA_CMD_WRITE_PIO; .afterdecision:mov edx,[ebx]add dx,7 ; command registerout dx,al; PRINTSTATUS; prologueadd esp,4pop ebxpop ebpret