From 6bcb2b7d1d551a99d6c58a9d28ece836884697c6 Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Mon, 27 May 2002 02:15:10 +0000 Subject: [PATCH] cleanup, resync for SiS chipsets --- src/config/Config | 1 + src/lib/Config | 2 +- src/northsouthbridge/sis/550/ipl.S | 26 +- src/northsouthbridge/sis/550/raminit.inc | 21 + src/northsouthbridge/sis/550/southbridge.c | 72 +-- src/northsouthbridge/sis/630/630_regs.inc | 2 +- src/northsouthbridge/sis/630/ipl.S | 34 +- src/northsouthbridge/sis/630/southbridge.c | 38 +- src/northsouthbridge/sis/635/635_regs.inc | 6 + src/northsouthbridge/sis/635/ipl.h | 9 - src/northsouthbridge/sis/730/730s_regs.inc | 2 +- src/northsouthbridge/sis/730/ipl.S | 36 +- src/northsouthbridge/sis/730/raminit.inc | 2 +- src/northsouthbridge/sis/730/southbridge.c | 114 ++-- src/northsouthbridge/sis/735/735_regs.inc | 6 + src/northsouthbridge/sis/735/ipl.h | 9 - src/pc80/ide/ide.c | 652 +++++++++++---------- src/rom/ide_fill_inbuf.c | 53 +- 18 files changed, 539 insertions(+), 546 deletions(-) diff --git a/src/config/Config b/src/config/Config index 1dd23cb30e..f9ab408cee 100644 --- a/src/config/Config +++ b/src/config/Config @@ -64,3 +64,4 @@ addaction clean rm -f build_opt_tbl option_table.c crt0.S dir /src/lib dir /src/boot dir /src/rom +dir /src/pc80 diff --git a/src/lib/Config b/src/lib/Config index 2b95709f19..60b426f155 100644 --- a/src/lib/Config +++ b/src/lib/Config @@ -13,7 +13,7 @@ object memcmp.o object malloc.o object elfboot.o USE_ELF_BOOT object do_inflate.o -object floppy_subr.o +object floppy_subr.o BOOT_FLOPPY object delay.o object fallback_boot.o HAVE_FALLBACK_BOOT object compute_ip_checksum.o \ No newline at end of file diff --git a/src/northsouthbridge/sis/550/ipl.S b/src/northsouthbridge/sis/550/ipl.S index d8c7578878..b493098eec 100644 --- a/src/northsouthbridge/sis/550/ipl.S +++ b/src/northsouthbridge/sis/550/ipl.S @@ -58,9 +58,11 @@ lpc_init_start: # inits LPC bridge for accessing lpc_init_complete: - movw $0x5501, %ax # Mode# enable, this bit + movw $0x5501, %ax # MDOE# enable, this bit CALL_SP(write_pci_register) # should be set before sizing. +/* -----------------------------------------------------------------------------------------*/ + #ifdef SIZE_ALL xorw %bx, %bx # clear %fs, %fs is used as "bitmap" of movw %bx, %fs # installed DIMM slot @@ -203,6 +205,8 @@ no_sdram: CALL_SP(write_pci_register) # write register 0x63 +/* -----------------------------------------------------------------------------------------*/ + movw $pci_init_table, %si init_sdram: lodsw (%si), %ax @@ -213,6 +217,9 @@ init_sdram: jmp init_sdram init_complete: + +/* -----------------------------------------------------------------------------------------*/ + sis630ipl_start: /* O.K. we have DRAM now, so set up STACK for CALL/RET */ movw $DOC_STACK_SEG, %ax @@ -234,7 +241,7 @@ sis630ipl_start: sis630ipl_end: jmp spl_vector # jump to SPL vector -/* ------------------------------------------------------------------------------------------*/ +/* -----------------------------------------------------------------------------------------*/ write_lpc_register: /* Input: AH - register number. AL - register value. */ @@ -257,10 +264,12 @@ write_common: movw $PCI_DATA_PORT, %dx andb $0x03, %al addb %al, %dl - movb %cl, %al + movb %cx, %ax # Restore %ax outb %al, %dx RET_SP # End of write_[lpc|pci]_reg +/* -----------------------------------------------------------------------------------------*/ + read_spd: /* Input: AH = 05h, AL = byte number of SPD to be read. Output: BL = The value of specified SPD byte. */ @@ -302,6 +311,8 @@ sis_set_smbus: outb %al, %dx RET_BP # End of sis_set_smbus +/* -----------------------------------------------------------------------------------------*/ + sdram_type_bank_1: # Column Number 8 9 10 11 Row Number .byte 0b0000, 0b0100, 0b1000, 0xff # 11 @@ -314,6 +325,8 @@ sdram_type_bank_2: .byte 0b0010, 0b0110, 0b1010, 0b1110 # 12 .byte 0b0011, 0b0111, 0b1011, 0b1111 # 13 +/* -----------------------------------------------------------------------------------------*/ + lpc_init_table: # High Byte -> Register Low Byte -> Value .word 0x408a # ACPI Enable, Decode E,F segment @@ -330,9 +343,6 @@ lpc_init_table: pci_init_table: # High Byte -> Register Low Byte -> Value - -//#include "dll.inc" - .word 0x8c44 # SDRCLK/SDWCLK .word 0x8d86 # SDWCLK @@ -346,6 +356,8 @@ pci_init_table: .word 0x5201 # Refresh Cycle Enable .word 0x0000 /* Null, End of table */ +/* -----------------------------------------------------------------------------------------*/ + #ifdef STD_FLASH .org 0xfff0 reset_vector: @@ -366,6 +378,8 @@ spl_vector: .byte 0xea # jmp to 8000:0000, where SPL .word 0x0000, SPL_RAM_SEG # (LinuxBIOS) starts in RAM +/* -----------------------------------------------------------------------------------------*/ + #ifdef STD_FLASH .org 0xffff #else /* !STD_FLASH i.e. DoC Mil */ diff --git a/src/northsouthbridge/sis/550/raminit.inc b/src/northsouthbridge/sis/550/raminit.inc index eee73748df..69ef98c7bb 100644 --- a/src/northsouthbridge/sis/550/raminit.inc +++ b/src/northsouthbridge/sis/550/raminit.inc @@ -33,6 +33,7 @@ #define PCI_DATA_PORT 0xcfc #define NORTH_BRIDGE_BASE_ADDR 0x80000000 +#define LPC_BRIDGE_BASE_ADDR 0x80000800 register_setting_start: movl $northbridge_init_table, %esi @@ -64,6 +65,26 @@ write_common: loopnz init_northbridge +#ifdef DISABLE_INTERNAL_DEVICES + movw $0x7c07, %ax # Writting undocumented LPC register +write_lpc_register: + /* Input: AH - register number. AL - register value. */ + movl $LPC_BRIDGE_BASE_ADDR, %edx + movl %eax, %ebx # Save %eax to %ebx. + + movzbl %bh, %eax # add register address to + addl %edx, %eax # PCI base address + + movw $PCI_COMMAND_PORT, %dx + outl %eax, %dx + + movw $PCI_DATA_PORT, %dx + andb $0x03, %al + addb %al, %dl + movb %bl, %al + outb %al, %dx +#endif /* DISABLE_INTERNAL_DEVICES */ + jmp register_setting_end #include "550_regs.inc" diff --git a/src/northsouthbridge/sis/550/southbridge.c b/src/northsouthbridge/sis/550/southbridge.c index a3e4606e9b..67766c6839 100644 --- a/src/northsouthbridge/sis/550/southbridge.c +++ b/src/northsouthbridge/sis/550/southbridge.c @@ -54,8 +54,8 @@ static const initreg_t ide_init[] = { { WORD, 0x2C, 0x00, 0x1039 }, /* Subsystem vendor ID. */ { WORD, 0x2E, 0x00, 0x5513 }, /* Subsystem ID. */ { BYTE, 0x3c, 0x00, 0x0e }, /* reserved don't do this, sets irq 14 */ - { BYTE, 0x40, 0x00, 0x01 }, /* Primary master data recovery time. 1 PCICLK */ - { BYTE, 0x41, 0x00, 0xb3 }, /* Primary master data active time. UDMA Mode 2 */ + { BYTE, 0x40, 0x00, 0x04 }, /* Primary master data recovery time. 4 PCICLK */ + { BYTE, 0x41, 0x00, 0xb4 }, /* Primary master data active time. UDMA Mode 2 */ { BYTE, 0x42, 0x00, 0x00 }, /* Primary slave data recovery time. */ { BYTE, 0x43, 0x00, 0x00 }, /* Primary slave data active time. */ { BYTE, 0x44, 0x00, 0x00 }, /* Secondary master data recovery time. */ @@ -116,6 +116,7 @@ void keyboard_on() u8 regval; struct pci_dev *pcidev; void pc_keyboard_init(void); + /* turn on sis630 keyboard/mouse controller */ pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL); if (pcidev != NULL) { @@ -138,23 +139,16 @@ void nvram_on() /* Enable FFF80000 to FFFFFFFF decode. You have to also enable PCI Posted write for devices on sourthbridge */ pci_write_config_byte(pcidev, 0x40, 0x33); - /* Flash can be flashed */ - pci_write_config_byte(pcidev, 0x45, 0x40); - printk_debug("Enabled in SIS 503 regs 0x40 and 0x45\n"); - + /* Flash can be flashed, enable USB device in undocumented Bit 6 */ + pci_write_config_byte(pcidev, 0x45, 0x60); } - printk_debug("Now try to turn off shadow\n"); +//#if !defined(STD_FLASH) /* turn off nvram shadow in 0xc0000 ~ 0xfffff, i.e. accessing segment C - F is actually to the DRAM not NVRAM. For 512KB NVRAM case, this one should be disabled */ pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550, (void *)NULL); - printk_debug("device for SiS 550 is 0x%x\n", pcidev); if (pcidev != NULL) { - /* read cycle goes to System Memory */ - //pci_write_config_word(pcidev, 0x70, 0x1fff); - /* write cycle goest to System Memory */ - //pci_write_config_word(pcidev, 0x72, 0x1fff); pci_write_config_word(pcidev, 0x70, 0xFFFF); pci_write_config_word(pcidev, 0x72, 0xFFFF); pci_write_config_word(pcidev, 0x74, 0xFFFF); @@ -162,6 +156,7 @@ void nvram_on() printk_debug("Shadow memory disabled in SiS 550\n"); } +//#endif } /* serial_irq_fixup: Enable Serial Interrupt. Serial interrupt is the IRQ line from SiS 950 @@ -192,15 +187,21 @@ south_fixup(void) pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL); if (pcidev != NULL) { - u8 reg; - pci_read_config_byte(pcidev, 0x77, ®); - pci_write_config_byte(pcidev, 0x77, reg & 0xEF); + u8 reg; + /* disable ROM delay transaction */ + pci_read_config_byte(pcidev, 0x77, ®); + pci_write_config_byte(pcidev, 0x77, reg & 0xEF); - /* IO address for CIR */ - pci_write_config_byte(pcidev, 0x4A, 0x11); - pci_write_config_byte(pcidev, 0x4B, 0x03); - /* IRQ for CIR */ - pci_write_config_byte(pcidev, 0x6C, 0x05); + /* IO address for CIR */ + pci_write_config_byte(pcidev, 0x4A, 0x11); + pci_write_config_byte(pcidev, 0x4B, 0x03); + /* IRQ for CIR */ + pci_write_config_byte(pcidev, 0x6C, 0x05); + } + + pcidev = pci_find_device(PCI_VENDOR_ID_SI, 0x7001, (void *)NULL); + if (pcidev != NULL) { + pci_read_config_byte(pcidev, 0x04, 0x17); } } @@ -212,46 +213,25 @@ acpi_fixup(void) pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL); if (pcidev != NULL) { unsigned char val; - unsigned short acpibase = 0xc000, temp; - int i; + unsigned short acpibase = 0xc000; // the following is to turn off software watchdogs. // we co-op the address space from c000-cfff here. Temporarily. // Later, we need a better way to do this. // But since Linux doesn't even understand this yet, no issue. // Set a base address for ACPI of 0xc000 - pci_read_config_word(pcidev, 0x74, &temp); - - printk_debug("acpibase was 0x%x\n", temp); pci_write_config_word(pcidev, 0x74, acpibase); - pci_read_config_word(pcidev, 0x74, &temp); - printk_debug("acpibase is 0x%x\n", temp); // now enable acpi pci_read_config_byte(pcidev, 0x40, &val); - printk_debug("acpi enable reg was 0x%x\n", val); val |= 0x80; pci_write_config_byte(pcidev, 0x40, val); - pci_read_config_byte(pcidev, 0x40, &val); - printk_debug("acpi enable reg after set is 0x%x\n", val); - printk_debug("acpi status: word at 0x56 is 0x%x\n", - inw(acpibase+0x56)); - printk_debug("acpi status: byte at 0x4b is 0x%x\n", - inb(acpibase + 0x4b)); - // now that it's on, get in there and call off the dogs. - // that's the recommended thing to do if MD40 iso on. - outw(0, acpibase + 0x56); - // does this help too? + /* Disable Auto-Reset */ + val = inb(acpibase + 0x56); + outw(val | 0x40, acpibase + 0x56); + /* Disable Software Watchdog */ outb(0, acpibase + 0x4b); - // ah ha! have to SET, NOT CLEAR! - outb(0x40, acpibase + 0x56); - printk_debug("acpibase + 0x56 is 0x%x\n", - inb(acpibase+0x56)); - val &= (~0x80); - pci_write_config_byte(pcidev, 0x40, val); - pci_read_config_byte(pcidev, 0x40, &val); - printk_debug("acpi disable reg after set is 0x%x\n", val); } else { printk_emerg("Can't find south bridge!\n"); } diff --git a/src/northsouthbridge/sis/630/630_regs.inc b/src/northsouthbridge/sis/630/630_regs.inc index 0c160f5eee..f168e74cf8 100644 --- a/src/northsouthbridge/sis/630/630_regs.inc +++ b/src/northsouthbridge/sis/630/630_regs.inc @@ -94,7 +94,7 @@ northbridge_init_table: .byte 0x94, 0x40 # Graphic Window Size == 64MB .byte 0x97, 0x01 # Page Table Cache Enable .byte 0x98, 0x00 # - .byte 0x9C, 0x02 # CPU to VGA MEM Posted Write + .byte 0x9C, 0x02 # Integrated VGA Enable /* DRAM Priority Timer Control Register */ .byte 0xA0, 0x00 diff --git a/src/northsouthbridge/sis/630/ipl.S b/src/northsouthbridge/sis/630/ipl.S index 1d50125aa0..c4ae67f2a8 100644 --- a/src/northsouthbridge/sis/630/ipl.S +++ b/src/northsouthbridge/sis/630/ipl.S @@ -47,9 +47,6 @@ sis630spd_start: movw %cs, %ax # makes data segment == movw %ax, %ds # code segment - movb $0x01, %al - outb %al, $0x80 - movw $0x408a, %ax # ACPI Enable. CALL_SP(write_lpc_register) # (for use of SMBus) @@ -59,6 +56,8 @@ sis630spd_start: movw $0x5501, %ax # MDOE# enable, this bit CALL_SP(write_pci_register) # should be set before sizing. +/* -----------------------------------------------------------------------------------------*/ + #ifdef SIZE_ALL xorw %bx, %bx # clear %fs, %fs is used as "bitmap" of movw %bx, %fs # install DIMM slot @@ -120,16 +119,6 @@ check_row_column: jl no_sdram #endif /* SAFTY_CHECK */ -#if 0 - subb $0x0b, %ch # row = row - 11 - shlb $0x02, %ch # row * 4 - - addb %ch, %cl # column + row * 4 - movzbw %cl, %bx # Get the SDRAM type. - - addw %bx, %si # sdram_type_bank[column + row * 4] - movb -8(%si), %cl # sdram_type_bank[column + row * 4 - 8] -#else /* This one is DANGEROUS TOO, be careful about OVERFLOW !!! */ shlb $0x02, %ch # row * 4 @@ -201,6 +190,8 @@ no_sdram: CALL_SP(write_pci_register) # write register 0x63 +/* -----------------------------------------------------------------------------------------*/ + movw $pci_init_table, %si init_sdram: lodsw (%si), %ax @@ -211,6 +202,9 @@ init_sdram: jmp init_sdram init_complete: + +/* -----------------------------------------------------------------------------------------*/ + sis630ipl_start: /* O.K. we have DRAM now, so set up STACK for CALL/RET */ movw $DOC_STACK_SEG, %ax @@ -233,7 +227,7 @@ sis630ipl_start: sis630ipl_end: jmp spl_vector # jump to SPL vector -/* ------------------------------------------------------------------------------------------*/ +/* -----------------------------------------------------------------------------------------*/ write_lpc_register: /* Input: AH - register number. AL - register value. */ @@ -256,10 +250,12 @@ write_common: movw $PCI_DATA_PORT, %dx andb $0x03, %al addb %al, %dl - movb %cl, %al + movw %cx, %ax # Restore %ax outb %al, %dx RET_SP # End of write_[lpc|pci]_reg +/* -----------------------------------------------------------------------------------------*/ + read_spd: /* Input: AH = 05h, AL = byte number of SPD to be read. Output: BL = The value of specified SPD byte. */ @@ -301,6 +297,8 @@ sis_set_smbus: outb %al, %dx RET_BP # End of sis_set_smbus +/* -----------------------------------------------------------------------------------------*/ + sdram_type_bank_1: # Column Number 8 9 10 11 Row Number .byte 0b0000, 0b0100, 0b1000, 0xff # 11 @@ -313,6 +311,8 @@ sdram_type_bank_2: .byte 0b0010, 0b0110, 0b1010, 0b1110 # 12 .byte 0b0011, 0b0111, 0b1011, 0b1111 # 13 +/* -----------------------------------------------------------------------------------------*/ + pci_init_table: # High Byte -> Register Low Byte -> Value @@ -326,6 +326,8 @@ pci_init_table: .word 0x5201 # Refresh Cycle Enable .word 0x0000 /* Null, End of table */ +/* -----------------------------------------------------------------------------------------*/ + #ifdef STD_FLASH .org 0xfff0 reset_vector: @@ -346,6 +348,8 @@ spl_vector: .byte 0xea # jmp to 8000:0000, where SPL .word 0x0000, SPL_RAM_SEG # (LinuxBIOS) starts in RAM +/* -----------------------------------------------------------------------------------------*/ + sis950_init_table: .byte 0x87, 0x01, 0x55, 0x55, 0x24 diff --git a/src/northsouthbridge/sis/630/southbridge.c b/src/northsouthbridge/sis/630/southbridge.c index 981983660e..f016dbe230 100644 --- a/src/northsouthbridge/sis/630/southbridge.c +++ b/src/northsouthbridge/sis/630/southbridge.c @@ -54,8 +54,8 @@ static const initreg_t ide_init[] = { { WORD, 0x2C, 0x00, 0x1039 }, /* Subsystem vendor ID. */ { WORD, 0x2E, 0x00, 0x5513 }, /* Subsystem ID. */ { BYTE, 0x3c, 0x00, 0x0e }, /* reserved don't do this, sets irq 14 */ - { BYTE, 0x40, 0x00, 0x01 }, /* Primary master data recovery time. 1 PCICLK */ - { BYTE, 0x41, 0x00, 0xb3 }, /* Primary master data active time. UDMA Mode 2 */ + { BYTE, 0x40, 0x00, 0x04 }, /* Primary master data recovery time. 4 PCICLK, PIO Mode 2 */ + { BYTE, 0x41, 0x00, 0xb4 }, /* Primary master data active time. UDMA Mode 2 */ { BYTE, 0x42, 0x00, 0x00 }, /* Primary slave data recovery time. */ { BYTE, 0x43, 0x00, 0x00 }, /* Primary slave data active time. */ { BYTE, 0x44, 0x00, 0x00 }, /* Secondary master data recovery time. */ @@ -63,7 +63,7 @@ static const initreg_t ide_init[] = { { BYTE, 0x46, 0x00, 0x00 }, /* Secondary slave data recovery time. */ { BYTE, 0x47, 0x00, 0x00 }, /* Secondary slave data active time. */ { BYTE, 0x48, 0x00, 0x05 }, /* Read/Write FIFO Threshold = 1/4 */ - { BYTE, 0x4A, 0x40, 0xe2 }, /* Enable Bus Master, Fast postwrite, IDE 0 */ + { BYTE, 0x4A, 0x40, 0xe6 }, /* Enable Bus Master, Fast postwrite, IDE 0,1 */ { BYTE, 0x4B, 0x00, 0x11 }, /* Enable Postwrite and Prefech for IDE0, Master */ { WORD, 0x4C, 0x00, 0x0200 }, /* Prefetch count of primary. */ { WORD, 0x4E, 0x00, 0x0200 }, /* Prefetch count of secondary. */ @@ -72,7 +72,6 @@ static const initreg_t ide_init[] = { void ide_fixup(void) { - struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, (void *) NULL); int i; @@ -116,6 +115,7 @@ void keyboard_on() u8 regval; struct pci_dev *pcidev; void pc_keyboard_init(void); + /* turn on sis630 keyboard/mouse controller */ pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL); if (pcidev != NULL) { @@ -300,45 +300,25 @@ acpi_fixup(void) pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL); if (pcidev != NULL) { unsigned char val; - unsigned short acpibase = 0xc000, temp; + unsigned short acpibase = 0xc000; // the following is to turn off software watchdogs. // we co-op the address space from c000-cfff here. Temporarily. // Later, we need a better way to do this. // But since Linux doesn't even understand this yet, no issue. // Set a base address for ACPI of 0xc000 - pci_read_config_word(pcidev, 0x74, &temp); - - printk_debug("acpibase was 0x%x\n", temp); pci_write_config_word(pcidev, 0x74, acpibase); - pci_read_config_word(pcidev, 0x74, &temp); - printk_debug("acpibase is 0x%x\n", temp); // now enable acpi pci_read_config_byte(pcidev, 0x40, &val); - printk_debug("acpi enable reg was 0x%x\n", val); val |= 0x80; pci_write_config_byte(pcidev, 0x40, val); - pci_read_config_byte(pcidev, 0x40, &val); - printk_debug("acpi enable reg after set is 0x%x\n", val); - printk_debug("acpi status: word at 0x56 is 0x%x\n", - inw(acpibase+0x56)); - printk_debug("acpi status: byte at 0x4b is 0x%x\n", - inb(acpibase + 0x4b)); - // now that it's on, get in there and call off the dogs. - // that's the recommended thing to do if MD40 iso on. - outw(0, acpibase + 0x56); - // does this help too? + /* Disable Auto-Reset */ + val = inb(acpibase + 0x56); + outw(val | 0x40, acpibase + 0x56); + /* Disable Software Watchdog */ outb(0, acpibase + 0x4b); - // ah ha! have to SET, NOT CLEAR! - outb(0x40, acpibase + 0x56); - printk_debug("acpibase + 0x56 is 0x%x\n", - inb(acpibase+0x56)); - val &= (~0x80); - pci_write_config_byte(pcidev, 0x40, val); - pci_read_config_byte(pcidev, 0x40, &val); - printk_debug("acpi disable reg after set is 0x%x\n", val); } else { printk_emerg("Can't find south bridge!\n"); } diff --git a/src/northsouthbridge/sis/635/635_regs.inc b/src/northsouthbridge/sis/635/635_regs.inc index 7d81c010cb..c877dbd231 100644 --- a/src/northsouthbridge/sis/635/635_regs.inc +++ b/src/northsouthbridge/sis/635/635_regs.inc @@ -62,6 +62,12 @@ northbridge_init_table: .word 0x8904 .word 0x8b04 + /* AGP GART */ + .word 0x9440 + .word 0x9501 + .word 0x9701 + .word 0x9800 + /* IO Buffer */ .word 0x9b42 .word 0x9f20 diff --git a/src/northsouthbridge/sis/635/ipl.h b/src/northsouthbridge/sis/635/ipl.h index 57c8d66a84..47714ad44c 100644 --- a/src/northsouthbridge/sis/635/ipl.h +++ b/src/northsouthbridge/sis/635/ipl.h @@ -21,15 +21,6 @@ #define DLL_RESET 0x60 #define DLL_DISABLE 0x70 -#define DDR_CMD DDR_CMD_ISSUE | DQS_ENABLE -#define DDR_CMD_PALL (DRAM_INIT_REG << 8 | PALL | DDR_CMD) -#define DDR_CMD_DLL_EN_N (DRAM_INIT_REG << 8 | DLL_EN_N | DDR_CMD) -#define DDR_CMD_DLL_RESET (DRAM_INIT_REG << 8 | DLL_RESET | DDR_CMD) -#define DDR_CMD_REF (DRAM_INIT_REG << 8 | REF | DDR_CMD) -#define DDR_CMD_MRS (DRAM_INIT_REG << 8 | MRS | DDR_CMD) - -#define ENABLE_FRESH_CYCLE 0x5d01 - #define DOC_WIN_SEG 0xfe00 #define DOC_STACK_SEG 0x0400 #define SPL_RAM_SEG 0x8000 diff --git a/src/northsouthbridge/sis/730/730s_regs.inc b/src/northsouthbridge/sis/730/730s_regs.inc index cde2342be6..f8e4142d9e 100644 --- a/src/northsouthbridge/sis/730/730s_regs.inc +++ b/src/northsouthbridge/sis/730/730s_regs.inc @@ -87,7 +87,7 @@ northbridge_init_table: .byte 0x96, 0x00 # .byte 0x97, 0x01 # - .byte 0x9C, 0x02 # CPU to VGA MEM Posted Write + .byte 0x9C, 0x02 # Integrated VGA Enable /* DRAM Priority Timer Control REgister */ .byte 0xA0, 0x00 diff --git a/src/northsouthbridge/sis/730/ipl.S b/src/northsouthbridge/sis/730/ipl.S index 4bd5b8a2c5..b337469e5d 100644 --- a/src/northsouthbridge/sis/730/ipl.S +++ b/src/northsouthbridge/sis/730/ipl.S @@ -53,9 +53,11 @@ sis730spd_start: movw $0x7550, %ax # Store ACPI Base Address. CALL_SP(write_lpc_register) # (for use of SMBus) - movw $0x5501, %ax # Mode# enable, this bit + movw $0x5501, %ax # MDOE# enable, this bit CALL_SP(write_pci_register) # should be set before sizing. +/* -----------------------------------------------------------------------------------------*/ + #ifdef SIZE_ALL xorw %bx, %bx # clear %fs, %fs is used as "bitmap" of movw %bx, %fs # install DIMM slot @@ -117,16 +119,6 @@ check_row_column: jl no_sdram #endif /* SAFTY_CHECK */ -#if 0 - subb $0x0b, %ch # row = row - 11 - shlb $0x02, %ch # row * 4 - - addb %ch, %cl # column + row * 4 - movzbw %cl, %bx # Get the SDRAM type. - - addw %bx, %si # sdram_type_bank[column + row * 4] - movb -8(%si), %cl # sdram_type_bank[column + row * 4 - 8] -#else /* This one is DANGEROUS TOO, be careful about OVERFLOW !!! */ shlb $0x02, %ch # row * 4 @@ -135,7 +127,6 @@ check_row_column: addw %cx, %si # sdram_type_bank[column + row * 4] movb -52(%si), %cl # sdram_type_bank[column + row * 4 - 52] -#endif #ifdef SIZE_ALL movb %ah, %bh # Restore DIMM slot number from AH to BH @@ -198,6 +189,8 @@ no_sdram: CALL_SP(write_pci_register) # write register 0x63 +/* -----------------------------------------------------------------------------------------*/ + movw $pci_init_table, %si init_sdram: lodsw (%si), %ax @@ -208,6 +201,9 @@ init_sdram: jmp init_sdram init_complete: + +/* -----------------------------------------------------------------------------------------*/ + sis730ipl_start: /* O.K. we have DRAM now, so set up STACK for CALL/RET */ movw $DOC_STACK_SEG, %ax @@ -230,7 +226,7 @@ sis730ipl_start: sis730ipl_end: jmp spl_vector # jump to SPL vector -/* ------------------------------------------------------------------------------------------*/ +/* -----------------------------------------------------------------------------------------*/ write_lpc_register: /* Input: AH - register number. AL - register value. */ @@ -253,10 +249,12 @@ write_common: movw $PCI_DATA_PORT, %dx andb $0x03, %al addb %al, %dl - movb %cl, %al + movw %cx, %ax # Resotre %ax outb %al, %dx RET_SP # End of write_[lpc|pci]_reg +/* -----------------------------------------------------------------------------------------*/ + read_spd: /* Input: AH = 05h, AL = byte number of SPD to be read. Output: BL = The value of specified SPD byte. */ @@ -298,6 +296,8 @@ sis_set_smbus: outb %al, %dx RET_BP # End of sis_set_smbus +/* -----------------------------------------------------------------------------------------*/ + sdram_type_bank_1: # Column Number 8 9 10 11 Row Number .byte 0b0000, 0b0100, 0b1000, 0xff # 11 @@ -310,6 +310,8 @@ sdram_type_bank_2: .byte 0b0010, 0b0110, 0b1010, 0b1110 # 12 .byte 0b0011, 0b0111, 0b1011, 0b1111 # 13 +/* -----------------------------------------------------------------------------------------*/ + pci_init_table: # High Byte -> Register Low Byte -> Value @@ -327,10 +329,10 @@ pci_init_table: .word 0x50c5 # Refresh Cycle Enable - #.byte 0x5601 # CAS = 3T - .word 0x0000 /* Null, End of table */ +/* -----------------------------------------------------------------------------------------*/ + #ifdef STD_FLASH .org 0xfff0 reset_vector: @@ -351,6 +353,8 @@ spl_vector: .byte 0xea # jmp to 8000:0000, where SPL .word 0x0000, SPL_RAM_SEG # (LinuxBIOS) starts in RAM +/* -----------------------------------------------------------------------------------------*/ + sis950_init_table: .byte 0x87, 0x01, 0x55, 0x55, 0x24 diff --git a/src/northsouthbridge/sis/730/raminit.inc b/src/northsouthbridge/sis/730/raminit.inc index e75135b3c5..48e9a5bac4 100644 --- a/src/northsouthbridge/sis/730/raminit.inc +++ b/src/northsouthbridge/sis/730/raminit.inc @@ -22,7 +22,7 @@ * * * Reference: - * 1. SiS 730S Specification + * 1. SiS 730S Data Sheet, Rev. 1.0, Oct. 31, 2000 * 2. SiS 730S Register Recommended Setting * Rev 1.0, Oct. 4, 2000 * diff --git a/src/northsouthbridge/sis/730/southbridge.c b/src/northsouthbridge/sis/730/southbridge.c index ba6be75058..8f89f09b6a 100644 --- a/src/northsouthbridge/sis/730/southbridge.c +++ b/src/northsouthbridge/sis/730/southbridge.c @@ -1,8 +1,25 @@ - /* - * Bootstrap code for the INTEL - * $Id$ + * southbridge.c: Southbridge Initialization For SiS 730 * + * Copyright 2002 Silicon Integrated Systems Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Reference: + * 1. SiS 730S Data Sheet Rev. 1.0, Otc. 21, 2000 */ #ifndef lint @@ -54,8 +71,8 @@ static const initreg_t ide_init[] = { { WORD, 0x2C, 0x00, 0x1039 }, /* Subsystem vendor ID. */ { WORD, 0x2E, 0x00, 0x5513 }, /* Subsystem ID. */ { BYTE, 0x3c, 0x00, 0x0e }, /* reserved don't do this, sets irq 14 */ - { BYTE, 0x40, 0x00, 0x01 }, /* Primary master data recovery time. 1 PCICLK */ - { BYTE, 0x41, 0x00, 0xb3 }, /* Primary master data active time. UDMA Mode 2 */ + { BYTE, 0x40, 0x00, 0x04 }, /* Primary master data recovery time. 4 PCICLK */ + { BYTE, 0x41, 0x00, 0xb4 }, /* Primary master data active time. UDMA Mode 2 */ { BYTE, 0x42, 0x00, 0x00 }, /* Primary slave data recovery time. */ { BYTE, 0x43, 0x00, 0x00 }, /* Primary slave data active time. */ { BYTE, 0x44, 0x00, 0x00 }, /* Secondary master data recovery time. */ @@ -143,19 +160,15 @@ void nvram_on() printk_debug("Enabled in SIS 503 regs 0x40 and 0x45\n"); } - printk_debug("Now try to turn off shadow\n"); #if !defined(STD_FLASH) /* turn off nvram shadow in 0xc0000 ~ 0xfffff, i.e. accessing segment C - F is actually to the DRAM not NVRAM. For 512KB NVRAM case, this one should be disabled */ pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_730, (void *)NULL); - printk_debug("device for SiS 730 is 0x%x\n", pcidev); if (pcidev != NULL) { - /* read cycle goes to System Memory */ - pci_write_config_word(pcidev, 0x70, 0x1fff); - /* write cycle goest to System Memory */ - pci_write_config_word(pcidev, 0x72, 0x1fff); + /* read/write cycle goes to System Memory */ + pci_write_config_byte(pcidev, 0x70, 0x03); printk_debug("Shadow memory disabled in SiS 730\n"); } @@ -185,9 +198,8 @@ serial_irq_fixedup(void) /* apc_fixup: Fix up the Mux-ed GPIO Lines controlled by APC registers * - * For SiS630A/B Mainboards, the MAC address of the internal SiS900 is stored in EEPROM - * on the board. The EEPROM interface lines are muxed with GPIO pins and are selected by - * some APC registers. + * SiS 730 Mux-ed Keyboard/Mouse controller pins with MII interface. We + * can choose only one. Most MBs just don't use the MII */ static void apc_fixup(void) @@ -202,16 +214,16 @@ apc_fixup(void) pci_read_config_byte(isa_bridge, 0x48, ®val); pci_write_config_byte(isa_bridge, 0x48, regval | 0x40); - /* Enable MAC Serial ROM Autoload */ - outb(0x01, 0x70); - regval = inb(0x71); - outb(regval | 0x80, 0x71); - /* select Keyboard/Mouse function for GPIO Pin [14:10] */ outb(0x02, 0x70); regval = inb(0x71); outb(regval | 0x40, 0x71); + /* Disable MII Interface Interface for GPIO Pin [15-14, 9-8, 6-0] and OC1-0 */ + outb(0x03, 0x70); + regval = inb(0x71) & 0xfc; + outb(regval, 0x71); + /* Enable ACPI S3,S5 */ outb(0x04, 0x70); regval = inb(0x71); @@ -287,46 +299,25 @@ acpi_fixup(void) pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL); if (pcidev != NULL) { unsigned char val; - unsigned short acpibase = 0xc000, temp; - int i; + unsigned short acpibase = 0xc000; // the following is to turn off software watchdogs. // we co-op the address space from c000-cfff here. Temporarily. // Later, we need a better way to do this. // But since Linux doesn't even understand this yet, no issue. // Set a base address for ACPI of 0xc000 - pci_read_config_word(pcidev, 0x74, &temp); - - printk_debug("acpibase was 0x%x\n", temp); pci_write_config_word(pcidev, 0x74, acpibase); - pci_read_config_word(pcidev, 0x74, &temp); - printk_debug("acpibase is 0x%x\n", temp); // now enable acpi pci_read_config_byte(pcidev, 0x40, &val); - printk_debug("acpi enable reg was 0x%x\n", val); val |= 0x80; pci_write_config_byte(pcidev, 0x40, val); - pci_read_config_byte(pcidev, 0x40, &val); - printk_debug("acpi enable reg after set is 0x%x\n", val); - printk_debug("acpi status: word at 0x56 is 0x%x\n", - inw(acpibase+0x56)); - printk_debug("acpi status: byte at 0x4b is 0x%x\n", - inb(acpibase + 0x4b)); - // now that it's on, get in there and call off the dogs. - // that's the recommended thing to do if MD40 iso on. - outw(0, acpibase + 0x56); - // does this help too? + /* Disable Auto-Reset */ + val = inb(acpibase + 0x56); + outw(val | 0x40, acpibase + 0x56); + /* Disable Software Watchdog */ outb(0, acpibase + 0x4b); - // ah ha! have to SET, NOT CLEAR! - outb(0x40, acpibase + 0x56); - printk_debug("acpibase + 0x56 is 0x%x\n", - inb(acpibase+0x56)); - val &= (~0x80); - pci_write_config_byte(pcidev, 0x40, val); - pci_read_config_byte(pcidev, 0x40, &val); - printk_debug("acpi disable reg after set is 0x%x\n", val); } else { printk_emerg("Can't find south bridge!\n"); } @@ -337,39 +328,6 @@ acpi_fixup(void) void final_southbridge_fixup() { -#ifdef OLD_KERNEL_HACK - struct pci_dev *pcidev; - - pcidev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, (void *)NULL); - if (pcidev != NULL) { - printk_info("Remapping IRQ on southbridge for OLD_KERNEL_HACK\n"); - // remap IRQ for PCI -- this is exactly what the BIOS does now. - pci_write_config_byte(pcidev, 0x42, 0xa); - pci_write_config_byte(pcidev, 0x43, 0xb); - pci_write_config_byte(pcidev, 0x44, 0xc); - } - // ethernet fixup. This should all work, and doesn't, yet. - // so we hack it for now. - // need a manifest constant for the enet device. - pcidev = pci_find_device(PCI_VENDOR_ID_SI, 0x0900, (void *)NULL); - if (pcidev != NULL) { - u32 bar0 = 0xb001; - // set the BAR 0 to 0xb000. Safe, high value, known good. - // pci config set doesn't work for reasons we don't understand. - pci_write_config_dword(pcidev, PCI_BASE_ADDRESS_0, bar0); - - // Make sure bus mastering is on. The tried-and-true probe in linuxpci.c - // doesn't set this for some reason. - pci_write_config_byte(pcidev, PCI_COMMAND, - PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - - // set the interrupt to 'b' - pci_write_config_byte(pcidev, PCI_INTERRUPT_LINE, 0xb); - } else { - printk_err("Can't find ethernet interface\n"); - } -#endif /* OLD_KERNEL_HACK */ - timer0_fixup(); rtc_fixup(); apc_fixup(); diff --git a/src/northsouthbridge/sis/735/735_regs.inc b/src/northsouthbridge/sis/735/735_regs.inc index 75915b1b3e..97ea49464d 100644 --- a/src/northsouthbridge/sis/735/735_regs.inc +++ b/src/northsouthbridge/sis/735/735_regs.inc @@ -61,6 +61,12 @@ northbridge_init_table: .word 0x890c .word 0x8b04 + /* AGP GART */ + .word 0x9440 + .word 0x9501 + .word 0x9701 + .word 0x9800 + /* IO Buffer */ .word 0x9b40 .word 0x9f10 diff --git a/src/northsouthbridge/sis/735/ipl.h b/src/northsouthbridge/sis/735/ipl.h index 57c8d66a84..47714ad44c 100644 --- a/src/northsouthbridge/sis/735/ipl.h +++ b/src/northsouthbridge/sis/735/ipl.h @@ -21,15 +21,6 @@ #define DLL_RESET 0x60 #define DLL_DISABLE 0x70 -#define DDR_CMD DDR_CMD_ISSUE | DQS_ENABLE -#define DDR_CMD_PALL (DRAM_INIT_REG << 8 | PALL | DDR_CMD) -#define DDR_CMD_DLL_EN_N (DRAM_INIT_REG << 8 | DLL_EN_N | DDR_CMD) -#define DDR_CMD_DLL_RESET (DRAM_INIT_REG << 8 | DLL_RESET | DDR_CMD) -#define DDR_CMD_REF (DRAM_INIT_REG << 8 | REF | DDR_CMD) -#define DDR_CMD_MRS (DRAM_INIT_REG << 8 | MRS | DDR_CMD) - -#define ENABLE_FRESH_CYCLE 0x5d01 - #define DOC_WIN_SEG 0xfe00 #define DOC_STACK_SEG 0x0400 #define SPL_RAM_SEG 0x8000 diff --git a/src/pc80/ide/ide.c b/src/pc80/ide/ide.c index 0cc6f5a49c..6db56c73fe 100644 --- a/src/pc80/ide/ide.c +++ b/src/pc80/ide/ide.c @@ -32,416 +32,424 @@ #include #include "ide.h" -static __inline__ int wait_for_notbusy(unsigned base) { - unsigned i = 0; - do { - if (((inb_p(IDE_REG_ERROR(base)) & 0x80) != 0x80) && - ((inb_p(IDE_REG_STATUS(base)) & 0x80) != 0x80)) - { - return 0; - } - i++; - } while (i != 0); - return 1; +static __inline__ int wait_for_notbusy(unsigned base) +{ + unsigned i = 0; + + do { + if (((inb_p(IDE_REG_ERROR(base)) & 0x80) != 0x80) && + ((inb_p(IDE_REG_STATUS(base)) & 0x80) != 0x80)) + { + return 0; + } + i++; + } while (i != 0); + + return 1; } -static __inline__ int wait_for_dataready(unsigned base) { - unsigned i = 0; - do { - if (((inb_p(IDE_REG_ERROR(base)) & 0x80) != 0x80) && - ((inb_p(IDE_REG_STATUS(base)) & 0x88) != 0x88)) - { - return 0; - } - i++; - } while (i != 0); - return 1; +static __inline__ int wait_for_dataready(unsigned base) +{ + unsigned i = 0; + + do { + if (((inb_p(IDE_REG_ERROR(base)) & 0x80) != 0x80) && + ((inb_p(IDE_REG_STATUS(base)) & 0x88) != 0x88)) + { + return 0; + } + i++; + } while (i != 0); + + return 1; } static __inline__ int write_command( - unsigned base, - ide_command_t command, - ide_cmd_param_t * params) + unsigned base, + ide_command_t command, + ide_cmd_param_t * params) { - if (wait_for_notbusy(base) != 0) return 1; - outb_p(params->precomp, IDE_REG_PRECOMP(base)); - outb_p(params->sector_count, IDE_REG_SECTOR_COUNT(base)); - outb_p(params->sector_number, IDE_REG_SECTOR_NUMBER(base)); - outb_p(params->cylinder & 0xFF, IDE_REG_CYLINDER_LSB(base)); - outb_p((params->cylinder >> 8) & 0x03, IDE_REG_CYLINDER_MSB(base)); - outb_p(params->drivehead, IDE_REG_DRIVEHEAD(base)); - if (wait_for_notbusy(base) != 0) return 1; - outb_p(command, IDE_REG_COMMAND(base)); - return 0; + if (wait_for_notbusy(base) != 0) + return 1; + + outb_p(params->precomp, IDE_REG_PRECOMP(base)); + outb_p(params->sector_count, IDE_REG_SECTOR_COUNT(base)); + outb_p(params->sector_number, IDE_REG_SECTOR_NUMBER(base)); + outb_p(params->cylinder & 0xFF, IDE_REG_CYLINDER_LSB(base)); + outb_p((params->cylinder >> 8) & 0x03, IDE_REG_CYLINDER_MSB(base)); + outb_p(params->drivehead, IDE_REG_DRIVEHEAD(base)); + + if (wait_for_notbusy(base) != 0) + return 1; + + outb_p(command, IDE_REG_COMMAND(base)); + + return 0; } int ide_shutdown(void) { - outb_p(IDE_CMD_STANDBY_IMMEDIATE, IDE_REG_COMMAND(IDE_BASE1)); - outb_p(IDE_CMD_STANDBY_IMMEDIATE2, IDE_REG_COMMAND(IDE_BASE1)); - return 0; + outb_p(IDE_CMD_STANDBY_IMMEDIATE, IDE_REG_COMMAND(IDE_BASE1)); + outb_p(IDE_CMD_STANDBY_IMMEDIATE2, IDE_REG_COMMAND(IDE_BASE1)); + return 0; } -int ide_read_data(unsigned base, void * buf, size_t size) { - register unsigned short * ptr = (unsigned short *) buf; - if (wait_for_dataready(base)) { - printk_debug("data not ready...\n"); - return 1; - } - while (size > 1) { - *ptr++ = inw_p(IDE_REG_DATA(base)); - size -= sizeof(unsigned short); - } - return 0; +int ide_read_data(unsigned base, void * buf, size_t size) +{ + register unsigned short * ptr = (unsigned short *) buf; + + if (wait_for_dataready(base)) { + printk_debug("data not ready...\n"); + return 1; + } + + while (size > 1) { + *ptr++ = inw_p(IDE_REG_DATA(base)); + size -= sizeof(unsigned short); + } + + return 0; } -int ide_write_data(unsigned base, void * buf, size_t size) { - register unsigned short * ptr = (unsigned short *) buf; - if (wait_for_dataready(base)) return 1; - while (size > 1) { - outw_p(*ptr, IDE_REG_DATA(base)); - ptr++; - size -= sizeof(unsigned short); - } - return 0; +int ide_write_data(unsigned base, void * buf, size_t size) +{ + register unsigned short * ptr = (unsigned short *) buf; + + if (wait_for_dataready(base)) + return 1; + while (size > 1) { + outw_p(*ptr, IDE_REG_DATA(base)); + ptr++; + size -= sizeof(unsigned short); + } + + return 0; } harddisk_info_t harddisk_info[NUM_HD]; static char buffer[512]; -static int init_drive(unsigned base, int driveno) { - volatile int delay; - ide_cmd_param_t cmd = IDE_DEFAULT_COMMAND; - unsigned char command_val; - //unsigned int idx; - //int retval; - unsigned short* drive_info; +static int init_drive(unsigned base, int driveno) +{ + volatile int delay; + ide_cmd_param_t cmd = IDE_DEFAULT_COMMAND; + unsigned char command_val; + unsigned short* drive_info; - harddisk_info[driveno].controller_port = base; - harddisk_info[driveno].num_heads = 0u; - harddisk_info[driveno].num_cylinders = 0u; - harddisk_info[driveno].num_sectors_per_track = 0u; - harddisk_info[driveno].num_sectors = 0ul; - harddisk_info[driveno].address_mode = IDE_DH_CHS; - harddisk_info[driveno].drive_exists = 0; + harddisk_info[driveno].controller_port = base; + harddisk_info[driveno].num_heads = 0u; + harddisk_info[driveno].num_cylinders = 0u; + harddisk_info[driveno].num_sectors_per_track = 0u; + harddisk_info[driveno].num_sectors = 0ul; + harddisk_info[driveno].address_mode = IDE_DH_CHS; + harddisk_info[driveno].drive_exists = 0; - cmd.drivehead = IDE_DH_DEFAULT | IDE_DH_HEAD(0) | IDE_DH_CHS | - IDE_DH_DRIVE(driveno); - write_command(base, IDE_CMD_GET_INFO, &cmd); - if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { - /* Well, if that command didn't work, we probably don't have drive. */ - printk_debug("Drive %d: detect FAILED\n", driveno); - return 1; - } - ide_read_data(base, buffer, IDE_SECTOR_SIZE); + cmd.drivehead = IDE_DH_DEFAULT | IDE_DH_HEAD(0) | IDE_DH_CHS | + IDE_DH_DRIVE(driveno); + write_command(base, IDE_CMD_GET_INFO, &cmd); - /* Now suck the data out */ -#if 0 - harddisk_info[driveno].num_heads = *((unsigned short *) (buffer + 0x6E)); - harddisk_info[driveno].num_cylinders = *((unsigned short *) (buffer + 0x6C)); - harddisk_info[driveno].num_sectors_per_track = - *((unsigned short *) (buffer + 0x70)); - harddisk_info[driveno].num_sectors = *((unsigned int *) (buffer + 0x72)); -#else - drive_info = (unsigned short*)buffer; - harddisk_info[driveno].num_heads = drive_info[3]; - harddisk_info[driveno].num_cylinders = drive_info[1]; - harddisk_info[driveno].num_sectors_per_track = drive_info[6]; - harddisk_info[driveno].num_sectors = *((unsigned int*)&(drive_info[60])); -#endif - harddisk_info[driveno].drive_exists = 1; + if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { + /* Well, if that command didn't work, we probably don't have drive. */ + printk_debug("Drive %d: detect FAILED\n", driveno); + return 1; + } + ide_read_data(base, buffer, IDE_SECTOR_SIZE); - printk_debug(__FUNCTION__ " sectors_per_track=[%d], num_heads=[%d], num_cylinders=[%d]\n", - harddisk_info[driveno].num_sectors_per_track, - harddisk_info[driveno].num_heads, - harddisk_info[driveno].num_cylinders); + /* Now suck the data out */ + drive_info = (unsigned short*)buffer; + harddisk_info[driveno].num_heads = drive_info[3]; + harddisk_info[driveno].num_cylinders = drive_info[1]; + harddisk_info[driveno].num_sectors_per_track = drive_info[6]; + harddisk_info[driveno].num_sectors = *((unsigned int*)&(drive_info[60])); + memcpy(harddisk_info[driveno].model_number, ((unsigned short*)&(drive_info[27])), 40); + harddisk_info[driveno].drive_exists = 1; + + printk_debug("%s \n", harddisk_info[driveno].model_number); + + printk_debug(__FUNCTION__ " sectors_per_track=[%d], num_heads=[%d], num_cylinders=[%d]\n", + harddisk_info[driveno].num_sectors_per_track, + harddisk_info[driveno].num_heads, + harddisk_info[driveno].num_cylinders); #define HD harddisk_info[driveno] if(drive_info[49] != 0) { - printk_debug("IDE%d %d/%d/%d cap: %04x\n", - (int)driveno, (int)HD.num_heads, (int)HD.num_cylinders, (int)HD.num_sectors_per_track, - (int) drive_info[49]); - } + printk_debug("IDE%d %d/%d/%d cap: %04x\n", + (int)driveno, + (int)HD.num_heads, (int)HD.num_cylinders, + (int)HD.num_sectors_per_track, + (int) drive_info[49]); + } -// printk_debug("drive %d detected heads=0x%X(%u) cyl=0x%X(%u) sec/trk=" -// "0x%X(%u) sects=0x%X(%u)\n", (int)driveno, (int)HD.num_heads, (int)HD.num_heads, -// HD.num_cylinders, (int)HD.num_cylinders, (int)HD.num_sectors_per_track, -// HD.num_sectors_per_track, (int)HD.num_sectors, (int)HD.num_sectors); - -// printk_debug" capability=[%04x]\n", (int)drive_info[49]); + if (drive_info[49] & 0x200) { /* bit 9 of capability word is lba supported bit */ + harddisk_info[driveno].address_mode = IDE_DH_LBA; + } else { + harddisk_info[driveno].address_mode = IDE_DH_CHS; + } + // harddisk_info[driveno].address_mode = IDE_DH_CHS; - if (drive_info[49] & 0x200) { /* bit 9 of capability word is lba supported bit */ - harddisk_info[driveno].address_mode = IDE_DH_LBA; - } else { - harddisk_info[driveno].address_mode = IDE_DH_CHS; - } - // harddisk_info[driveno].address_mode = IDE_DH_CHS; + /* Set up the Extended control register */ + if (harddisk_info[driveno].num_heads > 8) { + command_val = 0x0A; + } else { + command_val = 0x02; + } - /* Set up the Extended control register */ - if (harddisk_info[driveno].num_heads > 8) { - command_val = 0x0A; - } else { - command_val = 0x02; - } + outb_p(command_val, IDE_REG_CONTROL(base)); - outb_p(command_val, IDE_REG_CONTROL(base)); + /* Execute the drive diagnostics command */ + write_command(base, IDE_CMD_DRIVE_DIAG, &cmd); + if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { + return 1; + } - /* Execute the drive diagnostics command */ - write_command(base, IDE_CMD_DRIVE_DIAG, &cmd); - if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { - return 1; - } + /* Reset the bus (again) */ + outb_p(cmd.drivehead, IDE_REG_DRIVEHEAD(base)); + outb_p(0x04, IDE_REG_CONTROL(base)); + for (delay = 0x100; delay > 0; --delay); + outb_p(command_val, IDE_REG_CONTROL(base)); - /* Reset the bus (again) */ - outb_p(cmd.drivehead, IDE_REG_DRIVEHEAD(base)); - outb_p(0x04, IDE_REG_CONTROL(base)); - for (delay = 0x100; delay > 0; --delay); - outb_p(command_val, IDE_REG_CONTROL(base)); + /* Now do a drive recalibrate */ + write_command(base, IDE_CMD_RECALIBRATE, &cmd); + if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { + return 1; + } + (void)wait_for_notbusy(base); - /* Now do a drive recalibrate */ - write_command(base, IDE_CMD_RECALIBRATE, &cmd); - if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { - return 1; - } - (void)wait_for_notbusy(base); + /* Set device parameters */ + cmd.sector_count = harddisk_info[driveno].num_sectors_per_track; + cmd.drivehead = IDE_DH_DEFAULT | + IDE_DH_HEAD(harddisk_info[driveno].num_heads) | + IDE_DH_DRIVE(driveno) | + harddisk_info[driveno].address_mode; + write_command(base, IDE_CMD_SET_PARAMS, &cmd); - /* Set device parameters */ - cmd.sector_count = harddisk_info[driveno].num_sectors_per_track; - cmd.drivehead = IDE_DH_DEFAULT | - IDE_DH_HEAD(harddisk_info[driveno].num_heads) | - IDE_DH_DRIVE(driveno) | - harddisk_info[driveno].address_mode; - write_command(base, IDE_CMD_SET_PARAMS, &cmd); + /* Set multiple mode */ + cmd.sector_count = 0x10; /* Single-word DMA, mode 0 */ + cmd.drivehead = IDE_DH_DEFAULT | + IDE_DH_HEAD(0) | + IDE_DH_DRIVE(driveno) | + harddisk_info[driveno].address_mode; + write_command(base, IDE_CMD_SET_MULTIMODE, &cmd); - /* Set multiple mode */ - cmd.sector_count = 0x10; /* Single-word DMA, mode 0 */ - cmd.drivehead = IDE_DH_DEFAULT | - IDE_DH_HEAD(0) | - IDE_DH_DRIVE(driveno) | - harddisk_info[driveno].address_mode; - write_command(base, IDE_CMD_SET_MULTIMODE, &cmd); + /* Make sure command is still OK */ + outb_p(command_val, IDE_REG_CONTROL(base)); - /* Make sure command is still OK */ - outb_p(command_val, IDE_REG_CONTROL(base)); + /* Set parameters _again_ */ + cmd.sector_count = harddisk_info[driveno].num_sectors_per_track; + cmd.drivehead = IDE_DH_DEFAULT | + IDE_DH_HEAD(harddisk_info[driveno].num_heads) | + IDE_DH_DRIVE(driveno) | + harddisk_info[driveno].address_mode; + write_command(base, IDE_CMD_SET_PARAMS, &cmd); - /* Set parameters _again_ */ - cmd.sector_count = harddisk_info[driveno].num_sectors_per_track; - cmd.drivehead = IDE_DH_DEFAULT | - IDE_DH_HEAD(harddisk_info[driveno].num_heads) | - IDE_DH_DRIVE(driveno) | - harddisk_info[driveno].address_mode; - write_command(base, IDE_CMD_SET_PARAMS, &cmd); - - /* Make sure command is still OK */ - outb_p(command_val, IDE_REG_CONTROL(base)); + /* Make sure command is still OK */ + outb_p(command_val, IDE_REG_CONTROL(base)); #if 0 - /* Exercise the drive to see if it works OK */ - printk_debug("Exercising HardDisk- buffer=0x%08lX\n", (unsigned long) buffer); - outb_p(0x42, 0xeb); - while (1) { - for (idx = 0; idx < harddisk_info[driveno].num_sectors; ++idx) { - outb_p(idx & 0xFF, 0x80); - retval = ide_read_sector(driveno, buffer, idx); - if (retval != 0) { - printk_debug("readsector(driveno=%d, sector=%lu) returned %d!\n", - driveno, (unsigned long) idx, retval); - } - } - printk_debug("Exercise complete!\n"); - outb(0x42, 0xeb); - } + /* Exercise the drive to see if it works OK */ + printk_debug("Exercising HardDisk- buffer=0x%08lX\n", (unsigned long) buffer); + outb_p(0x42, 0xeb); + while (1) { + for (idx = 0; idx < harddisk_info[driveno].num_sectors; ++idx) { + outb_p(idx & 0xFF, 0x80); + retval = ide_read_sector(driveno, buffer, idx); + if (retval != 0) { + printk_debug("readsector(driveno=%d, sector=%lu) returned %d!\n", + driveno, (unsigned long) idx, retval); + } + } + printk_debug("Exercise complete!\n"); + outb(0x42, 0xeb); + } #endif /* 0 */ - return 0; + return 0; } static int init_controller(unsigned base, int basedrive) { - volatile int delay; + volatile int delay; - /* First, check to see if the controller even exists */ - outb_p(0x5, IDE_REG_SECTOR_COUNT(base)); - if (inb_p(IDE_REG_SECTOR_COUNT(base)) != 0x5) { - printk_debug("Controller %d: detect FAILED (1)\n", basedrive / 2); - return -1; - } - outb_p(0xA, IDE_REG_SECTOR_COUNT(base)); - if (inb_p(IDE_REG_SECTOR_COUNT(base)) != 0xA) { - printk_debug("Controller %d: detect FAILED (2)\n", basedrive / 2); - return -2; - } + /* First, check to see if the controller even exists */ + outb_p(0x5, IDE_REG_SECTOR_COUNT(base)); + if (inb_p(IDE_REG_SECTOR_COUNT(base)) != 0x5) { + printk_debug("Controller %d: detect FAILED (1)\n", basedrive / 2); + return -1; + } + outb_p(0xA, IDE_REG_SECTOR_COUNT(base)); + if (inb_p(IDE_REG_SECTOR_COUNT(base)) != 0xA) { + printk_debug("Controller %d: detect FAILED (2)\n", basedrive / 2); + return -2; + } - /* Reset the system */ - outb_p(0x4, IDE_REG_CONTROL(base)); - for (delay = 0x100; delay > 0; --delay); - outb_p(0x0, IDE_REG_CONTROL(base)); + /* Reset the system */ + outb_p(0x4, IDE_REG_CONTROL(base)); + for (delay = 0x100; delay > 0; --delay); + outb_p(0x0, IDE_REG_CONTROL(base)); - /* Now initialize the individual drives */ - init_drive(base, basedrive); - init_drive(base, basedrive+1); + /* Now initialize the individual drives */ + init_drive(base, basedrive); + init_drive(base, basedrive+1); - return 0; + return 0; } -int ide_init(void) { +int ide_init(void) +{ + outb_p(0x42, 0xEB); + printk_debug ("I am now initializing the ide system\n"); - outb_p(0x42, 0xEB); -printk_debug ("I am now initializing the ide system\n"); - - if(init_controller(IDE_BASE1, 0) < 0) { - printk_debug ("Initializing the main controller failed!\n"); - /* error return error */ - return -1; - }; + if (init_controller(IDE_BASE1, 0) < 0) { + printk_debug ("Initializing the main controller failed!\n"); + /* error return error */ + return -1; + }; #if (NUM_HD > 3) - init_controller(IDE_BASE2, 2); + init_controller(IDE_BASE2, 2); #endif #if (NUM_HD > 5) - init_controller(IDE_BASE3, 4); + init_controller(IDE_BASE3, 4); #endif #if (NUM_HD > 7) - init_controller(IDE_BASE4, 6); + init_controller(IDE_BASE4, 6); #endif - return 0; + return 0; } /* read a sector or a partial sector */ int ide_read_sector(int drive, void * buffer, unsigned int block, int byte_offset, - int n_bytes) { - ide_cmd_param_t cmd = IDE_DEFAULT_COMMAND; - unsigned base; - unsigned char sect_buffer[IDE_SECTOR_SIZE]; - unsigned int track; - int status; - int address_mode = harddisk_info[drive].address_mode; + int n_bytes) { + ide_cmd_param_t cmd = IDE_DEFAULT_COMMAND; + unsigned base; + unsigned char sect_buffer[IDE_SECTOR_SIZE]; + unsigned int track; + int status; + int address_mode = harddisk_info[drive].address_mode; + int i; - /* - printk_debug(__FUNCTION__ " drive[%d], buffer[%08x], block[%08x], offset[%d], n_bytes[%d]\n", - drive, buffer, block, byte_offset, n_bytes); - */ -// printk_debug(__FUNCTION__ " block(%08x) to addr(%08x)\r", block, (int)buffer); - if ((drive < 0) || (drive >= NUM_HD) || - (harddisk_info[drive].drive_exists == 0)) - { - printk_debug("unknown drive\n"); - return 1; - } - base = harddisk_info[drive].controller_port; + //printk_debug(__FUNCTION__ " drive[%d], buffer[%08x], block[%08x], offset[%d], n_bytes[%d]\n", + // drive, buffer, block, byte_offset, n_bytes); + // printk_debug(__FUNCTION__ " block(%08x) to addr(%08x)\r", block, (int)buffer); + if ((drive < 0) || (drive >= NUM_HD) || + (harddisk_info[drive].drive_exists == 0)) + { + printk_debug("unknown drive\n"); + return 1; + } + base = harddisk_info[drive].controller_port; - if (harddisk_info[drive].num_heads > 8) { - outb_p(0xA, IDE_REG_CONTROL(base)); - } else { - outb_p(0x2, IDE_REG_CONTROL(base)); - } + if (harddisk_info[drive].num_heads > 8) { + outb_p(0xA, IDE_REG_CONTROL(base)); + } else { + outb_p(0x2, IDE_REG_CONTROL(base)); + } - cmd.sector_count = 1; + cmd.sector_count = 1; - if (address_mode == IDE_DH_CHS) { - track = block / harddisk_info[drive].num_sectors_per_track; + if (address_mode == IDE_DH_CHS) { + track = block / harddisk_info[drive].num_sectors_per_track; - cmd.sector_number = 1+(block % harddisk_info[drive].num_sectors_per_track); - cmd.cylinder = track / harddisk_info[drive].num_heads; - cmd.drivehead = IDE_DH_DEFAULT | - IDE_DH_HEAD(track % harddisk_info[drive].num_heads) | - IDE_DH_DRIVE(drive) | - IDE_DH_CHS; - /* - printk_debug(__FUNCTION__ " CHS: track=[%d], sector_number=[%d], cylinder=[%d]\n", - track, cmd.sector_number, cmd.cylinder); - */ - } else { + cmd.sector_number = 1+(block % harddisk_info[drive].num_sectors_per_track); + cmd.cylinder = track / harddisk_info[drive].num_heads; + cmd.drivehead = IDE_DH_DEFAULT | + IDE_DH_HEAD(track % harddisk_info[drive].num_heads) | + IDE_DH_DRIVE(drive) | + IDE_DH_CHS; + /* + printk_debug(__FUNCTION__ " CHS: track=[%d], sector_number=[%d], cylinder=[%d]\n", + track, cmd.sector_number, cmd.cylinder); + */ + } else { #if 1 - cmd.sector_number = block & 0xff; /* lower byte of block (lba) */ - cmd.cylinder = (block >> 8) & 0xffff; /* middle 2 bytes of block (lba) */ - cmd.drivehead = IDE_DH_DEFAULT | /* set bits that must be on */ - ((block >> 24) & 0x0f) | /* lower nibble of byte 3 of block */ - IDE_DH_DRIVE(drive) | - IDE_DH_LBA; + cmd.sector_number = block & 0xff; /* lower byte of block (lba) */ + cmd.cylinder = (block >> 8) & 0xffff; /* middle 2 bytes of block (lba) */ + cmd.drivehead = IDE_DH_DEFAULT | /* set bits that must be on */ + ((block >> 24) & 0x0f) | /* lower nibble of byte 3 of block */ + IDE_DH_DRIVE(drive) | + IDE_DH_LBA; #else - cmd.sector_number = (block >> 24) & 0xff; /* byte 0 of block (lba) */ - cmd.cylinder = (block >> 8) & 0xffff; /* bytes 1 & 2 of block (lba) */ - cmd.drivehead = IDE_DH_DEFAULT | /* set bits that must be on */ - ((block >> 4) & 0x0f) | /* upper nibble of byte 3 of block */ - IDE_DH_DRIVE(drive) | - IDE_DH_LBA; + cmd.sector_number = (block >> 24) & 0xff; /* byte 0 of block (lba) */ + cmd.cylinder = (block >> 8) & 0xffff; /* bytes 1 & 2 of block (lba) */ + cmd.drivehead = IDE_DH_DEFAULT | /* set bits that must be on */ + ((block >> 4) & 0x0f) | /* upper nibble of byte 3 of block */ + IDE_DH_DRIVE(drive) | + IDE_DH_LBA; #endif - /* - printk_debug(__FUNCTION__ " LBA: drivehead[%0x], cylinder[%04x], sector[%0x], block[%8x]\n", - cmd.drivehead, cmd.cylinder, cmd.sector_number, block & 0x0fffffff); - */ - } + /* + printk_debug(__FUNCTION__ " LBA: drivehead[%0x], cylinder[%04x], sector[%0x], block[%8x]\n", + cmd.drivehead, cmd.cylinder, cmd.sector_number, block & 0x0fffffff); + */ + } - write_command(base, IDE_CMD_READ_MULTI_RETRY, &cmd); - if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { - printk_debug("ide not ready...\n"); - return 1; - } - if (n_bytes != IDE_SECTOR_SIZE) { - status = ide_read_data(base, sect_buffer, IDE_SECTOR_SIZE); - if (status == 0) { - memcpy(buffer, sect_buffer+byte_offset, n_bytes); - } - } else { - status = ide_read_data(base, buffer, IDE_SECTOR_SIZE); - } - // printk_debug(__FUNCTION__ " status = [%d]\n", status); - return status; + write_command(base, IDE_CMD_READ_MULTI_RETRY, &cmd); + if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { + printk_debug("ide not ready...\n"); + return 1; + } + if (n_bytes != IDE_SECTOR_SIZE) { + status = ide_read_data(base, sect_buffer, IDE_SECTOR_SIZE); + if (status == 0) { + memcpy(buffer, sect_buffer+byte_offset, n_bytes); + } + } else { + status = ide_read_data(base, buffer, IDE_SECTOR_SIZE); + } + return status; } #if 0 /* read a sector or a partial sector */ int ide_read_sector(int drive, void * buffer, unsigned int block, int byte_offset, - int n_bytes) { - ide_cmd_param_t cmd = IDE_DEFAULT_COMMAND; - unsigned base; - unsigned char sect_buffer[IDE_SECTOR_SIZE]; - unsigned int track; - int status; + int n_bytes) { + ide_cmd_param_t cmd = IDE_DEFAULT_COMMAND; + unsigned base; + unsigned char sect_buffer[IDE_SECTOR_SIZE]; + unsigned int track; + int status; - if ((drive < 0) || (drive >= NUM_HD) || - (harddisk_info[drive].drive_exists == 0)) - { - return 1; - } - base = harddisk_info[drive].controller_port; + if ((drive < 0) || (drive >= NUM_HD) || + (harddisk_info[drive].drive_exists == 0)) + { + return 1; + } + base = harddisk_info[drive].controller_port; - if (harddisk_info[drive].num_heads > 8) { - outb_p(0xA, IDE_REG_CONTROL(base)); - } else { - outb_p(0x2, IDE_REG_CONTROL(base)); - } + if (harddisk_info[drive].num_heads > 8) { + outb_p(0xA, IDE_REG_CONTROL(base)); + } else { + outb_p(0x2, IDE_REG_CONTROL(base)); + } - track = block / harddisk_info[drive].num_sectors_per_track; + track = block / harddisk_info[drive].num_sectors_per_track; - cmd.sector_count = 1; - cmd.sector_number = 1+(block % harddisk_info[drive].num_sectors_per_track); - cmd.cylinder = track % harddisk_info[drive].num_heads; - cmd.drivehead = IDE_DH_DEFAULT | - IDE_DH_HEAD(track / harddisk_info[drive].num_heads) | - IDE_DH_DRIVE(drive) | - IDE_DH_CHS; + cmd.sector_count = 1; + cmd.sector_number = 1+(block % harddisk_info[drive].num_sectors_per_track); + cmd.cylinder = track % harddisk_info[drive].num_heads; + cmd.drivehead = IDE_DH_DEFAULT | + IDE_DH_HEAD(track / harddisk_info[drive].num_heads) | + IDE_DH_DRIVE(drive) | + IDE_DH_CHS; // printk_debug(__FUNCTION__ " track=[%d], sector_number=[%d], cylinder=[%d]\n", // track, cmd.sector_number, cmd.cylinder); - write_command(base, IDE_CMD_READ_MULTI_RETRY, &cmd); - if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { - return 1; - } - if (n_bytes != IDE_SECTOR_SIZE) { - status = ide_read_data(base, sect_buffer, IDE_SECTOR_SIZE); - if (status == 0) { - memcpy(buffer, sect_buffer+byte_offset, n_bytes); - } - } else { - status = ide_read_data(base, buffer, IDE_SECTOR_SIZE); - } + write_command(base, IDE_CMD_READ_MULTI_RETRY, &cmd); + if ((inb_p(IDE_REG_STATUS(base)) & 1) != 0) { + return 1; + } + if (n_bytes != IDE_SECTOR_SIZE) { + status = ide_read_data(base, sect_buffer, IDE_SECTOR_SIZE); + if (status == 0) { + memcpy(buffer, sect_buffer+byte_offset, n_bytes); + } + } else { + status = ide_read_data(base, buffer, IDE_SECTOR_SIZE); + } // printk_debug(__FUNCTION__ " status = [%d]\n", status); - return status; + return status; } #endif diff --git a/src/rom/ide_fill_inbuf.c b/src/rom/ide_fill_inbuf.c index 81ab000070..15b5bf7c4e 100644 --- a/src/rom/ide_fill_inbuf.c +++ b/src/rom/ide_fill_inbuf.c @@ -13,21 +13,21 @@ extern int ide_read_sector(int drive, void * buffer, unsigned int block, int byt int n_bytes); extern int ide_init(void); - - static unsigned long offset; static int init_bytes(void) { int i; + printk_debug ("Trying polled ide\n"); printk_debug ("Waiting for ide disks to spin up\n"); printk_debug ("This is a hard coded delay and longer than necessary.\n"); - for(i = 0; i < 25; i++) { + for (i = 0; i < 15; i++) { printk_debug("."); delay(1); } printk_debug("\n"); - offset = 0; + + offset = 0x7e00; return ide_init(); } @@ -36,26 +36,53 @@ static void fini_bytes(void) return; } +static unsigned char buffer[512]; +static unsigned int block_num = 0; +static unsigned int first_fill = 1; + static byte_offset_t ide_read(void *vdest, byte_offset_t offset, byte_offset_t count) { byte_offset_t bytes = 0; unsigned char *dest = vdest; - while(bytes < count) { - unsigned int block, byte_offset, len; + + //printk_debug("ide_read count = %x\n", count); + while (bytes < count) { + unsigned int byte_offset, len; int result; - block = offset / 512; - byte_offset = offset %512; + int i, j; + + /* The block is not cached in memory or frist time called */ + if (block_num != offset / 512 || first_fill) { + block_num = offset / 512; + ide_read_sector(0, buffer, block_num, + 0, 512); + first_fill = 0; +#if 1 + //printk_debug("ide_read offset = %x\n", offset); + //printk_debug("ide_read block_num = %x\n", block_num); + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + printk_debug("%02x ", buffer[i*16 +j]); + } + printk_debug("\n"); + } + + printk_debug("\n"); +#endif + } + + byte_offset = offset % 512; len = 512 - byte_offset; if (len > (count - bytes)) { len = (count - bytes); } - result = ide_read_sector(0, dest, block , byte_offset, len); - if (result != 0) { - return bytes; - } + + memcpy(dest, buffer + byte_offset, len); + offset += len; bytes += len; dest += len; + } return bytes; } @@ -63,10 +90,12 @@ static byte_offset_t ide_read(void *vdest, byte_offset_t offset, byte_offset_t c static byte_offset_t read_bytes(void *vdest, byte_offset_t count) { byte_offset_t len; + len = ide_read(vdest, offset, count); if (len > 0) { offset += len; } + return len; }