LinuxAnswers - the LQ Linux tutorial section.
Go Back > Forums > Linux Forums > Linux - Hardware
User Name
Linux - Hardware This forum is for Hardware issues.
Having trouble installing a piece of hardware? Want to know if that peripheral is compatible with Linux?


Search this Thread
Old 08-30-2006, 07:11 PM   #1
Registered: Sep 2005
Location: Boynton Beach, FL
Distribution: Slackware
Posts: 801

Rep: Reputation: 247Reputation: 247Reputation: 247
Solution for Promise FastTrack PDC20378 PATA or RAID with 2.6.17 kernel

If you own a motherboard with the Promise PDC20378 FastTrack SATA/RAID controller you probably know the same frustration as me. Part of the problem with the PDC20378 and Linux is the fact that the PDC20378 has both SATA and PATA ports in the same device. The standard Linux implementation for ATA devices does not support a device with some SATA and some PATA ports. Devices are either SATA or PATA (not BOTH). Add to that the fact that Linux does not understand the RAID array metadata for the PDC20378. Here are some of the issues with the PDC20378.
  • Promise has a proprietary RAID driver only for kernel version 2.4
  • Linux only has an SATA driver (PATA port not supported)
  • The Linux developers have no definite plans for PATA support on the PDC20378
  • The few patches for PATA support are not for the "standard" kernel sources (only modified distros)

I have found a number of things that can provide solutions to some of these problems. For one thing, I reverse engineered the UBUNTU patch for PATA support and created a patch for the "standard" 2.6.17 version of the Linux kernel. I had to do that to support my RAID 0+1 configuration. I have two of my hard disks on the PATA port of my PDC20378

Here is a link to the patch (the whole patch is posted below).

Here are some solutions to using the PDC20378 in various configurations.

For the "standard" Linux kernel version 2.4 you can support one of these configurations.
  • Two SATA disks using standard Linux sata_promise driver
  • RAID 0, 1, or 0+1 on SATA and/or PATA using proprietary Promise ft3xx driver
  • Any kind of Linux software RAID on SATA

If you can find a distro patched for PATA support you can support these additional configurations.
  • Two SATA disks and/or two PATA disks
  • Any kind of Linux software RAID on SATA and/or PATA

With kernel version 2.4 you have basically three different choices of drivers. If you want to use the "fake simulated hardware RAID" implemented in the BIOS and Windows driver, you can download the proprietary "ft3xx" driver from the Promise web site. The "ft3xx" driver supports SATA and/or PATA, but ONLY in a RAID configuration. You can download a driver for Suse Linux, or the partial sources to compile your own. You can use the "standard" Linux driver, called "sata_proimse" that only supports two SATA drives (no PATA) in a non-RAID configuration. You can possibly find an older patched version of "sata_promise" in a 2.4 distro such as UBUNTU, FC or GENTOO that supports the PATA drives in addition to SATA. You can use the Linux software RAID with the "sata_promise" driver.

Assuming you decide to use the "ft3xx" driver, the process is quite involved. I posted a previous thread here about how to do that. Basically you have to compile and test the "ft3xx" driver using the partial sources from Promise. You probably need a normal hard disk on some other controller to do that. You have to create an "initrd" image that loads the "ft3xx" driver, since the driver will ONLY build as a module, not as part of the kernel.

Here is a link to download the "ft3xx" sources or Suse driver.

The "sata_promise" driver is part of the "standard" Linux distro, but Linux only officially supports two SATA drives. You can easily build that driver in the normal way. The "sata_proimse" driver does not understand the "hardware RAID" sets, created by the BIOS and accessed by the Windows RAID driver for the PDC20378. Of course you can use the Linux software RAID, treating the PDC20378 as a "normal" SATA controller.

If you can find a version of 2.4 that has the appropriate patch, you can build that driver and have PATA drives along with the SATA drives. I use the "ft3xx" driver with version 2.4 and didn't try to find or develop a patch for that version of "sata_promise".

For version 2.6 of the kernel, your options are more limited. Promise has made no effort to update the "ft3xx" driver for 2.6 and has made no promise either. I looked at the effort involved in updating their driver and concluded that it was considerable, and might not even be possible. Promise does not provide all of the sources, only some of the sources.

Here are the possibilities with the "standard" Linux kernel version 2.6
  • Two SATA disks using the standard Linux "sata_promise" driver
  • RAID 0 or RAID 1 on SATA (NOT RAID 0+1) using "dmraid"
  • Any kind of Linux software RAID on SATA using "sata_promise"

If you use the patch for PATA support you have these additional possibilities for 2.6
  • Two SATA disks and/or two PATA disks
  • RAID 0, RAID 1, or RAID 0+1 using "dmraid"

