Index: linux-2.6.18-armeb/drivers/ide/pci/via82cxxx.c =================================================================== --- linux-2.6.18-armeb.orig/drivers/ide/pci/via82cxxx.c +++ linux-2.6.18-armeb/drivers/ide/pci/via82cxxx.c @@ -79,6 +79,7 @@ static struct via_isa_bridge { u16 flags; } via_isa_bridges[] = { { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt6421", PCI_DEVICE_ID_VIA_6421, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, @@ -498,6 +499,7 @@ static struct pci_device_id via_pci_tbl[ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, via_pci_tbl); Index: linux-2.6.18-armeb/include/linux/pci_ids.h =================================================================== --- linux-2.6.18-armeb.orig/include/linux/pci_ids.h +++ linux-2.6.18-armeb/include/linux/pci_ids.h @@ -1313,6 +1313,7 @@ #define PCI_DEVICE_ID_VIA_8378_0 0x3205 #define PCI_DEVICE_ID_VIA_8783_0 0x3208 #define PCI_DEVICE_ID_VIA_8237 0x3227 +#define PCI_DEVICE_ID_VIA_6421 0x3249 #define PCI_DEVICE_ID_VIA_8251 0x3287 #define PCI_DEVICE_ID_VIA_8237A 0x3337 #define PCI_DEVICE_ID_VIA_8231 0x8231 Index: linux-2.6.18-armeb/drivers/scsi/libata-core.c =================================================================== --- linux-2.6.18-armeb.orig/drivers/scsi/libata-core.c +++ linux-2.6.18-armeb/drivers/scsi/libata-core.c @@ -3627,9 +3627,9 @@ void ata_pio_data_xfer(struct ata_device /* Transfer multiple of 2 bytes */ if (write_data) - outsw(ap->ioaddr.data_addr, buf, words); + outsw(ap->ioaddr.data_addr, (const u16*)buf, words); else - insw(ap->ioaddr.data_addr, buf, words); + insw(ap->ioaddr.data_addr, (u16*)buf, words); /* Transfer trailing 1 byte, if any. */ if (unlikely(buflen & 0x01)) { Index: linux-2.6.18-armeb/drivers/scsi/sata_via.c =================================================================== --- linux-2.6.18-armeb.orig/drivers/scsi/sata_via.c +++ linux-2.6.18-armeb/drivers/scsi/sata_via.c @@ -63,7 +63,7 @@ enum { PORT0 = (1 << 1), PORT1 = (1 << 0), ALL_PORTS = PORT0 | PORT1, - N_PORTS = 2, + N_PORTS = 3, NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), @@ -75,9 +75,11 @@ static int svia_init_one (struct pci_dev static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg); static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void vt6420_error_handler(struct ata_port *ap); +static void via_pata_phy_reset(struct ata_port *ap); +static void via_pata_set_piomode (struct ata_port *ap, struct ata_device *adev); +static void via_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev); static const struct pci_device_id svia_pci_tbl[] = { - { 0x1106, 0x0591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 }, { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 }, { 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 }, @@ -143,12 +145,17 @@ static const struct ata_port_operations static const struct ata_port_operations vt6421_sata_ops = { .port_disable = ata_port_disable, + .set_piomode = via_pata_set_piomode, + .set_dmamode = via_pata_set_dmamode, + .tf_load = ata_tf_load, .tf_read = ata_tf_read, .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, + .phy_reset = via_pata_phy_reset, //new LAWI + .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, @@ -166,8 +173,8 @@ static const struct ata_port_operations .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, - .scr_read = svia_scr_read, - .scr_write = svia_scr_write, +// .scr_read = svia_scr_read, +// .scr_write = svia_scr_write, .port_start = ata_port_start, .port_stop = ata_port_stop, @@ -290,27 +297,33 @@ static unsigned long svia_scr_addr(unsig { return addr + (port * 128); } - +/* static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port) { return addr + (port * 64); } - +*/ static void vt6421_init_addrs(struct ata_probe_ent *probe_ent, struct pci_dev *pdev, unsigned int port) { - unsigned long reg_addr = pci_resource_start(pdev, port); - unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8); - unsigned long scr_addr; + // by Freecom Technologies GmbH, Berlin + // Change port priority: highest -> SATA0 (internal SATA) + // middle -> ATA + // lowest -> SATA1 (external SATA) + unsigned int hPort = (port ? port ^ 3 : 0); + + unsigned long reg_addr = pci_resource_start(pdev, hPort); + unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (hPort * 8); +// unsigned long scr_addr; probe_ent->port[port].cmd_addr = reg_addr; probe_ent->port[port].altstatus_addr = probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS; probe_ent->port[port].bmdma_addr = bmdma_addr; - scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port); - probe_ent->port[port].scr_addr = scr_addr; +// scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port); +// probe_ent->port[port].scr_addr = scr_addr; ata_std_ports(&probe_ent->port[port]); } @@ -346,7 +359,8 @@ static struct ata_probe_ent *vt6421_init INIT_LIST_HEAD(&probe_ent->node); probe_ent->sht = &svia_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY; + //probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY; + probe_ent->host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY; probe_ent->port_ops = &vt6421_sata_ops; probe_ent->n_ports = N_PORTS; probe_ent->irq = pdev->irq; @@ -361,6 +375,175 @@ static struct ata_probe_ent *vt6421_init return probe_ent; } +//PATA CHANGES +/* add functions for pata */ + + +/** + * via_pata_cbl_detect - Probe host controller cable detect info + * @ap: Port for which cable detect info is desired + * + * Read 80c cable indicator from ATA PCI device's PCI config + * register. This register is normally set by firmware (BIOS). + * + * LOCKING: + * None (inherited from caller). + */ +static void via_pata_cbl_detect(struct ata_port *ap) +{ + struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); + int cfg_addr; + u8 tmp; + + + if (ap->port_no == 2) { /* PATA channel in VT6421 */ + ap->cbl = ATA_CBL_PATA80; + cfg_addr = 0xB3; + pci_read_config_byte(pdev, cfg_addr, &tmp); + if (tmp & 0x10) { /* 40pin cable */ + ap->cbl = ATA_CBL_PATA40; + } + else { /* 80pin cable */ + ap->cbl = ATA_CBL_PATA80; + } + } + else { /* channel 0 and 1 are SATA channels */ + ap->cbl = ATA_CBL_SATA; + } + + return; +} + +/** + * via_pata_phy_reset - Probe specified port on PATA host controller + * @ap: Port to probe + * + * Probe PATA phy. + * + * LOCKING: + * None (inherited from caller). + */ + +static void via_pata_phy_reset(struct ata_port *ap) +{ +// struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); + + via_pata_cbl_detect(ap); + + ata_port_probe(ap); + + ata_bus_reset(ap); +} + + +/** + * via_pata_set_piomode - Initialize host controller PATA PIO timings + * @ap: Port whose timings we are configuring + * @adev: um + * @pio: PIO mode, 0 - 4 + * + * Set PIO mode for device, in host controller PCI config space. + * + * LOCKING: + * None (inherited from caller). + */ + +static void via_pata_set_piomode (struct ata_port *ap, struct ata_device *adev) +{ + struct pci_dev *dev = to_pci_dev(ap->host_set->dev); + + u8 cfg_byte; + int cfg_addr; + + if (ap->port_no != 2) { /* SATA channel in VT6421 */ + /* no need to set */ + return; + } + + + cfg_addr = 0xAB; + switch (adev->pio_mode & 0x07) { + case 0: + cfg_byte = 0xa8; + break; + case 1: + cfg_byte = 0x65; + break; + case 2: + cfg_byte = 0x65; + break; + case 3: + cfg_byte = 0x31; + break; + case 4: + cfg_byte = 0x20; + break; + default: + cfg_byte = 0x20; + } + + pci_write_config_byte (dev, cfg_addr, cfg_byte); +} + +/** + * via_pata_set_dmamode - Initialize host controller PATA PIO timings + * @ap: Port whose timings we are configuring + * @adev: um + * @udma: udma mode, 0 - 6 + * + * Set UDMA mode for device, in host controller PCI config space. + * + * LOCKING: + * None (inherited from caller). + */ + +static void via_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev) +{ + struct pci_dev *dev = to_pci_dev(ap->host_set->dev); + + u8 cfg_byte; + int cfg_addr; + + if (ap->port_no != 2) { /* SATA channel in VT6421 */ + /* no need to set */ + return; + } + + cfg_addr = 0xB3; + switch (adev->dma_mode & 0x07) { + case 0: + cfg_byte = 0xee; + break; + case 1: + cfg_byte = 0xe8; + break; + case 2: + cfg_byte = 0xe6; + break; + case 3: + cfg_byte = 0xe4; + break; + case 4: + cfg_byte = 0xe2; + break; + case 5: + cfg_byte = 0xe1; + break; + case 6: + cfg_byte = 0xe0; + break; + default: + cfg_byte = 0xe0; + } + + pci_write_config_byte (dev, cfg_addr, cfg_byte); +} + + + + + + static void svia_configure(struct pci_dev *pdev) { u8 tmp8;