cleanup, resync for SiS chipsets

This commit is contained in:
Li-Ta Lo 2002-05-27 02:15:10 +00:00
parent 973edded0b
commit 6bcb2b7d1d
18 changed files with 539 additions and 546 deletions

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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"

View file

@ -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, &reg);
pci_write_config_byte(pcidev, 0x77, reg & 0xEF);
u8 reg;
/* disable ROM delay transaction */
pci_read_config_byte(pcidev, 0x77, &reg);
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");
}

View file

@ -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

View file

@ -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

View file

@ -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");
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
*

View file

@ -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, &regval);
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();

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}