I happen to use the Slackware distro that is essentially the unmodified Linux kernel. Since no "standard" Linux kernel release supports PATA in the "sata_promise" driver, I could not access my PATA drives, and could not access the mirror drives for my RAID 0+1 configuration. That's why I finally updated the patch for the driver. I chose 2.6.17 because it was the last stable release and is working well for me. 2.6.18 has not yet been officially released (that I know of). NOTE: No known plans for the "standard" 2.6.18 to support PATA on the PDC20378.

To use the "fake hardware RAID" provided by the BIOS and Windows RAID driver you need the "dmraid" utility. The "dmraid" program is essentially a RAID set detection and disk mapping program. It works in conjunction with the device-mapper in Linux to map the correct areas of the RAID volumes to "mapped" devices and partitions in "/dev/mapper". I am just beginning to work on making my system boot from RAID, and I hope to post more later about how to make an "initrd" for Slackware and "dmraid".

I don't claim to have invented the PATA patch for the "sata_proimse" driver. Someone else was kind enough to do that, and others ported it to a few distros. What I did was edit the standard 2.6.17 version of "sata_proimse" and create the appropriate patch. The real question is, "Will this change ever be put in the standard Linux kernel?". So far that doesn't appear promising.

Here is the PATA patch.
WARNING: I have done limited testing to verify correct operation in my configuration. Use at your own risk. This patch is not supported by anyone, but I will try to help if anyone has problems. I recommend starting by mounting any filesystems in read-only mode and checking carefully for problems.

--- oldlinux/drivers/scsi/libata-core.c	2006-08-30 17:03:45.000000000 -0400
+++ linux/drivers/scsi/libata-core.c	2006-08-30 15:36:00.000000000 -0400
@@ -4453,6 +4453,7 @@
 	ap->mwdma_mask = ent->mwdma_mask;
 	ap->udma_mask = ent->udma_mask;
 	ap->flags |= ent->host_flags;
+	ap->flags |= ent->port_flags[port_no];
 	ap->ops = ent->port_ops;
 	ap->cbl = ATA_CBL_NONE;
 	ap->active_tag = ATA_TAG_POISON;
--- oldlinux/include/linux/libata.h	2006-08-30 17:08:28.000000000 -0400
+++ linux/include/linux/libata.h	2006-08-30 15:36:22.000000000 -0400
@@ -281,6 +281,7 @@
 	unsigned long		irq;
 	unsigned int		irq_flags;
 	unsigned long		host_flags;
+	unsigned long		port_flags[ATA_MAX_PORTS];
 	unsigned long		host_set_flags;
 	void __iomem		*mmio_base;
 	void			*private_data;
