Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
This commit is contained in:
Коммит
d27ba47e7e
|
@ -130,8 +130,6 @@ Code Seq# Include File Comments
|
|||
<mailto:zapman@interlan.net>
|
||||
'i' 00-3F linux/i2o.h
|
||||
'j' 00-3F linux/joystick.h
|
||||
'k' all asm-sparc/kbio.h
|
||||
asm-sparc64/kbio.h
|
||||
'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system
|
||||
<http://mikonos.dia.unisa.it/tcfs>
|
||||
'l' 40-7F linux/udf_fs_i.h in development:
|
||||
|
|
|
@ -201,6 +201,14 @@ config SUN_OPENPROMFS
|
|||
Only choose N if you know in advance that you will not need to modify
|
||||
OpenPROM settings on the running system.
|
||||
|
||||
config SPARC_LED
|
||||
tristate "Sun4m LED driver"
|
||||
help
|
||||
This driver toggles the front-panel LED on sun4m systems
|
||||
in a user-specifyable manner. It's state can be probed
|
||||
by reading /proc/led and it's blinking mode can be changed
|
||||
via writes to /proc/led
|
||||
|
||||
source "fs/Kconfig.binfmt"
|
||||
|
||||
config SUNOS_EMUL
|
||||
|
|
|
@ -21,6 +21,7 @@ obj-$(CONFIG_SUN_AUXIO) += auxio.o
|
|||
obj-$(CONFIG_PCI) += ebus.o
|
||||
obj-$(CONFIG_SUN_PM) += apc.o pmc.o
|
||||
obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o
|
||||
obj-$(CONFIG_SPARC_LED) += led.o
|
||||
|
||||
ifdef CONFIG_SUNOS_EMUL
|
||||
obj-y += sys_sunos.o sunos_ioctl.o
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/auxio.h>
|
||||
|
||||
#define LED_MAX_LENGTH 8 /* maximum chars written to proc file */
|
||||
|
||||
static inline void led_toggle(void)
|
||||
{
|
||||
unsigned char val = get_auxio();
|
||||
unsigned char on, off;
|
||||
|
||||
if (val & AUXIO_LED) {
|
||||
on = 0;
|
||||
off = AUXIO_LED;
|
||||
} else {
|
||||
on = AUXIO_LED;
|
||||
off = 0;
|
||||
}
|
||||
|
||||
set_auxio(on, off);
|
||||
}
|
||||
|
||||
static struct timer_list led_blink_timer;
|
||||
|
||||
static void led_blink(unsigned long timeout)
|
||||
{
|
||||
led_toggle();
|
||||
|
||||
/* reschedule */
|
||||
if (!timeout) { /* blink according to load */
|
||||
led_blink_timer.expires = jiffies +
|
||||
((1 + (avenrun[0] >> FSHIFT)) * HZ);
|
||||
led_blink_timer.data = 0;
|
||||
} else { /* blink at user specified interval */
|
||||
led_blink_timer.expires = jiffies + (timeout * HZ);
|
||||
led_blink_timer.data = timeout;
|
||||
}
|
||||
add_timer(&led_blink_timer);
|
||||
}
|
||||
|
||||
static int led_read_proc(char *buf, char **start, off_t offset, int count,
|
||||
int *eof, void *data)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (get_auxio() & AUXIO_LED)
|
||||
len = sprintf(buf, "on\n");
|
||||
else
|
||||
len = sprintf(buf, "off\n");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int led_write_proc(struct file *file, const char *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
char *buf = NULL;
|
||||
|
||||
if (count > LED_MAX_LENGTH)
|
||||
count = LED_MAX_LENGTH;
|
||||
|
||||
buf = kmalloc(sizeof(char) * (count + 1), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(buf, buffer, count)) {
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
buf[count] = '\0';
|
||||
|
||||
/* work around \n when echo'ing into proc */
|
||||
if (buf[count - 1] == '\n')
|
||||
buf[count - 1] = '\0';
|
||||
|
||||
/* before we change anything we want to stop any running timers,
|
||||
* otherwise calls such as on will have no persistent effect
|
||||
*/
|
||||
del_timer_sync(&led_blink_timer);
|
||||
|
||||
if (!strcmp(buf, "on")) {
|
||||
auxio_set_led(AUXIO_LED_ON);
|
||||
} else if (!strcmp(buf, "toggle")) {
|
||||
led_toggle();
|
||||
} else if ((*buf > '0') && (*buf <= '9')) {
|
||||
led_blink(simple_strtoul(buf, NULL, 10));
|
||||
} else if (!strcmp(buf, "load")) {
|
||||
led_blink(0);
|
||||
} else {
|
||||
auxio_set_led(AUXIO_LED_OFF);
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct proc_dir_entry *led;
|
||||
|
||||
#define LED_VERSION "0.1"
|
||||
|
||||
static int __init led_init(void)
|
||||
{
|
||||
init_timer(&led_blink_timer);
|
||||
led_blink_timer.function = led_blink;
|
||||
|
||||
led = create_proc_entry("led", 0, NULL);
|
||||
if (!led)
|
||||
return -ENOMEM;
|
||||
|
||||
led->read_proc = led_read_proc; /* reader function */
|
||||
led->write_proc = led_write_proc; /* writer function */
|
||||
led->owner = THIS_MODULE;
|
||||
|
||||
printk(KERN_INFO
|
||||
"led: version %s, Lars Kotthoff <metalhead@metalhead.ws>\n",
|
||||
LED_VERSION);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit led_exit(void)
|
||||
{
|
||||
remove_proc_entry("led", NULL);
|
||||
del_timer_sync(&led_blink_timer);
|
||||
}
|
||||
|
||||
module_init(led_init);
|
||||
module_exit(led_exit);
|
||||
|
||||
MODULE_AUTHOR("Lars Kotthoff <metalhead@metalhead.ws>");
|
||||
MODULE_DESCRIPTION("Provides control of the front LED on SPARC systems.");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(LED_VERSION);
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/smp_lock.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/file.h>
|
||||
#include <asm/kbio.h>
|
||||
|
||||
#if 0
|
||||
extern char sunkbd_type;
|
||||
|
|
|
@ -11,33 +11,14 @@
|
|||
|
||||
#define INCLUDES
|
||||
#include "compat_ioctl.c"
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <asm/fbio.h>
|
||||
#include <asm/kbio.h>
|
||||
#include <asm/vuid_event.h>
|
||||
#include <asm/envctrl.h>
|
||||
#include <asm/display7seg.h>
|
||||
#include <asm/openpromio.h>
|
||||
#include <asm/audioio.h>
|
||||
#include <asm/watchdog.h>
|
||||
|
||||
/* Use this to get at 32-bit user passed pointers.
|
||||
* See sys_sparc32.c for description about it.
|
||||
*/
|
||||
#define A(__x) compat_ptr(__x)
|
||||
|
||||
static __inline__ void *alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
|
||||
if (!(test_thread_flag(TIF_32BIT)))
|
||||
usp += STACK_BIAS;
|
||||
|
||||
return (void *) (usp - len);
|
||||
}
|
||||
|
||||
#define CODE
|
||||
#include "compat_ioctl.c"
|
||||
|
||||
|
@ -111,357 +92,6 @@ static int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg)
|
|||
return sys_ioctl (fd, FBIOSCURSOR, (unsigned long)p);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
|
||||
/* This really belongs in include/linux/drm.h -DaveM */
|
||||
#include "../../../drivers/char/drm/drm.h"
|
||||
|
||||
typedef struct drm32_version {
|
||||
int version_major; /* Major version */
|
||||
int version_minor; /* Minor version */
|
||||
int version_patchlevel;/* Patch level */
|
||||
int name_len; /* Length of name buffer */
|
||||
u32 name; /* Name of driver */
|
||||
int date_len; /* Length of date buffer */
|
||||
u32 date; /* User-space buffer to hold date */
|
||||
int desc_len; /* Length of desc buffer */
|
||||
u32 desc; /* User-space buffer to hold desc */
|
||||
} drm32_version_t;
|
||||
#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t)
|
||||
|
||||
static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm32_version_t __user *uversion = (drm32_version_t __user *)arg;
|
||||
drm_version_t __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
compat_uptr_t addr;
|
||||
int n;
|
||||
int ret;
|
||||
|
||||
if (clear_user(p, 3 * sizeof(int)) ||
|
||||
get_user(n, &uversion->name_len) ||
|
||||
put_user(n, &p->name_len) ||
|
||||
get_user(addr, &uversion->name) ||
|
||||
put_user(compat_ptr(addr), &p->name) ||
|
||||
get_user(n, &uversion->date_len) ||
|
||||
put_user(n, &p->date_len) ||
|
||||
get_user(addr, &uversion->date) ||
|
||||
put_user(compat_ptr(addr), &p->date) ||
|
||||
get_user(n, &uversion->desc_len) ||
|
||||
put_user(n, &p->desc_len) ||
|
||||
get_user(addr, &uversion->desc) ||
|
||||
put_user(compat_ptr(addr), &p->desc))
|
||||
return -EFAULT;
|
||||
|
||||
ret = sys_ioctl(fd, DRM_IOCTL_VERSION, (unsigned long)p);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (copy_in_user(uversion, p, 3 * sizeof(int)) ||
|
||||
get_user(n, &p->name_len) ||
|
||||
put_user(n, &uversion->name_len) ||
|
||||
get_user(n, &p->date_len) ||
|
||||
put_user(n, &uversion->date_len) ||
|
||||
get_user(n, &p->desc_len) ||
|
||||
put_user(n, &uversion->desc_len))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct drm32_unique {
|
||||
int unique_len; /* Length of unique */
|
||||
u32 unique; /* Unique name for driver instantiation */
|
||||
} drm32_unique_t;
|
||||
#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t)
|
||||
#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t)
|
||||
|
||||
static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm32_unique_t __user *uarg = (drm32_unique_t __user *)arg;
|
||||
drm_unique_t __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
compat_uptr_t addr;
|
||||
int n;
|
||||
int ret;
|
||||
|
||||
if (get_user(n, &uarg->unique_len) ||
|
||||
put_user(n, &p->unique_len) ||
|
||||
get_user(addr, &uarg->unique) ||
|
||||
put_user(compat_ptr(addr), &p->unique))
|
||||
return -EFAULT;
|
||||
|
||||
if (cmd == DRM32_IOCTL_GET_UNIQUE)
|
||||
ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)p);
|
||||
else
|
||||
ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)p);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (get_user(n, &p->unique_len) || put_user(n, &uarg->unique_len))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct drm32_map {
|
||||
u32 offset; /* Requested physical address (0 for SAREA)*/
|
||||
u32 size; /* Requested physical size (bytes) */
|
||||
drm_map_type_t type; /* Type of memory to map */
|
||||
drm_map_flags_t flags; /* Flags */
|
||||
u32 handle; /* User-space: "Handle" to pass to mmap */
|
||||
/* Kernel-space: kernel-virtual address */
|
||||
int mtrr; /* MTRR slot used */
|
||||
/* Private data */
|
||||
} drm32_map_t;
|
||||
#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t)
|
||||
|
||||
static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm32_map_t __user *uarg = (drm32_map_t __user *) arg;
|
||||
drm_map_t karg;
|
||||
mm_segment_t old_fs;
|
||||
u32 tmp;
|
||||
int ret;
|
||||
|
||||
ret = get_user(karg.offset, &uarg->offset);
|
||||
ret |= get_user(karg.size, &uarg->size);
|
||||
ret |= get_user(karg.type, &uarg->type);
|
||||
ret |= get_user(karg.flags, &uarg->flags);
|
||||
ret |= get_user(tmp, &uarg->handle);
|
||||
ret |= get_user(karg.mtrr, &uarg->mtrr);
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
|
||||
karg.handle = (void *) (unsigned long) tmp;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg);
|
||||
set_fs(old_fs);
|
||||
|
||||
if (!ret) {
|
||||
ret = put_user(karg.offset, &uarg->offset);
|
||||
ret |= put_user(karg.size, &uarg->size);
|
||||
ret |= put_user(karg.type, &uarg->type);
|
||||
ret |= put_user(karg.flags, &uarg->flags);
|
||||
tmp = (u32) (long)karg.handle;
|
||||
ret |= put_user(tmp, &uarg->handle);
|
||||
ret |= put_user(karg.mtrr, &uarg->mtrr);
|
||||
if (ret)
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct drm32_buf_info {
|
||||
int count; /* Entries in list */
|
||||
u32 list; /* (drm_buf_desc_t *) */
|
||||
} drm32_buf_info_t;
|
||||
#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t)
|
||||
|
||||
static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm32_buf_info_t __user *uarg = (drm32_buf_info_t __user *)arg;
|
||||
drm_buf_info_t __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
compat_uptr_t addr;
|
||||
int n;
|
||||
int ret;
|
||||
|
||||
if (get_user(n, &uarg->count) || put_user(n, &p->count) ||
|
||||
get_user(addr, &uarg->list) || put_user(compat_ptr(addr), &p->list))
|
||||
return -EFAULT;
|
||||
|
||||
ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long)p);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (get_user(n, &p->count) || put_user(n, &uarg->count))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct drm32_buf_free {
|
||||
int count;
|
||||
u32 list; /* (int *) */
|
||||
} drm32_buf_free_t;
|
||||
#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t)
|
||||
|
||||
static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm32_buf_free_t __user *uarg = (drm32_buf_free_t __user *)arg;
|
||||
drm_buf_free_t __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
compat_uptr_t addr;
|
||||
int n;
|
||||
|
||||
if (get_user(n, &uarg->count) || put_user(n, &p->count) ||
|
||||
get_user(addr, &uarg->list) || put_user(compat_ptr(addr), &p->list))
|
||||
return -EFAULT;
|
||||
|
||||
return sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long)p);
|
||||
}
|
||||
|
||||
typedef struct drm32_buf_pub {
|
||||
int idx; /* Index into master buflist */
|
||||
int total; /* Buffer size */
|
||||
int used; /* Amount of buffer in use (for DMA) */
|
||||
u32 address; /* Address of buffer (void *) */
|
||||
} drm32_buf_pub_t;
|
||||
|
||||
typedef struct drm32_buf_map {
|
||||
int count; /* Length of buflist */
|
||||
u32 virtual; /* Mmaped area in user-virtual (void *) */
|
||||
u32 list; /* Buffer information (drm_buf_pub_t *) */
|
||||
} drm32_buf_map_t;
|
||||
#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t)
|
||||
|
||||
static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm32_buf_map_t __user *uarg = (drm32_buf_map_t __user *)arg;
|
||||
drm32_buf_pub_t __user *ulist;
|
||||
drm_buf_map_t __user *arg64;
|
||||
drm_buf_pub_t __user *list;
|
||||
int orig_count, ret, i;
|
||||
int n;
|
||||
compat_uptr_t addr;
|
||||
|
||||
if (get_user(orig_count, &uarg->count))
|
||||
return -EFAULT;
|
||||
|
||||
arg64 = compat_alloc_user_space(sizeof(drm_buf_map_t) +
|
||||
(size_t)orig_count * sizeof(drm_buf_pub_t));
|
||||
list = (void __user *)(arg64 + 1);
|
||||
|
||||
if (put_user(orig_count, &arg64->count) ||
|
||||
put_user(list, &arg64->list) ||
|
||||
get_user(addr, &uarg->virtual) ||
|
||||
put_user(compat_ptr(addr), &arg64->virtual) ||
|
||||
get_user(addr, &uarg->list))
|
||||
return -EFAULT;
|
||||
|
||||
ulist = compat_ptr(addr);
|
||||
|
||||
for (i = 0; i < orig_count; i++) {
|
||||
if (get_user(n, &ulist[i].idx) ||
|
||||
put_user(n, &list[i].idx) ||
|
||||
get_user(n, &ulist[i].total) ||
|
||||
put_user(n, &list[i].total) ||
|
||||
get_user(n, &ulist[i].used) ||
|
||||
put_user(n, &list[i].used) ||
|
||||
get_user(addr, &ulist[i].address) ||
|
||||
put_user(compat_ptr(addr), &list[i].address))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) arg64);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < orig_count; i++) {
|
||||
void __user *p;
|
||||
if (get_user(n, &list[i].idx) ||
|
||||
put_user(n, &ulist[i].idx) ||
|
||||
get_user(n, &list[i].total) ||
|
||||
put_user(n, &ulist[i].total) ||
|
||||
get_user(n, &list[i].used) ||
|
||||
put_user(n, &ulist[i].used) ||
|
||||
get_user(p, &list[i].address) ||
|
||||
put_user((unsigned long)p, &ulist[i].address))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (get_user(n, &arg64->count) || put_user(n, &uarg->count))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct drm32_dma {
|
||||
/* Indices here refer to the offset into
|
||||
buflist in drm_buf_get_t. */
|
||||
int context; /* Context handle */
|
||||
int send_count; /* Number of buffers to send */
|
||||
u32 send_indices; /* List of handles to buffers (int *) */
|
||||
u32 send_sizes; /* Lengths of data to send (int *) */
|
||||
drm_dma_flags_t flags; /* Flags */
|
||||
int request_count; /* Number of buffers requested */
|
||||
int request_size; /* Desired size for buffers */
|
||||
u32 request_indices; /* Buffer information (int *) */
|
||||
u32 request_sizes; /* (int *) */
|
||||
int granted_count; /* Number of buffers granted */
|
||||
} drm32_dma_t;
|
||||
#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t)
|
||||
|
||||
/* RED PEN The DRM layer blindly dereferences the send/request
|
||||
* index/size arrays even though they are userland
|
||||
* pointers. -DaveM
|
||||
*/
|
||||
static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm32_dma_t __user *uarg = (drm32_dma_t __user *) arg;
|
||||
drm_dma_t __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
compat_uptr_t addr;
|
||||
int ret;
|
||||
|
||||
if (copy_in_user(p, uarg, 2 * sizeof(int)) ||
|
||||
get_user(addr, &uarg->send_indices) ||
|
||||
put_user(compat_ptr(addr), &p->send_indices) ||
|
||||
get_user(addr, &uarg->send_sizes) ||
|
||||
put_user(compat_ptr(addr), &p->send_sizes) ||
|
||||
copy_in_user(&p->flags, &uarg->flags, sizeof(drm_dma_flags_t)) ||
|
||||
copy_in_user(&p->request_count, &uarg->request_count, sizeof(int))||
|
||||
copy_in_user(&p->request_size, &uarg->request_size, sizeof(int)) ||
|
||||
get_user(addr, &uarg->request_indices) ||
|
||||
put_user(compat_ptr(addr), &p->request_indices) ||
|
||||
get_user(addr, &uarg->request_sizes) ||
|
||||
put_user(compat_ptr(addr), &p->request_sizes) ||
|
||||
copy_in_user(&p->granted_count, &uarg->granted_count, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long)p);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (copy_in_user(uarg, p, 2 * sizeof(int)) ||
|
||||
copy_in_user(&uarg->flags, &p->flags, sizeof(drm_dma_flags_t)) ||
|
||||
copy_in_user(&uarg->request_count, &p->request_count, sizeof(int))||
|
||||
copy_in_user(&uarg->request_size, &p->request_size, sizeof(int)) ||
|
||||
copy_in_user(&uarg->granted_count, &p->granted_count, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct drm32_ctx_res {
|
||||
int count;
|
||||
u32 contexts; /* (drm_ctx_t *) */
|
||||
} drm32_ctx_res_t;
|
||||
#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t)
|
||||
|
||||
static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
drm32_ctx_res_t __user *uarg = (drm32_ctx_res_t __user *) arg;
|
||||
drm_ctx_res_t __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
compat_uptr_t addr;
|
||||
int ret;
|
||||
|
||||
if (copy_in_user(p, uarg, sizeof(int)) ||
|
||||
get_user(addr, &uarg->contexts) ||
|
||||
put_user(compat_ptr(addr), &p->contexts))
|
||||
return -EFAULT;
|
||||
|
||||
ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long)p);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (copy_in_user(uarg, p, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *);
|
||||
|
||||
#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl)
|
||||
|
@ -485,103 +115,14 @@ COMPATIBLE_IOCTL(FBIOSCURPOS)
|
|||
COMPATIBLE_IOCTL(FBIOGCURPOS)
|
||||
COMPATIBLE_IOCTL(FBIOGCURMAX)
|
||||
/* Little k */
|
||||
COMPATIBLE_IOCTL(KIOCTYPE)
|
||||
COMPATIBLE_IOCTL(KIOCLAYOUT)
|
||||
COMPATIBLE_IOCTL(KIOCGTRANS)
|
||||
COMPATIBLE_IOCTL(KIOCTRANS)
|
||||
COMPATIBLE_IOCTL(KIOCCMD)
|
||||
COMPATIBLE_IOCTL(KIOCSDIRECT)
|
||||
COMPATIBLE_IOCTL(KIOCSLED)
|
||||
COMPATIBLE_IOCTL(KIOCGLED)
|
||||
COMPATIBLE_IOCTL(KIOCSRATE)
|
||||
COMPATIBLE_IOCTL(KIOCGRATE)
|
||||
COMPATIBLE_IOCTL(VUIDSFORMAT)
|
||||
COMPATIBLE_IOCTL(VUIDGFORMAT)
|
||||
/* Little v, the video4linux ioctls */
|
||||
COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */
|
||||
COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_WARNING_TEMPERATURE)
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_SHUTDOWN_TEMPERATURE)
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_CPU_TEMPERATURE)
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_FAN_STATUS)
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_VOLTAGE_STATUS)
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_SCSI_TEMPERATURE)
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_ETHERNET_TEMPERATURE)
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_MTHRBD_TEMPERATURE)
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_CPU_VOLTAGE)
|
||||
COMPATIBLE_IOCTL(ENVCTRL_RD_GLOBALADDRESS)
|
||||
/* COMPATIBLE_IOCTL(D7SIOCRD) same value as ENVCTRL_RD_VOLTAGE_STATUS */
|
||||
COMPATIBLE_IOCTL(D7SIOCWR)
|
||||
COMPATIBLE_IOCTL(D7SIOCTM)
|
||||
/* OPENPROMIO, SunOS/Solaris only, the NetBSD one's have
|
||||
* embedded pointers in the arg which we'd need to clean up...
|
||||
*/
|
||||
COMPATIBLE_IOCTL(OPROMGETOPT)
|
||||
COMPATIBLE_IOCTL(OPROMSETOPT)
|
||||
COMPATIBLE_IOCTL(OPROMNXTOPT)
|
||||
COMPATIBLE_IOCTL(OPROMSETOPT2)
|
||||
COMPATIBLE_IOCTL(OPROMNEXT)
|
||||
COMPATIBLE_IOCTL(OPROMCHILD)
|
||||
COMPATIBLE_IOCTL(OPROMGETPROP)
|
||||
COMPATIBLE_IOCTL(OPROMNXTPROP)
|
||||
COMPATIBLE_IOCTL(OPROMU2P)
|
||||
COMPATIBLE_IOCTL(OPROMGETCONS)
|
||||
COMPATIBLE_IOCTL(OPROMGETFBNAME)
|
||||
COMPATIBLE_IOCTL(OPROMGETBOOTARGS)
|
||||
COMPATIBLE_IOCTL(OPROMSETCUR)
|
||||
COMPATIBLE_IOCTL(OPROMPCI2NODE)
|
||||
COMPATIBLE_IOCTL(OPROMPATH2NODE)
|
||||
/* Big L */
|
||||
COMPATIBLE_IOCTL(LOOP_SET_STATUS64)
|
||||
COMPATIBLE_IOCTL(LOOP_GET_STATUS64)
|
||||
/* Big A */
|
||||
COMPATIBLE_IOCTL(AUDIO_GETINFO)
|
||||
COMPATIBLE_IOCTL(AUDIO_SETINFO)
|
||||
COMPATIBLE_IOCTL(AUDIO_DRAIN)
|
||||
COMPATIBLE_IOCTL(AUDIO_GETDEV)
|
||||
COMPATIBLE_IOCTL(AUDIO_GETDEV_SUNOS)
|
||||
COMPATIBLE_IOCTL(AUDIO_FLUSH)
|
||||
COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI)
|
||||
#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_LOCK)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK)
|
||||
COMPATIBLE_IOCTL(DRM_IOCTL_FINISH)
|
||||
#endif /* DRM */
|
||||
COMPATIBLE_IOCTL(WIOCSTART)
|
||||
COMPATIBLE_IOCTL(WIOCSTOP)
|
||||
COMPATIBLE_IOCTL(WIOCGSTAT)
|
||||
/* And these ioctls need translation */
|
||||
/* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
|
||||
HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap)
|
||||
HANDLE_IOCTL(FBIOGETCMAP32, fbiogetputcmap)
|
||||
HANDLE_IOCTL(FBIOSCURSOR32, fbiogscursor)
|
||||
#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
|
||||
HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version)
|
||||
HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique)
|
||||
HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique)
|
||||
HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap)
|
||||
HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs)
|
||||
HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs)
|
||||
HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs)
|
||||
HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma)
|
||||
HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx)
|
||||
#endif /* DRM */
|
||||
#if 0
|
||||
HANDLE_IOCTL(RTC32_IRQP_READ, do_rtc_ioctl)
|
||||
HANDLE_IOCTL(RTC32_IRQP_SET, do_rtc_ioctl)
|
||||
|
|
|
@ -154,6 +154,7 @@ int prom_callback(long *args)
|
|||
pud_t *pudp;
|
||||
pmd_t *pmdp;
|
||||
pte_t *ptep;
|
||||
pte_t pte;
|
||||
|
||||
for_each_process(p) {
|
||||
mm = p->mm;
|
||||
|
@ -178,8 +179,9 @@ int prom_callback(long *args)
|
|||
* being called from inside OBP.
|
||||
*/
|
||||
ptep = pte_offset_map(pmdp, va);
|
||||
if (pte_present(*ptep)) {
|
||||
tte = pte_val(*ptep);
|
||||
pte = *ptep;
|
||||
if (pte_present(pte)) {
|
||||
tte = pte_val(pte);
|
||||
res = PROM_TRUE;
|
||||
}
|
||||
pte_unmap(ptep);
|
||||
|
@ -218,6 +220,7 @@ int prom_callback(long *args)
|
|||
pud_t *pudp;
|
||||
pmd_t *pmdp;
|
||||
pte_t *ptep;
|
||||
pte_t pte;
|
||||
int error;
|
||||
|
||||
if ((va >= LOW_OBP_ADDRESS) && (va < HI_OBP_ADDRESS)) {
|
||||
|
@ -240,8 +243,9 @@ int prom_callback(long *args)
|
|||
* being called from inside OBP.
|
||||
*/
|
||||
ptep = pte_offset_kernel(pmdp, va);
|
||||
if (pte_present(*ptep)) {
|
||||
tte = pte_val(*ptep);
|
||||
pte = *ptep;
|
||||
if (pte_present(pte)) {
|
||||
tte = pte_val(pte);
|
||||
res = PROM_TRUE;
|
||||
}
|
||||
goto done;
|
||||
|
|
|
@ -863,6 +863,7 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
|||
pud_t *pudp = pud_offset(pgdp, address);
|
||||
pmd_t *pmdp = pmd_offset(pudp, address);
|
||||
pte_t *ptep;
|
||||
pte_t pte;
|
||||
|
||||
regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
|
||||
|
||||
|
@ -873,9 +874,10 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
|||
|
||||
preempt_disable();
|
||||
ptep = pte_offset_map(pmdp, address);
|
||||
if (pte_present(*ptep)) {
|
||||
pte = *ptep;
|
||||
if (pte_present(pte)) {
|
||||
unsigned long page = (unsigned long)
|
||||
page_address(pte_page(*ptep));
|
||||
page_address(pte_page(pte));
|
||||
|
||||
wmb();
|
||||
__asm__ __volatile__("flush %0 + %1"
|
||||
|
|
|
@ -839,43 +839,29 @@ void smp_flush_tlb_all(void)
|
|||
* questionable (in theory the big win for threads is the massive sharing of
|
||||
* address space state across processors).
|
||||
*/
|
||||
|
||||
/* This currently is only used by the hugetlb arch pre-fault
|
||||
* hook on UltraSPARC-III+ and later when changing the pagesize
|
||||
* bits of the context register for an address space.
|
||||
*/
|
||||
void smp_flush_tlb_mm(struct mm_struct *mm)
|
||||
{
|
||||
/*
|
||||
* This code is called from two places, dup_mmap and exit_mmap. In the
|
||||
* former case, we really need a flush. In the later case, the callers
|
||||
* are single threaded exec_mmap (really need a flush), multithreaded
|
||||
* exec_mmap case (do not need to flush, since the caller gets a new
|
||||
* context via activate_mm), and all other callers of mmput() whence
|
||||
* the flush can be optimized since the associated threads are dead and
|
||||
* the mm is being torn down (__exit_mm and other mmput callers) or the
|
||||
* owning thread is dissociating itself from the mm. The
|
||||
* (atomic_read(&mm->mm_users) == 0) check ensures real work is done
|
||||
* for single thread exec and dup_mmap cases. An alternate check might
|
||||
* have been (current->mm != mm).
|
||||
* Kanoj Sarcar
|
||||
*/
|
||||
if (atomic_read(&mm->mm_users) == 0)
|
||||
return;
|
||||
u32 ctx = CTX_HWBITS(mm->context);
|
||||
int cpu = get_cpu();
|
||||
|
||||
{
|
||||
u32 ctx = CTX_HWBITS(mm->context);
|
||||
int cpu = get_cpu();
|
||||
|
||||
if (atomic_read(&mm->mm_users) == 1) {
|
||||
mm->cpu_vm_mask = cpumask_of_cpu(cpu);
|
||||
goto local_flush_and_out;
|
||||
}
|
||||
|
||||
smp_cross_call_masked(&xcall_flush_tlb_mm,
|
||||
ctx, 0, 0,
|
||||
mm->cpu_vm_mask);
|
||||
|
||||
local_flush_and_out:
|
||||
__flush_tlb_mm(ctx, SECONDARY_CONTEXT);
|
||||
|
||||
put_cpu();
|
||||
if (atomic_read(&mm->mm_users) == 1) {
|
||||
mm->cpu_vm_mask = cpumask_of_cpu(cpu);
|
||||
goto local_flush_and_out;
|
||||
}
|
||||
|
||||
smp_cross_call_masked(&xcall_flush_tlb_mm,
|
||||
ctx, 0, 0,
|
||||
mm->cpu_vm_mask);
|
||||
|
||||
local_flush_and_out:
|
||||
__flush_tlb_mm(ctx, SECONDARY_CONTEXT);
|
||||
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs)
|
||||
|
@ -883,34 +869,13 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long
|
|||
u32 ctx = CTX_HWBITS(mm->context);
|
||||
int cpu = get_cpu();
|
||||
|
||||
if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) {
|
||||
if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1)
|
||||
mm->cpu_vm_mask = cpumask_of_cpu(cpu);
|
||||
goto local_flush_and_out;
|
||||
} else {
|
||||
/* This optimization is not valid. Normally
|
||||
* we will be holding the page_table_lock, but
|
||||
* there is an exception which is copy_page_range()
|
||||
* when forking. The lock is held during the individual
|
||||
* page table updates in the parent, but not at the
|
||||
* top level, which is where we are invoked.
|
||||
*/
|
||||
if (0) {
|
||||
cpumask_t this_cpu_mask = cpumask_of_cpu(cpu);
|
||||
else
|
||||
smp_cross_call_masked(&xcall_flush_tlb_pending,
|
||||
ctx, nr, (unsigned long) vaddrs,
|
||||
mm->cpu_vm_mask);
|
||||
|
||||
/* By virtue of running under the mm->page_table_lock,
|
||||
* and mmu_context.h:switch_mm doing the same, the
|
||||
* following operation is safe.
|
||||
*/
|
||||
if (cpus_equal(mm->cpu_vm_mask, this_cpu_mask))
|
||||
goto local_flush_and_out;
|
||||
}
|
||||
}
|
||||
|
||||
smp_cross_call_masked(&xcall_flush_tlb_pending,
|
||||
ctx, nr, (unsigned long) vaddrs,
|
||||
mm->cpu_vm_mask);
|
||||
|
||||
local_flush_and_out:
|
||||
__flush_tlb_pending(ctx, nr, vaddrs);
|
||||
|
||||
put_cpu();
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <linux/smp_lock.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/compat.h>
|
||||
#include <asm/kbio.h>
|
||||
|
||||
#define SUNOS_NR_OPEN 256
|
||||
|
||||
|
|
|
@ -60,17 +60,6 @@ static void __iomem *mstk48t59_regs;
|
|||
|
||||
static int set_rtc_mmss(unsigned long);
|
||||
|
||||
static __init unsigned long dummy_get_tick(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __initdata struct sparc64_tick_ops dummy_tick_ops = {
|
||||
.get_tick = dummy_get_tick,
|
||||
};
|
||||
|
||||
struct sparc64_tick_ops *tick_ops __read_mostly = &dummy_tick_ops;
|
||||
|
||||
#define TICK_PRIV_BIT (1UL << 63)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -200,6 +189,8 @@ static struct sparc64_tick_ops tick_operations __read_mostly = {
|
|||
.softint_mask = 1UL << 0,
|
||||
};
|
||||
|
||||
struct sparc64_tick_ops *tick_ops __read_mostly = &tick_operations;
|
||||
|
||||
static void stick_init_tick(unsigned long offset)
|
||||
{
|
||||
tick_disable_protection();
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/ebus.h>
|
||||
#include <asm/oplib.h>
|
||||
|
@ -394,6 +395,28 @@ static int wd_ioctl(struct inode *inode, struct file *file,
|
|||
return(0);
|
||||
}
|
||||
|
||||
static long wd_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int rval = -ENOIOCTLCMD;
|
||||
|
||||
switch (cmd) {
|
||||
/* solaris ioctls are specific to this driver */
|
||||
case WIOCSTART:
|
||||
case WIOCSTOP:
|
||||
case WIOCGSTAT:
|
||||
lock_kernel();
|
||||
rval = wd_ioctl(file->f_dentry->d_inode, file, cmd, arg);
|
||||
lock_kernel();
|
||||
break;
|
||||
/* everything else is handled by the generic compat layer */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static ssize_t wd_write(struct file *file,
|
||||
const char __user *buf,
|
||||
size_t count,
|
||||
|
@ -441,6 +464,7 @@ static irqreturn_t wd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
static struct file_operations wd_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = wd_ioctl,
|
||||
.compat_ioctl = wd_compat_ioctl,
|
||||
.open = wd_open,
|
||||
.write = wd_write,
|
||||
.read = wd_read,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/ioport.h> /* request_region */
|
||||
#include <linux/smp_lock.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/ebus.h> /* EBus device */
|
||||
#include <asm/oplib.h> /* OpenProm Library */
|
||||
|
@ -114,22 +115,25 @@ static int d7s_release(struct inode *inode, struct file *f)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int d7s_ioctl(struct inode *inode, struct file *f,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
__u8 regs = readb(d7s_regs);
|
||||
__u8 ireg = 0;
|
||||
int error = 0
|
||||
|
||||
if (D7S_MINOR != iminor(inode))
|
||||
if (D7S_MINOR != iminor(file->f_dentry->d_inode))
|
||||
return -ENODEV;
|
||||
|
||||
lock_kernel();
|
||||
switch (cmd) {
|
||||
case D7SIOCWR:
|
||||
/* assign device register values
|
||||
* we mask-out D7S_FLIP if in sol_compat mode
|
||||
*/
|
||||
if (get_user(ireg, (int __user *) arg))
|
||||
return -EFAULT;
|
||||
if (get_user(ireg, (int __user *) arg)) {
|
||||
error = -EFAULT;
|
||||
break;
|
||||
}
|
||||
if (0 != sol_compat) {
|
||||
(regs & D7S_FLIP) ?
|
||||
(ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP);
|
||||
|
@ -144,8 +148,10 @@ static int d7s_ioctl(struct inode *inode, struct file *f,
|
|||
* This driver will not misinform you about the state
|
||||
* of your hardware while in sol_compat mode
|
||||
*/
|
||||
if (put_user(regs, (int __user *) arg))
|
||||
return -EFAULT;
|
||||
if (put_user(regs, (int __user *) arg)) {
|
||||
error = -EFAULT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case D7SIOCTM:
|
||||
|
@ -155,15 +161,17 @@ static int d7s_ioctl(struct inode *inode, struct file *f,
|
|||
writeb(regs, d7s_regs);
|
||||
break;
|
||||
};
|
||||
lock_kernel();
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static struct file_operations d7s_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = d7s_ioctl,
|
||||
.open = d7s_open,
|
||||
.release = d7s_release,
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = d7s_ioctl,
|
||||
.compat_ioctl = d7s_ioctl,
|
||||
.open = d7s_open,
|
||||
.release = d7s_release,
|
||||
};
|
||||
|
||||
static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops };
|
||||
|
|
|
@ -654,9 +654,8 @@ envctrl_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
|
|||
/* Function Description: Command what to read. Mapped to user ioctl().
|
||||
* Return: Gives 0 for implemented commands, -EINVAL otherwise.
|
||||
*/
|
||||
static int
|
||||
envctrl_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static long
|
||||
envctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
char __user *infobuf;
|
||||
|
||||
|
@ -715,11 +714,14 @@ envctrl_release(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
static struct file_operations envctrl_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = envctrl_read,
|
||||
.ioctl = envctrl_ioctl,
|
||||
.open = envctrl_open,
|
||||
.release = envctrl_release,
|
||||
.owner = THIS_MODULE,
|
||||
.read = envctrl_read,
|
||||
.unlocked_ioctl = envctrl_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = envctrl_ioctl,
|
||||
#endif
|
||||
.open = envctrl_open,
|
||||
.release = envctrl_release,
|
||||
};
|
||||
|
||||
static struct miscdevice envctrl_dev = {
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <asm/oplib.h>
|
||||
|
@ -565,6 +566,38 @@ static int openprom_ioctl(struct inode * inode, struct file * file,
|
|||
}
|
||||
}
|
||||
|
||||
static long openprom_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
long rval = -ENOTTY;
|
||||
|
||||
/*
|
||||
* SunOS/Solaris only, the NetBSD one's have embedded pointers in
|
||||
* the arg which we'd need to clean up...
|
||||
*/
|
||||
switch (cmd) {
|
||||
case OPROMGETOPT:
|
||||
case OPROMSETOPT:
|
||||
case OPROMNXTOPT:
|
||||
case OPROMSETOPT2:
|
||||
case OPROMNEXT:
|
||||
case OPROMCHILD:
|
||||
case OPROMGETPROP:
|
||||
case OPROMNXTPROP:
|
||||
case OPROMU2P:
|
||||
case OPROMGETCONS:
|
||||
case OPROMGETFBNAME:
|
||||
case OPROMGETBOOTARGS:
|
||||
case OPROMSETCUR:
|
||||
case OPROMPCI2NODE:
|
||||
case OPROMPATH2NODE:
|
||||
lock_kernel();
|
||||
rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg);
|
||||
lock_kernel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int openprom_open(struct inode * inode, struct file * file)
|
||||
{
|
||||
DATA *data;
|
||||
|
|
|
@ -1441,7 +1441,7 @@ static void sunsu_console_write(struct console *co, const char *s,
|
|||
* - initialize the serial port
|
||||
* Return non-zero if we didn't find a serial port.
|
||||
*/
|
||||
static int __init sunsu_console_setup(struct console *co, char *options)
|
||||
static int sunsu_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int baud = 9600;
|
||||
|
|
|
@ -653,12 +653,6 @@ static void cg6_chip_init(struct fb_info *info)
|
|||
sbus_writel(0, &fbc->clipminy);
|
||||
sbus_writel(info->var.xres - 1, &fbc->clipmaxx);
|
||||
sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
|
||||
|
||||
/* Disable cursor in Brooktree DAC. */
|
||||
sbus_writel(0x06 << 24, &par->bt->addr);
|
||||
tmp = sbus_readl(&par->bt->control);
|
||||
tmp &= ~(0x03 << 24);
|
||||
sbus_writel(tmp, &par->bt->control);
|
||||
}
|
||||
|
||||
struct all_info {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include <asm-sparc/kbio.h>
|
|
@ -1,4 +0,0 @@
|
|||
#ifndef _M68K_VUID_EVENT_H
|
||||
#define _M68K_VUID_EVENT_H
|
||||
#include <asm-sparc/vuid_event.h>
|
||||
#endif
|
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* include/asm-sparc/audioio.h
|
||||
*
|
||||
* Sparc Audio Midlayer
|
||||
* Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
|
||||
*/
|
||||
|
||||
#ifndef _AUDIOIO_H_
|
||||
#define _AUDIOIO_H_
|
||||
|
||||
/*
|
||||
* SunOS/Solaris /dev/audio interface
|
||||
*/
|
||||
|
||||
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
|
||||
#include <linux/types.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/ioctl.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This structure contains state information for audio device IO streams.
|
||||
*/
|
||||
typedef struct audio_prinfo {
|
||||
/*
|
||||
* The following values describe the audio data encoding.
|
||||
*/
|
||||
unsigned int sample_rate; /* samples per second */
|
||||
unsigned int channels; /* number of interleaved channels */
|
||||
unsigned int precision; /* bit-width of each sample */
|
||||
unsigned int encoding; /* data encoding method */
|
||||
|
||||
/*
|
||||
* The following values control audio device configuration
|
||||
*/
|
||||
unsigned int gain; /* gain level: 0 - 255 */
|
||||
unsigned int port; /* selected I/O port (see below) */
|
||||
unsigned int avail_ports; /* available I/O ports (see below) */
|
||||
unsigned int _xxx[2]; /* Reserved for future use */
|
||||
|
||||
unsigned int buffer_size; /* I/O buffer size */
|
||||
|
||||
/*
|
||||
* The following values describe driver state
|
||||
*/
|
||||
unsigned int samples; /* number of samples converted */
|
||||
unsigned int eof; /* End Of File counter (play only) */
|
||||
|
||||
unsigned char pause; /* non-zero for pause, zero to resume */
|
||||
unsigned char error; /* non-zero if overflow/underflow */
|
||||
unsigned char waiting; /* non-zero if a process wants access */
|
||||
unsigned char balance; /* stereo channel balance */
|
||||
|
||||
unsigned short minordev;
|
||||
|
||||
/*
|
||||
* The following values are read-only state flags
|
||||
*/
|
||||
unsigned char open; /* non-zero if open access permitted */
|
||||
unsigned char active; /* non-zero if I/O is active */
|
||||
} audio_prinfo_t;
|
||||
|
||||
|
||||
/*
|
||||
* This structure describes the current state of the audio device.
|
||||
*/
|
||||
typedef struct audio_info {
|
||||
/*
|
||||
* Per-stream information
|
||||
*/
|
||||
audio_prinfo_t play; /* output status information */
|
||||
audio_prinfo_t record; /* input status information */
|
||||
|
||||
/*
|
||||
* Per-unit/channel information
|
||||
*/
|
||||
unsigned int monitor_gain; /* input to output mix: 0 - 255 */
|
||||
unsigned char output_muted; /* non-zero if output is muted */
|
||||
unsigned char _xxx[3]; /* Reserved for future use */
|
||||
unsigned int _yyy[3]; /* Reserved for future use */
|
||||
} audio_info_t;
|
||||
|
||||
|
||||
/*
|
||||
* Audio encoding types
|
||||
*/
|
||||
#define AUDIO_ENCODING_NONE (0) /* no encoding assigned */
|
||||
#define AUDIO_ENCODING_ULAW (1) /* u-law encoding */
|
||||
#define AUDIO_ENCODING_ALAW (2) /* A-law encoding */
|
||||
#define AUDIO_ENCODING_LINEAR (3) /* Linear PCM encoding */
|
||||
#define AUDIO_ENCODING_FLOAT (4) /* IEEE float (-1. <-> +1.) */
|
||||
#define AUDIO_ENCODING_DVI (104) /* DVI ADPCM */
|
||||
#define AUDIO_ENCODING_LINEAR8 (105) /* 8 bit UNSIGNED */
|
||||
#define AUDIO_ENCODING_LINEARLE (106) /* Linear PCM LE encoding */
|
||||
|
||||
/*
|
||||
* These ranges apply to record, play, and monitor gain values
|
||||
*/
|
||||
#define AUDIO_MIN_GAIN (0) /* minimum gain value */
|
||||
#define AUDIO_MAX_GAIN (255) /* maximum gain value */
|
||||
|
||||
/*
|
||||
* These values apply to the balance field to adjust channel gain values
|
||||
*/
|
||||
#define AUDIO_LEFT_BALANCE (0) /* left channel only */
|
||||
#define AUDIO_MID_BALANCE (32) /* equal left/right channel */
|
||||
#define AUDIO_RIGHT_BALANCE (64) /* right channel only */
|
||||
#define AUDIO_BALANCE_SHIFT (3)
|
||||
|
||||
/*
|
||||
* Generic minimum/maximum limits for number of channels, both modes
|
||||
*/
|
||||
#define AUDIO_MIN_PLAY_CHANNELS (1)
|
||||
#define AUDIO_MAX_PLAY_CHANNELS (4)
|
||||
#define AUDIO_MIN_REC_CHANNELS (1)
|
||||
#define AUDIO_MAX_REC_CHANNELS (4)
|
||||
|
||||
/*
|
||||
* Generic minimum/maximum limits for sample precision
|
||||
*/
|
||||
#define AUDIO_MIN_PLAY_PRECISION (8)
|
||||
#define AUDIO_MAX_PLAY_PRECISION (32)
|
||||
#define AUDIO_MIN_REC_PRECISION (8)
|
||||
#define AUDIO_MAX_REC_PRECISION (32)
|
||||
|
||||
/*
|
||||
* Define some convenient names for typical audio ports
|
||||
*/
|
||||
/*
|
||||
* output ports (several may be enabled simultaneously)
|
||||
*/
|
||||
#define AUDIO_SPEAKER 0x01 /* output to built-in speaker */
|
||||
#define AUDIO_HEADPHONE 0x02 /* output to headphone jack */
|
||||
#define AUDIO_LINE_OUT 0x04 /* output to line out */
|
||||
|
||||
/*
|
||||
* input ports (usually only one at a time)
|
||||
*/
|
||||
#define AUDIO_MICROPHONE 0x01 /* input from microphone */
|
||||
#define AUDIO_LINE_IN 0x02 /* input from line in */
|
||||
#define AUDIO_CD 0x04 /* input from on-board CD inputs */
|
||||
#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* input from internal CDROM */
|
||||
#define AUDIO_ANALOG_LOOPBACK 0x40 /* input from output */
|
||||
|
||||
|
||||
/*
|
||||
* This macro initializes an audio_info structure to 'harmless' values.
|
||||
* Note that (~0) might not be a harmless value for a flag that was
|
||||
* a signed int.
|
||||
*/
|
||||
#define AUDIO_INITINFO(i) { \
|
||||
unsigned int *__x__; \
|
||||
for (__x__ = (unsigned int *)(i); \
|
||||
(char *) __x__ < (((char *)(i)) + sizeof (audio_info_t)); \
|
||||
*__x__++ = ~0); \
|
||||
}
|
||||
|
||||
/*
|
||||
* These allow testing for what the user wants to set
|
||||
*/
|
||||
#define AUD_INITVALUE (~0)
|
||||
#define Modify(X) ((unsigned int)(X) != AUD_INITVALUE)
|
||||
#define Modifys(X) ((X) != (unsigned short)AUD_INITVALUE)
|
||||
#define Modifyc(X) ((X) != (unsigned char)AUD_INITVALUE)
|
||||
|
||||
/*
|
||||
* Parameter for the AUDIO_GETDEV ioctl to determine current
|
||||
* audio devices.
|
||||
*/
|
||||
#define MAX_AUDIO_DEV_LEN (16)
|
||||
typedef struct audio_device {
|
||||
char name[MAX_AUDIO_DEV_LEN];
|
||||
char version[MAX_AUDIO_DEV_LEN];
|
||||
char config[MAX_AUDIO_DEV_LEN];
|
||||
} audio_device_t;
|
||||
|
||||
|
||||
/*
|
||||
* Ioctl calls for the audio device.
|
||||
*/
|
||||
|
||||
/*
|
||||
* AUDIO_GETINFO retrieves the current state of the audio device.
|
||||
*
|
||||
* AUDIO_SETINFO copies all fields of the audio_info structure whose
|
||||
* values are not set to the initialized value (-1) to the device state.
|
||||
* It performs an implicit AUDIO_GETINFO to return the new state of the
|
||||
* device. Note that the record.samples and play.samples fields are set
|
||||
* to the last value before the AUDIO_SETINFO took effect. This allows
|
||||
* an application to reset the counters while atomically retrieving the
|
||||
* last value.
|
||||
*
|
||||
* AUDIO_DRAIN suspends the calling process until the write buffers are
|
||||
* empty.
|
||||
*
|
||||
* AUDIO_GETDEV returns a structure of type audio_device_t which contains
|
||||
* three strings. The string "name" is a short identifying string (for
|
||||
* example, the SBus Fcode name string), the string "version" identifies
|
||||
* the current version of the device, and the "config" string identifies
|
||||
* the specific configuration of the audio stream. All fields are
|
||||
* device-dependent -- see the device specific manual pages for details.
|
||||
*
|
||||
* AUDIO_GETDEV_SUNOS returns a number which is an audio device defined
|
||||
* herein (making it not too portable)
|
||||
*
|
||||
* AUDIO_FLUSH stops all playback and recording, clears all queued buffers,
|
||||
* resets error counters, and restarts recording and playback as appropriate
|
||||
* for the current sampling mode.
|
||||
*/
|
||||
#define AUDIO_GETINFO _IOR('A', 1, audio_info_t)
|
||||
#define AUDIO_SETINFO _IOWR('A', 2, audio_info_t)
|
||||
#define AUDIO_DRAIN _IO('A', 3)
|
||||
#define AUDIO_GETDEV _IOR('A', 4, audio_device_t)
|
||||
#define AUDIO_GETDEV_SUNOS _IOR('A', 4, int)
|
||||
#define AUDIO_FLUSH _IO('A', 5)
|
||||
|
||||
/* Define possible audio hardware configurations for
|
||||
* old SunOS-style AUDIO_GETDEV ioctl */
|
||||
#define AUDIO_DEV_UNKNOWN (0) /* not defined */
|
||||
#define AUDIO_DEV_AMD (1) /* audioamd device */
|
||||
#define AUDIO_DEV_SPEAKERBOX (2) /* dbri device with speakerbox */
|
||||
#define AUDIO_DEV_CODEC (3) /* dbri device (internal speaker) */
|
||||
#define AUDIO_DEV_CS4231 (5) /* cs4231 device */
|
||||
|
||||
/*
|
||||
* The following ioctl sets the audio device into an internal loopback mode,
|
||||
* if the hardware supports this. The argument is TRUE to set loopback,
|
||||
* FALSE to reset to normal operation. If the hardware does not support
|
||||
* internal loopback, the ioctl should fail with EINVAL.
|
||||
* Causes ADC data to be digitally mixed in and sent to the DAC.
|
||||
*/
|
||||
#define AUDIO_DIAG_LOOPBACK _IOW('A', 101, int)
|
||||
|
||||
#endif /* _AUDIOIO_H_ */
|
|
@ -1,56 +0,0 @@
|
|||
#ifndef __LINUX_KBIO_H
|
||||
#define __LINUX_KBIO_H
|
||||
|
||||
/* Return keyboard type */
|
||||
#define KIOCTYPE _IOR('k', 9, int)
|
||||
/* Return Keyboard layout */
|
||||
#define KIOCLAYOUT _IOR('k', 20, int)
|
||||
|
||||
enum {
|
||||
TR_NONE,
|
||||
TR_ASCII, /* keyboard is in regular state */
|
||||
TR_EVENT, /* keystrokes sent as firm events */
|
||||
TR_UNTRANS_EVENT /* EVENT+up and down+no translation */
|
||||
};
|
||||
|
||||
/* Return the current keyboard translation */
|
||||
#define KIOCGTRANS _IOR('k', 5, int)
|
||||
/* Set the keyboard translation */
|
||||
#define KIOCTRANS _IOW('k', 0, int)
|
||||
|
||||
/* Send a keyboard command */
|
||||
#define KIOCCMD _IOW('k', 8, int)
|
||||
|
||||
/* Return if keystrokes are being sent to /dev/kbd */
|
||||
|
||||
/* Set routing of keystrokes to /dev/kbd */
|
||||
#define KIOCSDIRECT _IOW('k', 10, int)
|
||||
|
||||
/* Set keyboard leds */
|
||||
#define KIOCSLED _IOW('k', 14, unsigned char)
|
||||
|
||||
/* Get keyboard leds */
|
||||
#define KIOCGLED _IOR('k', 15, unsigned char)
|
||||
|
||||
/* Used by KIOC[GS]RATE */
|
||||
struct kbd_rate {
|
||||
unsigned char delay; /* Delay in Hz before first repeat. */
|
||||
unsigned char rate; /* In characters per second (0..50). */
|
||||
};
|
||||
|
||||
/* Set keyboard rate */
|
||||
#define KIOCSRATE _IOW('k', 40, struct kbd_rate)
|
||||
|
||||
/* Get keyboard rate */
|
||||
#define KIOCGRATE _IOW('k', 41, struct kbd_rate)
|
||||
|
||||
/* Top bit records if the key is up or down */
|
||||
#define KBD_UP 0x80
|
||||
|
||||
/* Usable information */
|
||||
#define KBD_KEYMASK 0x7f
|
||||
|
||||
/* All keys up */
|
||||
#define KBD_IDLE 0x75
|
||||
|
||||
#endif /* __LINUX_KBIO_H */
|
|
@ -38,15 +38,6 @@ struct sunos_ttysize {
|
|||
int st_columns; /* Columns on the terminal */
|
||||
};
|
||||
|
||||
/* Used for packet mode */
|
||||
#define TIOCPKT_DATA 0
|
||||
#define TIOCPKT_FLUSHREAD 1
|
||||
#define TIOCPKT_FLUSHWRITE 2
|
||||
#define TIOCPKT_STOP 4
|
||||
#define TIOCPKT_START 8
|
||||
#define TIOCPKT_NOSTOP 16
|
||||
#define TIOCPKT_DOSTOP 32
|
||||
|
||||
struct winsize {
|
||||
unsigned short ws_row;
|
||||
unsigned short ws_col;
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/* SunOS Virtual User Input Device (VUID) compatibility */
|
||||
|
||||
|
||||
typedef struct firm_event {
|
||||
unsigned short id; /* tag for this event */
|
||||
unsigned char pair_type; /* unused by X11 */
|
||||
unsigned char pair; /* unused by X11 */
|
||||
int value; /* VKEY_UP, VKEY_DOWN or delta */
|
||||
struct timeval time;
|
||||
} Firm_event;
|
||||
|
||||
enum {
|
||||
FE_PAIR_NONE,
|
||||
FE_PAIR_SET,
|
||||
FE_PAIR_DELTA,
|
||||
FE_PAIR_ABSOLUTE
|
||||
};
|
||||
|
||||
/* VUID stream formats */
|
||||
#define VUID_NATIVE 0 /* Native byte stream format */
|
||||
#define VUID_FIRM_EVENT 1 /* send firm_event structures */
|
||||
|
||||
/* ioctls */
|
||||
/* Set input device byte stream format (any of VUID_{NATIVE,FIRM_EVENT}) */
|
||||
#define VUIDSFORMAT _IOW('v', 1, int)
|
||||
/* Retrieve input device byte stream format */
|
||||
#define VUIDGFORMAT _IOR('v', 2, int)
|
||||
|
||||
/* Possible tag values */
|
||||
/* mouse buttons: */
|
||||
#define MS_LEFT 0x7f20
|
||||
#define MS_MIDDLE 0x7f21
|
||||
#define MS_RIGHT 0x7f22
|
||||
/* motion: */
|
||||
#define LOC_X_DELTA 0x7f80
|
||||
#define LOC_Y_DELTA 0x7f81
|
||||
#define LOC_X_ABSOLUTE 0x7f82 /* X compat, unsupported */
|
||||
#define LOC_Y_ABSOLUTE 0x7f83 /* X compat, unsupported */
|
||||
|
||||
#define VKEY_UP 0
|
||||
#define VKEY_DOWN 1
|
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* include/asm-sparc/audioio.h
|
||||
*
|
||||
* Sparc Audio Midlayer
|
||||
* Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
|
||||
*/
|
||||
|
||||
#ifndef _AUDIOIO_H_
|
||||
#define _AUDIOIO_H_
|
||||
|
||||
/*
|
||||
* SunOS/Solaris /dev/audio interface
|
||||
*/
|
||||
|
||||
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
|
||||
#include <linux/types.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/ioctl.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This structure contains state information for audio device IO streams.
|
||||
*/
|
||||
typedef struct audio_prinfo {
|
||||
/*
|
||||
* The following values describe the audio data encoding.
|
||||
*/
|
||||
unsigned int sample_rate; /* samples per second */
|
||||
unsigned int channels; /* number of interleaved channels */
|
||||
unsigned int precision; /* bit-width of each sample */
|
||||
unsigned int encoding; /* data encoding method */
|
||||
|
||||
/*
|
||||
* The following values control audio device configuration
|
||||
*/
|
||||
unsigned int gain; /* gain level: 0 - 255 */
|
||||
unsigned int port; /* selected I/O port (see below) */
|
||||
unsigned int avail_ports; /* available I/O ports (see below) */
|
||||
unsigned int _xxx[2]; /* Reserved for future use */
|
||||
|
||||
unsigned int buffer_size; /* I/O buffer size */
|
||||
|
||||
/*
|
||||
* The following values describe driver state
|
||||
*/
|
||||
unsigned int samples; /* number of samples converted */
|
||||
unsigned int eof; /* End Of File counter (play only) */
|
||||
|
||||
unsigned char pause; /* non-zero for pause, zero to resume */
|
||||
unsigned char error; /* non-zero if overflow/underflow */
|
||||
unsigned char waiting; /* non-zero if a process wants access */
|
||||
unsigned char balance; /* stereo channel balance */
|
||||
|
||||
unsigned short minordev;
|
||||
|
||||
/*
|
||||
* The following values are read-only state flags
|
||||
*/
|
||||
unsigned char open; /* non-zero if open access permitted */
|
||||
unsigned char active; /* non-zero if I/O is active */
|
||||
} audio_prinfo_t;
|
||||
|
||||
|
||||
/*
|
||||
* This structure describes the current state of the audio device.
|
||||
*/
|
||||
typedef struct audio_info {
|
||||
/*
|
||||
* Per-stream information
|
||||
*/
|
||||
audio_prinfo_t play; /* output status information */
|
||||
audio_prinfo_t record; /* input status information */
|
||||
|
||||
/*
|
||||
* Per-unit/channel information
|
||||
*/
|
||||
unsigned int monitor_gain; /* input to output mix: 0 - 255 */
|
||||
unsigned char output_muted; /* non-zero if output is muted */
|
||||
unsigned char _xxx[3]; /* Reserved for future use */
|
||||
unsigned int _yyy[3]; /* Reserved for future use */
|
||||
} audio_info_t;
|
||||
|
||||
|
||||
/*
|
||||
* Audio encoding types
|
||||
*/
|
||||
#define AUDIO_ENCODING_NONE (0) /* no encoding assigned */
|
||||
#define AUDIO_ENCODING_ULAW (1) /* u-law encoding */
|
||||
#define AUDIO_ENCODING_ALAW (2) /* A-law encoding */
|
||||
#define AUDIO_ENCODING_LINEAR (3) /* Linear PCM encoding */
|
||||
#define AUDIO_ENCODING_FLOAT (4) /* IEEE float (-1. <-> +1.) */
|
||||
#define AUDIO_ENCODING_DVI (104) /* DVI ADPCM */
|
||||
#define AUDIO_ENCODING_LINEAR8 (105) /* 8 bit UNSIGNED */
|
||||
#define AUDIO_ENCODING_LINEARLE (106) /* Linear PCM LE encoding */
|
||||
|
||||
/*
|
||||
* These ranges apply to record, play, and monitor gain values
|
||||
*/
|
||||
#define AUDIO_MIN_GAIN (0) /* minimum gain value */
|
||||
#define AUDIO_MAX_GAIN (255) /* maximum gain value */
|
||||
|
||||
/*
|
||||
* These values apply to the balance field to adjust channel gain values
|
||||
*/
|
||||
#define AUDIO_LEFT_BALANCE (0) /* left channel only */
|
||||
#define AUDIO_MID_BALANCE (32) /* equal left/right channel */
|
||||
#define AUDIO_RIGHT_BALANCE (64) /* right channel only */
|
||||
#define AUDIO_BALANCE_SHIFT (3)
|
||||
|
||||
/*
|
||||
* Generic minimum/maximum limits for number of channels, both modes
|
||||
*/
|
||||
#define AUDIO_MIN_PLAY_CHANNELS (1)
|
||||
#define AUDIO_MAX_PLAY_CHANNELS (4)
|
||||
#define AUDIO_MIN_REC_CHANNELS (1)
|
||||
#define AUDIO_MAX_REC_CHANNELS (4)
|
||||
|
||||
/*
|
||||
* Generic minimum/maximum limits for sample precision
|
||||
*/
|
||||
#define AUDIO_MIN_PLAY_PRECISION (8)
|
||||
#define AUDIO_MAX_PLAY_PRECISION (32)
|
||||
#define AUDIO_MIN_REC_PRECISION (8)
|
||||
#define AUDIO_MAX_REC_PRECISION (32)
|
||||
|
||||
/*
|
||||
* Define some convenient names for typical audio ports
|
||||
*/
|
||||
/*
|
||||
* output ports (several may be enabled simultaneously)
|
||||
*/
|
||||
#define AUDIO_SPEAKER 0x01 /* output to built-in speaker */
|
||||
#define AUDIO_HEADPHONE 0x02 /* output to headphone jack */
|
||||
#define AUDIO_LINE_OUT 0x04 /* output to line out */
|
||||
|
||||
/*
|
||||
* input ports (usually only one at a time)
|
||||
*/
|
||||
#define AUDIO_MICROPHONE 0x01 /* input from microphone */
|
||||
#define AUDIO_LINE_IN 0x02 /* input from line in */
|
||||
#define AUDIO_CD 0x04 /* input from on-board CD inputs */
|
||||
#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* input from internal CDROM */
|
||||
#define AUDIO_ANALOG_LOOPBACK 0x40 /* input from output */
|
||||
|
||||
|
||||
/*
|
||||
* This macro initializes an audio_info structure to 'harmless' values.
|
||||
* Note that (~0) might not be a harmless value for a flag that was
|
||||
* a signed int.
|
||||
*/
|
||||
#define AUDIO_INITINFO(i) { \
|
||||
unsigned int *__x__; \
|
||||
for (__x__ = (unsigned int *)(i); \
|
||||
(char *) __x__ < (((char *)(i)) + sizeof (audio_info_t)); \
|
||||
*__x__++ = ~0); \
|
||||
}
|
||||
|
||||
/*
|
||||
* These allow testing for what the user wants to set
|
||||
*/
|
||||
#define AUD_INITVALUE (~0)
|
||||
#define Modify(X) ((unsigned int)(X) != AUD_INITVALUE)
|
||||
#define Modifys(X) ((X) != (unsigned short)AUD_INITVALUE)
|
||||
#define Modifyc(X) ((X) != (unsigned char)AUD_INITVALUE)
|
||||
|
||||
/*
|
||||
* Parameter for the AUDIO_GETDEV ioctl to determine current
|
||||
* audio devices.
|
||||
*/
|
||||
#define MAX_AUDIO_DEV_LEN (16)
|
||||
typedef struct audio_device {
|
||||
char name[MAX_AUDIO_DEV_LEN];
|
||||
char version[MAX_AUDIO_DEV_LEN];
|
||||
char config[MAX_AUDIO_DEV_LEN];
|
||||
} audio_device_t;
|
||||
|
||||
|
||||
/*
|
||||
* Ioctl calls for the audio device.
|
||||
*/
|
||||
|
||||
/*
|
||||
* AUDIO_GETINFO retrieves the current state of the audio device.
|
||||
*
|
||||
* AUDIO_SETINFO copies all fields of the audio_info structure whose
|
||||
* values are not set to the initialized value (-1) to the device state.
|
||||
* It performs an implicit AUDIO_GETINFO to return the new state of the
|
||||
* device. Note that the record.samples and play.samples fields are set
|
||||
* to the last value before the AUDIO_SETINFO took effect. This allows
|
||||
* an application to reset the counters while atomically retrieving the
|
||||
* last value.
|
||||
*
|
||||
* AUDIO_DRAIN suspends the calling process until the write buffers are
|
||||
* empty.
|
||||
*
|
||||
* AUDIO_GETDEV returns a structure of type audio_device_t which contains
|
||||
* three strings. The string "name" is a short identifying string (for
|
||||
* example, the SBus Fcode name string), the string "version" identifies
|
||||
* the current version of the device, and the "config" string identifies
|
||||
* the specific configuration of the audio stream. All fields are
|
||||
* device-dependent -- see the device specific manual pages for details.
|
||||
*
|
||||
* AUDIO_GETDEV_SUNOS returns a number which is an audio device defined
|
||||
* herein (making it not too portable)
|
||||
*
|
||||
* AUDIO_FLUSH stops all playback and recording, clears all queued buffers,
|
||||
* resets error counters, and restarts recording and playback as appropriate
|
||||
* for the current sampling mode.
|
||||
*/
|
||||
#define AUDIO_GETINFO _IOR('A', 1, audio_info_t)
|
||||
#define AUDIO_SETINFO _IOWR('A', 2, audio_info_t)
|
||||
#define AUDIO_DRAIN _IO('A', 3)
|
||||
#define AUDIO_GETDEV _IOR('A', 4, audio_device_t)
|
||||
#define AUDIO_GETDEV_SUNOS _IOR('A', 4, int)
|
||||
#define AUDIO_FLUSH _IO('A', 5)
|
||||
|
||||
/* Define possible audio hardware configurations for
|
||||
* old SunOS-style AUDIO_GETDEV ioctl */
|
||||
#define AUDIO_DEV_UNKNOWN (0) /* not defined */
|
||||
#define AUDIO_DEV_AMD (1) /* audioamd device */
|
||||
#define AUDIO_DEV_SPEAKERBOX (2) /* dbri device with speakerbox */
|
||||
#define AUDIO_DEV_CODEC (3) /* dbri device (internal speaker) */
|
||||
#define AUDIO_DEV_CS4231 (5) /* cs4231 device */
|
||||
|
||||
/*
|
||||
* The following ioctl sets the audio device into an internal loopback mode,
|
||||
* if the hardware supports this. The argument is TRUE to set loopback,
|
||||
* FALSE to reset to normal operation. If the hardware does not support
|
||||
* internal loopback, the ioctl should fail with EINVAL.
|
||||
* Causes ADC data to be digitally mixed in and sent to the DAC.
|
||||
*/
|
||||
#define AUDIO_DIAG_LOOPBACK _IOW('A', 101, int)
|
||||
|
||||
#endif /* _AUDIOIO_H_ */
|
|
@ -79,6 +79,7 @@ extern int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr,
|
|||
size_t len);
|
||||
extern void ebus_dma_prepare(struct ebus_dma_info *p, int write);
|
||||
extern unsigned int ebus_dma_residue(struct ebus_dma_info *p);
|
||||
extern unsigned int ebus_dma_addr(struct ebus_dma_info *p);
|
||||
extern void ebus_dma_enable(struct ebus_dma_info *p, int on);
|
||||
|
||||
extern struct linux_ebus *ebus_chain;
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
#ifndef __LINUX_KBIO_H
|
||||
#define __LINUX_KBIO_H
|
||||
|
||||
/* Return keyboard type */
|
||||
#define KIOCTYPE _IOR('k', 9, int)
|
||||
/* Return Keyboard layout */
|
||||
#define KIOCLAYOUT _IOR('k', 20, int)
|
||||
|
||||
enum {
|
||||
TR_NONE,
|
||||
TR_ASCII, /* keyboard is in regular state */
|
||||
TR_EVENT, /* keystrokes sent as firm events */
|
||||
TR_UNTRANS_EVENT /* EVENT+up and down+no translation */
|
||||
};
|
||||
|
||||
/* Return the current keyboard translation */
|
||||
#define KIOCGTRANS _IOR('k', 5, int)
|
||||
/* Set the keyboard translation */
|
||||
#define KIOCTRANS _IOW('k', 0, int)
|
||||
|
||||
/* Send a keyboard command */
|
||||
#define KIOCCMD _IOW('k', 8, int)
|
||||
|
||||
/* Return if keystrokes are being sent to /dev/kbd */
|
||||
|
||||
/* Set routing of keystrokes to /dev/kbd */
|
||||
#define KIOCSDIRECT _IOW('k', 10, int)
|
||||
|
||||
/* Set keyboard leds */
|
||||
#define KIOCSLED _IOW('k', 14, unsigned char)
|
||||
|
||||
/* Get keyboard leds */
|
||||
#define KIOCGLED _IOR('k', 15, unsigned char)
|
||||
|
||||
/* Used by KIOC[GS]RATE */
|
||||
struct kbd_rate {
|
||||
unsigned char delay; /* Delay in Hz before first repeat. */
|
||||
unsigned char rate; /* In characters per second (0..50). */
|
||||
};
|
||||
|
||||
/* Set keyboard rate */
|
||||
#define KIOCSRATE _IOW('k', 40, struct kbd_rate)
|
||||
|
||||
/* Get keyboard rate */
|
||||
#define KIOCGRATE _IOW('k', 41, struct kbd_rate)
|
||||
|
||||
/* Top bit records if the key is up or down */
|
||||
#define KBD_UP 0x80
|
||||
|
||||
/* Usable information */
|
||||
#define KBD_KEYMASK 0x7f
|
||||
|
||||
/* All keys up */
|
||||
#define KBD_IDLE 0x75
|
||||
|
||||
#endif /* __LINUX_KBIO_H */
|
|
@ -87,37 +87,35 @@ extern void __flush_tlb_mm(unsigned long, unsigned long);
|
|||
static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
|
||||
{
|
||||
unsigned long ctx_valid;
|
||||
int cpu;
|
||||
|
||||
/* Note: page_table_lock is used here to serialize switch_mm
|
||||
* and activate_mm, and their calls to get_new_mmu_context.
|
||||
* This use of page_table_lock is unrelated to its other uses.
|
||||
*/
|
||||
spin_lock(&mm->page_table_lock);
|
||||
if (CTX_VALID(mm->context))
|
||||
ctx_valid = 1;
|
||||
else
|
||||
ctx_valid = 0;
|
||||
ctx_valid = CTX_VALID(mm->context);
|
||||
if (!ctx_valid)
|
||||
get_new_mmu_context(mm);
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
|
||||
if (!ctx_valid || (old_mm != mm)) {
|
||||
if (!ctx_valid)
|
||||
get_new_mmu_context(mm);
|
||||
|
||||
load_secondary_context(mm);
|
||||
reload_tlbmiss_state(tsk, mm);
|
||||
}
|
||||
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
/* Even if (mm == old_mm) we _must_ check
|
||||
* the cpu_vm_mask. If we do not we could
|
||||
* corrupt the TLB state because of how
|
||||
* smp_flush_tlb_{page,range,mm} on sparc64
|
||||
* and lazy tlb switches work. -DaveM
|
||||
*/
|
||||
if (!ctx_valid || !cpu_isset(cpu, mm->cpu_vm_mask)) {
|
||||
cpu_set(cpu, mm->cpu_vm_mask);
|
||||
__flush_tlb_mm(CTX_HWBITS(mm->context),
|
||||
SECONDARY_CONTEXT);
|
||||
}
|
||||
/* Even if (mm == old_mm) we _must_ check
|
||||
* the cpu_vm_mask. If we do not we could
|
||||
* corrupt the TLB state because of how
|
||||
* smp_flush_tlb_{page,range,mm} on sparc64
|
||||
* and lazy tlb switches work. -DaveM
|
||||
*/
|
||||
cpu = smp_processor_id();
|
||||
if (!ctx_valid || !cpu_isset(cpu, mm->cpu_vm_mask)) {
|
||||
cpu_set(cpu, mm->cpu_vm_mask);
|
||||
__flush_tlb_mm(CTX_HWBITS(mm->context),
|
||||
SECONDARY_CONTEXT);
|
||||
}
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
}
|
||||
|
||||
#define deactivate_mm(tsk,mm) do { } while (0)
|
||||
|
@ -127,6 +125,10 @@ static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm
|
|||
{
|
||||
int cpu;
|
||||
|
||||
/* Note: page_table_lock is used here to serialize switch_mm
|
||||
* and activate_mm, and their calls to get_new_mmu_context.
|
||||
* This use of page_table_lock is unrelated to its other uses.
|
||||
*/
|
||||
spin_lock(&mm->page_table_lock);
|
||||
if (!CTX_VALID(mm->context))
|
||||
get_new_mmu_context(mm);
|
||||
|
|
|
@ -38,15 +38,6 @@ struct sunos_ttysize {
|
|||
int st_columns; /* Columns on the terminal */
|
||||
};
|
||||
|
||||
/* Used for packet mode */
|
||||
#define TIOCPKT_DATA 0
|
||||
#define TIOCPKT_FLUSHREAD 1
|
||||
#define TIOCPKT_FLUSHWRITE 2
|
||||
#define TIOCPKT_STOP 4
|
||||
#define TIOCPKT_START 8
|
||||
#define TIOCPKT_NOSTOP 16
|
||||
#define TIOCPKT_DOSTOP 32
|
||||
|
||||
struct winsize {
|
||||
unsigned short ws_row;
|
||||
unsigned short ws_col;
|
||||
|
|
|
@ -58,11 +58,9 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned i
|
|||
static inline void tlb_flush_mmu(struct mmu_gather *mp)
|
||||
{
|
||||
if (mp->need_flush) {
|
||||
free_pages_and_swap_cache(mp->pages, mp->pages_nr);
|
||||
mp->pages_nr = 0;
|
||||
mp->need_flush = 0;
|
||||
if (!tlb_fast_mode(mp)) {
|
||||
free_pages_and_swap_cache(mp->pages, mp->pages_nr);
|
||||
mp->pages_nr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -78,11 +76,9 @@ static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, un
|
|||
{
|
||||
tlb_flush_mmu(mp);
|
||||
|
||||
if (mp->fullmm) {
|
||||
if (CTX_VALID(mp->mm->context))
|
||||
do_flush_tlb_mm(mp->mm);
|
||||
if (mp->fullmm)
|
||||
mp->fullmm = 0;
|
||||
} else
|
||||
else
|
||||
flush_tlb_pending();
|
||||
|
||||
/* keep the page table cache within bounds */
|
||||
|
@ -93,11 +89,11 @@ static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, un
|
|||
|
||||
static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page)
|
||||
{
|
||||
mp->need_flush = 1;
|
||||
if (tlb_fast_mode(mp)) {
|
||||
free_page_and_swap_cache(page);
|
||||
return;
|
||||
}
|
||||
mp->need_flush = 1;
|
||||
mp->pages[mp->pages_nr++] = page;
|
||||
if (mp->pages_nr >= FREE_PTE_NR)
|
||||
tlb_flush_mmu(mp);
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
/* SunOS Virtual User Input Device (VUID) compatibility */
|
||||
|
||||
typedef struct firm_event {
|
||||
unsigned short id; /* tag for this event */
|
||||
unsigned char pair_type; /* unused by X11 */
|
||||
unsigned char pair; /* unused by X11 */
|
||||
int value; /* VKEY_UP, VKEY_DOWN or delta */
|
||||
struct timeval time;
|
||||
} Firm_event;
|
||||
|
||||
enum {
|
||||
FE_PAIR_NONE,
|
||||
FE_PAIR_SET,
|
||||
FE_PAIR_DELTA,
|
||||
FE_PAIR_ABSOLUTE
|
||||
};
|
||||
|
||||
/* VUID stream formats */
|
||||
#define VUID_NATIVE 0 /* Native byte stream format */
|
||||
#define VUID_FIRM_EVENT 1 /* send firm_event structures */
|
||||
|
||||
/* ioctls */
|
||||
/* Set input device byte stream format (any of VUID_{NATIVE,FIRM_EVENT}) */
|
||||
#define VUIDSFORMAT _IOW('v', 1, int)
|
||||
/* Retrieve input device byte stream format */
|
||||
#define VUIDGFORMAT _IOR('v', 2, int)
|
||||
|
||||
/* Possible tag values */
|
||||
/* mouse buttons: */
|
||||
#define MS_LEFT 0x7f20
|
||||
#define MS_MIDDLE 0x7f21
|
||||
#define MS_RIGHT 0x7f22
|
||||
/* motion: */
|
||||
#define LOC_X_DELTA 0x7f80
|
||||
#define LOC_Y_DELTA 0x7f81
|
||||
#define LOC_X_ABSOLUTE 0x7f82 /* X compat, unsupported */
|
||||
#define LOC_Y_ABSOLUTE 0x7f83 /* X compat, unsupported */
|
||||
|
||||
#define VKEY_UP 0
|
||||
#define VKEY_DOWN 1
|
|
@ -470,13 +470,6 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
|
|||
if (clone_flags & CLONE_VM) {
|
||||
atomic_inc(&oldmm->mm_users);
|
||||
mm = oldmm;
|
||||
/*
|
||||
* There are cases where the PTL is held to ensure no
|
||||
* new threads start up in user mode using an mm, which
|
||||
* allows optimizing out ipis; the tlb_gather_mmu code
|
||||
* is an example.
|
||||
*/
|
||||
spin_unlock_wait(&oldmm->page_table_lock);
|
||||
goto good_mm;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,13 +61,37 @@ MODULE_DESCRIPTION("Sun CS4231");
|
|||
MODULE_LICENSE("GPL");
|
||||
MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}");
|
||||
|
||||
typedef struct snd_cs4231 {
|
||||
#ifdef SBUS_SUPPORT
|
||||
typedef struct sbus_dma_info {
|
||||
spinlock_t lock;
|
||||
int dir;
|
||||
void __iomem *regs;
|
||||
} sbus_dma_info_t;
|
||||
#endif
|
||||
|
||||
typedef struct snd_cs4231 cs4231_t;
|
||||
|
||||
typedef struct cs4231_dma_control {
|
||||
void (*prepare)(struct cs4231_dma_control *dma_cont, int dir);
|
||||
void (*enable)(struct cs4231_dma_control *dma_cont, int on);
|
||||
int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len);
|
||||
unsigned int (*address)(struct cs4231_dma_control *dma_cont);
|
||||
void (*reset)(cs4231_t *chip);
|
||||
void (*preallocate)(cs4231_t *chip, snd_pcm_t *pcm);
|
||||
#ifdef EBUS_SUPPORT
|
||||
struct ebus_dma_info ebus_info;
|
||||
#endif
|
||||
#ifdef SBUS_SUPPORT
|
||||
struct sbus_dma_info sbus_info;
|
||||
#endif
|
||||
} cs4231_dma_control_t;
|
||||
|
||||
struct snd_cs4231 {
|
||||
spinlock_t lock;
|
||||
void __iomem *port;
|
||||
#ifdef EBUS_SUPPORT
|
||||
struct ebus_dma_info eb2c;
|
||||
struct ebus_dma_info eb2p;
|
||||
#endif
|
||||
|
||||
cs4231_dma_control_t p_dma;
|
||||
cs4231_dma_control_t c_dma;
|
||||
|
||||
u32 flags;
|
||||
#define CS4231_FLAG_EBUS 0x00000001
|
||||
|
@ -106,7 +130,7 @@ typedef struct snd_cs4231 {
|
|||
unsigned int irq[2];
|
||||
unsigned int regs_size;
|
||||
struct snd_cs4231 *next;
|
||||
} cs4231_t;
|
||||
};
|
||||
|
||||
static cs4231_t *cs4231_list;
|
||||
|
||||
|
@ -251,6 +275,15 @@ static cs4231_t *cs4231_list;
|
|||
#define APCPNVA 0x38UL /* APC Play DMA Next Address */
|
||||
#define APCPNC 0x3cUL /* APC Play Next Count */
|
||||
|
||||
/* Defines for SBUS DMA-routines */
|
||||
|
||||
#define APCVA 0x0UL /* APC DMA Address */
|
||||
#define APCC 0x4UL /* APC Count */
|
||||
#define APCNVA 0x8UL /* APC DMA Next Address */
|
||||
#define APCNC 0xcUL /* APC Next Count */
|
||||
#define APC_PLAY 0x30UL /* Play registers start at 0x30 */
|
||||
#define APC_RECORD 0x20UL /* Record registers start at 0x20 */
|
||||
|
||||
/* APCCSR bits */
|
||||
|
||||
#define APC_INT_PENDING 0x800000 /* Interrupt Pending */
|
||||
|
@ -569,8 +602,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
|
|||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
}
|
||||
|
||||
#ifdef EBUS_SUPPORT
|
||||
static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent)
|
||||
static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, snd_pcm_substream_t *substream, unsigned int *periods_sent)
|
||||
{
|
||||
snd_pcm_runtime_t *runtime = substream->runtime;
|
||||
|
||||
|
@ -581,129 +613,41 @@ static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substre
|
|||
if (period_size >= (1 << 24))
|
||||
BUG();
|
||||
|
||||
if (ebus_dma_request(p, runtime->dma_addr + offset, period_size))
|
||||
if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size))
|
||||
return;
|
||||
(*periods_sent) = ((*periods_sent) + 1) % runtime->periods;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SBUS_SUPPORT
|
||||
static void snd_cs4231_sbus_advance_dma(snd_pcm_substream_t *substream, unsigned int *periods_sent)
|
||||
{
|
||||
cs4231_t *chip = snd_pcm_substream_chip(substream);
|
||||
snd_pcm_runtime_t *runtime = substream->runtime;
|
||||
|
||||
unsigned int period_size = snd_pcm_lib_period_bytes(substream);
|
||||
unsigned int offset = period_size * (*periods_sent % runtime->periods);
|
||||
|
||||
if (runtime->period_size > 0xffff + 1)
|
||||
BUG();
|
||||
|
||||
switch (substream->stream) {
|
||||
case SNDRV_PCM_STREAM_PLAYBACK:
|
||||
sbus_writel(runtime->dma_addr + offset, chip->port + APCPNVA);
|
||||
sbus_writel(period_size, chip->port + APCPNC);
|
||||
break;
|
||||
case SNDRV_PCM_STREAM_CAPTURE:
|
||||
sbus_writel(runtime->dma_addr + offset, chip->port + APCCNVA);
|
||||
sbus_writel(period_size, chip->port + APCCNC);
|
||||
break;
|
||||
}
|
||||
|
||||
(*periods_sent) = (*periods_sent + 1) % runtime->periods;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on)
|
||||
{
|
||||
cs4231_t *chip = snd_pcm_substream_chip(substream);
|
||||
cs4231_dma_control_t *dma_cont;
|
||||
|
||||
#ifdef EBUS_SUPPORT
|
||||
if (chip->flags & CS4231_FLAG_EBUS) {
|
||||
if (what & CS4231_PLAYBACK_ENABLE) {
|
||||
if (on) {
|
||||
ebus_dma_prepare(&chip->eb2p, 0);
|
||||
ebus_dma_enable(&chip->eb2p, 1);
|
||||
snd_cs4231_ebus_advance_dma(&chip->eb2p,
|
||||
chip->playback_substream,
|
||||
&chip->p_periods_sent);
|
||||
} else {
|
||||
ebus_dma_enable(&chip->eb2p, 0);
|
||||
}
|
||||
}
|
||||
if (what & CS4231_RECORD_ENABLE) {
|
||||
if (on) {
|
||||
ebus_dma_prepare(&chip->eb2c, 1);
|
||||
ebus_dma_enable(&chip->eb2c, 1);
|
||||
snd_cs4231_ebus_advance_dma(&chip->eb2c,
|
||||
chip->capture_substream,
|
||||
&chip->c_periods_sent);
|
||||
} else {
|
||||
ebus_dma_enable(&chip->eb2c, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
#ifdef SBUS_SUPPORT
|
||||
u32 csr = sbus_readl(chip->port + APCCSR);
|
||||
/* I don't know why, but on sbus the period counter must
|
||||
* only start counting after the first period is sent.
|
||||
* Therefore this dummy thing.
|
||||
*/
|
||||
unsigned int dummy = 0;
|
||||
|
||||
switch (what) {
|
||||
case CS4231_PLAYBACK_ENABLE:
|
||||
if (what & CS4231_PLAYBACK_ENABLE) {
|
||||
dma_cont = &chip->p_dma;
|
||||
if (on) {
|
||||
csr &= ~APC_XINT_PLAY;
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
|
||||
csr &= ~APC_PPAUSE;
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
|
||||
snd_cs4231_sbus_advance_dma(substream, &dummy);
|
||||
|
||||
csr |= APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA |
|
||||
APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL |
|
||||
APC_XINT_PENA | APC_PDMA_READY;
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
dma_cont->prepare(dma_cont, 0);
|
||||
dma_cont->enable(dma_cont, 1);
|
||||
snd_cs4231_advance_dma(dma_cont,
|
||||
chip->playback_substream,
|
||||
&chip->p_periods_sent);
|
||||
} else {
|
||||
csr |= APC_PPAUSE;
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
|
||||
csr &= ~APC_PDMA_READY;
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
dma_cont->enable(dma_cont, 0);
|
||||
}
|
||||
break;
|
||||
case CS4231_RECORD_ENABLE:
|
||||
}
|
||||
if (what & CS4231_RECORD_ENABLE) {
|
||||
dma_cont = &chip->c_dma;
|
||||
if (on) {
|
||||
csr &= ~APC_XINT_CAPT;
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
|
||||
csr &= ~APC_CPAUSE;
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
|
||||
snd_cs4231_sbus_advance_dma(substream, &dummy);
|
||||
|
||||
csr |= APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA |
|
||||
APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL |
|
||||
APC_CDMA_READY;
|
||||
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
dma_cont->prepare(dma_cont, 1);
|
||||
dma_cont->enable(dma_cont, 1);
|
||||
snd_cs4231_advance_dma(dma_cont,
|
||||
chip->capture_substream,
|
||||
&chip->c_periods_sent);
|
||||
} else {
|
||||
csr |= APC_CPAUSE;
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
|
||||
csr &= ~APC_CDMA_READY;
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
dma_cont->enable(dma_cont, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef EBUS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
|
||||
|
@ -1136,10 +1080,7 @@ static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream)
|
|||
if (runtime->period_size > 0xffff + 1)
|
||||
BUG();
|
||||
|
||||
snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
|
||||
snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
|
||||
chip->p_periods_sent = 0;
|
||||
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -1171,16 +1112,14 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream)
|
|||
static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream)
|
||||
{
|
||||
cs4231_t *chip = snd_pcm_substream_chip(substream);
|
||||
snd_pcm_runtime_t *runtime = substream->runtime;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE |
|
||||
CS4231_RECORD_PIO);
|
||||
|
||||
snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
|
||||
snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
|
||||
|
||||
chip->c_periods_sent = 0;
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -1199,134 +1138,55 @@ static void snd_cs4231_overrange(cs4231_t *chip)
|
|||
chip->capture_substream->runtime->overrange++;
|
||||
}
|
||||
|
||||
static irqreturn_t snd_cs4231_generic_interrupt(cs4231_t *chip)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned char status;
|
||||
|
||||
/*This is IRQ is not raised by the cs4231*/
|
||||
if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ))
|
||||
return IRQ_NONE;
|
||||
|
||||
status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
|
||||
|
||||
if (status & CS4231_TIMER_IRQ) {
|
||||
if (chip->timer)
|
||||
snd_timer_interrupt(chip->timer, chip->timer->sticks);
|
||||
}
|
||||
|
||||
if (status & CS4231_RECORD_IRQ)
|
||||
snd_cs4231_overrange(chip);
|
||||
|
||||
/* ACK the CS4231 interrupt. */
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SBUS_SUPPORT
|
||||
static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
cs4231_t *chip = dev_id;
|
||||
|
||||
/* ACK the APC interrupt. */
|
||||
u32 csr = sbus_readl(chip->port + APCCSR);
|
||||
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
|
||||
if ((chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) &&
|
||||
(csr & APC_PLAY_INT) &&
|
||||
(csr & APC_XINT_PNVA) &&
|
||||
!(csr & APC_XINT_EMPT)) {
|
||||
snd_cs4231_sbus_advance_dma(chip->playback_substream,
|
||||
&chip->p_periods_sent);
|
||||
snd_pcm_period_elapsed(chip->playback_substream);
|
||||
}
|
||||
|
||||
if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) &&
|
||||
(csr & APC_CAPT_INT) &&
|
||||
(csr & APC_XINT_CNVA)) {
|
||||
snd_cs4231_sbus_advance_dma(chip->capture_substream,
|
||||
&chip->c_periods_sent);
|
||||
snd_pcm_period_elapsed(chip->capture_substream);
|
||||
}
|
||||
|
||||
return snd_cs4231_generic_interrupt(chip);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EBUS_SUPPORT
|
||||
static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie)
|
||||
static void snd_cs4231_play_callback(cs4231_t *cookie)
|
||||
{
|
||||
cs4231_t *chip = cookie;
|
||||
|
||||
if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) {
|
||||
snd_pcm_period_elapsed(chip->playback_substream);
|
||||
snd_cs4231_ebus_advance_dma(p, chip->playback_substream,
|
||||
snd_cs4231_advance_dma(&chip->p_dma, chip->playback_substream,
|
||||
&chip->p_periods_sent);
|
||||
}
|
||||
}
|
||||
|
||||
static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie)
|
||||
static void snd_cs4231_capture_callback(cs4231_t *cookie)
|
||||
{
|
||||
cs4231_t *chip = cookie;
|
||||
|
||||
if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) {
|
||||
snd_pcm_period_elapsed(chip->capture_substream);
|
||||
snd_cs4231_ebus_advance_dma(p, chip->capture_substream,
|
||||
snd_cs4231_advance_dma(&chip->c_dma, chip->capture_substream,
|
||||
&chip->c_periods_sent);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream)
|
||||
{
|
||||
cs4231_t *chip = snd_pcm_substream_chip(substream);
|
||||
size_t ptr, residue, period_bytes;
|
||||
|
||||
cs4231_dma_control_t *dma_cont = &chip->p_dma;
|
||||
size_t ptr;
|
||||
|
||||
if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
|
||||
return 0;
|
||||
period_bytes = snd_pcm_lib_period_bytes(substream);
|
||||
ptr = period_bytes * chip->p_periods_sent;
|
||||
#ifdef EBUS_SUPPORT
|
||||
if (chip->flags & CS4231_FLAG_EBUS) {
|
||||
residue = ebus_dma_residue(&chip->eb2p);
|
||||
} else {
|
||||
#endif
|
||||
#ifdef SBUS_SUPPORT
|
||||
residue = sbus_readl(chip->port + APCPC);
|
||||
#endif
|
||||
#ifdef EBUS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
ptr += period_bytes - residue;
|
||||
|
||||
ptr = dma_cont->address(dma_cont);
|
||||
if (ptr != 0)
|
||||
ptr -= substream->runtime->dma_addr;
|
||||
|
||||
return bytes_to_frames(substream->runtime, ptr);
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream)
|
||||
{
|
||||
cs4231_t *chip = snd_pcm_substream_chip(substream);
|
||||
size_t ptr, residue, period_bytes;
|
||||
cs4231_dma_control_t *dma_cont = &chip->c_dma;
|
||||
size_t ptr;
|
||||
|
||||
if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
|
||||
return 0;
|
||||
period_bytes = snd_pcm_lib_period_bytes(substream);
|
||||
ptr = period_bytes * chip->c_periods_sent;
|
||||
#ifdef EBUS_SUPPORT
|
||||
if (chip->flags & CS4231_FLAG_EBUS) {
|
||||
residue = ebus_dma_residue(&chip->eb2c);
|
||||
} else {
|
||||
#endif
|
||||
#ifdef SBUS_SUPPORT
|
||||
residue = sbus_readl(chip->port + APCCC);
|
||||
#endif
|
||||
#ifdef EBUS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
ptr += period_bytes - residue;
|
||||
ptr = dma_cont->address(dma_cont);
|
||||
if (ptr != 0)
|
||||
ptr -= substream->runtime->dma_addr;
|
||||
|
||||
return bytes_to_frames(substream->runtime, ptr);
|
||||
}
|
||||
|
||||
|
@ -1362,30 +1222,8 @@ static int snd_cs4231_probe(cs4231_t *chip)
|
|||
spin_lock_irqsave(&chip->lock, flags);
|
||||
|
||||
|
||||
/* Reset DMA engine. */
|
||||
#ifdef EBUS_SUPPORT
|
||||
if (chip->flags & CS4231_FLAG_EBUS) {
|
||||
/* Done by ebus_dma_register */
|
||||
} else {
|
||||
#endif
|
||||
#ifdef SBUS_SUPPORT
|
||||
sbus_writel(APC_CHIP_RESET, chip->port + APCCSR);
|
||||
sbus_writel(0x00, chip->port + APCCSR);
|
||||
sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET,
|
||||
chip->port + APCCSR);
|
||||
|
||||
udelay(20);
|
||||
|
||||
sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET,
|
||||
chip->port + APCCSR);
|
||||
sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA |
|
||||
APC_XINT_PENA |
|
||||
APC_XINT_CENA),
|
||||
chip->port + APCCSR);
|
||||
#endif
|
||||
#ifdef EBUS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
/* Reset DMA engine (sbus only). */
|
||||
chip->p_dma.reset(chip);
|
||||
|
||||
__cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */
|
||||
__cs4231_writeb(chip, 0, CS4231P(chip, STATUS));
|
||||
|
@ -1505,8 +1343,8 @@ static int snd_cs4231_playback_close(snd_pcm_substream_t *substream)
|
|||
{
|
||||
cs4231_t *chip = snd_pcm_substream_chip(substream);
|
||||
|
||||
chip->playback_substream = NULL;
|
||||
snd_cs4231_close(chip, CS4231_MODE_PLAY);
|
||||
chip->playback_substream = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1515,8 +1353,8 @@ static int snd_cs4231_capture_close(snd_pcm_substream_t *substream)
|
|||
{
|
||||
cs4231_t *chip = snd_pcm_substream_chip(substream);
|
||||
|
||||
chip->capture_substream = NULL;
|
||||
snd_cs4231_close(chip, CS4231_MODE_RECORD);
|
||||
chip->capture_substream = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1571,21 +1409,7 @@ int snd_cs4231_pcm(cs4231_t *chip)
|
|||
pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
|
||||
strcpy(pcm->name, "CS4231");
|
||||
|
||||
#ifdef EBUS_SUPPORT
|
||||
if (chip->flags & CS4231_FLAG_EBUS) {
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
snd_dma_pci_data(chip->dev_u.pdev),
|
||||
64*1024, 128*1024);
|
||||
} else {
|
||||
#endif
|
||||
#ifdef SBUS_SUPPORT
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,
|
||||
snd_dma_sbus_data(chip->dev_u.sdev),
|
||||
64*1024, 128*1024);
|
||||
#endif
|
||||
#ifdef EBUS_SUPPORT
|
||||
}
|
||||
#endif
|
||||
chip->p_dma.preallocate(chip, pcm);
|
||||
|
||||
chip->pcm = pcm;
|
||||
|
||||
|
@ -1942,6 +1766,180 @@ out_err:
|
|||
}
|
||||
|
||||
#ifdef SBUS_SUPPORT
|
||||
|
||||
static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned char status;
|
||||
u32 csr;
|
||||
cs4231_t *chip = dev_id;
|
||||
|
||||
/*This is IRQ is not raised by the cs4231*/
|
||||
if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ))
|
||||
return IRQ_NONE;
|
||||
|
||||
/* ACK the APC interrupt. */
|
||||
csr = sbus_readl(chip->port + APCCSR);
|
||||
|
||||
sbus_writel(csr, chip->port + APCCSR);
|
||||
|
||||
if ((csr & APC_PDMA_READY) &&
|
||||
(csr & APC_PLAY_INT) &&
|
||||
(csr & APC_XINT_PNVA) &&
|
||||
!(csr & APC_XINT_EMPT))
|
||||
snd_cs4231_play_callback(chip);
|
||||
|
||||
if ((csr & APC_CDMA_READY) &&
|
||||
(csr & APC_CAPT_INT) &&
|
||||
(csr & APC_XINT_CNVA) &&
|
||||
!(csr & APC_XINT_EMPT))
|
||||
snd_cs4231_capture_callback(chip);
|
||||
|
||||
status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
|
||||
|
||||
if (status & CS4231_TIMER_IRQ) {
|
||||
if (chip->timer)
|
||||
snd_timer_interrupt(chip->timer, chip->timer->sticks);
|
||||
}
|
||||
|
||||
if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY))
|
||||
snd_cs4231_overrange(chip);
|
||||
|
||||
/* ACK the CS4231 interrupt. */
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SBUS DMA routines
|
||||
*/
|
||||
|
||||
int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 test, csr;
|
||||
int err;
|
||||
sbus_dma_info_t *base = &dma_cont->sbus_info;
|
||||
|
||||
if (len >= (1 << 24))
|
||||
return -EINVAL;
|
||||
spin_lock_irqsave(&base->lock, flags);
|
||||
csr = sbus_readl(base->regs + APCCSR);
|
||||
err = -EINVAL;
|
||||
test = APC_CDMA_READY;
|
||||
if ( base->dir == APC_PLAY )
|
||||
test = APC_PDMA_READY;
|
||||
if (!(csr & test))
|
||||
goto out;
|
||||
err = -EBUSY;
|
||||
csr = sbus_readl(base->regs + APCCSR);
|
||||
test = APC_XINT_CNVA;
|
||||
if ( base->dir == APC_PLAY )
|
||||
test = APC_XINT_PNVA;
|
||||
if (!(csr & test))
|
||||
goto out;
|
||||
err = 0;
|
||||
sbus_writel(bus_addr, base->regs + base->dir + APCNVA);
|
||||
sbus_writel(len, base->regs + base->dir + APCNC);
|
||||
out:
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 csr, test;
|
||||
sbus_dma_info_t *base = &dma_cont->sbus_info;
|
||||
|
||||
spin_lock_irqsave(&base->lock, flags);
|
||||
csr = sbus_readl(base->regs + APCCSR);
|
||||
test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA |
|
||||
APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL |
|
||||
APC_XINT_PENA;
|
||||
if ( base->dir == APC_RECORD )
|
||||
test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA |
|
||||
APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL;
|
||||
csr |= test;
|
||||
sbus_writel(csr, base->regs + APCCSR);
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
}
|
||||
|
||||
void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 csr, shift;
|
||||
sbus_dma_info_t *base = &dma_cont->sbus_info;
|
||||
|
||||
spin_lock_irqsave(&base->lock, flags);
|
||||
if (!on) {
|
||||
if (base->dir == APC_PLAY) {
|
||||
sbus_writel(0, base->regs + base->dir + APCNVA);
|
||||
sbus_writel(1, base->regs + base->dir + APCC);
|
||||
}
|
||||
else
|
||||
{
|
||||
sbus_writel(0, base->regs + base->dir + APCNC);
|
||||
sbus_writel(0, base->regs + base->dir + APCVA);
|
||||
}
|
||||
}
|
||||
udelay(600);
|
||||
csr = sbus_readl(base->regs + APCCSR);
|
||||
shift = 0;
|
||||
if ( base->dir == APC_PLAY )
|
||||
shift = 1;
|
||||
if (on)
|
||||
csr &= ~(APC_CPAUSE << shift);
|
||||
else
|
||||
csr |= (APC_CPAUSE << shift);
|
||||
sbus_writel(csr, base->regs + APCCSR);
|
||||
if (on)
|
||||
csr |= (APC_CDMA_READY << shift);
|
||||
else
|
||||
csr &= ~(APC_CDMA_READY << shift);
|
||||
sbus_writel(csr, base->regs + APCCSR);
|
||||
|
||||
spin_unlock_irqrestore(&base->lock, flags);
|
||||
}
|
||||
|
||||
unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont)
|
||||
{
|
||||
sbus_dma_info_t *base = &dma_cont->sbus_info;
|
||||
|
||||
return sbus_readl(base->regs + base->dir + APCVA);
|
||||
}
|
||||
|
||||
void sbus_dma_reset(cs4231_t *chip)
|
||||
{
|
||||
sbus_writel(APC_CHIP_RESET, chip->port + APCCSR);
|
||||
sbus_writel(0x00, chip->port + APCCSR);
|
||||
sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET,
|
||||
chip->port + APCCSR);
|
||||
|
||||
udelay(20);
|
||||
|
||||
sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET,
|
||||
chip->port + APCCSR);
|
||||
sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA |
|
||||
APC_XINT_PENA |
|
||||
APC_XINT_CENA),
|
||||
chip->port + APCCSR);
|
||||
}
|
||||
|
||||
void sbus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,
|
||||
snd_dma_sbus_data(chip->dev_u.sdev),
|
||||
64*1024, 128*1024);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init and exit routines
|
||||
*/
|
||||
|
||||
static int snd_cs4231_sbus_free(cs4231_t *chip)
|
||||
{
|
||||
if (chip->irq[0])
|
||||
|
@ -1983,6 +1981,8 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
|
|||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&chip->lock);
|
||||
spin_lock_init(&chip->c_dma.sbus_info.lock);
|
||||
spin_lock_init(&chip->p_dma.sbus_info.lock);
|
||||
init_MUTEX(&chip->mce_mutex);
|
||||
init_MUTEX(&chip->open_mutex);
|
||||
chip->card = card;
|
||||
|
@ -1998,6 +1998,25 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
chip->c_dma.sbus_info.regs = chip->port;
|
||||
chip->p_dma.sbus_info.regs = chip->port;
|
||||
chip->c_dma.sbus_info.dir = APC_RECORD;
|
||||
chip->p_dma.sbus_info.dir = APC_PLAY;
|
||||
|
||||
chip->p_dma.prepare = sbus_dma_prepare;
|
||||
chip->p_dma.enable = sbus_dma_enable;
|
||||
chip->p_dma.request = sbus_dma_request;
|
||||
chip->p_dma.address = sbus_dma_addr;
|
||||
chip->p_dma.reset = sbus_dma_reset;
|
||||
chip->p_dma.preallocate = sbus_dma_preallocate;
|
||||
|
||||
chip->c_dma.prepare = sbus_dma_prepare;
|
||||
chip->c_dma.enable = sbus_dma_enable;
|
||||
chip->c_dma.request = sbus_dma_request;
|
||||
chip->c_dma.address = sbus_dma_addr;
|
||||
chip->c_dma.reset = sbus_dma_reset;
|
||||
chip->c_dma.preallocate = sbus_dma_preallocate;
|
||||
|
||||
if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt,
|
||||
SA_SHIRQ, "cs4231", chip)) {
|
||||
snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n",
|
||||
|
@ -2051,15 +2070,70 @@ static int cs4231_sbus_attach(struct sbus_dev *sdev)
|
|||
#endif
|
||||
|
||||
#ifdef EBUS_SUPPORT
|
||||
|
||||
static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie)
|
||||
{
|
||||
cs4231_t *chip = cookie;
|
||||
|
||||
snd_cs4231_play_callback(chip);
|
||||
}
|
||||
|
||||
static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie)
|
||||
{
|
||||
cs4231_t *chip = cookie;
|
||||
|
||||
snd_cs4231_capture_callback(chip);
|
||||
}
|
||||
|
||||
/*
|
||||
* EBUS DMA wrappers
|
||||
*/
|
||||
|
||||
int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
|
||||
{
|
||||
return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len);
|
||||
}
|
||||
|
||||
void _ebus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
|
||||
{
|
||||
ebus_dma_enable(&dma_cont->ebus_info, on);
|
||||
}
|
||||
|
||||
void _ebus_dma_prepare(struct cs4231_dma_control *dma_cont, int dir)
|
||||
{
|
||||
ebus_dma_prepare(&dma_cont->ebus_info, dir);
|
||||
}
|
||||
|
||||
unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont)
|
||||
{
|
||||
return ebus_dma_addr(&dma_cont->ebus_info);
|
||||
}
|
||||
|
||||
void _ebus_dma_reset(cs4231_t *chip)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void _ebus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm)
|
||||
{
|
||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
|
||||
snd_dma_pci_data(chip->dev_u.pdev),
|
||||
64*1024, 128*1024);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init and exit routines
|
||||
*/
|
||||
|
||||
static int snd_cs4231_ebus_free(cs4231_t *chip)
|
||||
{
|
||||
if (chip->eb2c.regs) {
|
||||
ebus_dma_unregister(&chip->eb2c);
|
||||
iounmap(chip->eb2c.regs);
|
||||
if (chip->c_dma.ebus_info.regs) {
|
||||
ebus_dma_unregister(&chip->c_dma.ebus_info);
|
||||
iounmap(chip->c_dma.ebus_info.regs);
|
||||
}
|
||||
if (chip->eb2p.regs) {
|
||||
ebus_dma_unregister(&chip->eb2p);
|
||||
iounmap(chip->eb2p.regs);
|
||||
if (chip->p_dma.ebus_info.regs) {
|
||||
ebus_dma_unregister(&chip->p_dma.ebus_info);
|
||||
iounmap(chip->p_dma.ebus_info.regs);
|
||||
}
|
||||
|
||||
if (chip->port)
|
||||
|
@ -2097,8 +2171,8 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
|
|||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&chip->lock);
|
||||
spin_lock_init(&chip->eb2c.lock);
|
||||
spin_lock_init(&chip->eb2p.lock);
|
||||
spin_lock_init(&chip->c_dma.ebus_info.lock);
|
||||
spin_lock_init(&chip->p_dma.ebus_info.lock);
|
||||
init_MUTEX(&chip->mce_mutex);
|
||||
init_MUTEX(&chip->open_mutex);
|
||||
chip->flags |= CS4231_FLAG_EBUS;
|
||||
|
@ -2106,43 +2180,57 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
|
|||
chip->dev_u.pdev = edev->bus->self;
|
||||
memcpy(&chip->image, &snd_cs4231_original_image,
|
||||
sizeof(snd_cs4231_original_image));
|
||||
strcpy(chip->eb2c.name, "cs4231(capture)");
|
||||
chip->eb2c.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
|
||||
chip->eb2c.callback = snd_cs4231_ebus_capture_callback;
|
||||
chip->eb2c.client_cookie = chip;
|
||||
chip->eb2c.irq = edev->irqs[0];
|
||||
strcpy(chip->eb2p.name, "cs4231(play)");
|
||||
chip->eb2p.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
|
||||
chip->eb2p.callback = snd_cs4231_ebus_play_callback;
|
||||
chip->eb2p.client_cookie = chip;
|
||||
chip->eb2p.irq = edev->irqs[1];
|
||||
strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)");
|
||||
chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
|
||||
chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback;
|
||||
chip->c_dma.ebus_info.client_cookie = chip;
|
||||
chip->c_dma.ebus_info.irq = edev->irqs[0];
|
||||
strcpy(chip->p_dma.ebus_info.name, "cs4231(play)");
|
||||
chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
|
||||
chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback;
|
||||
chip->p_dma.ebus_info.client_cookie = chip;
|
||||
chip->p_dma.ebus_info.irq = edev->irqs[1];
|
||||
|
||||
chip->p_dma.prepare = _ebus_dma_prepare;
|
||||
chip->p_dma.enable = _ebus_dma_enable;
|
||||
chip->p_dma.request = _ebus_dma_request;
|
||||
chip->p_dma.address = _ebus_dma_addr;
|
||||
chip->p_dma.reset = _ebus_dma_reset;
|
||||
chip->p_dma.preallocate = _ebus_dma_preallocate;
|
||||
|
||||
chip->c_dma.prepare = _ebus_dma_prepare;
|
||||
chip->c_dma.enable = _ebus_dma_enable;
|
||||
chip->c_dma.request = _ebus_dma_request;
|
||||
chip->c_dma.address = _ebus_dma_addr;
|
||||
chip->c_dma.reset = _ebus_dma_reset;
|
||||
chip->c_dma.preallocate = _ebus_dma_preallocate;
|
||||
|
||||
chip->port = ioremap(edev->resource[0].start, 0x10);
|
||||
chip->eb2p.regs = ioremap(edev->resource[1].start, 0x10);
|
||||
chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10);
|
||||
if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) {
|
||||
chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10);
|
||||
chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10);
|
||||
if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) {
|
||||
snd_cs4231_ebus_free(chip);
|
||||
snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ebus_dma_register(&chip->eb2c)) {
|
||||
if (ebus_dma_register(&chip->c_dma.ebus_info)) {
|
||||
snd_cs4231_ebus_free(chip);
|
||||
snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
if (ebus_dma_irq_enable(&chip->eb2c, 1)) {
|
||||
if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) {
|
||||
snd_cs4231_ebus_free(chip);
|
||||
snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (ebus_dma_register(&chip->eb2p)) {
|
||||
if (ebus_dma_register(&chip->p_dma.ebus_info)) {
|
||||
snd_cs4231_ebus_free(chip);
|
||||
snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
if (ebus_dma_irq_enable(&chip->eb2p, 1)) {
|
||||
if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) {
|
||||
snd_cs4231_ebus_free(chip);
|
||||
snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev);
|
||||
return -EBUSY;
|
||||
|
|
Загрузка…
Ссылка в новой задаче