Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 118221
b: refs/heads/master
c: b9d5b89
h: refs/heads/master
i:
  118219: 7d74d77
v: v3
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed Oct 31, 2008
1 parent 7cbbd5f commit a6978d7
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ba14a9c291aa867896a90b3571fcc1c3759942ff
refs/heads/master: b9d5b89b487517cbd4cb4702da829e07ef9e4432
155 changes: 143 additions & 12 deletions trunk/drivers/ata/sata_via.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,16 @@
#include <linux/libata.h>

#define DRV_NAME "sata_via"
#define DRV_VERSION "2.3"
#define DRV_VERSION "2.4"

/*
* vt8251 is different from other sata controllers of VIA. It has two
* channels, each channel has both Master and Slave slot.
*/
enum board_ids_enum {
vt6420,
vt6421,
vt8251,
};

enum {
Expand All @@ -70,6 +75,8 @@ enum {
static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val);
static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val);
static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
static void svia_noop_freeze(struct ata_port *ap);
static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
Expand All @@ -79,12 +86,12 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);

static const struct pci_device_id svia_pci_tbl[] = {
{ PCI_VDEVICE(VIA, 0x5337), vt6420 },
{ PCI_VDEVICE(VIA, 0x0591), vt6420 },
{ PCI_VDEVICE(VIA, 0x3149), vt6420 },
{ PCI_VDEVICE(VIA, 0x3249), vt6421 },
{ PCI_VDEVICE(VIA, 0x5287), vt6420 },
{ PCI_VDEVICE(VIA, 0x0591), vt6420 }, /* 2 sata chnls (Master) */
{ PCI_VDEVICE(VIA, 0x3149), vt6420 }, /* 2 sata chnls (Master) */
{ PCI_VDEVICE(VIA, 0x3249), vt6421 }, /* 2 sata chnls, 1 pata chnl */
{ PCI_VDEVICE(VIA, 0x5372), vt6420 },
{ PCI_VDEVICE(VIA, 0x7372), vt6420 },
{ PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */

{ } /* terminate list */
};
Expand Down Expand Up @@ -128,6 +135,13 @@ static struct ata_port_operations vt6421_sata_ops = {
.scr_write = svia_scr_write,
};

static struct ata_port_operations vt8251_ops = {
.inherits = &svia_base_ops,
.hardreset = sata_std_hardreset,
.scr_read = vt8251_scr_read,
.scr_write = vt8251_scr_write,
};

static const struct ata_port_info vt6420_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
Expand All @@ -152,6 +166,15 @@ static struct ata_port_info vt6421_pport_info = {
.port_ops = &vt6421_pata_ops,
};

static struct ata_port_info vt8251_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS |
ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA6,
.port_ops = &vt8251_ops,
};

MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
MODULE_LICENSE("GPL");
Expand All @@ -174,6 +197,83 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
return 0;
}

static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
{
static const u8 ipm_tbl[] = { 1, 2, 6, 0 };
struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
int slot = 2 * link->ap->port_no + link->pmp;
u32 v = 0;
u8 raw;

switch (scr) {
case SCR_STATUS:
pci_read_config_byte(pdev, 0xA0 + slot, &raw);

/* read the DET field, bit0 and 1 of the config byte */
v |= raw & 0x03;

/* read the SPD field, bit4 of the configure byte */
if (raw & (1 << 4))
v |= 0x02 << 4;
else
v |= 0x01 << 4;

/* read the IPM field, bit2 and 3 of the config byte */
v |= ipm_tbl[(raw >> 2) & 0x3];
break;

case SCR_ERROR:
/* devices other than 5287 uses 0xA8 as base */
WARN_ON(pdev->device != 0x5287);
pci_read_config_dword(pdev, 0xB0 + slot * 4, &v);
break;

case SCR_CONTROL:
pci_read_config_byte(pdev, 0xA4 + slot, &raw);

/* read the DET field, bit0 and bit1 */
v |= ((raw & 0x02) << 1) | (raw & 0x01);

/* read the IPM field, bit2 and bit3 */
v |= ((raw >> 2) & 0x03) << 8;
break;

default:
return -EINVAL;
}

*val = v;
return 0;
}

static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val)
{
struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
int slot = 2 * link->ap->port_no + link->pmp;
u32 v = 0;

switch (scr) {
case SCR_ERROR:
/* devices other than 5287 uses 0xA8 as base */
WARN_ON(pdev->device != 0x5287);
pci_write_config_dword(pdev, 0xB0 + slot * 4, val);
return 0;

case SCR_CONTROL:
/* set the DET field */
v |= ((val & 0x4) >> 1) | (val & 0x1);

/* set the IPM field */
v |= ((val >> 8) & 0x3) << 2;

pci_write_config_byte(pdev, 0xA4 + slot, v);
return 0;

default:
return -EINVAL;
}
}

/**
* svia_tf_load - send taskfile registers to host controller
* @ap: Port to which output is sent
Expand Down Expand Up @@ -396,6 +496,30 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
return 0;
}

static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
{
const struct ata_port_info *ppi[] = { &vt8251_port_info, NULL };
struct ata_host *host;
int i, rc;

rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
if (rc)
return rc;
*r_host = host;

rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
if (rc) {
dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n");
return rc;
}

/* 8251 hosts four sata ports as M/S of the two channels */
for (i = 0; i < host->n_ports; i++)
ata_slave_link_init(host->ports[i]);

return 0;
}

static void svia_configure(struct pci_dev *pdev)
{
u8 tmp8;
Expand Down Expand Up @@ -451,10 +575,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;

if (board_id == vt6420)
bar_sizes = &svia_bar_sizes[0];
else
if (board_id == vt6421)
bar_sizes = &vt6421_bar_sizes[0];
else
bar_sizes = &svia_bar_sizes[0];

for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
if ((pci_resource_start(pdev, i) == 0) ||
Expand All @@ -467,12 +591,19 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENODEV;
}

if (board_id == vt6420)
switch (board_id) {
case vt6420:
rc = vt6420_prepare_host(pdev, &host);
else
break;
case vt6421:
rc = vt6421_prepare_host(pdev, &host);
if (rc)
return rc;
break;
case vt8251:
rc = vt8251_prepare_host(pdev, &host);
break;
default:
return -EINVAL;
}

svia_configure(pdev);

Expand Down

0 comments on commit a6978d7

Please sign in to comment.