Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
9636273d
Commit
9636273d
authored
May 20, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of
rsync://www.parisc-linux.org/~jejb/git/scsi-for-linus-2.6.git
parents
2df9fa36
2bf2c568
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
530 additions
and
1310 deletions
+530
-1310
drivers/scsi/aic7xxx/aic7770_osm.c
drivers/scsi/aic7xxx/aic7770_osm.c
+1
-51
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
+336
-1064
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/aic7xxx/aic7xxx_osm.h
+25
-144
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+1
-10
drivers/scsi/aic7xxx/aic7xxx_proc.c
drivers/scsi/aic7xxx/aic7xxx_proc.c
+0
-13
drivers/scsi/aic7xxx/aiclib.c
drivers/scsi/aic7xxx/aiclib.c
+0
-1
drivers/scsi/scsi_transport_spi.c
drivers/scsi/scsi_transport_spi.c
+161
-27
include/scsi/scsi_transport_spi.h
include/scsi/scsi_transport_spi.h
+6
-0
No files found.
drivers/scsi/aic7xxx/aic7770_osm.c
View file @
9636273d
...
...
@@ -41,7 +41,6 @@
#include "aic7xxx_osm.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#include <linux/device.h>
#include <linux/eisa.h>
...
...
@@ -62,13 +61,6 @@ static struct eisa_driver aic7770_driver = {
};
typedef
struct
device
*
aic7770_dev_t
;
#else
#define MINSLOT 1
#define NUMSLOTS 16
#define IDOFFSET 0x80
typedef
void
*
aic7770_dev_t
;
#endif
static
int
aic7770_linux_config
(
struct
aic7770_identity
*
entry
,
aic7770_dev_t
dev
,
u_int
eisaBase
);
...
...
@@ -76,7 +68,6 @@ static int aic7770_linux_config(struct aic7770_identity *entry,
int
ahc_linux_eisa_init
(
void
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
struct
eisa_device_id
*
eid
;
struct
aic7770_identity
*
id
;
int
i
;
...
...
@@ -110,44 +101,6 @@ ahc_linux_eisa_init(void)
eid
->
sig
[
0
]
=
0
;
return
eisa_driver_register
(
&
aic7770_driver
);
#else
/* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */
struct
aic7770_identity
*
entry
;
u_int
slot
;
u_int
eisaBase
;
u_int
i
;
int
ret
=
-
ENODEV
;
if
(
aic7xxx_probe_eisa_vl
==
0
)
return
ret
;
eisaBase
=
0x1000
+
AHC_EISA_SLOT_OFFSET
;
for
(
slot
=
1
;
slot
<
NUMSLOTS
;
eisaBase
+=
0x1000
,
slot
++
)
{
uint32_t
eisa_id
;
size_t
id_size
;
if
(
request_region
(
eisaBase
,
AHC_EISA_IOSIZE
,
"aic7xxx"
)
==
0
)
continue
;
eisa_id
=
0
;
id_size
=
sizeof
(
eisa_id
);
for
(
i
=
0
;
i
<
4
;
i
++
)
{
/* VLcards require priming*/
outb
(
0x80
+
i
,
eisaBase
+
IDOFFSET
);
eisa_id
|=
inb
(
eisaBase
+
IDOFFSET
+
i
)
<<
((
id_size
-
i
-
1
)
*
8
);
}
release_region
(
eisaBase
,
AHC_EISA_IOSIZE
);
if
(
eisa_id
&
0x80000000
)
continue
;
/* no EISA card in slot */
entry
=
aic7770_find_device
(
eisa_id
);
if
(
entry
!=
NULL
)
{
aic7770_linux_config
(
entry
,
NULL
,
eisaBase
);
ret
=
0
;
}
}
return
ret
;
#endif
}
void
...
...
@@ -187,11 +140,10 @@ aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev,
ahc_free
(
ahc
);
return
(
error
);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
dev
->
driver_data
=
(
void
*
)
ahc
;
if
(
aic7xxx_detect_complete
)
error
=
ahc_linux_register_host
(
ahc
,
&
aic7xxx_driver_template
);
#endif
return
(
error
);
}
...
...
@@ -225,7 +177,6 @@ aic7770_map_int(struct ahc_softc *ahc, u_int irq)
return
(
-
error
);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
static
int
aic7770_eisa_dev_probe
(
struct
device
*
dev
)
{
...
...
@@ -261,4 +212,3 @@ aic7770_eisa_dev_remove(struct device *dev)
return
(
0
);
}
#endif
drivers/scsi/aic7xxx/aic7xxx_osm.c
View file @
9636273d
This diff is collapsed.
Click to expand it.
drivers/scsi/aic7xxx/aic7xxx_osm.h
View file @
9636273d
This diff is collapsed.
Click to expand it.
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
View file @
9636273d
...
...
@@ -221,13 +221,11 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
&&
ahc_linux_get_memsize
()
>
0x80000000
&&
pci_set_dma_mask
(
pdev
,
mask_39bit
)
==
0
)
{
ahc
->
flags
|=
AHC_39BIT_ADDRESSING
;
ahc
->
platform_data
->
hw_dma_mask
=
mask_39bit
;
}
else
{
if
(
pci_set_dma_mask
(
pdev
,
DMA_32BIT_MASK
))
{
printk
(
KERN_WARNING
"aic7xxx: No suitable DMA available.
\n
"
);
return
(
-
ENODEV
);
}
ahc
->
platform_data
->
hw_dma_mask
=
DMA_32BIT_MASK
;
}
ahc
->
dev_softc
=
pci
;
error
=
ahc_pci_config
(
ahc
,
entry
);
...
...
@@ -236,15 +234,8 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return
(
-
error
);
}
pci_set_drvdata
(
pdev
,
ahc
);
if
(
aic7xxx_detect_complete
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
if
(
aic7xxx_detect_complete
)
ahc_linux_register_host
(
ahc
,
&
aic7xxx_driver_template
);
#else
printf
(
"aic7xxx: ignoring PCI device found after "
"initialization
\n
"
);
return
(
-
ENODEV
);
#endif
}
return
(
0
);
}
...
...
drivers/scsi/aic7xxx/aic7xxx_proc.c
View file @
9636273d
...
...
@@ -289,13 +289,8 @@ ahc_proc_write_seeprom(struct ahc_softc *ahc, char *buffer, int length)
* Return information to handle /proc support for the driver.
*/
int
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
ahc_linux_proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
hostno
,
int
inout
)
#else
ahc_linux_proc_info
(
struct
Scsi_Host
*
shost
,
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
,
int
inout
)
#endif
{
struct
ahc_softc
*
ahc
;
struct
info_str
info
;
...
...
@@ -307,15 +302,7 @@ ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
retval
=
-
EINVAL
;
ahc_list_lock
(
&
s
);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
TAILQ_FOREACH
(
ahc
,
&
ahc_tailq
,
links
)
{
if
(
ahc
->
platform_data
->
host
->
host_no
==
hostno
)
break
;
}
#else
ahc
=
ahc_find_softc
(
*
(
struct
ahc_softc
**
)
shost
->
hostdata
);
#endif
if
(
ahc
==
NULL
)
goto
done
;
...
...
drivers/scsi/aic7xxx/aiclib.c
View file @
9636273d
...
...
@@ -35,7 +35,6 @@
#include <linux/version.h>
/* Core SCSI definitions */
#include "scsi.h"
#include <scsi/scsi_host.h>
#include "aiclib.h"
#include "cam.h"
...
...
drivers/scsi/scsi_transport_spi.c
View file @
9636273d
...
...
@@ -35,7 +35,7 @@
#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a)
#define SPI_NUM_ATTRS 1
0
/* increase this if you add attributes */
#define SPI_NUM_ATTRS 1
3
/* increase this if you add attributes */
#define SPI_OTHER_ATTRS 1
/* Increase this if you add "always
* on" attributes */
#define SPI_HOST_ATTRS 1
...
...
@@ -219,8 +219,11 @@ static int spi_setup_transport_attrs(struct device *dev)
struct
scsi_target
*
starget
=
to_scsi_target
(
dev
);
spi_period
(
starget
)
=
-
1
;
/* illegal value */
spi_min_period
(
starget
)
=
0
;
spi_offset
(
starget
)
=
0
;
/* async */
spi_max_offset
(
starget
)
=
255
;
spi_width
(
starget
)
=
0
;
/* narrow */
spi_max_width
(
starget
)
=
1
;
spi_iu
(
starget
)
=
0
;
/* no IU */
spi_dt
(
starget
)
=
0
;
/* ST */
spi_qas
(
starget
)
=
0
;
...
...
@@ -235,6 +238,34 @@ static int spi_setup_transport_attrs(struct device *dev)
return
0
;
}
#define spi_transport_show_simple(field, format_string) \
\
static ssize_t \
show_spi_transport_##field(struct class_device *cdev, char *buf) \
{ \
struct scsi_target *starget = transport_class_to_starget(cdev); \
struct spi_transport_attrs *tp; \
\
tp = (struct spi_transport_attrs *)&starget->starget_data; \
return snprintf(buf, 20, format_string, tp->field); \
}
#define spi_transport_store_simple(field, format_string) \
\
static ssize_t \
store_spi_transport_##field(struct class_device *cdev, const char *buf, \
size_t count) \
{ \
int val; \
struct scsi_target *starget = transport_class_to_starget(cdev); \
struct spi_transport_attrs *tp; \
\
tp = (struct spi_transport_attrs *)&starget->starget_data; \
val = simple_strtoul(buf, NULL, 0); \
tp->field = val; \
return count; \
}
#define spi_transport_show_function(field, format_string) \
\
static ssize_t \
...
...
@@ -261,6 +292,25 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
struct spi_internal *i = to_spi_internal(shost->transportt); \
\
val = simple_strtoul(buf, NULL, 0); \
i->f->set_##field(starget, val); \
return count; \
}
#define spi_transport_store_max(field, format_string) \
static ssize_t \
store_spi_transport_##field(struct class_device *cdev, const char *buf, \
size_t count) \
{ \
int val; \
struct scsi_target *starget = transport_class_to_starget(cdev); \
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
struct spi_internal *i = to_spi_internal(shost->transportt); \
struct spi_transport_attrs *tp \
= (struct spi_transport_attrs *)&starget->starget_data; \
\
val = simple_strtoul(buf, NULL, 0); \
if (val > tp->max_##field) \
val = tp->max_##field; \
i->f->set_##field(starget, val); \
return count; \
}
...
...
@@ -272,9 +322,24 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \
show_spi_transport_##field, \
store_spi_transport_##field);
#define spi_transport_simple_attr(field, format_string) \
spi_transport_show_simple(field, format_string) \
spi_transport_store_simple(field, format_string) \
static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \
show_spi_transport_##field, \
store_spi_transport_##field);
#define spi_transport_max_attr(field, format_string) \
spi_transport_show_function(field, format_string) \
spi_transport_store_max(field, format_string) \
spi_transport_simple_attr(max_##field, format_string) \
static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \
show_spi_transport_##field, \
store_spi_transport_##field);
/* The Parallel SCSI Tranport Attributes: */
spi_transport_
rd
_attr
(
offset
,
"%d
\n
"
);
spi_transport_
rd
_attr
(
width
,
"%d
\n
"
);
spi_transport_
max
_attr
(
offset
,
"%d
\n
"
);
spi_transport_
max
_attr
(
width
,
"%d
\n
"
);
spi_transport_rd_attr
(
iu
,
"%d
\n
"
);
spi_transport_rd_attr
(
dt
,
"%d
\n
"
);
spi_transport_rd_attr
(
qas
,
"%d
\n
"
);
...
...
@@ -300,26 +365,18 @@ static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
/* Translate the period into ns according to the current spec
* for SDTR/PPR messages */
static
ssize_t
show_spi_transport_period
(
struct
class_device
*
cdev
,
char
*
buf
)
static
ssize_t
show_spi_transport_period_helper
(
struct
class_device
*
cdev
,
char
*
buf
,
int
period
)
{
struct
scsi_target
*
starget
=
transport_class_to_starget
(
cdev
);
struct
Scsi_Host
*
shost
=
dev_to_shost
(
starget
->
dev
.
parent
);
struct
spi_transport_attrs
*
tp
;
int
len
,
picosec
;
struct
spi_internal
*
i
=
to_spi_internal
(
shost
->
transportt
);
tp
=
(
struct
spi_transport_attrs
*
)
&
starget
->
starget_data
;
if
(
i
->
f
->
get_period
)
i
->
f
->
get_period
(
starget
);
if
(
tp
->
period
<
0
||
tp
->
period
>
0xff
)
{
if
(
period
<
0
||
period
>
0xff
)
{
picosec
=
-
1
;
}
else
if
(
tp
->
period
<=
SPI_STATIC_PPR
)
{
picosec
=
ppr_to_ps
[
tp
->
period
];
}
else
if
(
period
<=
SPI_STATIC_PPR
)
{
picosec
=
ppr_to_ps
[
period
];
}
else
{
picosec
=
tp
->
period
*
4000
;
picosec
=
period
*
4000
;
}
if
(
picosec
==
-
1
)
{
...
...
@@ -334,12 +391,9 @@ static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf)
}
static
ssize_t
store_spi_transport_period
(
struct
class_device
*
cdev
,
const
char
*
buf
,
size_t
count
)
store_spi_transport_period
_helper
(
struct
class_device
*
cdev
,
const
char
*
buf
,
size_t
count
,
int
*
periodp
)
{
struct
scsi_target
*
starget
=
transport_class_to_starget
(
cdev
);
struct
Scsi_Host
*
shost
=
dev_to_shost
(
starget
->
dev
.
parent
);
struct
spi_internal
*
i
=
to_spi_internal
(
shost
->
transportt
);
int
j
,
picosec
,
period
=
-
1
;
char
*
endp
;
...
...
@@ -368,15 +422,79 @@ store_spi_transport_period(struct class_device *cdev, const char *buf,
if
(
period
>
0xff
)
period
=
0xff
;
i
->
f
->
set_period
(
starget
,
period
)
;
*
periodp
=
period
;
return
count
;
}
static
ssize_t
show_spi_transport_period
(
struct
class_device
*
cdev
,
char
*
buf
)
{
struct
scsi_target
*
starget
=
transport_class_to_starget
(
cdev
);
struct
Scsi_Host
*
shost
=
dev_to_shost
(
starget
->
dev
.
parent
);
struct
spi_internal
*
i
=
to_spi_internal
(
shost
->
transportt
);
struct
spi_transport_attrs
*
tp
=
(
struct
spi_transport_attrs
*
)
&
starget
->
starget_data
;
if
(
i
->
f
->
get_period
)
i
->
f
->
get_period
(
starget
);
return
show_spi_transport_period_helper
(
cdev
,
buf
,
tp
->
period
);
}
static
ssize_t
store_spi_transport_period
(
struct
class_device
*
cdev
,
const
char
*
buf
,
size_t
count
)
{
struct
scsi_target
*
starget
=
transport_class_to_starget
(
cdev
);
struct
Scsi_Host
*
shost
=
dev_to_shost
(
starget
->
dev
.
parent
);
struct
spi_internal
*
i
=
to_spi_internal
(
shost
->
transportt
);
struct
spi_transport_attrs
*
tp
=
(
struct
spi_transport_attrs
*
)
&
starget
->
starget_data
;
int
period
,
retval
;
retval
=
store_spi_transport_period_helper
(
cdev
,
buf
,
count
,
&
period
);
if
(
period
<
tp
->
min_period
)
period
=
tp
->
min_period
;
i
->
f
->
set_period
(
starget
,
period
);
return
retval
;
}
static
CLASS_DEVICE_ATTR
(
period
,
S_IRUGO
|
S_IWUSR
,
show_spi_transport_period
,
store_spi_transport_period
);
static
ssize_t
show_spi_transport_min_period
(
struct
class_device
*
cdev
,
char
*
buf
)
{
struct
scsi_target
*
starget
=
transport_class_to_starget
(
cdev
);
struct
spi_transport_attrs
*
tp
=
(
struct
spi_transport_attrs
*
)
&
starget
->
starget_data
;
return
show_spi_transport_period_helper
(
cdev
,
buf
,
tp
->
min_period
);
}
static
ssize_t
store_spi_transport_min_period
(
struct
class_device
*
cdev
,
const
char
*
buf
,
size_t
count
)
{
struct
scsi_target
*
starget
=
transport_class_to_starget
(
cdev
);
struct
spi_transport_attrs
*
tp
=
(
struct
spi_transport_attrs
*
)
&
starget
->
starget_data
;
return
store_spi_transport_period_helper
(
cdev
,
buf
,
count
,
&
tp
->
min_period
);
}
static
CLASS_DEVICE_ATTR
(
min_period
,
S_IRUGO
|
S_IWUSR
,
show_spi_transport_min_period
,
store_spi_transport_min_period
);
static
ssize_t
show_spi_host_signalling
(
struct
class_device
*
cdev
,
char
*
buf
)
{
struct
Scsi_Host
*
shost
=
transport_class_to_shost
(
cdev
);
...
...
@@ -642,6 +760,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
{
struct
spi_internal
*
i
=
to_spi_internal
(
sreq
->
sr_host
->
transportt
);
struct
scsi_device
*
sdev
=
sreq
->
sr_device
;
struct
scsi_target
*
starget
=
sdev
->
sdev_target
;
int
len
=
sdev
->
inquiry_len
;
/* first set us up for narrow async */
DV_SET
(
offset
,
0
);
...
...
@@ -655,9 +774,11 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
}
/* test width */
if
(
i
->
f
->
set_width
&&
sdev
->
wdtr
)
{
if
(
i
->
f
->
set_width
&&
s
pi_max_width
(
starget
)
&&
s
dev
->
wdtr
)
{
i
->
f
->
set_width
(
sdev
->
sdev_target
,
1
);
printk
(
"WIDTH IS %d
\n
"
,
spi_max_width
(
starget
));
if
(
spi_dv_device_compare_inquiry
(
sreq
,
buffer
,
buffer
+
len
,
DV_LOOPS
)
...
...
@@ -684,8 +805,8 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
retry:
/* now set up to the maximum */
DV_SET
(
offset
,
255
);
DV_SET
(
period
,
1
);
DV_SET
(
offset
,
spi_max_offset
(
starget
)
);
DV_SET
(
period
,
spi_min_period
(
starget
)
);
if
(
len
==
0
)
{
SPI_PRINTK
(
sdev
->
sdev_target
,
KERN_INFO
,
"Domain Validation skipping write tests
\n
"
);
...
...
@@ -892,6 +1013,16 @@ EXPORT_SYMBOL(spi_display_xfer_agreement);
if (i->f->show_##field) \
count++
#define SETUP_RELATED_ATTRIBUTE(field, rel_field) \
i->private_attrs[count] = class_device_attr_##field; \
if (!i->f->set_##rel_field) { \
i->private_attrs[count].attr.mode = S_IRUGO; \
i->private_attrs[count].store = NULL; \
} \
i->attrs[count] = &i->private_attrs[count]; \
if (i->f->show_##rel_field) \
count++
#define SETUP_HOST_ATTRIBUTE(field) \
i->private_host_attrs[count] = class_device_attr_##field; \
if (!i->f->set_##field) { \
...
...
@@ -975,8 +1106,11 @@ spi_attach_transport(struct spi_function_template *ft)
i
->
f
=
ft
;
SETUP_ATTRIBUTE
(
period
);
SETUP_RELATED_ATTRIBUTE
(
min_period
,
period
);
SETUP_ATTRIBUTE
(
offset
);
SETUP_RELATED_ATTRIBUTE
(
max_offset
,
offset
);
SETUP_ATTRIBUTE
(
width
);
SETUP_RELATED_ATTRIBUTE
(
max_width
,
width
);
SETUP_ATTRIBUTE
(
iu
);
SETUP_ATTRIBUTE
(
dt
);
SETUP_ATTRIBUTE
(
qas
);
...
...
include/scsi/scsi_transport_spi.h
View file @
9636273d
...
...
@@ -27,8 +27,11 @@ struct scsi_transport_template;
struct
spi_transport_attrs
{
int
period
;
/* value in the PPR/SDTR command */
int
min_period
;
int
offset
;
int
max_offset
;
unsigned
int
width
:
1
;
/* 0 - narrow, 1 - wide */
unsigned
int
max_width
:
1
;
unsigned
int
iu
:
1
;
/* Information Units enabled */
unsigned
int
dt
:
1
;
/* DT clocking enabled */
unsigned
int
qas
:
1
;
/* Quick Arbitration and Selection enabled */
...
...
@@ -63,8 +66,11 @@ struct spi_host_attrs {
/* accessor functions */
#define spi_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->period)
#define spi_min_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->min_period)
#define spi_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->offset)
#define spi_max_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->max_offset)
#define spi_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->width)
#define spi_max_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->max_width)
#define spi_iu(x) (((struct spi_transport_attrs *)&(x)->starget_data)->iu)
#define spi_dt(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dt)
#define spi_qas(x) (((struct spi_transport_attrs *)&(x)->starget_data)->qas)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment