diff --git a/kernel/trunk/const.inc b/kernel/trunk/const.inc index 731a26cc25..3bc15cb16f 100644 --- a/kernel/trunk/const.inc +++ b/kernel/trunk/const.inc @@ -851,37 +851,6 @@ struct PCIDEV owner dd ? ; pointer to SRV or 0 ends -struct IDE_DATA - ProgrammingInterface dd ? - Interrupt dw ? - RegsBaseAddres dw ? - BAR0_val dw ? - BAR1_val dw ? - BAR2_val dw ? - BAR3_val dw ? - dma_hdd_channel_1 db ? - dma_hdd_channel_2 db ? - pcidev dd ? ; pointer to corresponding PCIDEV structure -ends - -struct IDE_CACHE - pointer dd ? - size dd ? ; not use - data_pointer dd ? - system_data_size dd ? ; not use - appl_data_size dd ? ; not use - system_data dd ? - appl_data dd ? - system_sad_size dd ? - appl_sad_size dd ? - search_start dd ? - appl_search_start dd ? -ends - -struct IDE_DEVICE - UDMA_possible_modes db ? - UDMA_set_mode db ? -ends ; The following macro assume that we are on uniprocessor machine. ; Serious work is needed for multiprocessor machines. diff --git a/kernel/trunk/detect/init_ata.inc b/kernel/trunk/detect/init_ata.inc index b2a8c9e07f..3bc1612e79 100644 --- a/kernel/trunk/detect/init_ata.inc +++ b/kernel/trunk/detect/init_ata.inc @@ -5,23 +5,43 @@ ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +struct IDE_DEVICE + UDMA_possible_modes db ? + UDMA_set_mode db ? +ends -; clear the DRIVE_DATA table -; author - Mario79 - xor eax, eax - mov edi, DRIVE_DATA - mov ecx, DRIVE_DATA_SIZE/4 - cld - rep stosd +struct IDE_CHANNEL ; sizeof = 2*dword + base dw ? ; BAR0 or BAR2 + ctrl dw ? ; (BAR1 or BAR3) + 2 + dev_0 IDE_DEVICE ; word -1 for not device + dev_1 IDE_DEVICE +ends + +struct IDE_DATA ; sizeof = 2*dword + 4*dword + 2*dword + ProgrammingInterface dd ? + Interrupt dw ? + RegsBaseAddres dw ? + channel_1 IDE_CHANNEL + channel_2 IDE_CHANNEL + dma_hdd_channel_1 db ? + dma_hdd_channel_2 db ? + dw ? + pcidev dd ? ; pointer to corresponding PCIDEV structure +ends + +init_ide: ;----------------------------------------------------------------------------- ; find the IDE controller in the device list ;----------------------------------------------------------------------------- + and dword[ide_dev_number], 0 + + mov ecx, IDE_controller_1 mov esi, pcidev_list ;-------------------------------------- align 4 .loop: - mov esi, [esi+PCIDEV.fd] + mov esi, [esi + PCIDEV.fd] cmp esi, pcidev_list jz find_IDE_controller_done @@ -33,17 +53,18 @@ align 4 jnz .loop ;-------------------------------------- .found: - mov eax, [esi+PCIDEV.class] + push esi ecx + mov eax, [esi + PCIDEV.class] DEBUGF 1, 'K : IDE controller programming interface %x\n', eax - mov [ecx+IDE_DATA.ProgrammingInterface], eax - mov [ecx+IDE_DATA.pcidev], esi + mov [ecx + IDE_DATA.ProgrammingInterface], eax + mov [ecx + IDE_DATA.pcidev], esi - mov ah, [esi+PCIDEV.bus] + mov ah, [esi + PCIDEV.bus] mov al, 2 - mov bh, [esi+PCIDEV.devfn] + mov bh, [esi + PCIDEV.devfn] ;-------------------------------------- mov dx, 0x1F0 - test byte [esi+PCIDEV.class], 1 + test byte [esi + PCIDEV.class], 1 jz @f mov bl, 0x10 push eax @@ -53,10 +74,10 @@ align 4 pop eax @@: DEBUGF 1, 'K : BAR0 IDE base addr %x\n', dx - mov [ecx+IDE_DATA.BAR0_val], dx + mov [ecx + IDE_DATA.channel_1.base], dx ;-------------------------------------- mov dx, 0x3F4 - test byte [esi+PCIDEV.class], 1 + test byte [esi + PCIDEV.class], 1 jz @f mov bl, 0x14 push eax @@ -66,10 +87,11 @@ align 4 pop eax @@: DEBUGF 1, 'K : BAR1 IDE base addr %x\n', dx - mov [ecx+IDE_DATA.BAR1_val], dx + add dx, 2 + mov [ecx + IDE_DATA.channel_1.ctrl], dx ;-------------------------------------- mov dx, 0x170 - test byte [esi+PCIDEV.class], 4 + test byte [esi + PCIDEV.class], 4 jz @f mov bl, 0x18 push eax @@ -79,10 +101,10 @@ align 4 pop eax @@: DEBUGF 1, 'K : BAR2 IDE base addr %x\n', dx - mov [ecx+IDE_DATA.BAR2_val], dx + mov [ecx + IDE_DATA.channel_2.base], dx ;-------------------------------------- mov dx, 0x374 - test byte [esi+PCIDEV.class], 4 + test byte [esi + PCIDEV.class], 4 jz @f mov bl, 0x1C push eax @@ -92,14 +114,15 @@ align 4 pop eax @@: DEBUGF 1, 'K : BAR3 IDE base addr %x\n', dx - mov [ecx+IDE_DATA.BAR3_val], dx + add dx, 2 + mov [ecx + IDE_DATA.channel_2.ctrl], dx ;-------------------------------------- mov bl, 0x20 push eax call pci_read_reg and eax, 0xFFFC DEBUGF 1, 'K : BAR4 IDE controller register base addr %x\n', ax - mov [ecx+IDE_DATA.RegsBaseAddres], ax + mov [ecx + IDE_DATA.RegsBaseAddres], ax pop eax ;-------------------------------------- mov bl, 0x3C @@ -107,39 +130,442 @@ align 4 call pci_read_reg and eax, 0xFF DEBUGF 1, 'K : IDE Interrupt %x\n', al - mov [ecx+IDE_DATA.Interrupt], ax + mov [ecx + IDE_DATA.Interrupt], ax pop eax +;-------------------------------------- + mov eax, -1 ; set full bit + mov dword[ecx + IDE_DATA.channel_1.dev_0], eax ; dev_0 and dev_1 + mov dword[ecx + IDE_DATA.channel_2.dev_0], eax ; dev_0 and dev_1 +;------- Init thish controller and enum all disk on chenals + mov esi, boot_disabling_ide + call boot_log +;-------------------------------------- +; Disable IDE interrupts, because the search +; for IDE partitions is in the PIO mode. +;-------------------------------------- +; Disable interrupts in IDE controller for PIO + mov al, 2 + mov dx, [ecx + IDE_DATA.channel_1.ctrl] + out dx, al + mov dx, [ecx + IDE_DATA.channel_2.ctrl] + out dx, al +;------- Find ide devices + ;ide_dev_number = ((1/0 channal) shl 1) + (1/0 device on channal) + mov ebp, esp + + sub esp, 16 + call ide_check_device + + inc dword[ide_dev_number] + sub esp, 16 + call ide_check_device + + inc dword[ide_dev_number] + sub esp, 16 + call ide_check_device + + inc dword[ide_dev_number] + sub esp, 16 + call ide_check_device + + inc dword[ide_dev_number] ; ide_dev_number + 4 +;-------------------------------------- + + mov dx, [ecx + IDE_DATA.RegsBaseAddres] +; test whether it is our interrupt? + add dx, 2 + in al, dx + test al, 100b + jz @f +; clear Bus Master IDE Status register +; clear Interrupt bit + out dx, al +;-------------------------------------- +@@: + add dx, 8 +; test whether it is our interrupt? + in al, dx + test al, 100b + jz @f +; clear Bus Master IDE Status register +; clear Interrupt bit + out dx, al +;-------------------------------------- +@@: +; read status register and remove the interrupt request + mov dx, [ecx + IDE_DATA.channel_1.base] + add dx, 0x7 ;0x1F7 + in al, dx + mov dx, [ecx + IDE_DATA.channel_2.base] + add dx, 0x7 ;0x177 + in al, dx +;----------------------------------------------------------------------------- +; set interrupts for IDE Controller +;----------------------------------------------------------------------------- + spin_lock_irqsave +.enable_IDE_interrupt: + mov esi, boot_enabling_ide + call boot_log + +;------- Set DMA mode + xor eax, eax + cmp dword[ecx + IDE_DATA.channel_1.dev_0], -1 + jne @f +;-------------------------------------- +.ch1_pio_set_no_devices: + DEBUGF 1, "K : IDE CH1 PIO because no devices\n" + jmp .ch1_pio_set_for_all +;------------------------------------- +.ch1_pio_set: + DEBUGF 1, "K : IDE CH1 PIO because device not support UDMA\n" +.ch1_pio_set_for_all: + mov [ecx + IDE_DATA.dma_hdd_channel_1], al + jmp .ch2_check + +@@: + cmp [ecx + IDE_DATA.channel_1.dev_0.UDMA_possible_modes], al + je .ch1_pio_set + + cmp [ecx + IDE_DATA.channel_1.dev_0.UDMA_set_mode], al + je .ch1_pio_set + + cmp [ecx + IDE_DATA.channel_1.dev_1.UDMA_possible_modes], al + je .ch1_pio_set + + cmp [ecx + IDE_DATA.channel_1.dev_1.UDMA_set_mode], al + je .ch1_pio_set + + mov dx, [ecx + IDE_DATA.channel_1.base] + add dx, 2 + out dx, al + call set_pci_command_bus_master + DEBUGF 1, "K : IDE CH1 DMA enabled\n" + mov [ecx + IDE_DATA.dma_hdd_channel_1], byte 1 + +.ch2_check: + cmp dword[ecx + IDE_DATA.channel_2.dev_0], -1 + jne @f + +;-------------------------------------- +.ch2_pio_set_no_devices: + DEBUGF 1, "K : IDE CH2 PIO because no devices\n" + jmp .ch2_pio_set_for_all +;-------------------------------------- +.ch2_pio_set: + DEBUGF 1, "K : IDE CH2 PIO because device not support UDMA\n" +;-------------------------------------- +.ch2_pio_set_for_all: + mov [ecx+IDE_DATA.dma_hdd_channel_2], al + jmp .set_interrupts_for_IDE_controllers + +@@: + cmp [ecx + IDE_DATA.channel_2.dev_0.UDMA_possible_modes], al + je .ch2_pio_set + + cmp [ecx + IDE_DATA.channel_2.dev_0.UDMA_set_mode], al + je .ch2_pio_set + + cmp [ecx + IDE_DATA.channel_2.dev_1.UDMA_possible_modes], al + je .ch2_pio_set + + cmp [ecx + IDE_DATA.channel_2.dev_1.UDMA_set_mode], al + je .ch2_pio_set + + mov dx, [ecx + IDE_DATA.channel_2.base] + add dx, 2 + out dx, al + call set_pci_command_bus_master + DEBUGF 1, "K : IDE CH2 DMA enabled\n" + mov [ecx+IDE_DATA.dma_hdd_channel_2], byte 1 + + ; set irq handlers +.set_interrupts_for_IDE_controllers: + mov esi, boot_set_int_IDE + call boot_log +;-------------------------------------- + mov eax, [ecx + IDE_DATA.ProgrammingInterface] + + test al, 1 ; 0 - legacy PCI mode, 1 - native PCI mode + jnz .sata_ide +;-------------------------------------- +.pata_ide: + cmp [ecx + IDE_DATA.RegsBaseAddres], 0 + je .end_set_interrupts + + push ecx + stdcall attach_int_handler, 14, IDE_irq_14_handler, ecx + pop ecx + DEBUGF 1, "K : Set IDE IRQ14 return code %x\n", eax + push ecx + stdcall attach_int_handler, 15, IDE_irq_15_handler, ecx + DEBUGF 1, "K : Set IDE IRQ15 return code %x\n", eax + pop ecx + + jmp .end_set_interrupts + +.sata_ide: +; Some weird controllers generate an interrupt even if IDE interrupts +; are disabled and no IDE devices. For example, notebook ASUS K72F - +; IDE controller 010185 generates false interrupt when we work with +; the IDE controller 01018f. For this reason, the interrupt handler +; does not need to be installed if both channel IDE controller +; running in PIO mode. + +; ...unfortunately, PCI interrupt can be shared with other devices +; which could enable it without consulting IDE code. +; So install the handler anyways and try to process +; even those interrupts which we are not expecting. + cmp [ecx + IDE_DATA.RegsBaseAddres], 0 + je .end_set_interrupts + + mov ax, [ecx + IDE_DATA.Interrupt] + movzx eax, al + push ecx + stdcall attach_int_handler, eax, IDE_common_irq_handler, ecx + pop ecx + DEBUGF 1, "K : Set IDE IRQ%d return code %x\n", [ecx + IDE_DATA.Interrupt]:1, eax +;-------------------------------------- +.end_set_interrupts: + spin_unlock_irqrestore + ; added disks in kernel list + ; [esp + 12] - pdata(HD_DATA/CD_DATA) + ; [esp + 8] - name \ ASCII name 'XXX' + ; [esp + 4] - name / 'hdXX' + ; [esp] - ptr to ide_disk_add/ide_atapi_add + + ; in ebp end of array params +@@: + pop eax + call eax + cmp esp, ebp + jnz @b +.end_init: +;-------------------------------------- + pop ecx esi add ecx, sizeof.IDE_DATA ;-------------------------------------- jmp .loop ;----------------------------------------------------------------------------- + +ide_disk_add: + lea eax, [esp + 4] + mov edx, [esp + 12] + stdcall disk_add, ide_callbacks, eax, edx, 0 + test eax, eax + jz @f + + stdcall disk_media_changed, eax, 1 +@@: + ret 12 + +ide_atapi_add: + lea eax, [esp + 4] + mov edi, [esp + 12] + ;stdcall disk_add, cd_callbacks, eax, edi, 0 + test eax, eax + jz @f + + ;mov [edi + CD_DATA.disk], eax + + ; check loading media + + ; mount media + ;stdcall disk_media_changed, eax, 1 +@@: + ret 12 + +;----------------------------------------------------------------------------- +; [esp + 16] - pdata(HD_DATA/CD_DATA) +; [esp + 12] - name \ ASCII name 'XXX' +; [esp + 8] - name / 'hdXX' +; [esp + 4] - ptr to ide_disk_add/ide_atapi_add +; ecx - IDE_DATA +ide_check_device: + push ecx ebx ebp + + mov ebx, [ide_dev_number] + shr ebx, 1 + and ebx, 1 + + lea ebp, [IDE_DATA.channel_1 + ebx*sizeof.IDE_CHANNEL] + add ebp, ecx + + DEBUGF 1, "K : Channel %d ",ebx + DEBUGF 1, "Disk %d\n",[ide_dev_number]:1 + + mov ebx, [ide_dev_number] + imul ebx, sizeof.HD_DATA + add ebx, hd0_data + mov [esp + 3*4 + 16], ebx ; ebx - HD_DATA + + mov ax, [ebp + IDE_CHANNEL.base] + mov [ebx + HD_DATA.hdbase], ax + + ; ebp - IDE_CHANNEL + ; ebx - HD_DATA + stdcall kernel_alloc, 512 ; allocate 512 byte(in real allocated 4096) + test eax, eax + jz .err_memory + + mov edi, eax; buffer + + call ide_ata_identify + cmp eax, 7 + je .end_mem + test eax, eax + jnz .FindCD + + cmp word[edi + 6], 16 + ja .FindCD + cmp word[edi + 12], 255 + ja .FindCD +.FindHDD: + mov word[esp + 3*4 + 8], 'hd' + mov dword[esp + 3*4 + 4], ide_disk_add + + mov ecx, [edi + 120] + mov dword[ebx + HD_DATA.sectors], ecx + and dword[ebx + HD_DATA.sectors+4], 0 + bt word [edi + 166], 10 + jnc .dev_found + + mov [ebx + HD_DATA.hd48], 1 + mov ecx, [edi + 200] + mov dword[ebx + HD_DATA.sectors], ecx + mov ecx, [edi + 204] + mov dword[ebx + HD_DATA.sectors+4], ecx + jmp .dev_found +.FindCD: + call ide_device_reset + test eax, eax + jnz .end_mem + + call ide_atapi_identify + test eax, eax + jnz .end_mem + + + mov word[esp + 3*4 + 8], 'cd' + mov dword[esp + 3*4 + 4], ide_atapi_add + +.dev_found: + add ebp, IDE_CHANNEL.dev_0 + test byte[ide_dev_number], 1b + je @f + add ebp, sizeof.IDE_DEVICE +@@: + ; ebp - IDE_DEVICE + +.copy_dev_name: + + push edi + lea esi, [edi + 27*2] ; Model number (40 ASCII characters) + mov edi, esi + mov ecx, 20 + cld +;-------------------------------------- +@@: + lodsw + xchg ah, al + stosw + loop @b + + xor ecx, ecx + mov edx, [esi] + mov eax, [esp] + mov [esi], ecx + add eax, 27*2 + DEBUGF 1, "K : Dev: %s \n", eax + mov [esi], edx + + pop edi + + ; set flags DMA mode of selected disk + xor eax, eax + mov edx, eax + mov ax, [edi + 64*2] + DEBUGF 1, "K : PIO possible modes %x\n", al + + mov ax, [edi + 51*2] + mov al, ah + + xor ah, ah + bsf dx, ax + jnz @f + xor edx, edx +@@: + DEBUGF 1, "K : PIO set mode %x\n", dl + + mov ax, [edi + 63*2] + DEBUGF 1, "K : Multiword DMA possible modes %x\n", al + mov al, ah + + xor ah, ah + bsf dx, ax + jnz @f + xor edx, edx +@@: + DEBUGF 1, "K : Multiword DMA set mode %x\n", dl + + mov ax, [edi + 88*2] + DEBUGF 1, "K : Ultra DMA possible modes %x\n", al + mov [ebp + IDE_DEVICE.UDMA_possible_modes], al + mov al, ah + + xor ah, ah + bsf dx, ax + jnz @f + xor edx, edx +@@: + DEBUGF 1, "K : Ultra DMA set mode %x\n", ah + mov [ebp + IDE_DEVICE.UDMA_set_mode], ah + + + ; calc and set number of disk + mov eax, [ide_dev_number] ; max 12 - 3 ide controllers + mov edx, '0' + add edx, eax + cmp eax, 10 + jb @f + + mov edx, '10' + sub eax, 10 + add dh, al +@@: + mov [esp + 3*4 + 10], edx + + ; fixed PIO mode for ATAPI device + cmp word[esp + 3*4 + 8], 'cd' + jne @f + + mov word[ebp], 0 ; clear DMA flags for set PIO mode +@@: + stdcall kernel_free, edi + pop ebp ebx ecx + ret + +.end_mem: + stdcall kernel_free, edi +.end: +.err_memory: + DEBUGF 1, "K : Device not found\n" + pop ebp ebx ecx + ret 16 + + + uglobal align 4 +; number use for found HD_DATA/CD_DATA, IDE_DATA and IDE_CHANNAL +ide_dev_number rd 1 ; number of device on ide controller +; (ide_controller_num shl 2) + (ide_channel shl 1) + dev_num ;-------------------------------------- IDE_controller_pointer dd ? ;-------------------------------------- IDE_controller_1 IDE_DATA IDE_controller_2 IDE_DATA IDE_controller_3 IDE_DATA -;-------------------------------------- -cache_ide0 IDE_CACHE -cache_ide1 IDE_CACHE -cache_ide2 IDE_CACHE -cache_ide3 IDE_CACHE -cache_ide4 IDE_CACHE -cache_ide5 IDE_CACHE -cache_ide6 IDE_CACHE -cache_ide7 IDE_CACHE -cache_ide8 IDE_CACHE -cache_ide9 IDE_CACHE -cache_ide10 IDE_CACHE -cache_ide11 IDE_CACHE -;-------------------------------------- -IDE_device_1 rd 2 -IDE_device_2 rd 2 -IDE_device_3 rd 2 -;-------------------------------------- endg ;-------------------------------------- @@ -166,312 +592,246 @@ PCI_COMMAND_BUS_MASTER = 0x0004 pop ecx eax ret -;----------------------------------------------------------------------------- -; START of initialisation IDE ATA code -;----------------------------------------------------------------------------- -Init_IDE_ATA_controller: - cmp [ecx+IDE_DATA.ProgrammingInterface], 0 - jne @f - ret -;-------------------------------------- -@@: - mov esi, boot_disabling_ide - call boot_log -;-------------------------------------- -; Disable IDE interrupts, because the search -; for IDE partitions is in the PIO mode. -;-------------------------------------- -.disable_IDE_interrupt: -; Disable interrupts in IDE controller for PIO - mov al, 2 - mov dx, [ecx+IDE_DATA.BAR1_val] ;0x3F4 - add dx, 2 ;0x3F6 +virtual at esp +ide_send_cmd_args: +.ATAFeatures db ? +.ATASectorCount db ? +.ATASectorNumber db ? +.ATACylinder dw ? +.ATAHead db ? +.ATACommand db ? +.size = $ - ide_send_cmd_args +end virtual + +ATA_ADDR_MODE_CHS = 0 +ATA_ADDR_MODE_LBA = 1 shl 6 +ATA_DISK_NUM_OFFSET = 4 + +ATA_HEAD_REG_VALUE = 10100000b + +;----------------------------------------------------------------------------- +; IN: ebp - IDE_CHANNEL +; [ide_dev_number] AND 1b - disk number +; edi - buffer for data(512 bytes) +; Saved edi, ebx and ebp registers +ide_ata_identify: + sub esp, ide_send_cmd_args.size + mov dword[ide_send_cmd_args.ATASectorCount], 0 + ; send device identification command + mov [ide_send_cmd_args.ATAFeatures], 0 + mov [ide_send_cmd_args.ATAHead], 0 + ATA_ADDR_MODE_CHS + mov [ide_send_cmd_args.ATACommand], 0xEC + + jmp ide_atapi_identify.send_command +;----------------------------------------------------------------------------- +; IN: ebp - IDE_CHANNEL +; [ide_dev_number] AND 1b - disk number +; edi - buffer for data(512 bytes) +; Saved edi, ebx and ebp registers +ide_atapi_identify: + sub esp, ide_send_cmd_args.size + ; Send command for device identification + mov [ide_send_cmd_args.ATAFeatures], 0 + mov [ide_send_cmd_args.ATASectorCount], 0 + mov [ide_send_cmd_args.ATASectorNumber], 0 + mov [ide_send_cmd_args.ATACylinder], 0 + mov [ide_send_cmd_args.ATAHead], 0 + ATA_ADDR_MODE_CHS + mov [ide_send_cmd_args.ATACommand], 0xA1 + +.send_command: + ; Waiting for HDD ready to receive a command + ; Choose desired disk + mov dx, [ebp + IDE_CHANNEL.base] + add dx, 6 ; address of the heads register + mov al, byte[ide_dev_number] + and al, 1b ; al = disk number (0 or 1) + + shl al, 4 + or al, 10100000b out dx, al - mov dx, [ecx+IDE_DATA.BAR3_val] ;0x374 - add dx, 2 ;0x376 - out dx, al -;----------------------------------------------------------------------------- -; set current ata bases -@@: - mov ax, [ecx+IDE_DATA.BAR0_val] - mov [StandardATABases], ax - mov ax, [ecx+IDE_DATA.BAR2_val] - mov [StandardATABases+2], ax - - mov esi, boot_detecthdcd - call boot_log -;-------------------------------------- -include 'dev_hdcd.inc' -;-------------------------------------- - ret -;----------------------------------------------------------------------------- -Init_IDE_ATA_controller_2: - cmp [ecx+IDE_DATA.ProgrammingInterface], 0 - jne @f - - ret -;-------------------------------------- -@@: - mov dx, [ecx+IDE_DATA.RegsBaseAddres] -; test whether it is our interrupt? - add dx, 2 + ; Waiting for disk ready + inc dx + mov ecx, 0xfff +.wait_ready: + ; Check waiting time + dec ecx + jz .err_timeout + ; Read the state register in al, dx - test al, 100b - jz @f -; clear Bus Master IDE Status register -; clear Interrupt bit - out dx, al -;-------------------------------------- -@@: - add dx, 8 -; test whether it is our interrupt? - in al, dx - test al, 100b - jz @f -; clear Bus Master IDE Status register -; clear Interrupt bit - out dx, al -;-------------------------------------- -@@: -; read status register and remove the interrupt request - mov dx, [ecx+IDE_DATA.BAR0_val] ;0x1F0 - add dx, 0x7 ;0x1F7 - in al, dx - mov dx, [ecx+IDE_DATA.BAR2_val] ;0x170 - add dx, 0x7 ;0x177 - in al, dx -;----------------------------------------------------------------------------- -; push eax edx -; mov dx, [ecx+IDE_DATA.RegsBaseAddres] -; xor eax, eax -; add dx, 2 -; in al, dx -; DEBUGF 1, "K : Primary Bus Master IDE Status Register %x\n", eax + ; Check the state of BSY signal + test al, 80h + jnz .wait_ready + ; Check the state of DRQ signal + test al, 08h + jnz .wait_ready -; add dx, 8 -; in al, dx -; DEBUGF 1, "K : Secondary Bus Master IDE Status Register %x\n", eax -; pop edx eax - -; cmp [ecx+IDE_DATA.RegsBaseAddres], 0 -; setnz [ecx+IDE_DATA.dma_hdd] -;----------------------------------------------------------------------------- -; set interrupts for IDE Controller -;----------------------------------------------------------------------------- - pushfd + ; load command to controller's registers cli -.enable_IDE_interrupt: - mov esi, boot_enabling_ide - call boot_log -; Enable interrupts in IDE controller for DMA - xor ebx, ebx - cmp ecx, IDE_controller_2 - jne @f - - add ebx, 5 - jmp .check_DRIVE_DATA -;-------------------------------------- -@@: - cmp ecx, IDE_controller_3 - jne .check_DRIVE_DATA - - add ebx, 10 -;-------------------------------------- -.check_DRIVE_DATA: - mov al, 0 - mov ah, [ebx+DRIVE_DATA+1] - test ah, 10100000b ; check for ATAPI devices - jz @f -;-------------------------------------- -.ch1_pio_set_ATAPI: - DEBUGF 1, "K : IDE CH1 PIO, because ATAPI drive present\n" - jmp .ch1_pio_set_for_all -;-------------------------------------- -.ch1_pio_set_no_devices: - DEBUGF 1, "K : IDE CH1 PIO because no devices\n" - jmp .ch1_pio_set_for_all -;------------------------------------- -.ch1_pio_set: - DEBUGF 1, "K : IDE CH1 PIO because device not support UDMA\n" -;------------------------------------- -.ch1_pio_set_for_all: - mov [ecx+IDE_DATA.dma_hdd_channel_1], al - jmp .ch2_check -;-------------------------------------- -@@: - xor ebx, ebx - call calculate_IDE_device_values_storage - - test ah, 1010000b - jz .ch1_pio_set_no_devices - - test ah, 1000000b - jz @f - - cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al - je .ch1_pio_set - - cmp [ebx+IDE_DEVICE.UDMA_set_mode], al - je .ch1_pio_set -;-------------------------------------- -@@: - test ah, 10000b - jz @f - - add ebx, 2 - - cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al - je .ch1_pio_set - - cmp [ebx+IDE_DEVICE.UDMA_set_mode], al - je .ch1_pio_set -;-------------------------------------- -@@: - mov dx, [ecx+IDE_DATA.BAR1_val] ;0x3F4 - add dx, 2 ;0x3F6 + mov dx, [ebp + IDE_CHANNEL.base] + inc dx ; "features" register + mov al, [ide_send_cmd_args.ATAFeatures] out dx, al - call set_pci_command_bus_master - DEBUGF 1, "K : IDE CH1 DMA enabled\n" - mov [ecx+IDE_DATA.dma_hdd_channel_1], byte 1 -;-------------------------------------- -.ch2_check: - test ah, 1010b ; check for ATAPI devices - jz @f -;-------------------------------------- -.ch2_pio_set_ATAPI: - DEBUGF 1, "K : IDE CH2 PIO, because ATAPI drive present\n" - jmp .ch2_pio_set_for_all -;-------------------------------------- -.ch2_pio_set_no_devices: - DEBUGF 1, "K : IDE CH2 PIO because no devices\n" - jmp .ch2_pio_set_for_all -;-------------------------------------- -.ch2_pio_set: - DEBUGF 1, "K : IDE CH2 PIO because device not support UDMA\n" -;-------------------------------------- -.ch2_pio_set_for_all: - mov [ecx+IDE_DATA.dma_hdd_channel_2], al - jmp .set_interrupts_for_IDE_controllers -;-------------------------------------- -@@: - mov ebx, 4 - call calculate_IDE_device_values_storage - - test ah, 101b - jz .ch2_pio_set_no_devices - - test ah, 100b - jz @f - - cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al - je .ch2_pio_set - - cmp [ebx+IDE_DEVICE.UDMA_set_mode], al - je .ch2_pio_set -;-------------------------------------- -@@: - test ah, 1b - jz @f - - add ebx, 2 - - cmp [ebx+IDE_DEVICE.UDMA_possible_modes], al - je .ch2_pio_set - - cmp [ebx+IDE_DEVICE.UDMA_set_mode], al - je .ch2_pio_set -;-------------------------------------- -@@: - mov dx, [ecx+IDE_DATA.BAR3_val] ;0x374 - add dx, 2 ;0x376 + inc dx ; sector counter + mov al, [ide_send_cmd_args.ATASectorCount] out dx, al - call set_pci_command_bus_master - DEBUGF 1, "K : IDE CH2 DMA enabled\n" - mov [ecx+IDE_DATA.dma_hdd_channel_2], byte 1 -;-------------------------------------- -.set_interrupts_for_IDE_controllers: - mov esi, boot_set_int_IDE - call boot_log -;-------------------------------------- - mov eax, [ecx+IDE_DATA.ProgrammingInterface] -; cmp ax, 0x0180 -; je .pata_ide + inc dx ; sector number register + mov al, [ide_send_cmd_args.ATASectorNumber] + out dx, al + inc dx ; cylinder number (low byte) + mov ax, [ide_send_cmd_args.ATACylinder] + out dx, al + inc dx ; cylinder number (high byte) + mov al, ah + out dx, al + inc dx ; head number / disk number -; cmp ax, 0x018a -; jne .sata_ide + mov al, byte[ide_dev_number] + and al, 1b ; al = disk number (0 or 1) + shl al, 4 - test al, 1 ; 0 - legacy PCI mode, 1 - native PCI mode - jnz .sata_ide -;-------------------------------------- -.pata_ide: - cmp [ecx+IDE_DATA.RegsBaseAddres], 0 - je .end_set_interrupts + or al, [ide_send_cmd_args.ATAHead] + or al, 10100000b + out dx, al + ; Send command + mov al, [ide_send_cmd_args.ATACommand] + inc dx ; command register + out dx, al + sti - push ecx - stdcall attach_int_handler, 14, IDE_irq_14_handler, ecx - pop ecx - DEBUGF 1, "K : Set IDE IRQ14 return code %x\n", eax - push ecx - stdcall attach_int_handler, 15, IDE_irq_15_handler, ecx - DEBUGF 1, "K : Set IDE IRQ15 return code %x\n", eax - pop ecx + ; Wait for HDD data ready + mov dx, [ebp + IDE_CHANNEL.base] + add dx, 7 ; address of state register + mov ecx, 0xffff +.wait: + ; Check command execution time + dec ecx + jz .err_timeout_limit ; timeout error + ; Check if ready or not + in al, dx + test al, 80h ; BSY signal state + jnz .wait - jmp .end_set_interrupts -;-------------------------------------- -.sata_ide: -; cmp ax, 0x0185 -; je .sata_ide_1 + test al, 1 ; ERR signal state + jnz .err_signal -; cmp ax, 0x018f -; jne .end_set_interrupts -;-------------------------------------- -;.sata_ide_1: -; Some weird controllers generate an interrupt even if IDE interrupts -; are disabled and no IDE devices. For example, notebook ASUS K72F - -; IDE controller 010185 generates false interrupt when we work with -; the IDE controller 01018f. For this reason, the interrupt handler -; does not need to be installed if both channel IDE controller -; running in PIO mode. - -; ...unfortunately, PCI interrupt can be shared with other devices -; which could enable it without consulting IDE code. -; So install the handler anyways and try to process -; even those interrupts which we are not expecting. - cmp [ecx+IDE_DATA.RegsBaseAddres], 0 - je .end_set_interrupts - - mov ax, [ecx+IDE_DATA.Interrupt] - movzx eax, al - push ecx - stdcall attach_int_handler, eax, IDE_common_irq_handler, ecx - pop ecx - DEBUGF 1, "K : Set IDE IRQ%d return code %x\n", [ecx+IDE_DATA.Interrupt]:1, eax -;-------------------------------------- -.end_set_interrupts: - popfd + test al, 08h ; DRQ signal state + jz .wait + ; Receive data block from controller + push edi + mov dx, [ebp + IDE_CHANNEL.base] + mov cx, 512/2 ; words read count + rep insw + pop edi + xor eax, eax ; err code - not error + add esp, ide_send_cmd_args.size ret +; write error code +.err_timeout_limit: + mov eax, 1 ; 1 - waiting time limit exceed + add esp, ide_send_cmd_args.size + ret +.err_timeout: + mov eax, 7 ; 7 - time out when choosing channel + add esp, ide_send_cmd_args.size + ret +.err_signal: + mov eax, 6 ; 6 - command execution error + add esp, ide_send_cmd_args.size + ret + +;----------------------------------------------------------------------------- +; IN: ebp - IDE_CHANNEL +; [ide_dev_number] AND 1b - disk number +; OUT: eax - 0 good +; - 1 err timeout +ide_device_reset: + ; Set base address + mov dx, [ebp + IDE_CHANNEL.base] + ; Choose desired disk + add dx, 6 ; address of heads register + mov al, byte[ide_dev_number] + and al, 1b ; al = disk number (0 or 1) + + shl al, 4 + or al, 10100000b + out dx, al + ; Send the "Reset" command + mov al, ATA_CMD_DEVICE_RESET + inc dx ; command register + out dx, al + mov ecx, 0x80000 +.wait_ready: + ; Check waiting time + dec ecx + je .err_timeout ; time out error + ; read the state register + in al, dx + ; Check the state of BSY signal + test al, ATA_SIGNAL_BSY + jnz .wait_ready + + ; reset the error sign + mov eax, 0 + ret + +.err_timeout: + mov eax, 1 + ret + ;----------------------------------------------------------------------------- ; END of initialisation IDE ATA code ;----------------------------------------------------------------------------- find_IDE_controller_done: - mov ecx, IDE_controller_1 - mov [IDE_controller_pointer], ecx - call Init_IDE_ATA_controller - mov ecx, IDE_controller_2 - mov [IDE_controller_pointer], ecx - call Init_IDE_ATA_controller - mov ecx, IDE_controller_3 - mov [IDE_controller_pointer], ecx - call Init_IDE_ATA_controller -;----------------------------------------------------------------------------- - mov esi, boot_getcache - call boot_log -include 'getcache.inc' -;----------------------------------------------------------------------------- - mov esi, boot_detectpart - call boot_log -include 'sear_par.inc' +; 3. Notify the system about /bd* disks. +; 3a. Check whether there are BIOS disks. If no, skip step 3. + xor esi, esi + cmp esi, [NumBiosDisks] + jz .nobd +; Loop over all disks. + push 0 + push 'bd' +.bdloop: +; 3b. Get the drive number for using in /bd* name. + lea eax, [esi*4] + movzx eax, [BiosDisksData+eax*4+BiosDiskData.DriveNumber] + sub al, 80h +; 3c. Convert eax to decimal and store starting with [esp+3]. +; First 2 bytes in [esp] are "bd". + lea edi, [esp+2] +; store digits in the stack, ending with -'0' + push -'0' +@@: + xor edx, edx +iglobal +align 4 +_10 dd 10 +endg + div [_10] + push edx + test eax, eax + jnz @b +; restore digits from the stack, this reverses the order; +; add '0', stop, when zero is reached +@@: + pop eax + add al, '0' + stosb + jnz @b +; 3e. Call the API with userdata = 80h + ecx. + mov eax, esp + lea edx, [esi+80h] + stdcall disk_add, bd_callbacks, eax, edx, 0 + test eax, eax + jz @f + stdcall disk_media_changed, eax, 1 +@@: +; 3f. Continue the loop. + inc esi + cmp esi, [NumBiosDisks] + jnz .bdloop + pop ecx ecx ; restore stack after name +.nobd: ;----------------------------------------------------------------------------- mov esi, boot_init_sys call boot_log @@ -482,14 +842,4 @@ if ~ defined extended_primary_loader ; READ RAMDISK IMAGE FROM HD include '../boot/rdload.inc' end if -;----------------------------------------------------------------------------- - mov ecx, IDE_controller_1 - mov [IDE_controller_pointer], ecx - call Init_IDE_ATA_controller_2 - mov ecx, IDE_controller_2 - mov [IDE_controller_pointer], ecx - call Init_IDE_ATA_controller_2 - mov ecx, IDE_controller_3 - mov [IDE_controller_pointer], ecx - call Init_IDE_ATA_controller_2 ;-----------------------------------------------------------------------------