Commit faf8ec06 authored by Jeff Garzik's avatar Jeff Garzik

Merge pobox.com:/spare/repo/linux-2.6

into pobox.com:/spare/repo/libata-2.6
parents 5c5b9c24 cbda3cb1
......@@ -125,15 +125,15 @@ static struct ata_port_operations piix_pata_ops = {
.set_piomode = piix_set_piomode,
.set_dmamode = piix_set_dmamode,
.tf_load = ata_tf_load_pio,
.tf_read = ata_tf_read_pio,
.check_status = ata_check_status_pio,
.exec_command = ata_exec_command_pio,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
.phy_reset = piix_pata_phy_reset,
.bmdma_setup = ata_bmdma_setup_pio,
.bmdma_start = ata_bmdma_start_pio,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
......@@ -149,15 +149,15 @@ static struct ata_port_operations piix_pata_ops = {
static struct ata_port_operations piix_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load_pio,
.tf_read = ata_tf_read_pio,
.check_status = ata_check_status_pio,
.exec_command = ata_exec_command_pio,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
.phy_reset = piix_sata_phy_reset,
.bmdma_setup = ata_bmdma_setup_pio,
.bmdma_start = ata_bmdma_start_pio,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
......
......@@ -68,17 +68,17 @@ MODULE_DESCRIPTION("Library module for ATA devices");
MODULE_LICENSE("GPL");
/**
* ata_tf_load_pio - send taskfile registers to host controller
* ata_tf_load - send taskfile registers to host controller
* @ap: Port to which output is sent
* @tf: ATA taskfile register set
*
* Outputs ATA taskfile to standard ATA host controller using PIO.
* Outputs ATA taskfile to standard ATA host controller.
*
* LOCKING:
* Inherited from caller.
*/
void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
......@@ -136,7 +136,7 @@ void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
* Inherited from caller.
*/
void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
......@@ -183,19 +183,27 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
ata_wait_idle(ap);
}
void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_tf_load_mmio(ap, tf);
else
ata_tf_load_pio(ap, tf);
}
/**
* ata_exec_command_pio - issue ATA command to host controller
* ata_exec_command - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues PIO write to ATA command register, with proper
* Issues PIO/MMIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
{
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
......@@ -216,7 +224,7 @@ void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
* spin_lock_irqsave(host_set lock)
*/
void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
......@@ -224,12 +232,20 @@ void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
ata_pause(ap);
}
void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_exec_command_mmio(ap, tf);
else
ata_exec_command_pio(ap, tf);
}
/**
* ata_exec - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
* Issues PIO write to ATA command register, with proper
* Issues PIO/MMIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
......@@ -252,7 +268,7 @@ static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf)
* @tf: ATA taskfile register set
*
* Issues ATA taskfile register set to ATA host controller,
* via PIO, with proper synchronization with interrupt handler and
* with proper synchronization with interrupt handler and
* other threads.
*
* LOCKING:
......@@ -272,7 +288,7 @@ static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf)
* @tf: ATA taskfile register set
*
* Issues ATA taskfile register set to ATA host controller,
* via PIO, with proper synchronization with interrupt handler and
* with proper synchronization with interrupt handler and
* other threads.
*
* LOCKING:
......@@ -286,18 +302,18 @@ void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
}
/**
* ata_tf_read_pio - input device's ATA taskfile shadow registers
* ata_tf_read - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
* Reads ATA taskfile registers for currently-selected device
* into @tf via PIO.
* into @tf.
*
* LOCKING:
* Inherited from caller.
*/
void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
......@@ -329,7 +345,7 @@ void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
* Inherited from caller.
*/
void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
......@@ -349,18 +365,26 @@ void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
}
}
void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
ata_tf_read_mmio(ap, tf);
else
ata_tf_read_pio(ap, tf);
}
/**
* ata_check_status_pio - Read device status reg & clear interrupt
* ata_check_status - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
* via PIO and return it's value. This also clears pending interrupts
* and return it's value. This also clears pending interrupts
* from this device
*
* LOCKING:
* Inherited from caller.
*/
u8 ata_check_status_pio(struct ata_port *ap)
static u8 ata_check_status_pio(struct ata_port *ap)
{
return inb(ap->ioaddr.status_addr);
}
......@@ -376,11 +400,18 @@ u8 ata_check_status_pio(struct ata_port *ap)
* LOCKING:
* Inherited from caller.
*/
u8 ata_check_status_mmio(struct ata_port *ap)
static u8 ata_check_status_mmio(struct ata_port *ap)
{
return readb((void __iomem *) ap->ioaddr.status_addr);
}
u8 ata_check_status(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO)
return ata_check_status_mmio(ap);
return ata_check_status_pio(ap);
}
/**
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
* @tf: Taskfile to convert
......@@ -671,7 +702,7 @@ static unsigned int ata_mmio_devchk(struct ata_port *ap,
}
/**
* ata_dev_devchk - PATA device presence detection
* ata_devchk - PATA device presence detection
* @ap: ATA channel to examine
* @device: Device to examine (starting at zero)
*
......@@ -683,7 +714,7 @@ static unsigned int ata_mmio_devchk(struct ata_port *ap,
* caller.
*/
static unsigned int ata_dev_devchk(struct ata_port *ap,
static unsigned int ata_devchk(struct ata_port *ap,
unsigned int device)
{
if (ap->flags & ATA_FLAG_MMIO)
......@@ -1439,13 +1470,13 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
unsigned int dev1 = devmask & (1 << 1);
unsigned long timeout;
/* if device 0 was found in ata_dev_devchk, wait for its
/* if device 0 was found in ata_devchk, wait for its
* BSY bit to clear
*/
if (dev0)
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
/* if device 1 was found in ata_dev_devchk, wait for
/* if device 1 was found in ata_devchk, wait for
* register access, then wait for BSY to clear
*/
timeout = jiffies + ATA_TMOUT_BOOT;
......@@ -1580,9 +1611,9 @@ void ata_bus_reset(struct ata_port *ap)
if (ap->flags & ATA_FLAG_SATA_RESET)
dev0 = 1;
else {
dev0 = ata_dev_devchk(ap, 0);
dev0 = ata_devchk(ap, 0);
if (slave_possible)
dev1 = ata_dev_devchk(ap, 1);
dev1 = ata_devchk(ap, 1);
}
if (dev0)
......@@ -2606,14 +2637,14 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
}
/**
* ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
* ata_bmdma_setup - Set up PCI IDE BMDMA transaction
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
......@@ -2636,14 +2667,14 @@ void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
}
/**
* ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
* ata_bmdma_start - Start a PCI IDE BMDMA transaction
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
......@@ -2674,7 +2705,7 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
* spin_lock_irqsave(host_set lock)
*/
void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
......@@ -2702,7 +2733,7 @@ void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
* spin_lock_irqsave(host_set lock)
*/
void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
u8 dmactl;
......@@ -2713,6 +2744,22 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
}
void ata_bmdma_start(struct ata_queued_cmd *qc)
{
if (qc->ap->flags & ATA_FLAG_MMIO)
ata_bmdma_start_mmio(qc);
else
ata_bmdma_start_pio(qc);
}
void ata_bmdma_setup(struct ata_queued_cmd *qc)
{
if (qc->ap->flags & ATA_FLAG_MMIO)
ata_bmdma_setup_mmio(qc);
else
ata_bmdma_setup_pio(qc);
}
void ata_bmdma_irq_clear(struct ata_port *ap)
{
ata_bmdma_ack_irq(ap);
......@@ -3205,6 +3252,95 @@ void ata_std_ports(struct ata_ioports *ioaddr)
ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
}
static struct ata_probe_ent *
ata_probe_ent_alloc(int n, struct pci_dev *pdev, struct ata_port_info **port)
{
struct ata_probe_ent *probe_ent;
int i;
probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL);
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
pci_name(pdev));
return NULL;
}
memset(probe_ent, 0, sizeof(*probe_ent) * n);
for (i = 0; i < n; i++) {
INIT_LIST_HEAD(&probe_ent[i].node);
probe_ent[i].pdev = pdev;
probe_ent[i].sht = port[i]->sht;
probe_ent[i].host_flags = port[i]->host_flags;
probe_ent[i].pio_mask = port[i]->pio_mask;
probe_ent[i].mwdma_mask = port[i]->mwdma_mask;
probe_ent[i].udma_mask = port[i]->udma_mask;
probe_ent[i].port_ops = port[i]->port_ops;
}
return probe_ent;
}
struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
{
struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(1, pdev, port);
if (!probe_ent)
return NULL;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
probe_ent->port[1].altstatus_addr =
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
ata_std_ports(&probe_ent->port[0]);
ata_std_ports(&probe_ent->port[1]);
return probe_ent;
}
struct ata_probe_ent *
ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port)
{
struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(2, pdev, port);
if (!probe_ent)
return NULL;
probe_ent[0].n_ports = 1;
probe_ent[0].irq = 14;
probe_ent[1].n_ports = 1;
probe_ent[1].irq = 15;
probe_ent[0].port[0].cmd_addr = 0x1f0;
probe_ent[0].port[0].altstatus_addr =
probe_ent[0].port[0].ctl_addr = 0x3f6;
probe_ent[0].port[0].bmdma_addr = pci_resource_start(pdev, 4);
probe_ent[1].port[0].cmd_addr = 0x170;
probe_ent[1].port[0].altstatus_addr =
probe_ent[1].port[0].ctl_addr = 0x376;
probe_ent[1].port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
ata_std_ports(&probe_ent[0].port[0]);
ata_std_ports(&probe_ent[1].port[0]);
return probe_ent;
}
/**
* ata_pci_init_one - Initialize/register PCI IDE host controller
* @pdev: Controller to be initialized
......@@ -3222,20 +3358,20 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports)
{
struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
struct ata_port_info *port0, *port1;
struct ata_port_info *port[2];
u8 tmp8, mask;
unsigned int legacy_mode = 0;
int rc;
DPRINTK("ENTER\n");
port0 = port_info[0];
port[0] = port_info[0];
if (n_ports > 1)
port1 = port_info[1];
port[1] = port_info[1];
else
port1 = port0;
port[1] = port[0];
if ((port0->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
/* TODO: support transitioning to native mode? */
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
mask = (1 << 2) | (1 << 0);
......@@ -3296,77 +3432,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
if (rc)
goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (legacy_mode) {
probe_ent = ata_pci_init_legacy_mode(pdev, port);
if (probe_ent)
probe_ent2 = &probe_ent[1];
} else
probe_ent = ata_pci_init_native_mode(pdev, port);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
}
memset(probe_ent, 0, sizeof(*probe_ent));
probe_ent->pdev = pdev;
INIT_LIST_HEAD(&probe_ent->node);
if (legacy_mode) {
probe_ent2 = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (!probe_ent2) {
rc = -ENOMEM;
goto err_out_free_ent;
}
memset(probe_ent2, 0, sizeof(*probe_ent));
probe_ent2->pdev = pdev;
INIT_LIST_HEAD(&probe_ent2->node);
}
probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
probe_ent->sht = port0->sht;
probe_ent->host_flags = port0->host_flags;
probe_ent->pio_mask = port0->pio_mask;
probe_ent->mwdma_mask = port0->mwdma_mask;
probe_ent->udma_mask = port0->udma_mask;
probe_ent->port_ops = port0->port_ops;
if (legacy_mode) {
probe_ent->port[0].cmd_addr = 0x1f0;
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr = 0x3f6;
probe_ent->n_ports = 1;
probe_ent->irq = 14;
ata_std_ports(&probe_ent->port[0]);
probe_ent2->port[0].cmd_addr = 0x170;
probe_ent2->port[0].altstatus_addr =
probe_ent2->port[0].ctl_addr = 0x376;
probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
probe_ent2->n_ports = 1;
probe_ent2->irq = 15;
ata_std_ports(&probe_ent2->port[0]);
probe_ent2->sht = port1->sht;
probe_ent2->host_flags = port1->host_flags;
probe_ent2->pio_mask = port1->pio_mask;
probe_ent2->mwdma_mask = port1->mwdma_mask;
probe_ent2->udma_mask = port1->udma_mask;
probe_ent2->port_ops = port1->port_ops;
} else {
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
ata_std_ports(&probe_ent->port[0]);
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
ata_std_ports(&probe_ent->port[1]);
probe_ent->port[1].altstatus_addr =
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
}
pci_set_master(pdev);
/* FIXME: check ata_device_add return */
......@@ -3375,17 +3451,13 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
ata_device_add(probe_ent);
if (legacy_mode & (1 << 1))
ata_device_add(probe_ent2);
kfree(probe_ent2);
} else {
ata_device_add(probe_ent);
assert(probe_ent2 == NULL);
}
kfree(probe_ent);
return 0;
err_out_free_ent:
kfree(probe_ent);
err_out_regions:
if (legacy_mode & (1 << 0))
release_region(0x1f0, 8);
......@@ -3535,24 +3607,20 @@ EXPORT_SYMBOL_GPL(ata_sg_init_one);
EXPORT_SYMBOL_GPL(ata_qc_complete);
EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
EXPORT_SYMBOL_GPL(ata_eng_timeout);
EXPORT_SYMBOL_GPL(ata_tf_load_pio);
EXPORT_SYMBOL_GPL(ata_tf_load_mmio);
EXPORT_SYMBOL_GPL(ata_tf_read_pio);
EXPORT_SYMBOL_GPL(ata_tf_read_mmio);
EXPORT_SYMBOL_GPL(ata_tf_load);
EXPORT_SYMBOL_GPL(ata_tf_read);
EXPORT_SYMBOL_GPL(ata_tf_to_fis);
EXPORT_SYMBOL_GPL(ata_tf_from_fis);
EXPORT_SYMBOL_GPL(ata_check_status_pio);
EXPORT_SYMBOL_GPL(ata_check_status_mmio);
EXPORT_SYMBOL_GPL(ata_exec_command_pio);
EXPORT_SYMBOL_GPL(ata_exec_command_mmio);
EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_check_status);
EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_port_stop);
EXPORT_SYMBOL_GPL(ata_interrupt);
EXPORT_SYMBOL_GPL(ata_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio);
EXPORT_SYMBOL_GPL(ata_bmdma_start_pio);
EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio);
EXPORT_SYMBOL_GPL(ata_bmdma_start_mmio);
EXPORT_SYMBOL_GPL(ata_bmdma_setup);
EXPORT_SYMBOL_GPL(ata_bmdma_start);
EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
EXPORT_SYMBOL_GPL(ata_port_probe);
EXPORT_SYMBOL_GPL(sata_phy_reset);
......
......@@ -50,8 +50,6 @@
#define NV_PIO_MASK 0x1f
#define NV_MWDMA_MASK 0x07
#define NV_UDMA_MASK 0x7f
#define NV_PORT0_BMDMA_REG_OFFSET 0x00
#define NV_PORT1_BMDMA_REG_OFFSET 0x08
#define NV_PORT0_SCR_REG_OFFSET 0x00
#define NV_PORT1_SCR_REG_OFFSET 0x40
......@@ -187,7 +185,7 @@ static Scsi_Host_Template nv_sht = {
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = ATA_MAX_PRD,
.sg_tablesize = LIBATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
......@@ -200,13 +198,13 @@ static Scsi_Host_Template nv_sht = {
static struct ata_port_operations nv_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load_pio,
.tf_read = ata_tf_read_pio,
.exec_command = ata_exec_command_pio,
.check_status = ata_check_status_pio,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.exec_command = ata_exec_command,
.check_status = ata_check_status,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup_pio,
.bmdma_start = ata_bmdma_start_pio,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
......@@ -219,6 +217,18 @@ static struct ata_port_operations nv_ops = {
.host_stop = nv_host_stop,
};
static struct ata_port_info nv_port_info = {
.sht = &nv_sht,
.host_flags = ATA_FLAG_SATA |
ATA_FLAG_SATA_RESET |
ATA_FLAG_SRST |
ATA_FLAG_NO_LEGACY,
.pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
.port_ops = &nv_ops,
};
MODULE_AUTHOR("NVIDIA");
MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
MODULE_LICENSE("GPL");
......@@ -299,6 +309,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version = 0;
struct nv_host *host;
struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent = NULL;
int rc;
......@@ -320,7 +331,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
ppi = &nv_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
......@@ -334,40 +346,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
host->host_desc = &nv_device_tbl[ent->driver_data];
memset(probe_ent, 0, sizeof(*probe_ent));
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->pdev = pdev;
probe_ent->sht = &nv_sht;
probe_ent->host_flags = ATA_FLAG_SATA |
ATA_FLAG_SATA_RESET |
ATA_FLAG_SRST |
ATA_FLAG_NO_LEGACY;
probe_ent->port_ops = &nv_ops;
probe_ent->n_ports = NV_PORTS;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->pio_mask = NV_PIO_MASK;
probe_ent->mwdma_mask = NV_MWDMA_MASK;
probe_ent->udma_mask = NV_UDMA_MASK;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
ata_std_ports(&probe_ent->port[0]);
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[0].bmdma_addr =
pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET;
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
ata_std_ports(&probe_ent->port[1]);
probe_ent->port[1].altstatus_addr =
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr =
pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET;
probe_ent->private_data = host;
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
......
......@@ -107,8 +107,8 @@ static Scsi_Host_Template pdc_sata_sht = {
static struct ata_port_operations pdc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read_mmio,
.check_status = ata_check_status_mmio,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = pdc_exec_command_mmio,
.phy_reset = pdc_phy_reset,
.qc_prep = pdc_qc_prep,
......@@ -468,7 +468,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
ata_tf_load_mmio(ap, tf);
ata_tf_load(ap, tf);
}
......@@ -476,7 +476,7 @@ static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
ata_exec_command_mmio(ap, tf);
ata_exec_command(ap, tf);
}
......
......@@ -125,14 +125,14 @@ static Scsi_Host_Template sil_sht = {
static struct ata_port_operations sil_ops = {
.port_disable = ata_port_disable,
.dev_config = sil_dev_config,
.tf_load = ata_tf_load_mmio,
.tf_read = ata_tf_read_mmio,
.check_status = ata_check_status_mmio,
.exec_command = ata_exec_command_mmio,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
.phy_reset = sata_phy_reset,
.post_set_mode = sil_post_set_mode,
.bmdma_setup = ata_bmdma_setup_mmio,
.bmdma_start = ata_bmdma_start_mmio,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
......
......@@ -94,13 +94,13 @@ static Scsi_Host_Template sis_sht = {
static struct ata_port_operations sis_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load_pio,
.tf_read = ata_tf_read_pio,
.check_status = ata_check_status_pio,
.exec_command = ata_exec_command_pio,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup_pio,
.bmdma_start = ata_bmdma_start_pio,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
......@@ -112,6 +112,16 @@ static struct ata_port_operations sis_ops = {
.port_stop = ata_port_stop,
};
static struct ata_port_info sis_port_info = {
.sht = &sis_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x7,
.udma_mask = 0x7f,
.port_ops = &sis_ops,
};
MODULE_AUTHOR("Uwe Koziolek");
MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
......@@ -185,6 +195,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_probe_ent *probe_ent = NULL;
int rc;
u32 genctl;
struct ata_port_info *ppi;
rc = pci_enable_device(pdev);
if (rc)
......@@ -201,20 +212,13 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
ppi = &sis_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
}
memset(probe_ent, 0, sizeof(*probe_ent));
probe_ent->pdev = pdev;
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->sht = &sis_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
ATA_FLAG_NO_LEGACY;
/* check and see if the SCRs are in IO space or PCI cfg space */
pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
......@@ -231,32 +235,12 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->host_flags |= SIS_FLAG_CFGSCR;
}
probe_ent->pio_mask = 0x1f;
probe_ent->mwdma_mask = 0x7;
probe_ent->udma_mask = 0x7f;
probe_ent->port_ops = &sis_ops;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
ata_std_ports(&probe_ent->port[0]);
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
probe_ent->port[0].scr_addr =
pci_resource_start(pdev, SIS_SCR_PCI_BAR);
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
ata_std_ports(&probe_ent->port[1]);
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
probe_ent->port[1].scr_addr =
pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
}
pci_set_master(pdev);
pci_enable_intx(pdev);
......
......@@ -148,6 +148,72 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
}
}
/**
* k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 dmactl;
void *mmio = (void *) ap->ioaddr.bmdma_addr;
/* load PRD table addr. */
mb(); /* make sure PRD table writes are visible to controller */
writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
/* specify data direction, triple-check start bit is clear */
dmactl = readb(mmio + ATA_DMA_CMD);
dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
if (!rw)
dmactl |= ATA_DMA_WR;
writeb(dmactl, mmio + ATA_DMA_CMD);
/* issue r/w command if this is not a ATA DMA command*/
if (qc->tf.protocol != ATA_PROT_DMA)
ap->ops->exec_command(ap, &qc->tf);
}
/**
* k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
void *mmio = (void *) ap->ioaddr.bmdma_addr;
u8 dmactl;
/* start host DMA transaction */
dmactl = readb(mmio + ATA_DMA_CMD);
writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
/* There is a race condition in certain SATA controllers that can
be seen when the r/w command is given to the controller before the
host DMA is started. On a Read command, the controller would initiate
the command to the drive even before it sees the DMA start. When there
are very fast drives connected to the controller, or when the data request
hits in the drive cache, there is the possibility that the drive returns a part
or all of the requested data to the controller before the DMA start is issued.
In this case, the controller would become confused as to what to do with the data.
In the worst case when all the data is returned back to the controller, the
controller could hang. In other cases it could return partial data returning
in data corruption. This problem has been seen in PPC systems and can also appear
on an system with very fast disks, where the SATA controller is sitting behind a
number of bridges, and hence there is significant latency between the r/w command
and the start command. */
/* issue r/w command if the access is to ATA*/
if (qc->tf.protocol == ATA_PROT_DMA)
ap->ops->exec_command(ap, &qc->tf);
}
static u8 k2_stat_check_status(struct ata_port *ap)
{
......@@ -230,10 +296,10 @@ static struct ata_port_operations k2_sata_ops = {
.tf_load = k2_sata_tf_load,
.tf_read = k2_sata_tf_read,
.check_status = k2_stat_check_status,
.exec_command = ata_exec_command_mmio,
.exec_command = ata_exec_command,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup_mmio,
.bmdma_start = ata_bmdma_start_mmio,
.bmdma_setup = k2_bmdma_setup_mmio,
.bmdma_start = k2_bmdma_start_mmio,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
......@@ -373,6 +439,8 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static struct pci_device_id k2_sata_pci_tbl[] = {
{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ }
};
......
......@@ -193,8 +193,8 @@ static Scsi_Host_Template pdc_sata_sht = {
static struct ata_port_operations pdc_20621_ops = {
.port_disable = ata_port_disable,
.tf_load = pdc_tf_load_mmio,
.tf_read = ata_tf_read_mmio,
.check_status = ata_check_status_mmio,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = pdc_exec_command_mmio,
.phy_reset = pdc_20621_phy_reset,
.qc_prep = pdc20621_qc_prep,
......@@ -887,7 +887,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
ata_tf_load_mmio(ap, tf);
ata_tf_load(ap, tf);
}
......@@ -895,7 +895,7 @@ static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
tf->protocol == ATA_PROT_NODATA);
ata_exec_command_mmio(ap, tf);
ata_exec_command(ap, tf);
}
......
......@@ -100,15 +100,15 @@ static Scsi_Host_Template svia_sht = {
static struct ata_port_operations svia_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load_pio,
.tf_read = ata_tf_read_pio,
.check_status = ata_check_status_pio,
.exec_command = ata_exec_command_pio,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup_pio,
.bmdma_start = ata_bmdma_start_pio,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
......@@ -124,6 +124,15 @@ static struct ata_port_operations svia_sata_ops = {
.port_stop = ata_port_stop,
};
static struct ata_port_info svia_port_info = {
.sht = &svia_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x7f,
.port_ops = &svia_sata_ops,
};
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
MODULE_LICENSE("GPL");
......@@ -157,6 +166,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int printed_version;
unsigned int i;
int rc;
struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent;
u8 tmp8;
......@@ -197,42 +207,17 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
ppi = &svia_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
pci_name(pdev));
rc = -ENOMEM;
goto err_out_regions;
}
memset(probe_ent, 0, sizeof(*probe_ent));
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->pdev = pdev;
probe_ent->sht = &svia_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
ATA_FLAG_NO_LEGACY;
probe_ent->port_ops = &svia_sata_ops;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->pio_mask = 0x1f;
probe_ent->mwdma_mask = 0x07;
probe_ent->udma_mask = 0x7f;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
ata_std_ports(&probe_ent->port[0]);
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
probe_ent->port[0].scr_addr =
svia_scr_addr(pci_resource_start(pdev, 5), 0);
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
ata_std_ports(&probe_ent->port[1]);
probe_ent->port[1].altstatus_addr =
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
probe_ent->port[1].scr_addr =
svia_scr_addr(pci_resource_start(pdev, 5), 1);
......
......@@ -211,11 +211,11 @@ static struct ata_port_operations vsc_sata_ops = {
.port_disable = ata_port_disable,
.tf_load = vsc_sata_tf_load,
.tf_read = vsc_sata_tf_read,
.exec_command = ata_exec_command_mmio,
.check_status = ata_check_status_mmio,
.exec_command = ata_exec_command,
.check_status = ata_check_status,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup_mmio,
.bmdma_start = ata_bmdma_start_mmio,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
......
......@@ -379,19 +379,19 @@ extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc
/*
* Default driver ops implementations
*/
extern void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp);
extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
extern u8 ata_check_status_pio(struct ata_port *ap);
extern u8 ata_check_status_mmio(struct ata_port *ap);
extern void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
extern u8 ata_check_status(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
extern struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
extern struct ata_probe_ent *
ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port);
extern void ata_qc_prep(struct ata_queued_cmd *qc);
extern int ata_qc_issue_prot(struct ata_queued_cmd *qc);
extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
......@@ -400,10 +400,8 @@ extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
unsigned int n_elem);
extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
unsigned int ofs, unsigned int len);
extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc);
extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc);
extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc);
extern void ata_bmdma_irq_clear(struct ata_port *ap);
extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment