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
20697cb7
Commit
20697cb7
authored
Jul 13, 2006
by
Stephen Rothwell
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'hvc_iseries'
parents
54f5cd8a
4e9e95a3
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
652 additions
and
41 deletions
+652
-41
arch/powerpc/platforms/iseries/Kconfig
arch/powerpc/platforms/iseries/Kconfig
+6
-2
arch/powerpc/platforms/iseries/dt.c
arch/powerpc/platforms/iseries/dt.c
+2
-1
drivers/char/Kconfig
drivers/char/Kconfig
+7
-0
drivers/char/Makefile
drivers/char/Makefile
+1
-0
drivers/char/hvc_console.c
drivers/char/hvc_console.c
+9
-5
drivers/char/hvc_console.h
drivers/char/hvc_console.h
+1
-1
drivers/char/hvc_iseries.c
drivers/char/hvc_iseries.c
+594
-0
drivers/char/hvc_rtas.c
drivers/char/hvc_rtas.c
+1
-1
drivers/char/hvc_vio.c
drivers/char/hvc_vio.c
+2
-1
drivers/char/viocons.c
drivers/char/viocons.c
+1
-30
include/asm-powerpc/iseries/vio.h
include/asm-powerpc/iseries/vio.h
+28
-0
No files found.
arch/powerpc/platforms/iseries/Kconfig
View file @
20697cb7
...
...
@@ -3,7 +3,11 @@ menu "iSeries device drivers"
depends on PPC_ISERIES
config VIOCONS
tristate "iSeries Virtual Console Support"
tristate "iSeries Virtual Console Support (Obsolete)"
help
This is the old virtual console driver for legacy iSeries.
You should use the iSeries Hypervisor Virtual Console
support instead.
config VIODASD
tristate "iSeries Virtual I/O disk support"
...
...
arch/powerpc/platforms/iseries/dt.c
View file @
20697cb7
...
...
@@ -298,7 +298,8 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
dt_prop_u32
(
dt
,
"#address-cells"
,
1
);
dt_prop_u32
(
dt
,
"#size-cells"
,
0
);
dt_do_vdevice
(
dt
,
"vty"
,
reg
,
-
1
,
device_type_serial
,
NULL
,
1
);
dt_do_vdevice
(
dt
,
"vty"
,
reg
,
-
1
,
device_type_serial
,
"IBM,iSeries-vty"
,
1
);
reg
++
;
dt_do_vdevice
(
dt
,
"v-scsi"
,
reg
,
-
1
,
device_type_vscsi
,
...
...
drivers/char/Kconfig
View file @
20697cb7
...
...
@@ -610,6 +610,13 @@ config HVC_CONSOLE
console. This driver allows each pSeries partition to have a console
which is accessed via the HMC.
config HVC_ISERIES
bool "iSeries Hypervisor Virtual Console support"
depends on PPC_ISERIES && !VIOCONS
select HVC_DRIVER
help
iSeries machines support a hypervisor virtual console.
config HVC_RTAS
bool "IBM RTAS Console support"
depends on PPC_RTAS
...
...
drivers/char/Makefile
View file @
20697cb7
...
...
@@ -42,6 +42,7 @@ obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_SX)
+=
sx.o generic_serial.o
obj-$(CONFIG_RIO)
+=
rio/ generic_serial.o
obj-$(CONFIG_HVC_CONSOLE)
+=
hvc_vio.o hvsi.o
obj-$(CONFIG_HVC_ISERIES)
+=
hvc_iseries.o
obj-$(CONFIG_HVC_RTAS)
+=
hvc_rtas.o
obj-$(CONFIG_HVC_DRIVER)
+=
hvc_console.o
obj-$(CONFIG_RAW_DRIVER)
+=
raw.o
...
...
drivers/char/hvc_console.c
View file @
20697cb7
...
...
@@ -80,7 +80,8 @@ struct hvc_struct {
struct
tty_struct
*
tty
;
unsigned
int
count
;
int
do_wakeup
;
char
outbuf
[
N_OUTBUF
]
__ALIGNED__
;
char
*
outbuf
;
int
outbuf_size
;
int
n_outbuf
;
uint32_t
vtermno
;
struct
hv_ops
*
ops
;
...
...
@@ -505,7 +506,7 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
if
(
hp
->
n_outbuf
>
0
)
hvc_push
(
hp
);
while
(
count
>
0
&&
(
rsize
=
N_OUTBUF
-
hp
->
n_outbuf
)
>
0
)
{
while
(
count
>
0
&&
(
rsize
=
hp
->
outbuf_size
-
hp
->
n_outbuf
)
>
0
)
{
if
(
rsize
>
count
)
rsize
=
count
;
memcpy
(
hp
->
outbuf
+
hp
->
n_outbuf
,
buf
,
rsize
);
...
...
@@ -538,7 +539,7 @@ static int hvc_write_room(struct tty_struct *tty)
if
(
!
hp
)
return
-
1
;
return
N_OUTBUF
-
hp
->
n_outbuf
;
return
hp
->
outbuf_size
-
hp
->
n_outbuf
;
}
static
int
hvc_chars_in_buffer
(
struct
tty_struct
*
tty
)
...
...
@@ -728,12 +729,13 @@ static struct kobj_type hvc_kobj_type = {
};
struct
hvc_struct
__devinit
*
hvc_alloc
(
uint32_t
vtermno
,
int
irq
,
struct
hv_ops
*
ops
)
struct
hv_ops
*
ops
,
int
outbuf_size
)
{
struct
hvc_struct
*
hp
;
int
i
;
hp
=
kmalloc
(
sizeof
(
*
hp
),
GFP_KERNEL
);
hp
=
kmalloc
(
ALIGN
(
sizeof
(
*
hp
),
sizeof
(
long
))
+
outbuf_size
,
GFP_KERNEL
);
if
(
!
hp
)
return
ERR_PTR
(
-
ENOMEM
);
...
...
@@ -742,6 +744,8 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
hp
->
vtermno
=
vtermno
;
hp
->
irq
=
irq
;
hp
->
ops
=
ops
;
hp
->
outbuf_size
=
outbuf_size
;
hp
->
outbuf
=
&
((
char
*
)
hp
)[
ALIGN
(
sizeof
(
*
hp
),
sizeof
(
long
))];
kobject_init
(
&
hp
->
kobj
);
hp
->
kobj
.
ktype
=
&
hvc_kobj_type
;
...
...
drivers/char/hvc_console.h
View file @
20697cb7
...
...
@@ -56,7 +56,7 @@ extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
/* register a vterm for hvc tty operation (module_init or hotplug add) */
extern
struct
hvc_struct
*
__devinit
hvc_alloc
(
uint32_t
vtermno
,
int
irq
,
struct
hv_ops
*
ops
);
struct
hv_ops
*
ops
,
int
outbuf_size
);
/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
extern
int
__devexit
hvc_remove
(
struct
hvc_struct
*
hp
);
...
...
drivers/char/hvc_iseries.c
0 → 100644
View file @
20697cb7
/*
* iSeries vio driver interface to hvc_console.c
*
* This code is based heavily on hvc_vio.c and viocons.c
*
* Copyright (C) 2006 Stephen Rothwell, IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/console.h>
#include <asm/hvconsole.h>
#include <asm/vio.h>
#include <asm/prom.h>
#include <asm/iseries/vio.h>
#include <asm/iseries/hv_call.h>
#include <asm/iseries/hv_lp_config.h>
#include <asm/iseries/hv_lp_event.h>
#include "hvc_console.h"
#define VTTY_PORTS 10
static
DEFINE_SPINLOCK
(
consolelock
);
static
DEFINE_SPINLOCK
(
consoleloglock
);
static
const
char
hvc_driver_name
[]
=
"hvc_console"
;
#define IN_BUF_SIZE 200
/*
* Our port information.
*/
static
struct
port_info
{
HvLpIndex
lp
;
u64
seq
;
/* sequence number of last HV send */
u64
ack
;
/* last ack from HV */
struct
hvc_struct
*
hp
;
int
in_start
;
int
in_end
;
unsigned
char
in_buf
[
IN_BUF_SIZE
];
}
port_info
[
VTTY_PORTS
]
=
{
[
0
...
VTTY_PORTS
-
1
]
=
{
.
lp
=
HvLpIndexInvalid
}
};
#define viochar_is_console(pi) ((pi) == &port_info[0])
static
struct
vio_device_id
hvc_driver_table
[]
__devinitdata
=
{
{
"serial"
,
"IBM,iSeries-vty"
},
{
""
,
""
}
};
MODULE_DEVICE_TABLE
(
vio
,
hvc_driver_table
);
static
void
hvlog
(
char
*
fmt
,
...)
{
int
i
;
unsigned
long
flags
;
va_list
args
;
static
char
buf
[
256
];
spin_lock_irqsave
(
&
consoleloglock
,
flags
);
va_start
(
args
,
fmt
);
i
=
vscnprintf
(
buf
,
sizeof
(
buf
)
-
1
,
fmt
,
args
);
va_end
(
args
);
buf
[
i
++
]
=
'\r'
;
HvCall_writeLogBuffer
(
buf
,
i
);
spin_unlock_irqrestore
(
&
consoleloglock
,
flags
);
}
/*
* Initialize the common fields in a charLpEvent
*/
static
void
init_data_event
(
struct
viocharlpevent
*
viochar
,
HvLpIndex
lp
)
{
struct
HvLpEvent
*
hev
=
&
viochar
->
event
;
memset
(
viochar
,
0
,
sizeof
(
struct
viocharlpevent
));
hev
->
flags
=
HV_LP_EVENT_VALID
|
HV_LP_EVENT_DEFERRED_ACK
|
HV_LP_EVENT_INT
;
hev
->
xType
=
HvLpEvent_Type_VirtualIo
;
hev
->
xSubtype
=
viomajorsubtype_chario
|
viochardata
;
hev
->
xSourceLp
=
HvLpConfig_getLpIndex
();
hev
->
xTargetLp
=
lp
;
hev
->
xSizeMinus1
=
sizeof
(
struct
viocharlpevent
);
hev
->
xSourceInstanceId
=
viopath_sourceinst
(
lp
);
hev
->
xTargetInstanceId
=
viopath_targetinst
(
lp
);
}
static
int
get_chars
(
uint32_t
vtermno
,
char
*
buf
,
int
count
)
{
struct
port_info
*
pi
;
int
n
=
0
;
unsigned
long
flags
;
if
(
vtermno
>=
VTTY_PORTS
)
return
-
EINVAL
;
if
(
count
==
0
)
return
0
;
pi
=
&
port_info
[
vtermno
];
spin_lock_irqsave
(
&
consolelock
,
flags
);
if
(
pi
->
in_end
==
0
)
goto
done
;
n
=
pi
->
in_end
-
pi
->
in_start
;
if
(
n
>
count
)
n
=
count
;
memcpy
(
buf
,
&
pi
->
in_buf
[
pi
->
in_start
],
n
);
pi
->
in_start
+=
n
;
if
(
pi
->
in_start
==
pi
->
in_end
)
{
pi
->
in_start
=
0
;
pi
->
in_end
=
0
;
}
done:
spin_unlock_irqrestore
(
&
consolelock
,
flags
);
return
n
;
}
static
int
put_chars
(
uint32_t
vtermno
,
const
char
*
buf
,
int
count
)
{
struct
viocharlpevent
*
viochar
;
struct
port_info
*
pi
;
HvLpEvent_Rc
hvrc
;
unsigned
long
flags
;
int
sent
=
0
;
if
(
vtermno
>=
VTTY_PORTS
)
return
-
EINVAL
;
pi
=
&
port_info
[
vtermno
];
spin_lock_irqsave
(
&
consolelock
,
flags
);
if
(
viochar_is_console
(
pi
)
&&
!
viopath_isactive
(
pi
->
lp
))
{
spin_lock_irqsave
(
&
consoleloglock
,
flags
);
HvCall_writeLogBuffer
(
buf
,
count
);
spin_unlock_irqrestore
(
&
consoleloglock
,
flags
);
sent
=
count
;
goto
done
;
}
viochar
=
vio_get_event_buffer
(
viomajorsubtype_chario
);
if
(
viochar
==
NULL
)
{
hvlog
(
"
\n\r
viocons: Can't get viochar buffer."
);
goto
done
;
}
while
((
count
>
0
)
&&
((
pi
->
seq
-
pi
->
ack
)
<
VIOCHAR_WINDOW
))
{
int
len
;
len
=
(
count
>
VIOCHAR_MAX_DATA
)
?
VIOCHAR_MAX_DATA
:
count
;
if
(
viochar_is_console
(
pi
))
{
spin_lock_irqsave
(
&
consoleloglock
,
flags
);
HvCall_writeLogBuffer
(
buf
,
len
);
spin_unlock_irqrestore
(
&
consoleloglock
,
flags
);
}
init_data_event
(
viochar
,
pi
->
lp
);
viochar
->
len
=
len
;
viochar
->
event
.
xCorrelationToken
=
pi
->
seq
++
;
viochar
->
event
.
xSizeMinus1
=
offsetof
(
struct
viocharlpevent
,
data
)
+
len
;
memcpy
(
viochar
->
data
,
buf
,
len
);
hvrc
=
HvCallEvent_signalLpEvent
(
&
viochar
->
event
);
if
(
hvrc
)
hvlog
(
"
\n\r
error sending event! return code %d
\n\r
"
,
(
int
)
hvrc
);
sent
+=
len
;
count
-=
len
;
buf
+=
len
;
}
vio_free_event_buffer
(
viomajorsubtype_chario
,
viochar
);
done:
spin_unlock_irqrestore
(
&
consolelock
,
flags
);
return
sent
;
}
static
struct
hv_ops
hvc_get_put_ops
=
{
.
get_chars
=
get_chars
,
.
put_chars
=
put_chars
,
};
static
int
__devinit
hvc_vio_probe
(
struct
vio_dev
*
vdev
,
const
struct
vio_device_id
*
id
)
{
struct
hvc_struct
*
hp
;
struct
port_info
*
pi
;
/* probed with invalid parameters. */
if
(
!
vdev
||
!
id
)
return
-
EPERM
;
if
(
vdev
->
unit_address
>=
VTTY_PORTS
)
return
-
ENODEV
;
pi
=
&
port_info
[
vdev
->
unit_address
];
hp
=
hvc_alloc
(
vdev
->
unit_address
,
vdev
->
irq
,
&
hvc_get_put_ops
,
VIOCHAR_MAX_DATA
);
if
(
IS_ERR
(
hp
))
return
PTR_ERR
(
hp
);
pi
->
hp
=
hp
;
dev_set_drvdata
(
&
vdev
->
dev
,
pi
);
return
0
;
}
static
int
__devexit
hvc_vio_remove
(
struct
vio_dev
*
vdev
)
{
struct
port_info
*
pi
=
dev_get_drvdata
(
&
vdev
->
dev
);
struct
hvc_struct
*
hp
=
pi
->
hp
;
return
hvc_remove
(
hp
);
}
static
struct
vio_driver
hvc_vio_driver
=
{
.
id_table
=
hvc_driver_table
,
.
probe
=
hvc_vio_probe
,
.
remove
=
hvc_vio_remove
,
.
driver
=
{
.
name
=
hvc_driver_name
,
.
owner
=
THIS_MODULE
,
}
};
static
void
hvc_open_event
(
struct
HvLpEvent
*
event
)
{
unsigned
long
flags
;
struct
viocharlpevent
*
cevent
=
(
struct
viocharlpevent
*
)
event
;
u8
port
=
cevent
->
virtual_device
;
struct
port_info
*
pi
;
int
reject
=
0
;
if
(
hvlpevent_is_ack
(
event
))
{
if
(
port
>=
VTTY_PORTS
)
return
;
spin_lock_irqsave
(
&
consolelock
,
flags
);
pi
=
&
port_info
[
port
];
if
(
event
->
xRc
==
HvLpEvent_Rc_Good
)
{
pi
->
seq
=
pi
->
ack
=
0
;
/*
* This line allows connections from the primary
* partition but once one is connected from the
* primary partition nothing short of a reboot
* of linux will allow access from the hosting
* partition again without a required iSeries fix.
*/
pi
->
lp
=
event
->
xTargetLp
;
}
spin_unlock_irqrestore
(
&
consolelock
,
flags
);
if
(
event
->
xRc
!=
HvLpEvent_Rc_Good
)
printk
(
KERN_WARNING
"hvc: handle_open_event: event->xRc == (%d).
\n
"
,
event
->
xRc
);
if
(
event
->
xCorrelationToken
!=
0
)
{
atomic_t
*
aptr
=
(
atomic_t
*
)
event
->
xCorrelationToken
;
atomic_set
(
aptr
,
1
);
}
else
printk
(
KERN_WARNING
"hvc: weird...got open ack without atomic
\n
"
);
return
;
}
/* This had better require an ack, otherwise complain */
if
(
!
hvlpevent_need_ack
(
event
))
{
printk
(
KERN_WARNING
"hvc: viocharopen without ack bit!
\n
"
);
return
;
}
spin_lock_irqsave
(
&
consolelock
,
flags
);
/* Make sure this is a good virtual tty */
if
(
port
>=
VTTY_PORTS
)
{
event
->
xRc
=
HvLpEvent_Rc_SubtypeError
;
cevent
->
subtype_result_code
=
viorc_openRejected
;
/*
* Flag state here since we can't printk while holding
* the consolelock spinlock.
*/
reject
=
1
;
}
else
{
pi
=
&
port_info
[
port
];
if
((
pi
->
lp
!=
HvLpIndexInvalid
)
&&
(
pi
->
lp
!=
event
->
xSourceLp
))
{
/*
* If this is tty is already connected to a different
* partition, fail.
*/
event
->
xRc
=
HvLpEvent_Rc_SubtypeError
;
cevent
->
subtype_result_code
=
viorc_openRejected
;
reject
=
2
;
}
else
{
pi
->
lp
=
event
->
xSourceLp
;
event
->
xRc
=
HvLpEvent_Rc_Good
;
cevent
->
subtype_result_code
=
viorc_good
;
pi
->
seq
=
pi
->
ack
=
0
;
}
}
spin_unlock_irqrestore
(
&
consolelock
,
flags
);
if
(
reject
==
1
)
printk
(
KERN_WARNING
"hvc: open rejected: bad virtual tty.
\n
"
);
else
if
(
reject
==
2
)
printk
(
KERN_WARNING
"hvc: open rejected: console in exclusive "
"use by another partition.
\n
"
);
/* Return the acknowledgement */
HvCallEvent_ackLpEvent
(
event
);
}
/*
* Handle a close charLpEvent. This should ONLY be an Interrupt because the
* virtual console should never actually issue a close event to the hypervisor
* because the virtual console never goes away. A close event coming from the
* hypervisor simply means that there are no client consoles connected to the
* virtual console.
*/
static
void
hvc_close_event
(
struct
HvLpEvent
*
event
)
{
unsigned
long
flags
;
struct
viocharlpevent
*
cevent
=
(
struct
viocharlpevent
*
)
event
;
u8
port
=
cevent
->
virtual_device
;
if
(
!
hvlpevent_is_int
(
event
))
{
printk
(
KERN_WARNING
"hvc: got unexpected close acknowlegement
\n
"
);
return
;
}
if
(
port
>=
VTTY_PORTS
)
{
printk
(
KERN_WARNING
"hvc: close message from invalid virtual device.
\n
"
);
return
;
}
/* For closes, just mark the console partition invalid */
spin_lock_irqsave
(
&
consolelock
,
flags
);
if
(
port_info
[
port
].
lp
==
event
->
xSourceLp
)
port_info
[
port
].
lp
=
HvLpIndexInvalid
;
spin_unlock_irqrestore
(
&
consolelock
,
flags
);
}
static
void
hvc_data_event
(
struct
HvLpEvent
*
event
)
{
unsigned
long
flags
;
struct
viocharlpevent
*
cevent
=
(
struct
viocharlpevent
*
)
event
;
struct
port_info
*
pi
;
int
n
;
u8
port
=
cevent
->
virtual_device
;
if
(
port
>=
VTTY_PORTS
)
{
printk
(
KERN_WARNING
"hvc: data on invalid virtual device %d
\n
"
,
port
);
return
;
}
if
(
cevent
->
len
==
0
)
return
;
/*
* Change 05/01/2003 - Ryan Arnold: If a partition other than
* the current exclusive partition tries to send us data
* events then just drop them on the floor because we don't
* want his stinking data. He isn't authorized to receive
* data because he wasn't the first one to get the console,
* therefore he shouldn't be allowed to send data either.
* This will work without an iSeries fix.
*/
pi
=
&
port_info
[
port
];
if
(
pi
->
lp
!=
event
->
xSourceLp
)
return
;
spin_lock_irqsave
(
&
consolelock
,
flags
);
n
=
IN_BUF_SIZE
-
pi
->
in_end
;
if
(
n
>
cevent
->
len
)
n
=
cevent
->
len
;
if
(
n
>
0
)
{
memcpy
(
&
pi
->
in_buf
[
pi
->
in_end
],
cevent
->
data
,
n
);
pi
->
in_end
+=
n
;
}
spin_unlock_irqrestore
(
&
consolelock
,
flags
);
if
(
n
==
0
)
printk
(
KERN_WARNING
"hvc: input buffer overflow
\n
"
);
}
static
void
hvc_ack_event
(
struct
HvLpEvent
*
event
)
{
struct
viocharlpevent
*
cevent
=
(
struct
viocharlpevent
*
)
event
;
unsigned
long
flags
;
u8
port
=
cevent
->
virtual_device
;
if
(
port
>=
VTTY_PORTS
)
{
printk
(
KERN_WARNING
"hvc: data on invalid virtual device
\n
"
);
return
;
}
spin_lock_irqsave
(
&
consolelock
,
flags
);
port_info
[
port
].
ack
=
event
->
xCorrelationToken
;
spin_unlock_irqrestore
(
&
consolelock
,
flags
);
}
static
void
hvc_config_event
(
struct
HvLpEvent
*
event
)
{
struct
viocharlpevent
*
cevent
=
(
struct
viocharlpevent
*
)
event
;
if
(
cevent
->
data
[
0
]
==
0x01
)
printk
(
KERN_INFO
"hvc: window resized to %d: %d: %d: %d
\n
"
,
cevent
->
data
[
1
],
cevent
->
data
[
2
],
cevent
->
data
[
3
],
cevent
->
data
[
4
]);
else
printk
(
KERN_WARNING
"hvc: unknown config event
\n
"
);
}
static
void
hvc_handle_event
(
struct
HvLpEvent
*
event
)
{
int
charminor
;
if
(
event
==
NULL
)
return
;
charminor
=
event
->
xSubtype
&
VIOMINOR_SUBTYPE_MASK
;
switch
(
charminor
)
{
case
viocharopen
:
hvc_open_event
(
event
);
break
;
case
viocharclose
:
hvc_close_event
(
event
);
break
;
case
viochardata
:
hvc_data_event
(
event
);
break
;
case
viocharack
:
hvc_ack_event
(
event
);
break
;
case
viocharconfig
:
hvc_config_event
(
event
);
break
;
default:
if
(
hvlpevent_is_int
(
event
)
&&
hvlpevent_need_ack
(
event
))
{
event
->
xRc
=
HvLpEvent_Rc_InvalidSubtype
;
HvCallEvent_ackLpEvent
(
event
);
}
}
}
static
int
send_open
(
HvLpIndex
remoteLp
,
void
*
sem
)
{
return
HvCallEvent_signalLpEventFast
(
remoteLp
,
HvLpEvent_Type_VirtualIo
,
viomajorsubtype_chario
|
viocharopen
,
HvLpEvent_AckInd_DoAck
,
HvLpEvent_AckType_ImmediateAck
,
viopath_sourceinst
(
remoteLp
),
viopath_targetinst
(
remoteLp
),
(
u64
)(
unsigned
long
)
sem
,
VIOVERSION
<<
16
,
0
,
0
,
0
,
0
);
}
static
int
hvc_vio_init
(
void
)
{
atomic_t
wait_flag
;
int
rc
;
/* +2 for fudge */
rc
=
viopath_open
(
HvLpConfig_getPrimaryLpIndex
(),
viomajorsubtype_chario
,
VIOCHAR_WINDOW
+
2
);
if
(
rc
)
printk
(
KERN_WARNING
"hvc: error opening to primary %d
\n
"
,
rc
);
if
(
viopath_hostLp
==
HvLpIndexInvalid
)
vio_set_hostlp
();
/*
* And if the primary is not the same as the hosting LP, open to the
* hosting lp
*/
if
((
viopath_hostLp
!=
HvLpIndexInvalid
)
&&
(
viopath_hostLp
!=
HvLpConfig_getPrimaryLpIndex
()))
{
printk
(
KERN_INFO
"hvc: open path to hosting (%d)
\n
"
,
viopath_hostLp
);
rc
=
viopath_open
(
viopath_hostLp
,
viomajorsubtype_chario
,
VIOCHAR_WINDOW
+
2
);
/* +2 for fudge */
if
(
rc
)
printk
(
KERN_WARNING
"error opening to partition %d: %d
\n
"
,
viopath_hostLp
,
rc
);
}
if
(
vio_setHandler
(
viomajorsubtype_chario
,
hvc_handle_event
)
<
0
)
printk
(
KERN_WARNING
"hvc: error seting handler for console events!
\n
"
);
/*
* First, try to open the console to the hosting lp.
* Wait on a semaphore for the response.
*/
atomic_set
(
&
wait_flag
,
0
);
if
((
viopath_isactive
(
viopath_hostLp
))
&&
(
send_open
(
viopath_hostLp
,
&
wait_flag
)
==
0
))
{
printk
(
KERN_INFO
"hvc: hosting partition %d
\n
"
,
viopath_hostLp
);
while
(
atomic_read
(
&
wait_flag
)
==
0
)
mb
();
atomic_set
(
&
wait_flag
,
0
);
}
/*
* If we don't have an active console, try the primary
*/
if
((
!
viopath_isactive
(
port_info
[
0
].
lp
))
&&
(
viopath_isactive
(
HvLpConfig_getPrimaryLpIndex
()))
&&
(
send_open
(
HvLpConfig_getPrimaryLpIndex
(),
&
wait_flag
)
==
0
))
{
printk
(
KERN_INFO
"hvc: opening console to primary partition
\n
"
);
while
(
atomic_read
(
&
wait_flag
)
==
0
)
mb
();
}
/* Register as a vio device to receive callbacks */
rc
=
vio_register_driver
(
&
hvc_vio_driver
);
return
rc
;
}
module_init
(
hvc_vio_init
);
/* after drivers/char/hvc_console.c */
static
void
hvc_vio_exit
(
void
)
{
vio_unregister_driver
(
&
hvc_vio_driver
);
}
module_exit
(
hvc_vio_exit
);
/* the device tree order defines our numbering */
static
int
hvc_find_vtys
(
void
)
{
struct
device_node
*
vty
;
int
num_found
=
0
;
for
(
vty
=
of_find_node_by_name
(
NULL
,
"vty"
);
vty
!=
NULL
;
vty
=
of_find_node_by_name
(
vty
,
"vty"
))
{
uint32_t
*
vtermno
;
/* We have statically defined space for only a certain number
* of console adapters.
*/
if
((
num_found
>=
MAX_NR_HVC_CONSOLES
)
||
(
num_found
>=
VTTY_PORTS
))
break
;
vtermno
=
(
uint32_t
*
)
get_property
(
vty
,
"reg"
,
NULL
);
if
(
!
vtermno
)
continue
;
if
(
!
device_is_compatible
(
vty
,
"IBM,iSeries-vty"
))
continue
;
if
(
num_found
==
0
)
add_preferred_console
(
"hvc"
,
0
,
NULL
);
hvc_instantiate
(
*
vtermno
,
num_found
,
&
hvc_get_put_ops
);
++
num_found
;
}
return
num_found
;
}
console_initcall
(
hvc_find_vtys
);
drivers/char/hvc_rtas.c
View file @
20697cb7
...
...
@@ -94,7 +94,7 @@ static int hvc_rtas_init(void)
/* Allocate an hvc_struct for the console device we instantiated
* earlier. Save off hp so that we can return it on exit */
hp
=
hvc_alloc
(
hvc_rtas_cookie
,
NO_IRQ
,
&
hvc_rtas_get_put_ops
);
hp
=
hvc_alloc
(
hvc_rtas_cookie
,
NO_IRQ
,
&
hvc_rtas_get_put_ops
,
16
);
if
(
IS_ERR
(
hp
))
return
PTR_ERR
(
hp
);
...
...
drivers/char/hvc_vio.c
View file @
20697cb7
...
...
@@ -90,7 +90,8 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
if
(
!
vdev
||
!
id
)
return
-
EPERM
;
hp
=
hvc_alloc
(
vdev
->
unit_address
,
vdev
->
irq
,
&
hvc_get_put_ops
);
hp
=
hvc_alloc
(
vdev
->
unit_address
,
vdev
->
irq
,
&
hvc_get_put_ops
,
MAX_VIO_PUT_CHARS
);
if
(
IS_ERR
(
hp
))
return
PTR_ERR
(
hp
);
dev_set_drvdata
(
&
vdev
->
dev
,
hp
);
...
...
drivers/char/viocons.c
View file @
20697cb7
...
...
@@ -43,7 +43,6 @@
#include <linux/sysrq.h>
#include <asm/iseries/vio.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/hv_call_event.h>
#include <asm/iseries/hv_lp_config.h>
...
...
@@ -67,35 +66,6 @@ static int vio_sysrq_pressed;
extern
int
sysrq_enabled
;
#endif
/*
* The structure of the events that flow between us and OS/400. You can't
* mess with this unless the OS/400 side changes too
*/
struct
viocharlpevent
{
struct
HvLpEvent
event
;
u32
reserved
;
u16
version
;
u16
subtype_result_code
;
u8
virtual_device
;
u8
len
;
u8
data
[
VIOCHAR_MAX_DATA
];
};
#define VIOCHAR_WINDOW 10
#define VIOCHAR_HIGHWATERMARK 3
enum
viocharsubtype
{
viocharopen
=
0x0001
,
viocharclose
=
0x0002
,
viochardata
=
0x0003
,
viocharack
=
0x0004
,
viocharconfig
=
0x0005
};
enum
viochar_rc
{
viochar_rc_ebusy
=
1
};
#define VIOCHAR_NUM_BUF 16
/*
...
...
@@ -1183,6 +1153,7 @@ static int __init viocons_init(void)
port_info
[
i
].
magic
=
VIOTTY_MAGIC
;
}
HvCall_setLogBufferFormatAndCodepage
(
HvCall_LogBuffer_ASCII
,
437
);
add_preferred_console
(
"viocons"
,
0
,
NULL
);
register_console
(
&
viocons_early
);
return
0
;
}
...
...
include/asm-powerpc/iseries/vio.h
View file @
20697cb7
...
...
@@ -122,6 +122,34 @@ enum viorc {
viorc_openRejected
=
0x0301
};
/*
* The structure of the events that flow between us and OS/400 for chario
* events. You can't mess with this unless the OS/400 side changes too.
*/
struct
viocharlpevent
{
struct
HvLpEvent
event
;
u32
reserved
;
u16
version
;
u16
subtype_result_code
;
u8
virtual_device
;
u8
len
;
u8
data
[
VIOCHAR_MAX_DATA
];
};
#define VIOCHAR_WINDOW 10
enum
viocharsubtype
{
viocharopen
=
0x0001
,
viocharclose
=
0x0002
,
viochardata
=
0x0003
,
viocharack
=
0x0004
,
viocharconfig
=
0x0005
};
enum
viochar_rc
{
viochar_rc_ebusy
=
1
};
struct
device
;
extern
struct
device
*
iSeries_vio_dev
;
...
...
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