Commit d4fec892 authored by Jeff Garzik's avatar Jeff Garzik

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

into pobox.com:/garz/repo/libata-2.6
parents 72aa1a62 341caaec
......@@ -250,6 +250,8 @@ static struct pci_device_id ahci_pci_tbl[] = {
board_ahci }, /* ICH7R */
{ PCI_VENDOR_ID_INTEL, 0x27c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH7R */
{ PCI_VENDOR_ID_AL, 0x5288, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ULi M5288 */
{ } /* terminate list */
};
......
......@@ -1700,6 +1700,69 @@ void ata_bus_reset(struct ata_port *ap)
DPRINTK("EXIT\n");
}
static void ata_pr_blacklisted(struct ata_port *ap, struct ata_device *dev)
{
printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n",
ap->id, dev->devno);
}
static const char * ata_dma_blacklist [] = {
"WDC AC11000H",
"WDC AC22100H",
"WDC AC32500H",
"WDC AC33100H",
"WDC AC31600H",
"WDC AC32100H",
"WDC AC23200L",
"Compaq CRD-8241B",
"CRD-8400B",
"CRD-8480B",
"CRD-8482B",
"CRD-84",
"SanDisk SDP3B",
"SanDisk SDP3B-64",
"SANYO CD-ROM CRD",
"HITACHI CDR-8",
"HITACHI CDR-8335",
"HITACHI CDR-8435",
"Toshiba CD-ROM XM-6202B",
"CD-532E-A",
"E-IDE CD-ROM CR-840",
"CD-ROM Drive/F5A",
"WPI CDD-820",
"SAMSUNG CD-ROM SC-148C",
"SAMSUNG CD-ROM SC",
"SanDisk SDP3B-64",
"SAMSUNG CD-ROM SN-124",
"ATAPI CD-ROM DRIVE 40X MAXIMUM",
"_NEC DV5800A",
};
static int ata_dma_blacklisted(struct ata_port *ap, struct ata_device *dev)
{
unsigned char model_num[40];
char *s;
unsigned int len;
int i;
ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
sizeof(model_num));
s = &model_num[0];
len = strnlen(s, sizeof(model_num));
/* ATAPI specifies that empty space is blank-filled; remove blanks */
while ((len > 0) && (s[len - 1] == ' ')) {
len--;
s[len] = 0;
}
for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++)
if (!strncmp(ata_dma_blacklist[i], s, len))
return 1;
return 0;
}
static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
{
struct ata_device *master, *slave;
......@@ -1712,17 +1775,37 @@ static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
if (shift == ATA_SHIFT_UDMA) {
mask = ap->udma_mask;
if (ata_dev_present(master))
if (ata_dev_present(master)) {
mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
if (ata_dev_present(slave))
if (ata_dma_blacklisted(ap, master)) {
mask = 0;
ata_pr_blacklisted(ap, master);
}
}
if (ata_dev_present(slave)) {
mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
if (ata_dma_blacklisted(ap, slave)) {
mask = 0;
ata_pr_blacklisted(ap, slave);
}
}
}
else if (shift == ATA_SHIFT_MWDMA) {
mask = ap->mwdma_mask;
if (ata_dev_present(master))
if (ata_dev_present(master)) {
mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
if (ata_dev_present(slave))
if (ata_dma_blacklisted(ap, master)) {
mask = 0;
ata_pr_blacklisted(ap, master);
}
}
if (ata_dev_present(slave)) {
mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
if (ata_dma_blacklisted(ap, slave)) {
mask = 0;
ata_pr_blacklisted(ap, slave);
}
}
}
else if (shift == ATA_SHIFT_PIO) {
mask = ap->pio_mask;
......@@ -3452,32 +3535,28 @@ void ata_std_ports(struct ata_ioports *ioaddr)
}
static struct ata_probe_ent *
ata_probe_ent_alloc(int n, struct device *dev, struct ata_port_info **port)
ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
{
struct ata_probe_ent *probe_ent;
int i;
probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL);
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
kobject_name(&(dev->kobj)));
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].dev = dev;
memset(probe_ent, 0, sizeof(*probe_ent));
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;
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->dev = dev;
}
probe_ent->sht = port->sht;
probe_ent->host_flags = port->host_flags;
probe_ent->pio_mask = port->pio_mask;
probe_ent->mwdma_mask = port->mwdma_mask;
probe_ent->udma_mask = port->udma_mask;
probe_ent->port_ops = port->port_ops;
return probe_ent;
}
......@@ -3487,7 +3566,7 @@ 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, pci_dev_to_dev(pdev), port);
ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
if (!probe_ent)
return NULL;
......@@ -3513,39 +3592,47 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
return probe_ent;
}
struct ata_probe_ent *
ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port)
static struct ata_probe_ent *
ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
struct ata_probe_ent **ppe2)
{
struct ata_probe_ent *probe_ent =
ata_probe_ent_alloc(2, pci_dev_to_dev(pdev), port);
struct ata_probe_ent *probe_ent, *probe_ent2;
probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
if (!probe_ent)
return NULL;
probe_ent2 = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[1]);
if (!probe_ent2) {
kfree(probe_ent);
return NULL;
}
probe_ent[0].n_ports = 1;
probe_ent[0].irq = 14;
probe_ent->n_ports = 1;
probe_ent->irq = 14;
probe_ent[0].hard_port_no = 0;
probe_ent[0].legacy_mode = 1;
probe_ent->hard_port_no = 0;
probe_ent->legacy_mode = 1;
probe_ent[1].n_ports = 1;
probe_ent[1].irq = 15;
probe_ent2->n_ports = 1;
probe_ent2->irq = 15;
probe_ent[1].hard_port_no = 1;
probe_ent[1].legacy_mode = 1;
probe_ent2->hard_port_no = 1;
probe_ent2->legacy_mode = 1;
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->port[0].cmd_addr = 0x1f0;
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr = 0x3f6;
probe_ent->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;
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;
ata_std_ports(&probe_ent[0].port[0]);
ata_std_ports(&probe_ent[1].port[0]);
ata_std_ports(&probe_ent->port[0]);
ata_std_ports(&probe_ent2->port[0]);
*ppe2 = probe_ent2;
return probe_ent;
}
......@@ -3579,7 +3666,8 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
else
port[1] = port[0];
if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
&& (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
/* TODO: support transitioning to native mode? */
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
mask = (1 << 2) | (1 << 0);
......@@ -3641,9 +3729,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
goto err_out_regions;
if (legacy_mode) {
probe_ent = ata_pci_init_legacy_mode(pdev, port);
if (probe_ent)
probe_ent2 = &probe_ent[1];
probe_ent = ata_pci_init_legacy_mode(pdev, port, &probe_ent2);
} else
probe_ent = ata_pci_init_native_mode(pdev, port);
if (!probe_ent) {
......@@ -3657,8 +3743,12 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
if (legacy_mode) {
if (legacy_mode & (1 << 0))
ata_device_add(probe_ent);
else
kfree(probe_ent);
if (legacy_mode & (1 << 1))
ata_device_add(probe_ent2);
else
kfree(probe_ent2);
} else {
ata_device_add(probe_ent);
}
......@@ -3848,7 +3938,6 @@ EXPORT_SYMBOL_GPL(ata_scsi_simulate);
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
......
......@@ -202,7 +202,7 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
{0x40, MEDIUM_ERROR, 0x11, 0x04}, // Uncorrectable ECC error Unrecovered read error
/* BBD - block marked bad */
{0x80, MEDIUM_ERROR, 0x11, 0x04}, // Block marked bad Medium error, unrecovered read error
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
};
static unsigned char stat_table[][4] = {
/* Must be first because BUSY means no other bits valid */
......@@ -210,22 +210,22 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
{0x20, HARDWARE_ERROR, 0x00, 0x00}, // Device fault
{0x08, ABORTED_COMMAND, 0x47, 0x00}, // Timed out in xfer, fake parity for now
{0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
};
int i = 0;
cmd->result = SAM_STAT_CHECK_CONDITION;
/*
* Is this an error we can process/parse
*/
if(drv_stat & ATA_ERR)
/* Read the err bits */
err = ata_chk_err(qc->ap);
/* Display the ATA level error info */
printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
if(drv_stat & 0x80)
{
......@@ -242,7 +242,7 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
if(drv_stat & 0x01) printk("Error ");
}
printk("}\n");
if(err)
{
printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
......@@ -259,11 +259,11 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
if(err & 0x02) printk("TrackZeroNotFound ");
if(err & 0x01) printk("AddrMarkNotFound ");
printk("}\n");
/* Should we dump sector info here too ?? */
}
/* Look for err */
while(sense_table[i][0] != 0xFF)
{
......@@ -301,7 +301,7 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
/* No error ?? */
printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
/* additional-sense-code[-qualifier] */
sb[0] = 0x70;
sb[2] = MEDIUM_ERROR;
sb[7] = 0x0A;
......@@ -488,19 +488,24 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
}
if (lba48) {
tf->command = ATA_CMD_VERIFY_EXT;
tf->hob_nsect = (n_sect >> 8) & 0xff;
tf->hob_lbah = (sect >> 40) & 0xff;
tf->hob_lbam = (sect >> 32) & 0xff;
tf->hob_lbal = (sect >> 24) & 0xff;
} else
} else {
tf->command = ATA_CMD_VERIFY;
tf->device |= (sect >> 24) & 0xf;
}
tf->nsect = n_sect & 0xff;
tf->hob_lbah = (sect >> 16) & 0xff;
tf->hob_lbam = (sect >> 8) & 0xff;
tf->hob_lbal = sect & 0xff;
tf->lbah = (sect >> 16) & 0xff;
tf->lbam = (sect >> 8) & 0xff;
tf->lbal = sect & 0xff;
return 0;
}
......@@ -600,7 +605,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
return 1;
/* stores LBA27:24 in lower 4 bits of device reg */
tf->device |= scsicmd[2];
tf->device |= scsicmd[6];
qc->nsect = scsicmd[13];
}
......
......@@ -20,6 +20,10 @@
* If you do not delete the provisions above, a recipient may use your
* version of this file under either the OSL or the GPL.
*
* 0.06
* - Added generic SATA support by using a pci_device_id that filters on
* the IDE storage class code.
*
* 0.03
* - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using
* mmio_base, which is only set for the CK804/MCP04 case.
......@@ -44,7 +48,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_nv"
#define DRV_VERSION "0.5"
#define DRV_VERSION "0.6"
#define NV_PORTS 2
#define NV_PIO_MASK 0x1f
......@@ -108,6 +112,7 @@ static void nv_check_hotplug_ck804(struct ata_host_set *host_set);
enum nv_host_type
{
GENERIC,
NFORCE2,
NFORCE3,
CK804
......@@ -128,6 +133,9 @@ static struct pci_device_id nv_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CK804 },
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
{ 0, } /* terminate list */
};
......@@ -136,29 +144,31 @@ static struct pci_device_id nv_pci_tbl[] = {
struct nv_host_desc
{
enum nv_host_type host_type;
unsigned long host_flags;
void (*enable_hotplug)(struct ata_probe_ent *probe_ent);
void (*disable_hotplug)(struct ata_host_set *host_set);
void (*check_hotplug)(struct ata_host_set *host_set);
};
static struct nv_host_desc nv_device_tbl[] = {
{
.host_type = GENERIC,
.enable_hotplug = NULL,
.disable_hotplug= NULL,
.check_hotplug = NULL,
},
{
.host_type = NFORCE2,
.host_flags = 0x00000000,
.enable_hotplug = nv_enable_hotplug,
.disable_hotplug= nv_disable_hotplug,
.check_hotplug = nv_check_hotplug,
},
{
.host_type = NFORCE3,
.host_flags = 0x00000000,
.enable_hotplug = nv_enable_hotplug,
.disable_hotplug= nv_disable_hotplug,
.check_hotplug = nv_check_hotplug,
},
{ .host_type = CK804,
.host_flags = NV_HOST_FLAGS_SCR_MMIO,
.enable_hotplug = nv_enable_hotplug_ck804,
.disable_hotplug= nv_disable_hotplug_ck804,
.check_hotplug = nv_check_hotplug_ck804,
......@@ -168,6 +178,7 @@ static struct nv_host_desc nv_device_tbl[] = {
struct nv_host
{
struct nv_host_desc *host_desc;
unsigned long host_flags;
};
static struct pci_driver nv_pci_driver = {
......@@ -284,8 +295,8 @@ static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
return readl((void*)ap->ioaddr.scr_addr + (sc_reg * 4));
else
return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
......@@ -298,8 +309,8 @@ static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
if (sc_reg > SCR_CONTROL)
return;
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
writel(val, (void*)ap->ioaddr.scr_addr + (sc_reg * 4));
else
outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
}
......@@ -322,6 +333,14 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent;
int rc;
u32 bar;
// Make sure this is a SATA controller by counting the number of bars
// (NVIDIA SATA controllers will always have six bars). Otherwise,
// it's an IDE controller and we ignore it.
for (bar=0; bar<6; bar++)
if (pci_resource_start(pdev, bar) == 0)
return -ENODEV;
if (!printed_version++)
printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
......@@ -352,11 +371,15 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (!host)
goto err_out_free_ent;
memset(host, 0, sizeof(struct nv_host));
host->host_desc = &nv_device_tbl[ent->driver_data];
probe_ent->private_data = host;
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
if (pci_resource_flags(pdev, 5) & IORESOURCE_MEM)
host->host_flags |= NV_HOST_FLAGS_SCR_MMIO;
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
unsigned long base;
probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
......@@ -395,7 +418,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
err_out_iounmap:
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
iounmap(probe_ent->mmio_base);
err_out_free_host:
kfree(host);
......
......@@ -156,10 +156,18 @@ static struct pci_device_id pdc_ata_pci_tbl[] = {
board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3574, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
{ } /* terminate list */
};
......@@ -406,9 +414,11 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
return IRQ_NONE;
}
spin_lock(&host_set->lock);
spin_lock(&host_set->lock);
writel(mask, mmio_base + PDC_INT_SEQMASK);
for (i = 0; i < host_set->n_ports; i++) {
for (i = 0; i < host_set->n_ports; i++) {
VPRINTK("port %u\n", i);
ap = host_set->ports[i];
tmp = mask & (1 << (i + 1));
......
......@@ -86,6 +86,7 @@ struct sil_drivelist {
{ "ST330013AS", SIL_QUIRK_MOD15WRITE },
{ "ST340017AS", SIL_QUIRK_MOD15WRITE },
{ "ST360015AS", SIL_QUIRK_MOD15WRITE },
{ "ST380013AS", SIL_QUIRK_MOD15WRITE },
{ "ST380023AS", SIL_QUIRK_MOD15WRITE },
{ "ST3120023AS", SIL_QUIRK_MOD15WRITE },
{ "ST3160023AS", SIL_QUIRK_MOD15WRITE },
......
......@@ -123,6 +123,8 @@ enum {
ATA_CMD_PIO_WRITE_EXT = 0x34,
ATA_CMD_SET_FEATURES = 0xEF,
ATA_CMD_PACKET = 0xA0,
ATA_CMD_VERIFY = 0x40,
ATA_CMD_VERIFY_EXT = 0x42,
/* SETFEATURES stuff */
SETFEATURES_XFER = 0x03,
......
......@@ -436,8 +436,6 @@ struct pci_bits {
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 int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
#endif /* CONFIG_PCI */
......
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