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
7da60b9c
Commit
7da60b9c
authored
Mar 21, 2003
by
Alan Cox
Committed by
Linus Torvalds
Mar 21, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] Remove i2o pci abstractions
parent
fe015954
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
409 additions
and
175 deletions
+409
-175
drivers/message/i2o/i2o_block.c
drivers/message/i2o/i2o_block.c
+3
-3
drivers/message/i2o/i2o_core.c
drivers/message/i2o/i2o_core.c
+335
-87
drivers/message/i2o/i2o_pci.c
drivers/message/i2o/i2o_pci.c
+0
-3
drivers/message/i2o/i2o_proc.c
drivers/message/i2o/i2o_proc.c
+62
-44
include/linux/i2o.h
include/linux/i2o.h
+9
-38
No files found.
drivers/message/i2o/i2o_block.c
View file @
7da60b9c
...
@@ -754,7 +754,7 @@ static int i2ob_evt(void *dummy)
...
@@ -754,7 +754,7 @@ static int i2ob_evt(void *dummy)
* hit the fan big time. The card seems to recover but loses
* hit the fan big time. The card seems to recover but loses
* the pending writes. Deeply ungood except for testing fsck
* the pending writes. Deeply ungood except for testing fsck
*/
*/
if
(
i2ob_dev
[
unit
].
i2odev
->
controller
->
bus
.
pci
.
promise
)
if
(
i2ob_dev
[
unit
].
i2odev
->
controller
->
promise
)
panic
(
"I2O controller firmware failed. Reboot and force a filesystem check.
\n
"
);
panic
(
"I2O controller firmware failed. Reboot and force a filesystem check.
\n
"
);
default:
default:
printk
(
KERN_INFO
"%s: Received event 0x%X we didn't register for
\n
"
printk
(
KERN_INFO
"%s: Received event 0x%X we didn't register for
\n
"
...
@@ -1140,10 +1140,10 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
...
@@ -1140,10 +1140,10 @@ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, i
if
(
d
->
controller
->
battery
==
0
)
if
(
d
->
controller
->
battery
==
0
)
i2ob_dev
[
i
].
wcache
=
CACHE_WRITETHROUGH
;
i2ob_dev
[
i
].
wcache
=
CACHE_WRITETHROUGH
;
if
(
d
->
controller
->
type
==
I2O_TYPE_PCI
&&
d
->
controller
->
bus
.
pci
.
promise
)
if
(
d
->
controller
->
promise
)
i2ob_dev
[
i
].
wcache
=
CACHE_WRITETHROUGH
;
i2ob_dev
[
i
].
wcache
=
CACHE_WRITETHROUGH
;
if
(
d
->
controller
->
type
==
I2O_TYPE_PCI
&&
d
->
controller
->
bus
.
pci
.
short_req
)
if
(
d
->
controller
->
short_req
)
{
{
blk_queue_max_sectors
(
q
,
8
);
blk_queue_max_sectors
(
q
,
8
);
blk_queue_max_phys_segments
(
q
,
8
);
blk_queue_max_phys_segments
(
q
,
8
);
...
...
drivers/message/i2o/i2o_core.c
View file @
7da60b9c
...
@@ -50,6 +50,9 @@
...
@@ -50,6 +50,9 @@
#include <asm/io.h>
#include <asm/io.h>
#include <linux/reboot.h>
#include <linux/reboot.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif // CONFIG_MTRR
#include "i2o_lan.h"
#include "i2o_lan.h"
...
@@ -103,6 +106,8 @@ static int i2o_dyn_lct(void *);
...
@@ -103,6 +106,8 @@ static int i2o_dyn_lct(void *);
void
i2o_report_controller_unit
(
struct
i2o_controller
*
,
struct
i2o_device
*
);
void
i2o_report_controller_unit
(
struct
i2o_controller
*
,
struct
i2o_device
*
);
static
void
i2o_pci_dispose
(
struct
i2o_controller
*
c
);
/*
/*
* I2O System Table. Contains information about
* I2O System Table. Contains information about
* all the IOPs in the system. Used to inform IOPs
* all the IOPs in the system. Used to inform IOPs
...
@@ -206,7 +211,6 @@ static struct notifier_block i2o_reboot_notifier =
...
@@ -206,7 +211,6 @@ static struct notifier_block i2o_reboot_notifier =
*/
*/
static
int
verbose
;
static
int
verbose
;
MODULE_PARM
(
verbose
,
"i"
);
/*
/*
* I2O Core reply handler
* I2O Core reply handler
...
@@ -549,7 +553,8 @@ int i2o_delete_controller(struct i2o_controller *c)
...
@@ -549,7 +553,8 @@ int i2o_delete_controller(struct i2o_controller *c)
if
(
__i2o_delete_device
(
c
->
devices
)
<
0
)
if
(
__i2o_delete_device
(
c
->
devices
)
<
0
)
{
{
/* Shouldnt happen */
/* Shouldnt happen */
c
->
bus_disable
(
c
);
I2O_IRQ_WRITE32
(
c
,
0xFFFFFFFF
);
c
->
enabled
=
0
;
up
(
&
i2o_configuration_lock
);
up
(
&
i2o_configuration_lock
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
...
@@ -584,7 +589,7 @@ int i2o_delete_controller(struct i2o_controller *c)
...
@@ -584,7 +589,7 @@ int i2o_delete_controller(struct i2o_controller *c)
i2o_reset_controller
(
c
);
i2o_reset_controller
(
c
);
/* Release IRQ */
/* Release IRQ */
c
->
destructor
(
c
);
i2o_pci_dispose
(
c
);
*
p
=
c
->
next
;
*
p
=
c
->
next
;
up
(
&
i2o_configuration_lock
);
up
(
&
i2o_configuration_lock
);
...
@@ -1651,7 +1656,7 @@ static int i2o_reset_controller(struct i2o_controller *c)
...
@@ -1651,7 +1656,7 @@ static int i2o_reset_controller(struct i2o_controller *c)
for
(
iop
=
i2o_controller_chain
;
iop
;
iop
=
iop
->
next
)
for
(
iop
=
i2o_controller_chain
;
iop
;
iop
=
iop
->
next
)
{
{
if
(
iop
->
type
!=
I2O_TYPE_PCI
||
!
iop
->
bus
.
pci
.
dpt
)
if
(
!
iop
->
dpt
)
i2o_quiesce_controller
(
iop
);
i2o_quiesce_controller
(
iop
);
}
}
...
@@ -1911,65 +1916,62 @@ static int i2o_systab_send(struct i2o_controller *iop)
...
@@ -1911,65 +1916,62 @@ static int i2o_systab_send(struct i2o_controller *iop)
u32
msg
[
12
];
u32
msg
[
12
];
dma_addr_t
sys_tbl_phys
;
dma_addr_t
sys_tbl_phys
;
int
ret
;
int
ret
;
struct
resource
*
root
;
u32
*
privbuf
=
kmalloc
(
16
,
GFP_KERNEL
);
u32
*
privbuf
=
kmalloc
(
16
,
GFP_KERNEL
);
if
(
privbuf
==
NULL
)
if
(
privbuf
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
if
(
iop
->
type
==
I2O_TYPE_PCI
)
{
struct
resource
*
root
;
if
(
iop
->
status_block
->
current_mem_size
<
iop
->
status_block
->
desired_mem_size
)
if
(
iop
->
status_block
->
current_mem_size
<
iop
->
status_block
->
desired_mem_size
)
{
struct
resource
*
res
=
&
iop
->
mem_resource
;
res
->
name
=
iop
->
pdev
->
bus
->
name
;
res
->
flags
=
IORESOURCE_MEM
;
res
->
start
=
0
;
res
->
end
=
0
;
printk
(
"%s: requires private memory resources.
\n
"
,
iop
->
name
);
root
=
pci_find_parent_resource
(
iop
->
pdev
,
res
);
if
(
root
==
NULL
)
printk
(
"Can't find parent resource!
\n
"
);
if
(
root
&&
allocate_resource
(
root
,
res
,
iop
->
status_block
->
desired_mem_size
,
iop
->
status_block
->
desired_mem_size
,
iop
->
status_block
->
desired_mem_size
,
1
<<
20
,
/* Unspecified, so use 1Mb and play safe */
NULL
,
NULL
)
>=
0
)
{
{
struct
resource
*
res
=
&
iop
->
mem_resource
;
iop
->
mem_alloc
=
1
;
res
->
name
=
iop
->
pdev
->
bus
->
name
;
iop
->
status_block
->
current_mem_size
=
1
+
res
->
end
-
res
->
start
;
res
->
flags
=
IORESOURCE_MEM
;
iop
->
status_block
->
current_mem_base
=
res
->
start
;
res
->
start
=
0
;
printk
(
KERN_INFO
"%s: allocated %ld bytes of PCI memory at 0x%08lX.
\n
"
,
res
->
end
=
0
;
iop
->
name
,
1
+
res
->
end
-
res
->
start
,
res
->
start
);
printk
(
"%s: requires private memory resources.
\n
"
,
iop
->
name
);
root
=
pci_find_parent_resource
(
iop
->
pdev
,
res
);
if
(
root
==
NULL
)
printk
(
"Can't find parent resource!
\n
"
);
if
(
root
&&
allocate_resource
(
root
,
res
,
iop
->
status_block
->
desired_mem_size
,
iop
->
status_block
->
desired_mem_size
,
iop
->
status_block
->
desired_mem_size
,
1
<<
20
,
/* Unspecified, so use 1Mb and play safe */
NULL
,
NULL
)
>=
0
)
{
iop
->
mem_alloc
=
1
;
iop
->
status_block
->
current_mem_size
=
1
+
res
->
end
-
res
->
start
;
iop
->
status_block
->
current_mem_base
=
res
->
start
;
printk
(
KERN_INFO
"%s: allocated %ld bytes of PCI memory at 0x%08lX.
\n
"
,
iop
->
name
,
1
+
res
->
end
-
res
->
start
,
res
->
start
);
}
}
}
if
(
iop
->
status_block
->
current_io_size
<
iop
->
status_block
->
desired_io_size
)
}
if
(
iop
->
status_block
->
current_io_size
<
iop
->
status_block
->
desired_io_size
)
{
struct
resource
*
res
=
&
iop
->
io_resource
;
res
->
name
=
iop
->
pdev
->
bus
->
name
;
res
->
flags
=
IORESOURCE_IO
;
res
->
start
=
0
;
res
->
end
=
0
;
printk
(
"%s: requires private memory resources.
\n
"
,
iop
->
name
);
root
=
pci_find_parent_resource
(
iop
->
pdev
,
res
);
if
(
root
==
NULL
)
printk
(
"Can't find parent resource!
\n
"
);
if
(
root
&&
allocate_resource
(
root
,
res
,
iop
->
status_block
->
desired_io_size
,
iop
->
status_block
->
desired_io_size
,
iop
->
status_block
->
desired_io_size
,
1
<<
20
,
/* Unspecified, so use 1Mb and play safe */
NULL
,
NULL
)
>=
0
)
{
{
struct
resource
*
res
=
&
iop
->
io_resource
;
iop
->
io_alloc
=
1
;
res
->
name
=
iop
->
pdev
->
bus
->
name
;
iop
->
status_block
->
current_io_size
=
1
+
res
->
end
-
res
->
start
;
res
->
flags
=
IORESOURCE_IO
;
iop
->
status_block
->
current_mem_base
=
res
->
start
;
res
->
start
=
0
;
printk
(
KERN_INFO
"%s: allocated %ld bytes of PCI I/O at 0x%08lX.
\n
"
,
res
->
end
=
0
;
iop
->
name
,
1
+
res
->
end
-
res
->
start
,
res
->
start
);
printk
(
"%s: requires private memory resources.
\n
"
,
iop
->
name
);
root
=
pci_find_parent_resource
(
iop
->
pdev
,
res
);
if
(
root
==
NULL
)
printk
(
"Can't find parent resource!
\n
"
);
if
(
root
&&
allocate_resource
(
root
,
res
,
iop
->
status_block
->
desired_io_size
,
iop
->
status_block
->
desired_io_size
,
iop
->
status_block
->
desired_io_size
,
1
<<
20
,
/* Unspecified, so use 1Mb and play safe */
NULL
,
NULL
)
>=
0
)
{
iop
->
io_alloc
=
1
;
iop
->
status_block
->
current_io_size
=
1
+
res
->
end
-
res
->
start
;
iop
->
status_block
->
current_mem_base
=
res
->
start
;
printk
(
KERN_INFO
"%s: allocated %ld bytes of PCI I/O at 0x%08lX.
\n
"
,
iop
->
name
,
1
+
res
->
end
-
res
->
start
,
res
->
start
);
}
}
}
}
}
else
else
...
@@ -3427,48 +3429,256 @@ static int i2o_reboot_event(struct notifier_block *n, unsigned long code, void
...
@@ -3427,48 +3429,256 @@ static int i2o_reboot_event(struct notifier_block *n, unsigned long code, void
}
}
EXPORT_SYMBOL
(
i2o_controller_chain
);
EXPORT_SYMBOL
(
i2o_num_controllers
);
EXPORT_SYMBOL
(
i2o_find_controller
);
EXPORT_SYMBOL
(
i2o_unlock_controller
);
EXPORT_SYMBOL
(
i2o_status_get
);
EXPORT_SYMBOL
(
i2o_install_handler
);
EXPORT_SYMBOL
(
i2o_remove_handler
);
EXPORT_SYMBOL
(
i2o_install_controller
);
/**
EXPORT_SYMBOL
(
i2o_delete_controller
);
* i2o_pci_dispose - Free bus specific resources
EXPORT_SYMBOL
(
i2o_run_queue
);
* @c: I2O controller
*
* Disable interrupts and then free interrupt, I/O and mtrr resources
* used by this controller. Called by the I2O core on unload.
*/
static
void
i2o_pci_dispose
(
struct
i2o_controller
*
c
)
{
I2O_IRQ_WRITE32
(
c
,
0xFFFFFFFF
);
if
(
c
->
irq
>
0
)
free_irq
(
c
->
irq
,
c
);
iounmap
(((
u8
*
)
c
->
post_port
)
-
0x40
);
#ifdef CONFIG_MTRR
if
(
c
->
mtrr_reg0
>
0
)
mtrr_del
(
c
->
mtrr_reg0
,
0
,
0
);
if
(
c
->
mtrr_reg1
>
0
)
mtrr_del
(
c
->
mtrr_reg1
,
0
,
0
);
#endif
}
EXPORT_SYMBOL
(
i2o_claim_device
);
/**
EXPORT_SYMBOL
(
i2o_release_device
);
* i2o_pci_interrupt - Bus specific interrupt handler
EXPORT_SYMBOL
(
i2o_device_notify_on
);
* @irq: interrupt line
EXPORT_SYMBOL
(
i2o_device_notify_off
);
* @dev_id: cookie
*
* Handle an interrupt from a PCI based I2O controller. This turns out
* to be rather simple. We keep the controller pointer in the cookie.
*/
static
void
i2o_pci_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
r
)
{
struct
i2o_controller
*
c
=
dev_id
;
i2o_run_queue
(
c
);
}
EXPORT_SYMBOL
(
i2o_post_this
);
/**
EXPORT_SYMBOL
(
i2o_post_wait
);
* i2o_pci_install - Install a PCI i2o controller
EXPORT_SYMBOL
(
i2o_post_wait_mem
);
* @dev: PCI device of the I2O controller
*
* Install a PCI (or in theory AGP) i2o controller. Devices are
* initialized, configured and registered with the i2o core subsystem. Be
* very careful with ordering. There may be pending interrupts.
*
* To Do: Add support for polled controllers
*/
EXPORT_SYMBOL
(
i2o_query_scalar
);
int
__init
i2o_pci_install
(
struct
pci_dev
*
dev
)
EXPORT_SYMBOL
(
i2o_set_scalar
);
{
EXPORT_SYMBOL
(
i2o_query_table
);
struct
i2o_controller
*
c
=
kmalloc
(
sizeof
(
struct
i2o_controller
),
EXPORT_SYMBOL
(
i2o_clear_table
);
GFP_KERNEL
);
EXPORT_SYMBOL
(
i2o_row_add_table
);
unsigned
long
mem
;
EXPORT_SYMBOL
(
i2o_issue_params
);
u32
memptr
=
0
;
u32
size
;
int
i
;
EXPORT_SYMBOL
(
i2o_event_register
);
if
(
c
==
NULL
)
EXPORT_SYMBOL
(
i2o_event_ack
);
{
printk
(
KERN_ERR
"i2o: Insufficient memory to add controller.
\n
"
);
return
-
ENOMEM
;
}
memset
(
c
,
0
,
sizeof
(
*
c
));
EXPORT_SYMBOL
(
i2o_report_status
);
for
(
i
=
0
;
i
<
6
;
i
++
)
EXPORT_SYMBOL
(
i2o_dump_message
);
{
/* Skip I/O spaces */
if
(
!
(
pci_resource_flags
(
dev
,
i
)
&
IORESOURCE_IO
))
{
memptr
=
pci_resource_start
(
dev
,
i
);
break
;
}
}
if
(
i
==
6
)
{
printk
(
KERN_ERR
"i2o: I2O controller has no memory regions defined.
\n
"
);
kfree
(
c
);
return
-
EINVAL
;
}
size
=
dev
->
resource
[
i
].
end
-
dev
->
resource
[
i
].
start
+
1
;
/* Map the I2O controller */
printk
(
KERN_INFO
"i2o: PCI I2O controller at 0x%08X size=%d
\n
"
,
memptr
,
size
);
mem
=
(
unsigned
long
)
ioremap
(
memptr
,
size
);
if
(
mem
==
0
)
{
printk
(
KERN_ERR
"i2o: Unable to map controller.
\n
"
);
kfree
(
c
);
return
-
EINVAL
;
}
EXPORT_SYMBOL
(
i2o_get_class_name
);
c
->
irq
=
-
1
;
c
->
dpt
=
0
;
c
->
short_req
=
0
;
c
->
pdev
=
dev
;
EXPORT_SYMBOL_GPL
(
i2o_sys_init
);
c
->
irq_mask
=
mem
+
0x34
;
c
->
post_port
=
mem
+
0x40
;
c
->
reply_port
=
mem
+
0x44
;
MODULE_AUTHOR
(
"Red Hat Software"
);
c
->
mem_phys
=
memptr
;
MODULE_DESCRIPTION
(
"I2O Core"
);
c
->
mem_offset
=
mem
;
MODULE_LICENSE
(
"GPL"
);
/*
* Cards that fall apart if you hit them with large I/O
* loads...
*/
if
(
dev
->
vendor
==
PCI_VENDOR_ID_NCR
&&
dev
->
device
==
0x0630
)
{
c
->
short_req
=
1
;
printk
(
KERN_INFO
"I2O: Symbios FC920 workarounds activated.
\n
"
);
}
if
(
dev
->
subsystem_vendor
==
PCI_VENDOR_ID_PROMISE
)
{
c
->
promise
=
1
;
printk
(
KERN_INFO
"I2O: Promise workarounds activated.
\n
"
);
}
/*
* Cards that go bananas if you quiesce them before you reset
* them
*/
if
(
dev
->
vendor
==
PCI_VENDOR_ID_DPT
)
c
->
dpt
=
1
;
/*
* Enable Write Combining MTRR for IOP's memory region
*/
#ifdef CONFIG_MTRR
c
->
mtrr_reg0
=
mtrr_add
(
c
->
mem_phys
,
size
,
MTRR_TYPE_WRCOMB
,
1
);
/*
* If it is an INTEL i960 I/O processor then set the first 64K to
* Uncacheable since the region contains the Messaging unit which
* shouldn't be cached.
*/
c
->
mtrr_reg1
=
-
1
;
if
(
dev
->
vendor
==
PCI_VENDOR_ID_INTEL
||
dev
->
vendor
==
PCI_VENDOR_ID_DPT
)
{
printk
(
KERN_INFO
"I2O: MTRR workaround for Intel i960 processor
\n
"
);
c
->
mtrr_reg1
=
mtrr_add
(
c
->
mem_phys
,
65536
,
MTRR_TYPE_UNCACHABLE
,
1
);
if
(
c
->
mtrr_reg1
<
0
)
{
printk
(
KERN_INFO
"i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE
\n
"
);
mtrr_del
(
c
->
mtrr_reg0
,
c
->
mem_phys
,
size
);
c
->
mtrr_reg0
=
-
1
;
}
}
#endif
I2O_IRQ_WRITE32
(
c
,
0xFFFFFFFF
);
i
=
i2o_install_controller
(
c
);
if
(
i
<
0
)
{
printk
(
KERN_ERR
"i2o: Unable to install controller.
\n
"
);
kfree
(
c
);
iounmap
((
void
*
)
mem
);
return
i
;
}
c
->
irq
=
dev
->
irq
;
if
(
c
->
irq
)
{
i
=
request_irq
(
dev
->
irq
,
i2o_pci_interrupt
,
SA_SHIRQ
,
c
->
name
,
c
);
if
(
i
<
0
)
{
printk
(
KERN_ERR
"%s: unable to allocate interrupt %d.
\n
"
,
c
->
name
,
dev
->
irq
);
c
->
irq
=
-
1
;
i2o_delete_controller
(
c
);
iounmap
((
void
*
)
mem
);
return
-
EBUSY
;
}
}
printk
(
KERN_INFO
"%s: Installed at IRQ%d
\n
"
,
c
->
name
,
dev
->
irq
);
I2O_IRQ_WRITE32
(
c
,
0x0
);
c
->
enabled
=
1
;
return
0
;
}
static
int
dpt
;
/**
* i2o_pci_scan - Scan the pci bus for controllers
*
* Scan the PCI devices on the system looking for any device which is a
* memory of the Intelligent, I2O class. We attempt to set up each such device
* and register it with the core.
*
* Returns the number of controllers registered
*
* Note; Do not change this to a hot plug interface. I2O 1.5 itself
* does not support hot plugging.
*/
int
__init
i2o_pci_scan
(
void
)
{
struct
pci_dev
*
dev
;
int
count
=
0
;
printk
(
KERN_INFO
"i2o: Checking for PCI I2O controllers...
\n
"
);
pci_for_each_dev
(
dev
)
{
if
((
dev
->
class
>>
8
)
!=
PCI_CLASS_INTELLIGENT_I2O
)
continue
;
if
(
dev
->
vendor
==
PCI_VENDOR_ID_DPT
&&
!
dpt
)
{
if
(
dev
->
device
==
0xA501
||
dev
->
device
==
0xA511
)
{
printk
(
KERN_INFO
"i2o: Skipping Adaptec/DPT I2O raid with preferred native driver.
\n
"
);
continue
;
}
}
if
((
dev
->
class
&
0xFF
)
>
1
)
{
printk
(
KERN_INFO
"i2o: I2O Controller found but does not support I2O 1.5 (skipping).
\n
"
);
continue
;
}
if
(
pci_enable_device
(
dev
))
continue
;
printk
(
KERN_INFO
"i2o: I2O controller on bus %d at %d.
\n
"
,
dev
->
bus
->
number
,
dev
->
devfn
);
if
(
pci_set_dma_mask
(
dev
,
0xffffffff
))
{
printk
(
KERN_WARNING
"I2O controller on bus %d at %d : No suitable DMA available
\n
"
,
dev
->
bus
->
number
,
dev
->
devfn
);
continue
;
}
pci_set_master
(
dev
);
if
(
i2o_pci_install
(
dev
)
==
0
)
count
++
;
}
if
(
count
)
printk
(
KERN_INFO
"i2o: %d I2O controller%s found and installed.
\n
"
,
count
,
count
==
1
?
""
:
"s"
);
return
count
?
count
:-
ENODEV
;
}
static
int
i2o_core_init
(
void
)
static
int
i2o_core_init
(
void
)
{
{
...
@@ -3496,6 +3706,7 @@ static int i2o_core_init(void)
...
@@ -3496,6 +3706,7 @@ static int i2o_core_init(void)
else
else
printk
(
KERN_INFO
"I2O: Event thread created as pid %d
\n
"
,
evt_pid
);
printk
(
KERN_INFO
"I2O: Event thread created as pid %d
\n
"
,
evt_pid
);
i2o_pci_scan
();
if
(
i2o_num_controllers
)
if
(
i2o_num_controllers
)
i2o_sys_init
();
i2o_sys_init
();
...
@@ -3532,3 +3743,40 @@ static void i2o_core_exit(void)
...
@@ -3532,3 +3743,40 @@ static void i2o_core_exit(void)
module_init
(
i2o_core_init
);
module_init
(
i2o_core_init
);
module_exit
(
i2o_core_exit
);
module_exit
(
i2o_core_exit
);
MODULE_PARM
(
dpt
,
"i"
);
MODULE_PARM_DESC
(
dpt
,
"Set this if you want to drive DPT cards normally handled by dpt_i2o"
);
MODULE_PARM
(
verbose
,
"i"
);
MODULE_PARM_DESC
(
verbose
,
"Verbose diagnostics"
);
MODULE_AUTHOR
(
"Red Hat Software"
);
MODULE_DESCRIPTION
(
"I2O Core"
);
MODULE_LICENSE
(
"GPL"
);
EXPORT_SYMBOL
(
i2o_controller_chain
);
EXPORT_SYMBOL
(
i2o_num_controllers
);
EXPORT_SYMBOL
(
i2o_find_controller
);
EXPORT_SYMBOL
(
i2o_unlock_controller
);
EXPORT_SYMBOL
(
i2o_status_get
);
EXPORT_SYMBOL
(
i2o_install_handler
);
EXPORT_SYMBOL
(
i2o_remove_handler
);
EXPORT_SYMBOL
(
i2o_install_controller
);
EXPORT_SYMBOL
(
i2o_delete_controller
);
EXPORT_SYMBOL
(
i2o_run_queue
);
EXPORT_SYMBOL
(
i2o_claim_device
);
EXPORT_SYMBOL
(
i2o_release_device
);
EXPORT_SYMBOL
(
i2o_device_notify_on
);
EXPORT_SYMBOL
(
i2o_device_notify_off
);
EXPORT_SYMBOL
(
i2o_post_this
);
EXPORT_SYMBOL
(
i2o_post_wait
);
EXPORT_SYMBOL
(
i2o_post_wait_mem
);
EXPORT_SYMBOL
(
i2o_query_scalar
);
EXPORT_SYMBOL
(
i2o_set_scalar
);
EXPORT_SYMBOL
(
i2o_query_table
);
EXPORT_SYMBOL
(
i2o_clear_table
);
EXPORT_SYMBOL
(
i2o_row_add_table
);
EXPORT_SYMBOL
(
i2o_issue_params
);
EXPORT_SYMBOL
(
i2o_event_register
);
EXPORT_SYMBOL
(
i2o_event_ack
);
EXPORT_SYMBOL
(
i2o_report_status
);
EXPORT_SYMBOL
(
i2o_dump_message
);
EXPORT_SYMBOL
(
i2o_get_class_name
);
drivers/message/i2o/i2o_pci.c
View file @
7da60b9c
...
@@ -32,9 +32,6 @@
...
@@ -32,9 +32,6 @@
#include <asm/io.h>
#include <asm/io.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif // CONFIG_MTRR
static
int
dpt
;
static
int
dpt
;
...
...
drivers/message/i2o/i2o_proc.c
View file @
7da60b9c
...
@@ -836,10 +836,14 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len,
...
@@ -836,10 +836,14 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len,
u16
row_count
;
u16
row_count
;
u16
more_flag
;
u16
more_flag
;
i2o_exec_execute_ddm_table
ddm_table
[
MAX_I2O_MODULES
];
i2o_exec_execute_ddm_table
ddm_table
[
MAX_I2O_MODULES
];
}
result
;
}
*
result
;
i2o_exec_execute_ddm_table
ddm_table
;
i2o_exec_execute_ddm_table
ddm_table
;
result
=
kmalloc
(
sizeof
(
*
result
),
GFP_KERNEL
);
if
(
!
result
)
return
-
ENOMEM
;
spin_lock
(
&
i2o_proc_lock
);
spin_lock
(
&
i2o_proc_lock
);
len
=
0
;
len
=
0
;
...
@@ -847,18 +851,17 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len,
...
@@ -847,18 +851,17 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len,
c
,
ADAPTER_TID
,
c
,
ADAPTER_TID
,
0x0003
,
-
1
,
0x0003
,
-
1
,
NULL
,
0
,
NULL
,
0
,
&
result
,
sizeof
(
result
));
result
,
sizeof
(
*
result
));
if
(
token
<
0
)
{
if
(
token
<
0
)
{
len
+=
i2o_report_query_status
(
buf
+
len
,
token
,
"0x0003 Executing DDM List"
);
len
+=
i2o_report_query_status
(
buf
+
len
,
token
,
"0x0003 Executing DDM List"
);
spin_unlock
(
&
i2o_proc_lock
);
goto
out
;
return
len
;
}
}
len
+=
sprintf
(
buf
+
len
,
"Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size
\n
"
);
len
+=
sprintf
(
buf
+
len
,
"Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size
\n
"
);
ddm_table
=
result
.
ddm_table
[
0
];
ddm_table
=
result
->
ddm_table
[
0
];
for
(
i
=
0
;
i
<
result
.
row_count
;
ddm_table
=
result
.
ddm_table
[
++
i
])
for
(
i
=
0
;
i
<
result
->
row_count
;
ddm_table
=
result
->
ddm_table
[
++
i
])
{
{
len
+=
sprintf
(
buf
+
len
,
"0x%03x "
,
ddm_table
.
ddm_tid
&
0xFFF
);
len
+=
sprintf
(
buf
+
len
,
"0x%03x "
,
ddm_table
.
ddm_tid
&
0xFFF
);
...
@@ -882,9 +885,9 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len,
...
@@ -882,9 +885,9 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len,
len
+=
sprintf
(
buf
+
len
,
"
\n
"
);
len
+=
sprintf
(
buf
+
len
,
"
\n
"
);
}
}
out:
spin_unlock
(
&
i2o_proc_lock
);
spin_unlock
(
&
i2o_proc_lock
);
kfree
(
result
);
return
len
;
return
len
;
}
}
...
@@ -1047,7 +1050,11 @@ int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len,
...
@@ -1047,7 +1050,11 @@ int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len,
u16
row_count
;
u16
row_count
;
u16
more_flag
;
u16
more_flag
;
i2o_group_info
group
[
256
];
i2o_group_info
group
[
256
];
}
result
;
}
*
result
;
result
=
kmalloc
(
sizeof
(
*
result
),
GFP_KERNEL
);
if
(
!
result
)
return
-
ENOMEM
;
spin_lock
(
&
i2o_proc_lock
);
spin_lock
(
&
i2o_proc_lock
);
...
@@ -1055,24 +1062,23 @@ int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len,
...
@@ -1055,24 +1062,23 @@ int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len,
token
=
i2o_query_table
(
I2O_PARAMS_TABLE_GET
,
token
=
i2o_query_table
(
I2O_PARAMS_TABLE_GET
,
d
->
controller
,
d
->
lct_data
.
tid
,
0xF000
,
-
1
,
NULL
,
0
,
d
->
controller
,
d
->
lct_data
.
tid
,
0xF000
,
-
1
,
NULL
,
0
,
&
result
,
sizeof
(
result
));
result
,
sizeof
(
*
result
));
if
(
token
<
0
)
{
if
(
token
<
0
)
{
len
=
i2o_report_query_status
(
buf
+
len
,
token
,
"0xF000 Params Descriptor"
);
len
=
i2o_report_query_status
(
buf
+
len
,
token
,
"0xF000 Params Descriptor"
);
spin_unlock
(
&
i2o_proc_lock
);
goto
out
;
return
len
;
}
}
len
+=
sprintf
(
buf
+
len
,
"# Group FieldCount RowCount Type Add Del Clear
\n
"
);
len
+=
sprintf
(
buf
+
len
,
"# Group FieldCount RowCount Type Add Del Clear
\n
"
);
for
(
i
=
0
;
i
<
result
.
row_count
;
i
++
)
for
(
i
=
0
;
i
<
result
->
row_count
;
i
++
)
{
{
len
+=
sprintf
(
buf
+
len
,
"%-3d"
,
i
);
len
+=
sprintf
(
buf
+
len
,
"%-3d"
,
i
);
len
+=
sprintf
(
buf
+
len
,
"0x%04X "
,
result
.
group
[
i
].
group_number
);
len
+=
sprintf
(
buf
+
len
,
"0x%04X "
,
result
->
group
[
i
].
group_number
);
len
+=
sprintf
(
buf
+
len
,
"%10d "
,
result
.
group
[
i
].
field_count
);
len
+=
sprintf
(
buf
+
len
,
"%10d "
,
result
->
group
[
i
].
field_count
);
len
+=
sprintf
(
buf
+
len
,
"%8d "
,
result
.
group
[
i
].
row_count
);
len
+=
sprintf
(
buf
+
len
,
"%8d "
,
result
->
group
[
i
].
row_count
);
properties
=
result
.
group
[
i
].
properties
;
properties
=
result
->
group
[
i
].
properties
;
if
(
properties
&
0x1
)
len
+=
sprintf
(
buf
+
len
,
"Table "
);
if
(
properties
&
0x1
)
len
+=
sprintf
(
buf
+
len
,
"Table "
);
else
len
+=
sprintf
(
buf
+
len
,
"Scalar "
);
else
len
+=
sprintf
(
buf
+
len
,
"Scalar "
);
if
(
properties
&
0x2
)
len
+=
sprintf
(
buf
+
len
,
" + "
);
if
(
properties
&
0x2
)
len
+=
sprintf
(
buf
+
len
,
" + "
);
...
@@ -1085,11 +1091,11 @@ int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len,
...
@@ -1085,11 +1091,11 @@ int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len,
len
+=
sprintf
(
buf
+
len
,
"
\n
"
);
len
+=
sprintf
(
buf
+
len
,
"
\n
"
);
}
}
if
(
result
.
more_flag
)
if
(
result
->
more_flag
)
len
+=
sprintf
(
buf
+
len
,
"There is more...
\n
"
);
len
+=
sprintf
(
buf
+
len
,
"There is more...
\n
"
);
out:
spin_unlock
(
&
i2o_proc_lock
);
spin_unlock
(
&
i2o_proc_lock
);
kfree
(
result
);
return
len
;
return
len
;
}
}
...
@@ -1220,7 +1226,11 @@ int i2o_proc_read_users(char *buf, char **start, off_t offset, int len,
...
@@ -1220,7 +1226,11 @@ int i2o_proc_read_users(char *buf, char **start, off_t offset, int len,
u16
row_count
;
u16
row_count
;
u16
more_flag
;
u16
more_flag
;
i2o_user_table
user
[
64
];
i2o_user_table
user
[
64
];
}
result
;
}
*
result
;
result
=
kmalloc
(
sizeof
(
*
result
),
GFP_KERNEL
);
if
(
!
result
)
return
-
ENOMEM
;
spin_lock
(
&
i2o_proc_lock
);
spin_lock
(
&
i2o_proc_lock
);
len
=
0
;
len
=
0
;
...
@@ -1228,28 +1238,28 @@ int i2o_proc_read_users(char *buf, char **start, off_t offset, int len,
...
@@ -1228,28 +1238,28 @@ int i2o_proc_read_users(char *buf, char **start, off_t offset, int len,
token
=
i2o_query_table
(
I2O_PARAMS_TABLE_GET
,
token
=
i2o_query_table
(
I2O_PARAMS_TABLE_GET
,
d
->
controller
,
d
->
lct_data
.
tid
,
d
->
controller
,
d
->
lct_data
.
tid
,
0xF003
,
-
1
,
NULL
,
0
,
0xF003
,
-
1
,
NULL
,
0
,
&
result
,
sizeof
(
result
));
result
,
sizeof
(
*
result
));
if
(
token
<
0
)
{
if
(
token
<
0
)
{
len
+=
i2o_report_query_status
(
buf
+
len
,
token
,
"0xF003 User Table"
);
len
+=
i2o_report_query_status
(
buf
+
len
,
token
,
"0xF003 User Table"
);
spin_unlock
(
&
i2o_proc_lock
);
goto
out
;
return
len
;
}
}
len
+=
sprintf
(
buf
+
len
,
"# Instance UserTid ClaimType
\n
"
);
len
+=
sprintf
(
buf
+
len
,
"# Instance UserTid ClaimType
\n
"
);
for
(
i
=
0
;
i
<
result
.
row_count
;
i
++
)
for
(
i
=
0
;
i
<
result
->
row_count
;
i
++
)
{
{
len
+=
sprintf
(
buf
+
len
,
"%-3d"
,
i
);
len
+=
sprintf
(
buf
+
len
,
"%-3d"
,
i
);
len
+=
sprintf
(
buf
+
len
,
"%#8x "
,
result
.
user
[
i
].
instance
);
len
+=
sprintf
(
buf
+
len
,
"%#8x "
,
result
->
user
[
i
].
instance
);
len
+=
sprintf
(
buf
+
len
,
"%#7x "
,
result
.
user
[
i
].
user_tid
);
len
+=
sprintf
(
buf
+
len
,
"%#7x "
,
result
->
user
[
i
].
user_tid
);
len
+=
sprintf
(
buf
+
len
,
"%#9x
\n
"
,
result
.
user
[
i
].
claim_type
);
len
+=
sprintf
(
buf
+
len
,
"%#9x
\n
"
,
result
->
user
[
i
].
claim_type
);
}
}
if
(
result
.
more_flag
)
if
(
result
->
more_flag
)
len
+=
sprintf
(
buf
+
len
,
"There is more...
\n
"
);
len
+=
sprintf
(
buf
+
len
,
"There is more...
\n
"
);
out:
spin_unlock
(
&
i2o_proc_lock
);
spin_unlock
(
&
i2o_proc_lock
);
kfree
(
result
);
return
len
;
return
len
;
}
}
...
@@ -2264,24 +2274,27 @@ int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset,
...
@@ -2264,24 +2274,27 @@ int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset,
u16
row_count
;
u16
row_count
;
u16
more_flag
;
u16
more_flag
;
u8
mc_addr
[
256
][
8
];
u8
mc_addr
[
256
][
8
];
}
result
;
}
*
result
;
result
=
kmalloc
(
sizeof
(
*
result
),
GFP_KERNEL
);
if
(
!
result
)
return
-
ENOMEM
;
spin_lock
(
&
i2o_proc_lock
);
spin_lock
(
&
i2o_proc_lock
);
len
=
0
;
len
=
0
;
token
=
i2o_query_table
(
I2O_PARAMS_TABLE_GET
,
token
=
i2o_query_table
(
I2O_PARAMS_TABLE_GET
,
d
->
controller
,
d
->
lct_data
.
tid
,
0x0002
,
-
1
,
d
->
controller
,
d
->
lct_data
.
tid
,
0x0002
,
-
1
,
NULL
,
0
,
&
result
,
sizeof
(
result
));
NULL
,
0
,
result
,
sizeof
(
*
result
));
if
(
token
<
0
)
{
if
(
token
<
0
)
{
len
+=
i2o_report_query_status
(
buf
+
len
,
token
,
"0x002 LAN Multicast MAC Address"
);
len
+=
i2o_report_query_status
(
buf
+
len
,
token
,
"0x002 LAN Multicast MAC Address"
);
spin_unlock
(
&
i2o_proc_lock
);
goto
out
;
return
len
;
}
}
for
(
i
=
0
;
i
<
result
.
row_count
;
i
++
)
for
(
i
=
0
;
i
<
result
->
row_count
;
i
++
)
{
{
memcpy
(
mc_addr
,
result
.
mc_addr
[
i
],
8
);
memcpy
(
mc_addr
,
result
->
mc_addr
[
i
],
8
);
len
+=
sprintf
(
buf
+
len
,
"MC MAC address[%d]: "
len
+=
sprintf
(
buf
+
len
,
"MC MAC address[%d]: "
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
...
@@ -2289,8 +2302,9 @@ int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset,
...
@@ -2289,8 +2302,9 @@ int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset,
mc_addr
[
3
],
mc_addr
[
4
],
mc_addr
[
5
],
mc_addr
[
3
],
mc_addr
[
4
],
mc_addr
[
5
],
mc_addr
[
6
],
mc_addr
[
7
]);
mc_addr
[
6
],
mc_addr
[
7
]);
}
}
out:
spin_unlock
(
&
i2o_proc_lock
);
spin_unlock
(
&
i2o_proc_lock
);
kfree
(
result
);
return
len
;
return
len
;
}
}
...
@@ -2495,32 +2509,36 @@ int i2o_proc_read_lan_alt_addr(char *buf, char **start, off_t offset, int len,
...
@@ -2495,32 +2509,36 @@ int i2o_proc_read_lan_alt_addr(char *buf, char **start, off_t offset, int len,
u16
row_count
;
u16
row_count
;
u16
more_flag
;
u16
more_flag
;
u8
alt_addr
[
256
][
8
];
u8
alt_addr
[
256
][
8
];
}
result
;
}
*
result
;
result
=
kmalloc
(
sizeof
(
*
result
),
GFP_KERNEL
);
if
(
!
result
)
return
-
ENOMEM
;
spin_lock
(
&
i2o_proc_lock
);
spin_lock
(
&
i2o_proc_lock
);
len
=
0
;
len
=
0
;
token
=
i2o_query_table
(
I2O_PARAMS_TABLE_GET
,
token
=
i2o_query_table
(
I2O_PARAMS_TABLE_GET
,
d
->
controller
,
d
->
lct_data
.
tid
,
d
->
controller
,
d
->
lct_data
.
tid
,
0x0006
,
-
1
,
NULL
,
0
,
&
result
,
sizeof
(
result
));
0x0006
,
-
1
,
NULL
,
0
,
result
,
sizeof
(
*
result
));
if
(
token
<
0
)
{
if
(
token
<
0
)
{
len
+=
i2o_report_query_status
(
buf
+
len
,
token
,
"0x0006 LAN Alternate Address (optional)"
);
len
+=
i2o_report_query_status
(
buf
+
len
,
token
,
"0x0006 LAN Alternate Address (optional)"
);
spin_unlock
(
&
i2o_proc_lock
);
goto
out
;
return
len
;
}
}
for
(
i
=
0
;
i
<
result
.
row_count
;
i
++
)
for
(
i
=
0
;
i
<
result
->
row_count
;
i
++
)
{
{
memcpy
(
alt_addr
,
result
.
alt_addr
[
i
],
8
);
memcpy
(
alt_addr
,
result
->
alt_addr
[
i
],
8
);
len
+=
sprintf
(
buf
+
len
,
"Alternate address[%d]: "
len
+=
sprintf
(
buf
+
len
,
"Alternate address[%d]: "
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
i
,
alt_addr
[
0
],
alt_addr
[
1
],
alt_addr
[
2
],
i
,
alt_addr
[
0
],
alt_addr
[
1
],
alt_addr
[
2
],
alt_addr
[
3
],
alt_addr
[
4
],
alt_addr
[
5
],
alt_addr
[
3
],
alt_addr
[
4
],
alt_addr
[
5
],
alt_addr
[
6
],
alt_addr
[
7
]);
alt_addr
[
6
],
alt_addr
[
7
]);
}
}
out:
spin_unlock
(
&
i2o_proc_lock
);
spin_unlock
(
&
i2o_proc_lock
);
kfree
(
result
);
return
len
;
return
len
;
}
}
...
...
include/linux/i2o.h
View file @
7da60b9c
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
#include <linux/i2o-dev.h>
#include <linux/i2o-dev.h>
/* How many different OSM's are we allowing */
/* How many different OSM's are we allowing */
#define MAX_I2O_MODULES
6
4
#define MAX_I2O_MODULES 4
/* How many OSMs can register themselves for device status updates? */
/* How many OSMs can register themselves for device status updates? */
#define I2O_MAX_MANAGERS 4
#define I2O_MAX_MANAGERS 4
...
@@ -76,10 +76,16 @@ struct i2o_device
...
@@ -76,10 +76,16 @@ struct i2o_device
};
};
/*
/*
*
Resource data for each PCI I2O controller
*
Each I2O controller has one of these objects
*/
*/
struct
i2o_
pci
struct
i2o_
controller
{
{
char
name
[
16
];
int
unit
;
int
type
;
int
enabled
;
struct
pci_dev
*
pdev
;
/* PCI device */
int
irq
;
int
irq
;
int
short_req
:
1
;
/* Use small block sizes */
int
short_req
:
1
;
/* Use small block sizes */
int
dpt
:
1
;
/* Don't quiesce */
int
dpt
:
1
;
/* Don't quiesce */
...
@@ -88,25 +94,6 @@ struct i2o_pci
...
@@ -88,25 +94,6 @@ struct i2o_pci
int
mtrr_reg0
;
int
mtrr_reg0
;
int
mtrr_reg1
;
int
mtrr_reg1
;
#endif
#endif
};
/*
* Transport types supported by I2O stack
*/
#define I2O_TYPE_PCI 0x01
/* PCI I2O controller */
/*
* Each I2O controller has one of these objects
*/
struct
i2o_controller
{
struct
pci_dev
*
pdev
;
/* PCI device */
char
name
[
16
];
int
unit
;
int
type
;
int
enabled
;
struct
notifier_block
*
event_notifer
;
/* Events */
struct
notifier_block
*
event_notifer
;
/* Events */
atomic_t
users
;
atomic_t
users
;
...
@@ -143,22 +130,6 @@ struct i2o_controller
...
@@ -143,22 +130,6 @@ struct i2o_controller
struct
proc_dir_entry
*
proc_entry
;
/* /proc dir */
struct
proc_dir_entry
*
proc_entry
;
/* /proc dir */
union
{
/* Bus information */
struct
i2o_pci
pci
;
}
bus
;
/* Bus specific destructor */
void
(
*
destructor
)(
struct
i2o_controller
*
);
/* Bus specific attach/detach */
int
(
*
bind
)(
struct
i2o_controller
*
,
struct
i2o_device
*
);
/* Bus specific initiator */
int
(
*
unbind
)(
struct
i2o_controller
*
,
struct
i2o_device
*
);
/* Bus specific enable/disable */
void
(
*
bus_enable
)(
struct
i2o_controller
*
);
void
(
*
bus_disable
)(
struct
i2o_controller
*
);
void
*
page_frame
;
/* Message buffers */
void
*
page_frame
;
/* Message buffers */
dma_addr_t
page_frame_map
;
/* Cache map */
dma_addr_t
page_frame_map
;
/* Cache map */
...
...
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