--- oldlinux/drivers/scsi/sata_promise.c	2006-08-30 17:06:58.000000000 -0400
+++ linux/drivers/scsi/sata_promise.c	2006-08-30 15:34:45.000000000 -0400
@@ -96,6 +96,7 @@
 static void pdc_eng_timeout(struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
 static void pdc_port_stop(struct ata_port *ap);
+static void pdc_phy_reset(struct ata_port *ap);
 static void pdc_pata_phy_reset(struct ata_port *ap);
 static void pdc_sata_phy_reset(struct ata_port *ap);
 static void pdc_qc_prep(struct ata_queued_cmd *qc);
@@ -131,7 +132,7 @@
 	.exec_command		= pdc_exec_command_mmio,
 	.dev_select		= ata_std_dev_select,
-	.phy_reset		= pdc_sata_phy_reset,
+	.phy_reset		= pdc_phy_reset,
 	.qc_prep		= pdc_qc_prep,
 	.qc_issue		= pdc_qc_issue_prot,
@@ -154,7 +155,7 @@
 	.exec_command		= pdc_exec_command_mmio,
 	.dev_select		= ata_std_dev_select,
-	.phy_reset		= pdc_pata_phy_reset,
+	.phy_reset		= pdc_phy_reset,
 	.qc_prep		= pdc_qc_prep,
 	.qc_issue		= pdc_qc_issue_prot,
@@ -168,10 +169,10 @@
 static const struct ata_port_info pdc_port_info[] = {
-	/* board_2037x */
+	/* board_2037x (two SATA ports and possibly one PATA port) */
 		.sht		= &pdc_ata_sht,
-		.host_flags	= PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+		.host_flags	= PDC_COMMON_FLAGS, /* ATA_FLAG_SATA is port specific */
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
@@ -357,6 +358,17 @@
 	readl(mmio);	/* flush */
+/* Reset a port that might be either SATA or PATA */
+static void pdc_phy_reset(struct ata_port *ap)
+	/* If it is an SATA port */
+	if (ap->flags & ATA_FLAG_SATA)
+		pdc_sata_phy_reset(ap);
+	/* Else, it is a PATA port */
+	else
+		pdc_pata_phy_reset(ap);
 static void pdc_sata_phy_reset(struct ata_port *ap)
@@ -365,9 +377,17 @@
 static void pdc_pata_phy_reset(struct ata_port *ap)
-	/* FIXME: add cable detect.  Don't assume 40-pin cable */
-	ap->cbl = ATA_CBL_PATA40;
-	ap->udma_mask &= ATA_UDMA_MASK_40C;
+	u8 tmp;
+	void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
+	tmp = readb(mmio);
+	if (tmp & 0x01) {
+		ap->cbl = ATA_CBL_PATA40;
+		ap->udma_mask &= ATA_UDMA_MASK_40C;
+	} else {
+		ap->cbl = ATA_CBL_PATA80;
+	}
@@ -672,6 +692,7 @@
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	int pci_dev_busy = 0;
 	int rc;
+	u8 tmp;
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@@ -740,14 +761,14 @@
 	probe_ent->port[0].scr_addr = base + 0x400;
 	probe_ent->port[1].scr_addr = base + 0x500;
-	/* notice 4-port boards */
+	/* Board specific initialization */
 	switch (board_idx) {
 	case board_40518:
 		/* Override hotplug offset for SATAII150 */
 		hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
 		/* Fall through */
 	case board_20319:
-       		probe_ent->n_ports = 4;
+       	probe_ent->n_ports = 4;
 		pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
 		pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
@@ -758,10 +779,25 @@
 	case board_2057x:
 		/* Override hotplug offset for SATAII150 */
 		hp->hotplug_offset = PDC2_SATA_PLUG_CSR;
-		/* Fall through */
-	case board_2037x:
 		probe_ent->n_ports = 2;
+	case board_2037x:
+		/* First two ports are always SATA */
+		probe_ent->port_flags[0] = ATA_FLAG_SATA;
+		probe_ent->port_flags[1] = ATA_FLAG_SATA;
+		/* Some boards have also PATA port */
+		tmp = readb((void *)(base + PDC_FLASH_CTL+1));
+		if (!(tmp & 0x80)) {
+			probe_ent->n_ports = 3;
+			pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
+			/* The PATA port can have a slave drive */
+			probe_ent->port_flags[2] = ATA_FLAG_SLAVE_POSS;
+			printk(KERN_INFO DRV_NAME " PATA port found\n");
+		} else {
+       		probe_ent->n_ports = 2;
+		}
+		break;
 	case board_20771:
 		probe_ent->n_ports = 2;

Last edited by Erik_FL; 08-30-2006 at 07:24 PM.
Old 09-30-2006, 12:47 AM   #2
LQ Newbie
Registered: Sep 2006
Posts: 2

Rep: Reputation: 0
Thanks for this writeup. Your patch is working great for me on this device:

02:04.0 RAID bus controller: Promise Technology, Inc. PDC20378 (FastTrak 378/SATA 378) (rev 02)
Subsystem: ASUSTeK Computer Inc. K8V Deluxe/PC-DL Deluxe motherboard
Flags: bus master, 66Mhz, medium devsel, latency 96, IRQ 11
I/O ports at df00 [size=64]
I/O ports at dfa0 [size=16]
I/O ports at d880 [size=128]
Memory at feaff000 (32-bit, non-prefetchable) [size=4K]
Memory at feaa0000 (32-bit, non-prefetchable) [size=128K]
Capabilities: [60] Power Management version 2

Thanks once again!
Old 09-30-2006, 01:57 PM   #3
Registered: Sep 2005
Location: Boynton Beach, FL
Distribution: Slackware
Posts: 801

Original Poster
Rep: Reputation: 247Reputation: 247Reputation: 247
Booting From RAID using dmraid

I'm glad to hear that that it works for you. I've been using the patched driver for reading, writing and booting Linux from the RAID. I dual boot with Windows XP and both operating systems can read each other's files. I use Paragon Partition Manager that comes with a program allowing Windows XP to read read and write ext3 files.

You may find this information useful. It covers the issues and solutions for booting from a RAID array using "dmraid".
How to make an initrd for dmraid
Old 09-30-2006, 04:59 PM   #4
LQ Veteran
Registered: Mar 2003
Location: Milwaukee, WI
Distribution: Mint
Posts: 6,642

Rep: Reputation: 69
Erik_FL - great write-up. Please consider submitting it as a Linux Answer The typical lifespan of a thread in this forum is about a week while an LQ Answer will be permanent. Either way thanks for posting


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
Promise FastTrack 374 and Linux Kernel v2.6 Erik_FL Linux - General 0 08-01-2006 11:34 AM
Promise Fasttrack RAID on Mandrake 10.1 | dmraid, driver, headaches, Debian? rokkon Linux - Hardware 7 12-18-2005 08:15 AM
Installing Promise FastTrack 374 RAID Erik_FL Slackware - Installation 4 12-13-2005 10:41 AM
Promise Fasttrack Sata RAID problems slackzor Slackware 4 12-11-2005 05:59 PM
Monitor Promise FastTrack TX2000 RAID controller Minuteman Linux - Software 5 08-20-2003 10:44 AM

All times are GMT -5. The time now is 05:13 AM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration