Commit 1a6407d9 authored by Russell King's avatar Russell King

[ARM] Update PCI host bridge drivers for GregKH PCI cleanups.

parent 5097d470
......@@ -34,9 +34,9 @@
#define PLX_SET_CONFIG \
{ unsigned long flags; \
local_irq_save(flags); \
__raw_writel((1<<31 | (dev->bus->number << 16) \
| (dev->devfn << 8) | (where & ~3) \
| ((dev->bus->number == 0)?0:1)), PLX_BASE + 0xac); \
__raw_writel((1<<31 | (bus->number << 16) \
| (devfn << 8) | (where & ~3) \
| ((bus->number == 0)?0:1)), PLX_BASE + 0xac); \
#define PLX_CONFIG_WRITE(size) \
PLX_SET_CONFIG \
......@@ -59,46 +59,46 @@
/* Configuration space access routines */
static int
plx90x0_read_config_byte (struct pci_dev *dev,
int where, u8 *value)
plx90x0_read_config (struct pci_bus *bus, unsigned int devfn, int where,
int where, int size, u32 *value)
{
switch (size) {
case 1:
PLX_CONFIG_READ(b)
}
static int
plx90x0_read_config_word (struct pci_dev *dev,
int where, u16 *value)
{
break;
case 2:
PLX_CONFIG_READ(w)
}
static int
plx90x0_read_config_dword (struct pci_dev *dev,
int where, u32 *value)
{
break;
case 4:
PLX_CONFIG_READ(l)
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int
plx90x0_write_config_byte (struct pci_dev *dev,
int where, u8 value)
plx90x0_write_config (struct pci_bus *bus, unsigned int devfn, int where,
int where, int size, u32 value)
{
switch (size) {
case 1:
PLX_CONFIG_WRITE(b)
}
static int
plx90x0_write_config_word (struct pci_dev *dev,
int where, u16 value)
{
break;
case 2:
PLX_CONFIG_WRITE(w)
break;
case 4:
PLX_CONFIG_WRITE(l)
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int
plx90x0_write_config_dword (struct pci_dev *dev,
int where, u32 value)
static struct pci_ops plx90x0_ops =
{
PLX_CONFIG_WRITE(l)
}
.read = plx90x0_read_config,
.write = plx90x0_write_config,
};
static void
plx_syserr_handler(int irq, void *handle, struct pt_regs *regs)
......@@ -108,17 +108,6 @@ plx_syserr_handler(int irq, void *handle, struct pt_regs *regs)
__raw_writew(0xf000, PLX_BASE + 6);
}
static struct pci_ops
plx90x0_ops =
{
plx90x0_read_config_byte,
plx90x0_read_config_word,
plx90x0_read_config_dword,
plx90x0_write_config_byte,
plx90x0_write_config_word,
plx90x0_write_config_dword,
};
/*
* Initialise the PCI system.
*/
......
......@@ -15,63 +15,49 @@
#define MAX_SLOTS 7
#define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3))
#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
static int
via82c505_read_config_byte(struct pci_dev *dev, int where, u8 *value)
via82c505_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value)
{
outl(CONFIG_CMD(dev,where),0xCF8);
switch (size) {
case 1:
*value=inb(0xCFC + (where&3));
return PCIBIOS_SUCCESSFUL;
}
static int
via82c505_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
outl(CONFIG_CMD(dev,where),0xCF8);
break;
case 2:
*value=inw(0xCFC + (where&2));
return PCIBIOS_SUCCESSFUL;
}
static int
via82c505_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
outl(CONFIG_CMD(dev,where),0xCF8);
break;
case 4:
*value=inl(0xCFC);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int
via82c505_write_config_byte(struct pci_dev *dev, int where, u8 value)
via82c505_write_config(struct pci_bus *bus, unsigned int devfn, int where
int size, u32 value)
{
outl(CONFIG_CMD(dev,where),0xCF8);
outl(CONFIG_CMD(bus,devfn,where),0xCF8);
switch (size) {
case 1:
outb(value, 0xCFC + (where&3));
return PCIBIOS_SUCCESSFUL;
}
static int
via82c505_write_config_word(struct pci_dev *dev, int where, u16 value)
{
outl(CONFIG_CMD(dev,where),0xCF8);
break;
case 2:
outw(value, 0xCFC + (where&2));
return PCIBIOS_SUCCESSFUL;
}
static int
via82c505_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
outl(CONFIG_CMD(dev,where),0xCF8);
break;
case 4:
outl(value, 0xCFC);
break;
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops via82c505_ops = {
via82c505_read_config_byte,
via82c505_read_config_word,
via82c505_read_config_dword,
via82c505_write_config_byte,
via82c505_write_config_word,
via82c505_write_config_dword,
.read = via82c505_read_config,
.write = via82c505_write_config,
};
void __init via82c505_preinit(void *sysdata)
......
......@@ -36,12 +36,11 @@ extern void pcibios_report_status(u_int status_mask, int warn);
extern void register_isa_ports(unsigned int, unsigned int, unsigned int);
static unsigned long
dc21285_base_address(struct pci_dev *dev)
dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
{
unsigned long addr = 0;
unsigned int devfn = dev->devfn;
if (dev->bus->number == 0) {
if (bus->number == 0) {
if (PCI_SLOT(devfn) == 0)
/*
* For devfn 0, point at the 21285
......@@ -54,54 +53,33 @@ dc21285_base_address(struct pci_dev *dev)
addr = PCICFG0_BASE | 0xc00000 | (devfn << 8);
}
} else
addr = PCICFG1_BASE | (dev->bus->number << 16) | (devfn << 8);
addr = PCICFG1_BASE | (bus->number << 16) | (devfn << 8);
return addr;
}
static int
dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value)
dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value)
{
unsigned long addr = dc21285_base_address(dev);
u8 v;
unsigned long addr = dc21285_base_address(bus, devfn);
u32 v;
if (addr)
switch (size) {
case 1:
asm("ldr%?b %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where));
else
v = 0xff;
*value = v;
return PCIBIOS_SUCCESSFUL;
}
static int
dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
unsigned long addr = dc21285_base_address(dev);
u16 v;
if (addr)
break;
case 2:
asm("ldr%?h %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where));
else
v = 0xffff;
*value = v;
return PCIBIOS_SUCCESSFUL;
}
static int
dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
unsigned long addr = dc21285_base_address(dev);
u32 v;
if (addr)
break;
case 4:
asm("ldr%? %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where));
break;
}
else
v = 0xffffffff;
......@@ -111,48 +89,33 @@ dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value)
}
static int
dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value)
dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 value)
{
unsigned long addr = dc21285_base_address(dev);
unsigned long addr = dc21285_base_address(bus, devfn);
if (addr)
switch (size) {
case 1:
asm("str%?b %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where));
return PCIBIOS_SUCCESSFUL;
}
static int
dc21285_write_config_word(struct pci_dev *dev, int where, u16 value)
{
unsigned long addr = dc21285_base_address(dev);
if (addr)
break;
case 2:
asm("str%?h %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where));
return PCIBIOS_SUCCESSFUL;
}
static int
dc21285_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
unsigned long addr = dc21285_base_address(dev);
if (addr)
break;
case 4:
asm("str%? %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where));
break;
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops dc21285_ops = {
dc21285_read_config_byte,
dc21285_read_config_word,
dc21285_read_config_dword,
dc21285_write_config_byte,
dc21285_write_config_word,
dc21285_write_config_dword,
.read = dc21285_read_config,
.write = dc21285_write_config,
};
static struct timer_list serr_timer;
......
......@@ -181,11 +181,12 @@ static spinlock_t v3_lock = SPIN_LOCK_UNLOCKED;
#undef V3_LB_BASE_PREFETCH
#define V3_LB_BASE_PREFETCH 0
static unsigned long v3_open_config_window(struct pci_dev *dev, int offset)
static unsigned long v3_open_config_window(struct pci_bus *bus,
unsigned int devfn, int offset)
{
unsigned int address, mapaddress, busnr;
busnr = dev->bus->number;
busnr = bus->number;
/*
* Trap out illegal values
......@@ -194,11 +195,11 @@ static unsigned long v3_open_config_window(struct pci_dev *dev, int offset)
BUG();
if (busnr > 255)
BUG();
if (dev->devfn > 255)
if (devfn > 255)
BUG();
if (busnr == 0) {
int slot = PCI_SLOT(dev->devfn);
int slot = PCI_SLOT(devfn);
/*
* local bus segment so need a type 0 config cycle
......@@ -210,7 +211,7 @@ static unsigned long v3_open_config_window(struct pci_dev *dev, int offset)
* 3:1 = config cycle (101)
* 0 = PCI A1 & A0 are 0 (0)
*/
address = PCI_FUNC(dev->devfn) << 8;
address = PCI_FUNC(devfn) << 8;
mapaddress = V3_LB_MAP_TYPE_CONFIG;
if (slot > 12)
......@@ -237,7 +238,7 @@ static unsigned long v3_open_config_window(struct pci_dev *dev, int offset)
* 0 = PCI A1 & A0 from host bus (1)
*/
mapaddress = V3_LB_MAP_TYPE_CONFIG | V3_LB_MAP_AD_LOW_EN;
address = (busnr << 16) | (dev->devfn << 8);
address = (busnr << 16) | (devfn << 8);
}
/*
......@@ -276,52 +277,29 @@ static void v3_close_config_window(void)
V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE);
}
static int v3_read_config_byte(struct pci_dev *dev, int where, u8 *val)
static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
unsigned long addr;
unsigned long flags;
u8 v;
u32 v;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
addr = v3_open_config_window(bus, devfn, where);
switch (size) {
case 1:
v = __raw_readb(addr);
break;
v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags);
*val = v;
return PCIBIOS_SUCCESSFUL;
}
static int v3_read_config_word(struct pci_dev *dev, int where, u16 *val)
{
unsigned long addr;
unsigned long flags;
u16 v;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
case 2:
v = __raw_readw(addr);
break;
v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags);
*val = v;
return PCIBIOS_SUCCESSFUL;
}
static int v3_read_config_dword(struct pci_dev *dev, int where, u32 *val)
{
unsigned long addr;
unsigned long flags;
u32 v;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
case 4:
v = __raw_readl(addr);
break;
}
v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags);
......@@ -330,50 +308,31 @@ static int v3_read_config_dword(struct pci_dev *dev, int where, u32 *val)
return PCIBIOS_SUCCESSFUL;
}
static int v3_write_config_byte(struct pci_dev *dev, int where, u8 val)
static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
unsigned long addr;
unsigned long flags;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
addr = v3_open_config_window(bus, devfn, where);
__raw_writeb(val, addr);
switch (size) {
case 1:
__raw_writeb((u8)val, addr);
__raw_readb(addr);
break;
v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags);
return PCIBIOS_SUCCESSFUL;
}
static int v3_write_config_word(struct pci_dev *dev, int where, u16 val)
{
unsigned long addr;
unsigned long flags;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
__raw_writew(val, addr);
case 2:
__raw_writew((u16)val, addr);
__raw_readw(addr);
break;
v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags);
return PCIBIOS_SUCCESSFUL;
}
static int v3_write_config_dword(struct pci_dev *dev, int where, u32 val)
{
unsigned long addr;
unsigned long flags;
spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(dev, where);
case 4:
__raw_writel(val, addr);
__raw_readl(addr);
break;
}
v3_close_config_window();
spin_unlock_irqrestore(&v3_lock, flags);
......@@ -382,12 +341,8 @@ static int v3_write_config_dword(struct pci_dev *dev, int where, u32 val)
}
static struct pci_ops pci_v3_ops = {
.read_byte = v3_read_config_byte,
.read_word = v3_read_config_word,
.read_dword = v3_read_config_dword,
.write_byte = v3_write_config_byte,
.write_word = v3_write_config_word,
.write_dword = v3_write_config_dword,
.read = v3_read_config,
.write = v3_write_config,
};
static struct resource non_mem = {
......
......@@ -55,22 +55,23 @@
#define DBG(x...) do { } while (0)
#endif
extern int (*external_fault)(unsigned long, struct pt_regs *);
static u32 iop310_cfg_address(struct pci_dev *dev, int where)
/*
* Calculate the address, etc from the bus, devfn and register
* offset. Note that we have two root buses, so we need some
* method to determine whether we need config type 0 or 1 cycles.
* We use a root bus number in our bus->sysdata structure for this.
*/
static u32 iop310_cfg_address(struct pci_bus *bus, int devfn, int where)
{
struct pci_sys_data *sys = dev->sysdata;
struct pci_sys_data *sys = bus->sysdata;
u32 addr;
where &= ~3;
if (sys->busnr == dev->bus->number)
addr = 1 << (PCI_SLOT(dev->devfn) + 16);
if (sys->busnr == bus->number)
addr = 1 << (PCI_SLOT(devfn) + 16);
else
addr = dev->bus->number << 16 |
PCI_SLOT(dev->devfn) << 11 | 1;
addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
addr |= PCI_FUNC(dev->devfn) << 8 | where;
addr |= PCI_FUNC(devfn) << 8 | (where & ~3);
return addr;
}
......@@ -106,9 +107,13 @@ static int iop310_pri_pci_status(void)
return ret;
}
static inline u32 iop310_pri_read(struct pci_dev *dev, int where)
/*
* Simply write the address register and read the configuration
* data. Note that the 4 nop's ensure that we are able to handle
* a delayed abort (in theory.)
*/
static inline u32 iop310_pri_read(unsigned long addr)
{
unsigned long addr = iop310_cfg_address(dev, where);
u32 val;
__asm__ __volatile__(
......@@ -125,92 +130,42 @@ static inline u32 iop310_pri_read(struct pci_dev *dev, int where)
}
static int
iop310_pri_rd_cfg_byte(struct pci_dev *dev, int where, u8 *p)
iop310_pri_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value)
{
u8 val;
val = iop310_pri_read(dev, where) >> ((where & 3) * 8);
if (iop310_pri_pci_status())
val = 0xff;
*p = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_pri_rd_cfg_word(struct pci_dev *dev, int where, u16 *p)
{
u16 val;
val = iop310_pri_read(dev, where) >> ((where & 3) * 8);
if (iop310_pri_pci_status())
val = 0xffff;
*p = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_pri_rd_cfg_dword(struct pci_dev *dev, int where, u32 *p)
{
u32 val;
val = iop310_pri_read(dev, where);
unsigned long addr = iop310_cfg_address(bus, devfn, where);
u32 val = iop310_pri_read(addr) >> ((where & 3) * 8);
if (iop310_pri_pci_status())
val = 0xffffffff;
*p = val;
*value = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_pri_wr_cfg_byte(struct pci_dev *dev, int where, u8 v)
iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where
int size, u32 value)
{
unsigned long addr = iop310_cfg_address(bus, devfn, where);
u32 val;
val = iop310_pri_read(dev, where);
if (iop310_pri_pci_status() == 0) {
where = (where & 3) * 8;
val &= ~(0xff << where);
val |= v << where;
*IOP310_POCCDR = val;
}
if (size != 4) {
val = iop310_pri_read(addr);
if (!iop310_pri_pci_status() == 0)
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_pri_wr_cfg_word(struct pci_dev *dev, int where, u16 v)
{
u32 val;
val = iop310_pri_read(dev, where);
where = (where & 3) * 8;
if (iop310_pri_pci_status() == 0) {
where = (where & 2) * 8;
if (size == 1)
val &= ~(0xff << where);
else
val &= ~(0xffff << where);
val |= v << where;
*IOP310_POCCDR = val;
}
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_pri_wr_cfg_dword(struct pci_dev *dev, int where, u32 val)
{
unsigned long addr;
addr = iop310_cfg_address(dev, where);
__asm__ __volatile__(
*IOP310_POCCDR = val | v << where;
} else {
asm volatile(
"str %1, [%2]\n\t"
"str %0, [%3]\n\t"
"nop\n\t"
......@@ -218,18 +173,16 @@ iop310_pri_wr_cfg_dword(struct pci_dev *dev, int where, u32 val)
"nop\n\t"
"nop\n\t"
:
: "r" (val), "r" (addr), "r" (IOP310_POCCAR), "r" (IOP310_POCCDR));
: "r" (val), "r" (addr),
"r" (IOP310_POCCAR), "r" (IOP310_POCCDR));
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops iop310_primary_ops = {
iop310_pri_rd_cfg_byte,
iop310_pri_rd_cfg_word,
iop310_pri_rd_cfg_dword,
iop310_pri_wr_cfg_byte,
iop310_pri_wr_cfg_word,
iop310_pri_wr_cfg_dword,
.read = iop310_pri_read_config,
.write = iop310_pri_write_config,
};
/*
......@@ -255,9 +208,13 @@ static int iop310_sec_pci_status(void)
return ret;
}
static inline u32 iop310_sec_read(struct pci_dev *dev, int where)
/*
* Simply write the address register and read the configuration
* data. Note that the 4 nop's ensure that we are able to handle
* a delayed abort (in theory.)
*/
static inline u32 iop310_sec_read(unsigned long addr)
{
unsigned long addr = iop310_cfg_address(dev, where);
u32 val;
__asm__ __volatile__(
......@@ -274,92 +231,43 @@ static inline u32 iop310_sec_read(struct pci_dev *dev, int where)
}
static int
iop310_sec_rd_cfg_byte(struct pci_dev *dev, int where, u8 *p)
{
u8 val;
val = iop310_sec_read(dev, where) >> ((where & 3) * 8);
if (iop310_sec_pci_status())
val = 0xff;
*p = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_sec_rd_cfg_word(struct pci_dev *dev, int where, u16 *p)
{
u16 val;
val = iop310_sec_read(dev, where) >> ((where & 3) * 8);
if (iop310_sec_pci_status())
val = 0xffff;
*p = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_sec_rd_cfg_dword(struct pci_dev *dev, int where, u32 *p)
iop310_sec_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value)
{
u32 val;
val = iop310_sec_read(dev, where);
unsigned long addr = iop310_cfg_address(bus, devfn, where);
u32 val = iop310_sec_read(addr) >> ((where & 3) * 8);
if (iop310_sec_pci_status())
val = 0xffffffff;
*p = val;
*value = val;
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_sec_wr_cfg_byte(struct pci_dev *dev, int where, u8 v)
iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where
int size, u32 value)
{
unsigned long addr = iop310_cfg_address(bus, devfn, where);
u32 val;
val = iop310_sec_read(dev, where);
if (iop310_sec_pci_status() == 0) {
where = (where & 3) * 8;
val &= ~(0xff << where);
val |= v << where;
*IOP310_SOCCDR = val;
}
if (size != 4) {
val = iop310_sec_read(addr);
if (!iop310_sec_pci_status() == 0)
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_sec_wr_cfg_word(struct pci_dev *dev, int where, u16 v)
{
u32 val;
val = iop310_sec_read(dev, where);
where = (where & 3) * 8;
if (iop310_sec_pci_status() == 0) {
where = (where & 2) * 8;
if (size == 1)
val &= ~(0xff << where);
else
val &= ~(0xffff << where);
val |= v << where;
*IOP310_SOCCDR = val;
}
return PCIBIOS_SUCCESSFUL;
}
static int
iop310_sec_wr_cfg_dword(struct pci_dev *dev, int where, u32 val)
{
unsigned long addr;
addr = iop310_cfg_address(dev, where);
__asm__ __volatile__(
*IOP310_SOCCDR = val | v << where;
} else {
asm volatile(
"str %1, [%2]\n\t"
"str %0, [%3]\n\t"
"nop\n\t"
......@@ -367,18 +275,16 @@ iop310_sec_wr_cfg_dword(struct pci_dev *dev, int where, u32 val)
"nop\n\t"
"nop\n\t"
:
: "r" (val), "r" (addr), "r" (IOP310_SOCCAR), "r" (IOP310_SOCCDR));
: "r" (val), "r" (addr),
"r" (IOP310_SOCCAR), "r" (IOP310_SOCCDR));
}
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops iop310_secondary_ops = {
iop310_sec_rd_cfg_byte,
iop310_sec_rd_cfg_word,
iop310_sec_rd_cfg_dword,
iop310_sec_wr_cfg_byte,
iop310_sec_wr_cfg_word,
iop310_sec_wr_cfg_dword,
.read = iop310_sec_read_config,
.write = iop310_sec_write_config,
};
/*
......@@ -524,5 +430,5 @@ void iop310_init(void)
*/
*IOP310_PCR &= 0xfff8;
hook_fault_code(6, iop310_pci_abort, SIGBUS, "imprecise external abort");
hook_fault_code(16+6, iop310_pci_abort, SIGBUS, "imprecise external abort");
}
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