Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
20697cb7
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
20697cb7
编写于
7月 13, 2006
作者:
S
Stephen Rothwell
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'hvc_iseries'
上级
54f5cd8a
4e9e95a3
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
652 addition
and
41 deletion
+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
未找到文件。
arch/powerpc/platforms/iseries/Kconfig
浏览文件 @
20697cb7
...
...
@@ -3,13 +3,17 @@ 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"
help
If you are running on an iSeries system and you want to use
virtual disks created and managed by OS/400, say Y.
virtual disks created and managed by OS/400, say Y.
config VIOCD
tristate "iSeries Virtual I/O CD support"
...
...
arch/powerpc/platforms/iseries/dt.c
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录