You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
sh: maple: Support block reads and writes.
This patch updates the maple bus to support asynchronous block reads and writes as well as generally improving the quality of the code and supporting concurrency (all needed to support the Dreamcast visual memory unit - a driver will also be posted for that). Changes in the bus driver necessitate some changes in the two maple bus input drivers that are currently in mainline. As well as supporting block reads and writes this code clean up removes some poor handling of locks, uses an atomic status variable to serialise access to devices and more robusly handles the general performance problems of the bus. Signed-off-by: Adrian McMenamin <adrian@mcmen.demon.co.uk> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
committed by
Paul Mundt
parent
41480ae7a3
commit
b233b28eac
@@ -3,7 +3,7 @@
|
||||
* Based on drivers/usb/iforce.c
|
||||
*
|
||||
* Copyright Yaegashi Takeshi, 2001
|
||||
* Adrian McMenamin, 2008
|
||||
* Adrian McMenamin, 2008 - 2009
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
@@ -29,7 +29,7 @@ static void dc_pad_callback(struct mapleq *mq)
|
||||
struct maple_device *mapledev = mq->dev;
|
||||
struct dc_pad *pad = maple_get_drvdata(mapledev);
|
||||
struct input_dev *dev = pad->dev;
|
||||
unsigned char *res = mq->recvbuf;
|
||||
unsigned char *res = mq->recvbuf->buf;
|
||||
|
||||
buttons = ~le16_to_cpup((__le16 *)(res + 8));
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* SEGA Dreamcast keyboard driver
|
||||
* Based on drivers/usb/usbkbd.c
|
||||
* Copyright YAEGASHI Takeshi, 2001
|
||||
* Porting to 2.6 Copyright Adrian McMenamin, 2007, 2008
|
||||
* Copyright (c) YAEGASHI Takeshi, 2001
|
||||
* Porting to 2.6 Copyright (c) Adrian McMenamin, 2007 - 2009
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,7 +33,7 @@ static DEFINE_MUTEX(maple_keyb_mutex);
|
||||
|
||||
#define NR_SCANCODES 256
|
||||
|
||||
MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin");
|
||||
MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk");
|
||||
MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -115,7 +115,7 @@ static void dc_scan_kbd(struct dc_kbd *kbd)
|
||||
input_event(dev, EV_MSC, MSC_SCAN, code);
|
||||
input_report_key(dev, keycode, 0);
|
||||
} else
|
||||
printk(KERN_DEBUG "maple_keyb: "
|
||||
dev_dbg(&dev->dev,
|
||||
"Unknown key (scancode %#x) released.",
|
||||
code);
|
||||
}
|
||||
@@ -127,7 +127,7 @@ static void dc_scan_kbd(struct dc_kbd *kbd)
|
||||
input_event(dev, EV_MSC, MSC_SCAN, code);
|
||||
input_report_key(dev, keycode, 1);
|
||||
} else
|
||||
printk(KERN_DEBUG "maple_keyb: "
|
||||
dev_dbg(&dev->dev,
|
||||
"Unknown key (scancode %#x) pressed.",
|
||||
code);
|
||||
}
|
||||
@@ -140,7 +140,7 @@ static void dc_kbd_callback(struct mapleq *mq)
|
||||
{
|
||||
struct maple_device *mapledev = mq->dev;
|
||||
struct dc_kbd *kbd = maple_get_drvdata(mapledev);
|
||||
unsigned long *buf = mq->recvbuf;
|
||||
unsigned long *buf = (unsigned long *)(mq->recvbuf->buf);
|
||||
|
||||
/*
|
||||
* We should always get the lock because the only
|
||||
@@ -159,22 +159,27 @@ static void dc_kbd_callback(struct mapleq *mq)
|
||||
|
||||
static int probe_maple_kbd(struct device *dev)
|
||||
{
|
||||
struct maple_device *mdev = to_maple_dev(dev);
|
||||
struct maple_driver *mdrv = to_maple_driver(dev->driver);
|
||||
struct maple_device *mdev;
|
||||
struct maple_driver *mdrv;
|
||||
int i, error;
|
||||
struct dc_kbd *kbd;
|
||||
struct input_dev *idev;
|
||||
|
||||
if (!(mdev->function & MAPLE_FUNC_KEYBOARD))
|
||||
return -EINVAL;
|
||||
mdev = to_maple_dev(dev);
|
||||
mdrv = to_maple_driver(dev->driver);
|
||||
|
||||
kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
|
||||
idev = input_allocate_device();
|
||||
if (!kbd || !idev) {
|
||||
if (!kbd) {
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
idev = input_allocate_device();
|
||||
if (!idev) {
|
||||
error = -ENOMEM;
|
||||
goto fail_idev_alloc;
|
||||
}
|
||||
|
||||
kbd->dev = idev;
|
||||
memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode));
|
||||
|
||||
@@ -195,7 +200,7 @@ static int probe_maple_kbd(struct device *dev)
|
||||
|
||||
error = input_register_device(idev);
|
||||
if (error)
|
||||
goto fail;
|
||||
goto fail_register;
|
||||
|
||||
/* Maple polling is locked to VBLANK - which may be just 50/s */
|
||||
maple_getcond_callback(mdev, dc_kbd_callback, HZ/50,
|
||||
@@ -207,10 +212,12 @@ static int probe_maple_kbd(struct device *dev)
|
||||
|
||||
return error;
|
||||
|
||||
fail:
|
||||
input_free_device(idev);
|
||||
kfree(kbd);
|
||||
fail_register:
|
||||
maple_set_drvdata(mdev, NULL);
|
||||
input_free_device(idev);
|
||||
fail_idev_alloc:
|
||||
kfree(kbd);
|
||||
fail:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
+235
-228
File diff suppressed because it is too large
Load Diff
+41
-21
@@ -8,33 +8,49 @@ extern struct bus_type maple_bus_type;
|
||||
|
||||
/* Maple Bus command and response codes */
|
||||
enum maple_code {
|
||||
MAPLE_RESPONSE_FILEERR = -5,
|
||||
MAPLE_RESPONSE_AGAIN = -4, /* request should be retransmitted */
|
||||
MAPLE_RESPONSE_BADCMD = -3,
|
||||
MAPLE_RESPONSE_BADFUNC = -2,
|
||||
MAPLE_RESPONSE_NONE = -1, /* unit didn't respond at all */
|
||||
MAPLE_COMMAND_DEVINFO = 1,
|
||||
MAPLE_COMMAND_ALLINFO = 2,
|
||||
MAPLE_COMMAND_RESET = 3,
|
||||
MAPLE_COMMAND_KILL = 4,
|
||||
MAPLE_RESPONSE_DEVINFO = 5,
|
||||
MAPLE_RESPONSE_ALLINFO = 6,
|
||||
MAPLE_RESPONSE_OK = 7,
|
||||
MAPLE_RESPONSE_DATATRF = 8,
|
||||
MAPLE_COMMAND_GETCOND = 9,
|
||||
MAPLE_COMMAND_GETMINFO = 10,
|
||||
MAPLE_COMMAND_BREAD = 11,
|
||||
MAPLE_COMMAND_BWRITE = 12,
|
||||
MAPLE_COMMAND_SETCOND = 14
|
||||
MAPLE_RESPONSE_FILEERR = -5,
|
||||
MAPLE_RESPONSE_AGAIN, /* retransmit */
|
||||
MAPLE_RESPONSE_BADCMD,
|
||||
MAPLE_RESPONSE_BADFUNC,
|
||||
MAPLE_RESPONSE_NONE, /* unit didn't respond*/
|
||||
MAPLE_COMMAND_DEVINFO = 1,
|
||||
MAPLE_COMMAND_ALLINFO,
|
||||
MAPLE_COMMAND_RESET,
|
||||
MAPLE_COMMAND_KILL,
|
||||
MAPLE_RESPONSE_DEVINFO,
|
||||
MAPLE_RESPONSE_ALLINFO,
|
||||
MAPLE_RESPONSE_OK,
|
||||
MAPLE_RESPONSE_DATATRF,
|
||||
MAPLE_COMMAND_GETCOND,
|
||||
MAPLE_COMMAND_GETMINFO,
|
||||
MAPLE_COMMAND_BREAD,
|
||||
MAPLE_COMMAND_BWRITE,
|
||||
MAPLE_COMMAND_BSYNC,
|
||||
MAPLE_COMMAND_SETCOND,
|
||||
MAPLE_COMMAND_MICCONTROL
|
||||
};
|
||||
|
||||
enum maple_file_errors {
|
||||
MAPLE_FILEERR_INVALID_PARTITION = 0x01000000,
|
||||
MAPLE_FILEERR_PHASE_ERROR = 0x02000000,
|
||||
MAPLE_FILEERR_INVALID_BLOCK = 0x04000000,
|
||||
MAPLE_FILEERR_WRITE_ERROR = 0x08000000,
|
||||
MAPLE_FILEERR_INVALID_WRITE_LENGTH = 0x10000000,
|
||||
MAPLE_FILEERR_BAD_CRC = 0x20000000
|
||||
};
|
||||
|
||||
struct maple_buffer {
|
||||
char bufx[0x400];
|
||||
void *buf;
|
||||
};
|
||||
|
||||
struct mapleq {
|
||||
struct list_head list;
|
||||
struct maple_device *dev;
|
||||
void *sendbuf, *recvbuf, *recvbufdcsp;
|
||||
struct maple_buffer *recvbuf;
|
||||
void *sendbuf, *recvbuf_p2;
|
||||
unsigned char length;
|
||||
enum maple_code command;
|
||||
struct mutex mutex;
|
||||
};
|
||||
|
||||
struct maple_devinfo {
|
||||
@@ -52,11 +68,15 @@ struct maple_device {
|
||||
struct maple_driver *driver;
|
||||
struct mapleq *mq;
|
||||
void (*callback) (struct mapleq * mq);
|
||||
void (*fileerr_handler)(struct maple_device *mdev, void *recvbuf);
|
||||
int (*can_unload)(struct maple_device *mdev);
|
||||
unsigned long when, interval, function;
|
||||
struct maple_devinfo devinfo;
|
||||
unsigned char port, unit;
|
||||
char product_name[32];
|
||||
char product_licence[64];
|
||||
atomic_t busy;
|
||||
wait_queue_head_t maple_wait;
|
||||
struct device dev;
|
||||
};
|
||||
|
||||
@@ -72,7 +92,7 @@ void maple_getcond_callback(struct maple_device *dev,
|
||||
int maple_driver_register(struct maple_driver *);
|
||||
void maple_driver_unregister(struct maple_driver *);
|
||||
|
||||
int maple_add_packet_sleeps(struct maple_device *mdev, u32 function,
|
||||
int maple_add_packet(struct maple_device *mdev, u32 function,
|
||||
u32 command, u32 length, void *data);
|
||||
void maple_clear_dev(struct maple_device *mdev);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user