Hi Zheng,
On 25.12.2008 05:10, Bao, Zheng wrote:
On 24.12.2008 16:00, Carl-Daniel Hailfinger wrote:
On 23.12.2008 08:10, Bao, Zheng wrote:
Sorry, I tested it again and tried it on 4 ports. It only works on 1st and 4th ports, while doesn't work on 2nd and 3rd ports. It loops at driver no longer selected after 10ms, retrying init driver no longer selected after 10ms, retrying init
My SATA drive is 250 GB Seagate Barracuda ST3250620NS.
Thanks for testing! This is very strange. It seems the hardware does not follow the BDG. Did you have 4 drives attached at the same time or was it 1 drive attached to another port each time?
What you said reminded me to connect more drives when the board boots. Yes, it changed. If 1st and 2nd ports are both connected, they can both be correctly detected and initialized. Then I unplugged the drive on 1st post and didn't change the BIOS, the 2nd ports couldn't be initialized as it was. I check our asm code and can't find any tip.
I have modified the code to avoid the endless loop and print better diagnostic messages. It will work if only 1st or if 1st and 2nd port are connected. If only 2nd is connected and the hardware acts strange, it will print an error message and continue. I have not tested 3rd and 4th port.
Can you please test if this works for you?
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: LinuxBIOSv2-asus_m2a-vm/src/southbridge/amd/sb600/sb600_sata.c =================================================================== --- LinuxBIOSv2-asus_m2a-vm/src/southbridge/amd/sb600/sb600_sata.c (Revision 3844) +++ LinuxBIOSv2-asus_m2a-vm/src/southbridge/amd/sb600/sb600_sata.c (Arbeitskopie) @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008 Carl-Daniel Hailfinger * * 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 @@ -26,6 +27,28 @@ #include <arch/io.h> #include "sb600.h"
+int sata_drive_detect(int portnum, u16 iobar) +{ + u8 byte, byte2; + int i = 0; + outb(0xA0 + 0x10 * (portnum % 2), iobar + 0x6); + while (byte = inb(iobar + 0x6), + byte2 = inb(iobar + 0x7), + (byte != (0xA0 + 0x10 * (portnum % 2))) || + ((byte2 & 0x88) != 0)) { + printk_spew("0x6=%x, 0x7=%x\n", byte, byte2); + if (byte != (0xA0 + 0x10 * (portnum % 2))) { + printk_debug("drive no longer selected after %i ms, retrying init\n", i * 10); + return 1; + } else + printk_spew("drive detection not yet completed, waiting...\n"); + mdelay(10); + i++; + } + printk_spew("drive detection done after %i ms\n", i * 10); + return 0; +} + static void sata_init(struct device *dev) { u8 byte; @@ -33,6 +56,7 @@ u32 dword; u8 *sata_bar5; u16 sata_bar0, sata_bar1, sata_bar2, sata_bar3, sata_bar4; + int i, j;
struct southbridge_ati_sb600_config *conf; conf = dev->chip_info; @@ -62,12 +86,12 @@ sata_bar3 = pci_read_config16(dev, 0x1C) & ~0x7; sata_bar4 = pci_read_config16(dev, 0x20) & ~0x7;
- /* printk_debug("sata_bar0=%x\n", sata_bar0); */ /* 3030 */ - /* printk_debug("sata_bar1=%x\n", sata_bar1); */ /* 3070 */ - /* printk_debug("sata_bar2=%x\n", sata_bar2); */ /* 3040 */ - /* printk_debug("sata_bar3=%x\n", sata_bar3); */ /* 3080 */ - /* printk_debug("sata_bar4=%x\n", sata_bar4); */ /* 3000 */ - /* printk_debug("sata_bar5=%x\n", sata_bar5); */ /* e0309000 */ + printk_spew("sata_bar0=%x\n", sata_bar0); /* 3030 */ + printk_spew("sata_bar1=%x\n", sata_bar1); /* 3070 */ + printk_spew("sata_bar2=%x\n", sata_bar2); /* 3040 */ + printk_spew("sata_bar3=%x\n", sata_bar3); /* 3080 */ + printk_spew("sata_bar4=%x\n", sata_bar4); /* 3000 */ + printk_spew("sata_bar5=%x\n", sata_bar5); /* e0309000 */
/* Program the 2C to 0x43801002 */ dword = 0x43801002; @@ -131,31 +155,36 @@ dword |= 1 << 25; pci_write_config32(dev, 0x40, dword);
- /* Enable the I/O ,MM ,BusMaster access for SATA */ + /* Enable the I/O, MM, BusMaster access for SATA */ byte = pci_read_config8(dev, 0x4); byte |= 7 << 0; pci_write_config8(dev, 0x4, byte);
- /* RPR6.6 SATA drive detection. Currently we detect Primary Master Device only */ - /* Use BAR5+0x1A8,BAR0+0x6 for Primary Slave */ - /* Use BAR5+0x228,BAR0+0x6 for Secondary Master */ - /* Use BAR5+0x2A8,BAR0+0x6 for Secondary Slave */ + /* RPR6.6 SATA drive detection. */ + /* Use BAR5+0x128,BAR0 for Primary Slave */ + /* Use BAR5+0x1A8,BAR0 for Primary Slave */ + /* Use BAR5+0x228,BAR2 for Secondary Master */ + /* Use BAR5+0x2A8,BAR2 for Secondary Slave */
- byte = readb(sata_bar5 + 0x128); - /* printk_debug("byte=%x\n", byte); */ - byte &= 0xF; - if (byte == 0x3) { - outb(0xA0, sata_bar0 + 0x6); - while ((inb(sata_bar0 + 0x6) != 0xA0) - || ((inb(sata_bar0 + 0x7) & 0x88) != 0)) { - mdelay(10); - /* printk_debug("0x6=%x,0x7=%x\n", inb(sata_bar0 + 0x6), - inb(sata_bar0 + 0x7)); */ - printk_debug("drive detection fail,trying...\n"); + for (i = 0; i < 4; i++) { + byte = readb(sata_bar5 + 0x128 + 0x80 * i); + printk_spew("SATA port %i status = %x\n", i, byte); + byte &= 0xF; + if (byte == 0x3) { + for (j = 0; j < 10; j++) { + if (!sata_drive_detect(i, ((i / 2) == 0) ? sata_bar0 : sata_bar2)) + break; + } + printk_debug("%s %s device is %sready after %i tries\n", + (i / 2) ? "Secondary" : "Primary", + (i % 2 ) ? "Slave" : "Master", + (j == 10) ? "not " : "", + (j == 10) ? j : j + 1); + } else { + printk_debug("No %s %s SATA drive on Slot%i\n", + (i / 2) ? "Secondary" : "Primary", + (i % 2 ) ? "Slave" : "Master", i); } - printk_debug("Primary master device is ready\n"); - } else { - printk_debug("No Primary master SATA drive on Slot0\n"); }
/* Below is CIM InitSataLateFar */