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
Kirill Smelkov
linux
Commits
a9386036
Commit
a9386036
authored
Nov 14, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge Radeon driver updates from DRI CVS (add support for
R200 cube map registers)
parent
2c0889e4
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
158 additions
and
26 deletions
+158
-26
drivers/char/drm/drm_sarea.h
drivers/char/drm/drm_sarea.h
+57
-0
drivers/char/drm/radeon.h
drivers/char/drm/radeon.h
+5
-1
drivers/char/drm/radeon_drm.h
drivers/char/drm/radeon_drm.h
+15
-2
drivers/char/drm/radeon_drv.h
drivers/char/drm/radeon_drv.h
+43
-2
drivers/char/drm/radeon_state.c
drivers/char/drm/radeon_state.c
+38
-21
No files found.
drivers/char/drm/drm_sarea.h
0 → 100644
View file @
a9386036
/* sarea.h -- SAREA definitions -*- linux-c -*-
*
* Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Michel Dänzer <michel@daenzer.net>
*/
#ifndef _DRM_SAREA_H_
#define _DRM_SAREA_H_
#define SAREA_MAX_DRAWABLES 256
typedef
struct
_drm_sarea_drawable_t
{
unsigned
int
stamp
;
unsigned
int
flags
;
}
drm_sarea_drawable_t
;
typedef
struct
_dri_sarea_frame_t
{
unsigned
int
x
;
unsigned
int
y
;
unsigned
int
width
;
unsigned
int
height
;
unsigned
int
fullscreen
;
}
drm_sarea_frame_t
;
typedef
struct
_drm_sarea_t
{
/* first thing is always the drm locking structure */
drm_hw_lock_t
lock
;
/* NOT_DONE: Use readers/writer lock for drawable_lock */
drm_hw_lock_t
drawable_lock
;
drm_sarea_drawable_t
drawableTable
[
SAREA_MAX_DRAWABLES
];
drm_sarea_frame_t
frame
;
drm_context_t
dummy_context
;
}
drm_sarea_t
;
#endif
/* _DRM_SAREA_H_ */
drivers/char/drm/radeon.h
View file @
a9386036
...
@@ -51,7 +51,7 @@
...
@@ -51,7 +51,7 @@
#define DRIVER_DATE "20020828"
#define DRIVER_DATE "20020828"
#define DRIVER_MAJOR 1
#define DRIVER_MAJOR 1
#define DRIVER_MINOR
6
#define DRIVER_MINOR
7
#define DRIVER_PATCHLEVEL 0
#define DRIVER_PATCHLEVEL 0
/* Interface history:
/* Interface history:
...
@@ -73,6 +73,10 @@
...
@@ -73,6 +73,10 @@
* Add irq ioctls and irq_active getparam.
* Add irq ioctls and irq_active getparam.
* Add wait command for cmdbuf ioctl
* Add wait command for cmdbuf ioctl
* Add agp offset query for getparam
* Add agp offset query for getparam
* 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5]
* and R200_PP_CUBIC_OFFSET_F1_[0..5].
* Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and
* R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian)
*/
*/
#define DRIVER_IOCTLS \
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
...
...
drivers/char/drm/radeon_drm.h
View file @
a9386036
...
@@ -27,7 +27,7 @@
...
@@ -27,7 +27,7 @@
* Authors:
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
* Gareth Hughes <gareth@valinux.com>
* Keith Whitwell <keith
_whitwell@yahoo
.com>
* Keith Whitwell <keith
@tungstengraphics
.com>
*/
*/
#ifndef __RADEON_DRM_H__
#ifndef __RADEON_DRM_H__
...
@@ -129,7 +129,19 @@
...
@@ -129,7 +129,19 @@
#define R200_EMIT_SE_VTX_STATE_CNTL 58
/* cst/1 */
#define R200_EMIT_SE_VTX_STATE_CNTL 58
/* cst/1 */
#define R200_EMIT_RE_POINTSIZE 59
/* cst/1 */
#define R200_EMIT_RE_POINTSIZE 59
/* cst/1 */
#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60
/* cst/4 */
#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0 60
/* cst/4 */
#define RADEON_MAX_STATE_PACKETS 61
#define R200_EMIT_PP_CUBIC_FACES_0 61
#define R200_EMIT_PP_CUBIC_OFFSETS_0 62
#define R200_EMIT_PP_CUBIC_FACES_1 63
#define R200_EMIT_PP_CUBIC_OFFSETS_1 64
#define R200_EMIT_PP_CUBIC_FACES_2 65
#define R200_EMIT_PP_CUBIC_OFFSETS_2 66
#define R200_EMIT_PP_CUBIC_FACES_3 67
#define R200_EMIT_PP_CUBIC_OFFSETS_3 68
#define R200_EMIT_PP_CUBIC_FACES_4 69
#define R200_EMIT_PP_CUBIC_OFFSETS_4 70
#define R200_EMIT_PP_CUBIC_FACES_5 71
#define R200_EMIT_PP_CUBIC_OFFSETS_5 72
#define RADEON_MAX_STATE_PACKETS 73
/* Commands understood by cmd_buffer ioctl. More can be added but
/* Commands understood by cmd_buffer ioctl. More can be added but
...
@@ -343,6 +355,7 @@ typedef struct {
...
@@ -343,6 +355,7 @@ typedef struct {
int
ctx_owner
;
int
ctx_owner
;
int
pfState
;
/* number of 3d windows (0,1,2ormore) */
int
pfState
;
/* number of 3d windows (0,1,2ormore) */
int
pfCurrentPage
;
/* which buffer is being displayed? */
int
pfCurrentPage
;
/* which buffer is being displayed? */
int
crtc2_base
;
/* CRTC2 frame offset */
}
drm_radeon_sarea_t
;
}
drm_radeon_sarea_t
;
...
...
drivers/char/drm/radeon_drv.h
View file @
a9386036
...
@@ -109,8 +109,6 @@ typedef struct drm_radeon_private {
...
@@ -109,8 +109,6 @@ typedef struct drm_radeon_private {
int
do_boxes
;
int
do_boxes
;
int
page_flipping
;
int
page_flipping
;
int
current_page
;
int
current_page
;
u32
crtc_offset
;
u32
crtc_offset_cntl
;
u32
color_fmt
;
u32
color_fmt
;
unsigned
int
front_offset
;
unsigned
int
front_offset
;
...
@@ -230,6 +228,8 @@ extern int radeon_emit_irq(drm_device_t *dev);
...
@@ -230,6 +228,8 @@ extern int radeon_emit_irq(drm_device_t *dev);
#define RADEON_CRTC_OFFSET_CNTL 0x0228
#define RADEON_CRTC_OFFSET_CNTL 0x0228
# define RADEON_CRTC_TILE_EN (1 << 15)
# define RADEON_CRTC_TILE_EN (1 << 15)
# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16)
# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16)
#define RADEON_CRTC2_OFFSET 0x0324
#define RADEON_CRTC2_OFFSET_CNTL 0x0328
#define RADEON_RB3D_COLORPITCH 0x1c48
#define RADEON_RB3D_COLORPITCH 0x1c48
...
@@ -574,6 +574,9 @@ extern int radeon_emit_irq(drm_device_t *dev);
...
@@ -574,6 +574,9 @@ extern int radeon_emit_irq(drm_device_t *dev);
#define RADEON_TXFORMAT_RGBA8888 7
#define RADEON_TXFORMAT_RGBA8888 7
#define RADEON_TXFORMAT_VYUY422 10
#define RADEON_TXFORMAT_VYUY422 10
#define RADEON_TXFORMAT_YVYU422 11
#define RADEON_TXFORMAT_YVYU422 11
#define RADEON_TXFORMAT_DXT1 12
#define RADEON_TXFORMAT_DXT23 14
#define RADEON_TXFORMAT_DXT45 15
#define R200_PP_TXCBLEND_0 0x2f00
#define R200_PP_TXCBLEND_0 0x2f00
#define R200_PP_TXCBLEND_1 0x2f10
#define R200_PP_TXCBLEND_1 0x2f10
...
@@ -602,6 +605,44 @@ extern int radeon_emit_irq(drm_device_t *dev);
...
@@ -602,6 +605,44 @@ extern int radeon_emit_irq(drm_device_t *dev);
#define R200_PP_TXOFFSET_2 0x2d30
#define R200_PP_TXOFFSET_2 0x2d30
#define R200_PP_TXOFFSET_1 0x2d18
#define R200_PP_TXOFFSET_1 0x2d18
#define R200_PP_TXOFFSET_0 0x2d00
#define R200_PP_TXOFFSET_0 0x2d00
#define R200_PP_CUBIC_FACES_0 0x2c18
#define R200_PP_CUBIC_FACES_1 0x2c38
#define R200_PP_CUBIC_FACES_2 0x2c58
#define R200_PP_CUBIC_FACES_3 0x2c78
#define R200_PP_CUBIC_FACES_4 0x2c98
#define R200_PP_CUBIC_FACES_5 0x2cb8
#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04
#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08
#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c
#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10
#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14
#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c
#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20
#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24
#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28
#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c
#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34
#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38
#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c
#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40
#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44
#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c
#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50
#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54
#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58
#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c
#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64
#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68
#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c
#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70
#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74
#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c
#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80
#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84
#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88
#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c
#define R200_RE_AUX_SCISSOR_CNTL 0x26f0
#define R200_RE_AUX_SCISSOR_CNTL 0x26f0
#define R200_SE_VTE_CNTL 0x20b0
#define R200_SE_VTE_CNTL 0x20b0
#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250
#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250
...
...
drivers/char/drm/radeon_state.c
View file @
a9386036
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
#include "radeon.h"
#include "radeon.h"
#include "drmP.h"
#include "drmP.h"
#include "drm.h"
#include "drm.h"
#include "drm_sarea.h"
#include "radeon_drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
#include "radeon_drv.h"
...
@@ -279,6 +280,18 @@ static struct {
...
@@ -279,6 +280,18 @@ static struct {
{
R200_SE_VTX_STATE_CNTL
,
1
,
"R200_SE_VTX_STATE_CNTL"
},
{
R200_SE_VTX_STATE_CNTL
,
1
,
"R200_SE_VTX_STATE_CNTL"
},
{
R200_RE_POINTSIZE
,
1
,
"R200_RE_POINTSIZE"
},
{
R200_RE_POINTSIZE
,
1
,
"R200_RE_POINTSIZE"
},
{
R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0
,
4
,
"R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"
},
{
R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0
,
4
,
"R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"
},
{
R200_PP_CUBIC_FACES_0
,
1
,
"R200_PP_CUBIC_FACES_0"
},
/* 61 */
{
R200_PP_CUBIC_OFFSET_F1_0
,
5
,
"R200_PP_CUBIC_OFFSET_F1_0"
},
/* 62 */
{
R200_PP_CUBIC_FACES_1
,
1
,
"R200_PP_CUBIC_FACES_1"
},
{
R200_PP_CUBIC_OFFSET_F1_1
,
5
,
"R200_PP_CUBIC_OFFSET_F1_1"
},
{
R200_PP_CUBIC_FACES_2
,
1
,
"R200_PP_CUBIC_FACES_2"
},
{
R200_PP_CUBIC_OFFSET_F1_2
,
5
,
"R200_PP_CUBIC_OFFSET_F1_2"
},
{
R200_PP_CUBIC_FACES_3
,
1
,
"R200_PP_CUBIC_FACES_3"
},
{
R200_PP_CUBIC_OFFSET_F1_3
,
5
,
"R200_PP_CUBIC_OFFSET_F1_3"
},
{
R200_PP_CUBIC_FACES_4
,
1
,
"R200_PP_CUBIC_FACES_4"
},
{
R200_PP_CUBIC_OFFSET_F1_4
,
5
,
"R200_PP_CUBIC_OFFSET_F1_4"
},
{
R200_PP_CUBIC_FACES_5
,
1
,
"R200_PP_CUBIC_FACES_5"
},
{
R200_PP_CUBIC_OFFSET_F1_5
,
5
,
"R200_PP_CUBIC_OFFSET_F1_5"
},
};
};
...
@@ -791,6 +804,9 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev )
...
@@ -791,6 +804,9 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev )
static
void
radeon_cp_dispatch_flip
(
drm_device_t
*
dev
)
static
void
radeon_cp_dispatch_flip
(
drm_device_t
*
dev
)
{
{
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
drm_radeon_private_t
*
dev_priv
=
dev
->
dev_private
;
drm_sarea_t
*
sarea
=
(
drm_sarea_t
*
)
dev_priv
->
sarea
->
handle
;
int
offset
=
(
dev_priv
->
current_page
==
1
)
?
dev_priv
->
front_offset
:
dev_priv
->
back_offset
;
RING_LOCALS
;
RING_LOCALS
;
DRM_DEBUG
(
"%s: page=%d pfCurrentPage=%d
\n
"
,
DRM_DEBUG
(
"%s: page=%d pfCurrentPage=%d
\n
"
,
__FUNCTION__
,
__FUNCTION__
,
...
@@ -804,18 +820,17 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
...
@@ -804,18 +820,17 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
radeon_cp_performance_boxes
(
dev_priv
);
radeon_cp_performance_boxes
(
dev_priv
);
}
}
BEGIN_RING
(
4
);
/* Update the frame offsets for both CRTCs
*/
BEGIN_RING
(
6
);
RADEON_WAIT_UNTIL_3D_IDLE
();
RADEON_WAIT_UNTIL_3D_IDLE
();
OUT_RING
(
CP_PACKET0
(
RADEON_CRTC_OFFSET
,
0
)
);
OUT_RING_REG
(
RADEON_CRTC_OFFSET
,
(
(
sarea
->
frame
.
y
*
dev_priv
->
front_pitch
+
sarea
->
frame
.
x
if
(
dev_priv
->
current_page
==
0
)
{
*
(
dev_priv
->
color_fmt
-
2
)
)
&
~
7
)
OUT_RING
(
dev_priv
->
back_offset
);
+
offset
);
dev_priv
->
current_page
=
1
;
OUT_RING_REG
(
RADEON_CRTC2_OFFSET
,
dev_priv
->
sarea_priv
->
crtc2_base
}
else
{
+
offset
);
OUT_RING
(
dev_priv
->
front_offset
);
dev_priv
->
current_page
=
0
;
}
ADVANCE_RING
();
ADVANCE_RING
();
...
@@ -824,7 +839,8 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
...
@@ -824,7 +839,8 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
* performing the swapbuffer ioctl.
* performing the swapbuffer ioctl.
*/
*/
dev_priv
->
sarea_priv
->
last_frame
++
;
dev_priv
->
sarea_priv
->
last_frame
++
;
dev_priv
->
sarea_priv
->
pfCurrentPage
=
dev_priv
->
current_page
;
dev_priv
->
sarea_priv
->
pfCurrentPage
=
dev_priv
->
current_page
=
1
-
dev_priv
->
current_page
;
BEGIN_RING
(
2
);
BEGIN_RING
(
2
);
...
@@ -1292,12 +1308,12 @@ static int radeon_do_init_pageflip( drm_device_t *dev )
...
@@ -1292,12 +1308,12 @@ static int radeon_do_init_pageflip( drm_device_t *dev )
DRM_DEBUG
(
"
\n
"
);
DRM_DEBUG
(
"
\n
"
);
dev_priv
->
crtc_offset_cntl
=
RADEON_READ
(
RADEON_CRTC_OFFSET_CNTL
);
BEGIN_RING
(
6
);
BEGIN_RING
(
4
);
RADEON_WAIT_UNTIL_3D_IDLE
();
RADEON_WAIT_UNTIL_3D_IDLE
();
OUT_RING
(
CP_PACKET0
(
RADEON_CRTC_OFFSET_CNTL
,
0
)
);
OUT_RING
(
CP_PACKET0
(
RADEON_CRTC_OFFSET_CNTL
,
0
)
);
OUT_RING
(
dev_priv
->
crtc_offset_cntl
|
RADEON_CRTC_OFFSET_FLIP_CNTL
);
OUT_RING
(
RADEON_READ
(
RADEON_CRTC_OFFSET_CNTL
)
|
RADEON_CRTC_OFFSET_FLIP_CNTL
);
OUT_RING
(
CP_PACKET0
(
RADEON_CRTC2_OFFSET_CNTL
,
0
)
);
OUT_RING
(
RADEON_READ
(
RADEON_CRTC2_OFFSET_CNTL
)
|
RADEON_CRTC_OFFSET_FLIP_CNTL
);
ADVANCE_RING
();
ADVANCE_RING
();
dev_priv
->
page_flipping
=
1
;
dev_priv
->
page_flipping
=
1
;
...
@@ -1318,10 +1334,6 @@ int radeon_do_cleanup_pageflip( drm_device_t *dev )
...
@@ -1318,10 +1334,6 @@ int radeon_do_cleanup_pageflip( drm_device_t *dev )
if
(
dev_priv
->
current_page
!=
0
)
if
(
dev_priv
->
current_page
!=
0
)
radeon_cp_dispatch_flip
(
dev
);
radeon_cp_dispatch_flip
(
dev
);
/* FIXME: If the X server changes screen resolution, it
* clobbers the value of RADEON_CRTC_OFFSET_CNTL, above,
* leading to a flashing efect.
*/
dev_priv
->
page_flipping
=
0
;
dev_priv
->
page_flipping
=
0
;
return
0
;
return
0
;
}
}
...
@@ -1792,11 +1804,16 @@ static int radeon_emit_packets(
...
@@ -1792,11 +1804,16 @@ static int radeon_emit_packets(
drm_radeon_cmd_buffer_t
*
cmdbuf
)
drm_radeon_cmd_buffer_t
*
cmdbuf
)
{
{
int
id
=
(
int
)
header
.
packet
.
packet_id
;
int
id
=
(
int
)
header
.
packet
.
packet_id
;
int
sz
=
packet
[
id
].
len
;
int
sz
,
reg
;
int
reg
=
packet
[
id
].
start
;
int
*
data
=
(
int
*
)
cmdbuf
->
buf
;
int
*
data
=
(
int
*
)
cmdbuf
->
buf
;
RING_LOCALS
;
RING_LOCALS
;
if
(
id
>=
RADEON_MAX_STATE_PACKETS
)
return
DRM_ERR
(
EINVAL
);
sz
=
packet
[
id
].
len
;
reg
=
packet
[
id
].
start
;
if
(
sz
*
sizeof
(
int
)
>
cmdbuf
->
bufsz
)
if
(
sz
*
sizeof
(
int
)
>
cmdbuf
->
bufsz
)
return
DRM_ERR
(
EINVAL
);
return
DRM_ERR
(
EINVAL
);
...
...
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