mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
cleanup, resync for SiS chipsets
This commit is contained in:
parent
973edded0b
commit
6bcb2b7d1d
18 changed files with 539 additions and 546 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,416 +32,424 @@
|
|||
#include <string.h>
|
||||
#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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue