From b45d44e7e00c1726dac9437b66c05d3d27acb3f0 Mon Sep 17 00:00:00 2001 From: Nicolas Léveillé Date: Tue, 29 Dec 2009 20:39:05 -0800 Subject: Input: xpad - allow using triggers as buttons rather than axes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Certain devices implement triggers as buttons rather than axes. In particular, arcade sticks such as the HORI Real Arcade Pro.EX do not have analog buttons. These devices are now setup to present buttons rather than axes for triggers. User-space applications often also have problems with axes-as-buttons. Activating MAP_TRIGGERS_TO_BUTTONS for a device removes the artificial difference between buttons and triggers. Signed-off-by: Nicolas Léveillé Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 200 +++++++++++++++++++++++++----------------- 1 file changed, 121 insertions(+), 79 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 482cb1204e43..5483fb9bd819 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -86,9 +86,8 @@ /* xbox d-pads should map to buttons, as is required for DDR pads but we map them to axes when possible to simplify things */ -#define MAP_DPAD_TO_BUTTONS 0 -#define MAP_DPAD_TO_AXES 1 -#define MAP_DPAD_UNKNOWN 2 +#define MAP_DPAD_TO_BUTTONS (1 << 0) +#define MAP_TRIGGERS_TO_BUTTONS (1 << 1) #define XTYPE_XBOX 0 #define XTYPE_XBOX360 1 @@ -99,57 +98,61 @@ static int dpad_to_buttons; module_param(dpad_to_buttons, bool, S_IRUGO); MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); +static int triggers_to_buttons; +module_param(triggers_to_buttons, bool, S_IRUGO); +MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads"); + static const struct xpad_device { u16 idVendor; u16 idProduct; char *name; - u8 dpad_mapping; + u8 mapping; u8 xtype; } xpad_device[] = { - { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX }, + { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, + { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, + { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, + { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, - { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, - { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX }, + { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, + { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, + { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, + { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX }, + { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX }, + { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX }, + { 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX }, + { 0x0738, 0x4522, "Mad Catz LumiCON", 0, XTYPE_XBOX }, + { 0x0738, 0x4526, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX }, + { 0x0738, 0x4536, "Mad Catz MicroCON", 0, XTYPE_XBOX }, { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, - { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, - { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, + { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX }, + { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, - { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, - { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, + { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, + { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, + { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, + { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, + { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX }, + { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX }, + { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX }, + { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, + { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, + { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, + { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, + { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, + { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, - { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, + { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, - { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, - { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, + { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, + { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, - { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, - { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, - { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } + { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, + { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } }; /* buttons shared with xbox and xbox360 */ @@ -165,13 +168,20 @@ static const signed short xpad_btn[] = { -1 /* terminating entry */ }; -/* only used if MAP_DPAD_TO_BUTTONS */ +/* used when dpad is mapped to nuttons */ static const signed short xpad_btn_pad[] = { BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ BTN_0, BTN_1, /* d-pad up, down (XXX names??) */ -1 /* terminating entry */ }; +/* used when triggers are mapped to buttons */ +static const signed short xpad_btn_triggers[] = { + BTN_TL2, BTN_TR2, /* triggers left/right */ + -1 +}; + + static const signed short xpad360_btn[] = { /* buttons for x360 controller */ BTN_TL, BTN_TR, /* Button LB/RB */ BTN_MODE, /* The big X button */ @@ -181,16 +191,21 @@ static const signed short xpad360_btn[] = { /* buttons for x360 controller */ static const signed short xpad_abs[] = { ABS_X, ABS_Y, /* left stick */ ABS_RX, ABS_RY, /* right stick */ - ABS_Z, ABS_RZ, /* triggers left/right */ -1 /* terminating entry */ }; -/* only used if MAP_DPAD_TO_AXES */ +/* used when dpad is mapped to axes */ static const signed short xpad_abs_pad[] = { ABS_HAT0X, ABS_HAT0Y, /* d-pad axes */ -1 /* terminating entry */ }; +/* used when triggers are mapped to axes */ +static const signed short xpad_abs_triggers[] = { + ABS_Z, ABS_RZ, /* triggers left/right */ + -1 +}; + /* Xbox 360 has a vendor-specific class, so we cannot match it with only * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we * match against vendor id as well. Wired Xbox 360 devices have protocol 1, @@ -246,7 +261,7 @@ struct usb_xpad { char phys[64]; /* physical device path */ - int dpad_mapping; /* map d-pad to buttons or to axes */ + int mapping; /* map d-pad to buttons or to axes */ int xtype; /* type of xbox device */ }; @@ -277,20 +292,25 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d ~(__s16) le16_to_cpup((__le16 *)(data + 18))); /* triggers left/right */ - input_report_abs(dev, ABS_Z, data[10]); - input_report_abs(dev, ABS_RZ, data[11]); + if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { + input_report_key(dev, BTN_TL2, data[10]); + input_report_key(dev, BTN_TR2, data[11]); + } else { + input_report_abs(dev, ABS_Z, data[10]); + input_report_abs(dev, ABS_RZ, data[11]); + } /* digital pad */ - if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { - input_report_abs(dev, ABS_HAT0X, - !!(data[2] & 0x08) - !!(data[2] & 0x04)); - input_report_abs(dev, ABS_HAT0Y, - !!(data[2] & 0x02) - !!(data[2] & 0x01)); - } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { + if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { input_report_key(dev, BTN_LEFT, data[2] & 0x04); input_report_key(dev, BTN_RIGHT, data[2] & 0x08); input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ + } else { + input_report_abs(dev, ABS_HAT0X, + !!(data[2] & 0x08) - !!(data[2] & 0x04)); + input_report_abs(dev, ABS_HAT0Y, + !!(data[2] & 0x02) - !!(data[2] & 0x01)); } /* start/back buttons and stick press left/right */ @@ -328,17 +348,17 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev = xpad->dev; /* digital pad */ - if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { - input_report_abs(dev, ABS_HAT0X, - !!(data[2] & 0x08) - !!(data[2] & 0x04)); - input_report_abs(dev, ABS_HAT0Y, - !!(data[2] & 0x02) - !!(data[2] & 0x01)); - } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) { + if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { /* dpad as buttons (right, left, down, up) */ input_report_key(dev, BTN_LEFT, data[2] & 0x04); input_report_key(dev, BTN_RIGHT, data[2] & 0x08); input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ + } else { + input_report_abs(dev, ABS_HAT0X, + !!(data[2] & 0x08) - !!(data[2] & 0x04)); + input_report_abs(dev, ABS_HAT0Y, + !!(data[2] & 0x02) - !!(data[2] & 0x01)); } /* start/back buttons */ @@ -371,8 +391,13 @@ static void xpad360_process_packet(struct usb_xpad *xpad, ~(__s16) le16_to_cpup((__le16 *)(data + 12))); /* triggers left/right */ - input_report_abs(dev, ABS_Z, data[4]); - input_report_abs(dev, ABS_RZ, data[5]); + if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { + input_report_key(dev, BTN_TL2, data[4]); + input_report_key(dev, BTN_TR2, data[5]); + } else { + input_report_abs(dev, ABS_Z, data[4]); + input_report_abs(dev, ABS_RZ, data[5]); + } input_sync(dev); } @@ -712,11 +737,11 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128); break; case ABS_Z: - case ABS_RZ: /* the triggers */ + case ABS_RZ: /* the triggers (if mapped to axes) */ input_set_abs_params(input_dev, abs, 0, 255, 0, 0); break; case ABS_HAT0X: - case ABS_HAT0Y: /* the d-pad (only if MAP_DPAD_TO_AXES) */ + case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */ input_set_abs_params(input_dev, abs, -1, 1, 0, 0); break; } @@ -752,10 +777,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id goto fail2; xpad->udev = udev; - xpad->dpad_mapping = xpad_device[i].dpad_mapping; + xpad->mapping = xpad_device[i].mapping; xpad->xtype = xpad_device[i].xtype; - if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) - xpad->dpad_mapping = !dpad_to_buttons; + if (xpad->xtype == XTYPE_UNKNOWN) { if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) @@ -764,7 +788,13 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->xtype = XTYPE_XBOX360; } else xpad->xtype = XTYPE_XBOX; + + if (dpad_to_buttons) + xpad->mapping |= MAP_DPAD_TO_BUTTONS; + if (triggers_to_buttons) + xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS; } + xpad->dev = input_dev; usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); @@ -781,25 +811,37 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - /* set up buttons */ + /* set up standard buttons and axes */ for (i = 0; xpad_common_btn[i] >= 0; i++) - set_bit(xpad_common_btn[i], input_dev->keybit); - if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W)) - for (i = 0; xpad360_btn[i] >= 0; i++) - set_bit(xpad360_btn[i], input_dev->keybit); - else - for (i = 0; xpad_btn[i] >= 0; i++) - set_bit(xpad_btn[i], input_dev->keybit); - if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) - for (i = 0; xpad_btn_pad[i] >= 0; i++) - set_bit(xpad_btn_pad[i], input_dev->keybit); + __set_bit(xpad_common_btn[i], input_dev->keybit); - /* set up axes */ for (i = 0; xpad_abs[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs[i]); - if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) + + /* Now set up model-specific ones */ + if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) { + for (i = 0; xpad360_btn[i] >= 0; i++) + __set_bit(xpad360_btn[i], input_dev->keybit); + } else { + for (i = 0; xpad_btn[i] >= 0; i++) + __set_bit(xpad_btn[i], input_dev->keybit); + } + + if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { + for (i = 0; xpad_btn_pad[i] >= 0; i++) + __set_bit(xpad_btn_pad[i], input_dev->keybit); + } else { for (i = 0; xpad_abs_pad[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs_pad[i]); + } + + if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { + for (i = 0; xpad_btn_triggers[i] >= 0; i++) + __set_bit(xpad_btn_triggers[i], input_dev->keybit); + } else { + for (i = 0; xpad_abs_triggers[i] >= 0; i++) + xpad_set_up_abs(input_dev, xpad_abs_triggers[i]); + } error = xpad_init_output(intf, xpad); if (error) -- cgit v1.2.3 From 386d8772980be01b94bd463ea1e745732d7eb502 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:03 -0800 Subject: Input: serio - use device core to create 'id' attribute group Instead of creating 'id' sysfs attribute group by ourselves rely on device core to do that for us. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 0236f0d5fd91..0a278f9f1d3a 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -452,6 +452,11 @@ static struct attribute_group serio_id_attr_group = { .attrs = serio_device_id_attrs, }; +static const struct attribute_group *serio_device_attr_groups[] = { + &serio_id_attr_group, + NULL +}; + static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct serio *serio = to_serio_port(dev); @@ -539,6 +544,7 @@ static void serio_init_port(struct serio *serio) (long)atomic_inc_return(&serio_no) - 1); serio->dev.bus = &serio_bus; serio->dev.release = serio_release_port; + serio->dev.groups = serio_device_attr_groups; if (serio->parent) { serio->dev.parent = &serio->parent->dev; serio->depth = serio->parent->depth + 1; @@ -562,21 +568,17 @@ static void serio_add_port(struct serio *serio) } list_add_tail(&serio->node, &serio_list); + if (serio->start) serio->start(serio); + error = device_add(&serio->dev); if (error) printk(KERN_ERR "serio: device_add() failed for %s (%s), error: %d\n", serio->phys, serio->name, error); - else { + else serio->registered = true; - error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group); - if (error) - printk(KERN_ERR - "serio: sysfs_create_group() failed for %s (%s), error: %d\n", - serio->phys, serio->name, error); - } } /* @@ -604,7 +606,6 @@ static void serio_destroy_port(struct serio *serio) } if (serio->registered) { - sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group); device_del(&serio->dev); serio->registered = false; } -- cgit v1.2.3 From ddf1ffbd40c92ff1e58c45fa96d309788f7beb60 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:04 -0800 Subject: Input: serio - let device core tell us if device was registered No need to keep track of it by ourselves. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 8 ++------ include/linux/serio.h | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 0a278f9f1d3a..d89880450f77 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -577,8 +577,6 @@ static void serio_add_port(struct serio *serio) printk(KERN_ERR "serio: device_add() failed for %s (%s), error: %d\n", serio->phys, serio->name, error); - else - serio->registered = true; } /* @@ -605,10 +603,8 @@ static void serio_destroy_port(struct serio *serio) serio->parent = NULL; } - if (serio->registered) { + if (device_is_registered(&serio->dev)) device_del(&serio->dev); - serio->registered = false; - } list_del_init(&serio->node); serio_remove_pending_events(serio); @@ -995,7 +991,7 @@ irqreturn_t serio_interrupt(struct serio *serio, if (likely(serio->drv)) { ret = serio->drv->interrupt(serio, data, dfl); - } else if (!dfl && serio->registered) { + } else if (!dfl && device_is_registered(&serio->dev)) { serio_rescan(serio); ret = IRQ_HANDLED; } diff --git a/include/linux/serio.h b/include/linux/serio.h index e2f3044d4a4a..d0fb702059cd 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -30,7 +30,6 @@ struct serio { char phys[32]; bool manual_bind; - bool registered; /* port has been fully registered with driver core */ struct serio_device_id id; -- cgit v1.2.3 From 4516c8183213b59c3645d810ccb04b70c2606743 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:04 -0800 Subject: Input: serio - use list_first_entry() helper Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index d89880450f77..7fbf7670ae09 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -230,14 +230,12 @@ static void serio_free_event(struct serio_event *event) static void serio_remove_duplicate_events(struct serio_event *event) { - struct list_head *node, *next; - struct serio_event *e; + struct serio_event *e, *next; unsigned long flags; spin_lock_irqsave(&serio_event_lock, flags); - list_for_each_safe(node, next, &serio_event_list) { - e = list_entry(node, struct serio_event, node); + list_for_each_entry_safe(e, next, &serio_event_list, node) { if (event->object == e->object) { /* * If this event is of different type we should not @@ -247,7 +245,7 @@ static void serio_remove_duplicate_events(struct serio_event *event) if (event->type != e->type) break; - list_del_init(node); + list_del_init(&e->node); serio_free_event(e); } } @@ -258,23 +256,18 @@ static void serio_remove_duplicate_events(struct serio_event *event) static struct serio_event *serio_get_event(void) { - struct serio_event *event; - struct list_head *node; + struct serio_event *event = NULL; unsigned long flags; spin_lock_irqsave(&serio_event_lock, flags); - if (list_empty(&serio_event_list)) { - spin_unlock_irqrestore(&serio_event_lock, flags); - return NULL; + if (!list_empty(&serio_event_list)) { + event = list_first_entry(&serio_event_list, + struct serio_event, node); + list_del_init(&event->node); } - node = serio_event_list.next; - event = list_entry(node, struct serio_event, node); - list_del_init(node); - spin_unlock_irqrestore(&serio_event_lock, flags); - return event; } @@ -331,16 +324,14 @@ static void serio_handle_event(void) */ static void serio_remove_pending_events(void *object) { - struct list_head *node, *next; - struct serio_event *event; + struct serio_event *event, *next; unsigned long flags; spin_lock_irqsave(&serio_event_lock, flags); - list_for_each_safe(node, next, &serio_event_list) { - event = list_entry(node, struct serio_event, node); + list_for_each_entry_safe(event, next, &serio_event_list, node) { if (event->object == object) { - list_del_init(node); + list_del_init(&event->node); serio_free_event(event); } } -- cgit v1.2.3 From cac9169bf75ea8cbaab75be9dbe5eb79a2bad6f5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:04 -0800 Subject: Input: serio - use pr_xxx() and dev_xxx() helpers pr_xxx() and dev_xxx() helpers ensure that all messages emitted by the module have consistent prefixes, so let's use them. Also fix some formatting issues. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 77 +++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 42 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 7fbf7670ae09..ee69ec399e08 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -26,6 +26,8 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -119,11 +121,10 @@ static int serio_bind_driver(struct serio *serio, struct serio_driver *drv) error = device_bind_driver(&serio->dev); if (error) { - printk(KERN_WARNING - "serio: device_bind_driver() failed " - "for %s (%s) and %s, error: %d\n", - serio->phys, serio->name, - drv->description, error); + dev_warn(&serio->dev, + "device_bind_driver() failed for %s (%s) and %s, error: %d\n", + serio->phys, serio->name, + drv->description, error); serio_disconnect_driver(serio); serio->dev.driver = NULL; return error; @@ -138,9 +139,9 @@ static void serio_find_driver(struct serio *serio) error = device_attach(&serio->dev); if (error < 0) - printk(KERN_WARNING - "serio: device_attach() failed for %s (%s), error: %d\n", - serio->phys, serio->name, error); + dev_warn(&serio->dev, + "device_attach() failed for %s (%s), error: %d\n", + serio->phys, serio->name, error); } @@ -194,17 +195,14 @@ static int serio_queue_event(void *object, struct module *owner, event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); if (!event) { - printk(KERN_ERR - "serio: Not enough memory to queue event %d\n", - event_type); + pr_err("Not enough memory to queue event %d\n", event_type); retval = -ENOMEM; goto out; } if (!try_module_get(owner)) { - printk(KERN_WARNING - "serio: Can't get module reference, dropping event %d\n", - event_type); + pr_warning("Can't get module reference, dropping event %d\n", + event_type); kfree(event); retval = -EINVAL; goto out; @@ -286,29 +284,27 @@ static void serio_handle_event(void) if ((event = serio_get_event())) { switch (event->type) { - case SERIO_REGISTER_PORT: - serio_add_port(event->object); - break; - case SERIO_RECONNECT_PORT: - serio_reconnect_port(event->object); - break; + case SERIO_REGISTER_PORT: + serio_add_port(event->object); + break; - case SERIO_RESCAN_PORT: - serio_disconnect_port(event->object); - serio_find_driver(event->object); - break; + case SERIO_RECONNECT_PORT: + serio_reconnect_port(event->object); + break; - case SERIO_RECONNECT_CHAIN: - serio_reconnect_chain(event->object); - break; + case SERIO_RESCAN_PORT: + serio_disconnect_port(event->object); + serio_find_driver(event->object); + break; - case SERIO_ATTACH_DRIVER: - serio_attach_driver(event->object); - break; + case SERIO_RECONNECT_CHAIN: + serio_reconnect_chain(event->object); + break; - default: - break; + case SERIO_ATTACH_DRIVER: + serio_attach_driver(event->object); + break; } serio_remove_duplicate_events(event); @@ -378,7 +374,6 @@ static int serio_thread(void *nothing) kthread_should_stop() || !list_empty(&serio_event_list)); } while (!kthread_should_stop()); - printk(KERN_DEBUG "serio: kseriod exiting\n"); return 0; } @@ -565,8 +560,8 @@ static void serio_add_port(struct serio *serio) error = device_add(&serio->dev); if (error) - printk(KERN_ERR - "serio: device_add() failed for %s (%s), error: %d\n", + dev_err(&serio->dev, + "device_add() failed for %s (%s), error: %d\n", serio->phys, serio->name, error); } @@ -793,9 +788,8 @@ static void serio_attach_driver(struct serio_driver *drv) error = driver_attach(&drv->driver); if (error) - printk(KERN_WARNING - "serio: driver_attach() failed for %s with error %d\n", - drv->driver.name, error); + pr_warning("driver_attach() failed for %s with error %d\n", + drv->driver.name, error); } int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name) @@ -815,8 +809,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons error = driver_register(&drv->driver); if (error) { - printk(KERN_ERR - "serio: driver_register() failed for %s, error: %d\n", + pr_err("driver_register() failed for %s, error: %d\n", drv->driver.name, error); return error; } @@ -1013,7 +1006,7 @@ static int __init serio_init(void) error = bus_register(&serio_bus); if (error) { - printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error); + pr_err("Failed to register serio bus, error: %d\n", error); return error; } @@ -1021,7 +1014,7 @@ static int __init serio_init(void) if (IS_ERR(serio_task)) { bus_unregister(&serio_bus); error = PTR_ERR(serio_task); - printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error); + pr_err("Failed to start kseriod, error: %d\n", error); return error; } -- cgit v1.2.3 From 361b7b5b032338361ea88412f1fc45479fdd5859 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:03 -0800 Subject: Input: gameport - let device core tell us if device was registered No need to keep track of it by ourselves. Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/gameport.c | 6 +----- include/linux/gameport.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index ac11be08585e..f9e5f8e1690b 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -561,8 +561,6 @@ static void gameport_add_port(struct gameport *gameport) printk(KERN_ERR "gameport: device_add() failed for %s (%s), error: %d\n", gameport->phys, gameport->name, error); - else - gameport->registered = 1; } /* @@ -584,10 +582,8 @@ static void gameport_destroy_port(struct gameport *gameport) gameport->parent = NULL; } - if (gameport->registered) { + if (device_is_registered(&gameport->dev)) device_del(&gameport->dev); - gameport->registered = 0; - } list_del_init(&gameport->node); diff --git a/include/linux/gameport.h b/include/linux/gameport.h index 1bc08541c2b9..48e68da097f6 100644 --- a/include/linux/gameport.h +++ b/include/linux/gameport.h @@ -46,7 +46,6 @@ struct gameport { struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */ struct device dev; - unsigned int registered; /* port has been fully registered with driver core */ struct list_head node; }; -- cgit v1.2.3 From d621af473079851caac873adc5431a05c9d78dfd Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:03 -0800 Subject: Input: gameport - make use of list_first_entry() helper Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/gameport.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index f9e5f8e1690b..953a20bf26e8 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -298,14 +298,12 @@ static void gameport_free_event(struct gameport_event *event) static void gameport_remove_duplicate_events(struct gameport_event *event) { - struct list_head *node, *next; - struct gameport_event *e; + struct gameport_event *e, *next; unsigned long flags; spin_lock_irqsave(&gameport_event_lock, flags); - list_for_each_safe(node, next, &gameport_event_list) { - e = list_entry(node, struct gameport_event, node); + list_for_each_entry_safe(e, next, &gameport_event_list, node) { if (event->object == e->object) { /* * If this event is of different type we should not @@ -315,7 +313,7 @@ static void gameport_remove_duplicate_events(struct gameport_event *event) if (event->type != e->type) break; - list_del_init(node); + list_del_init(&e->node); gameport_free_event(e); } } @@ -325,21 +323,17 @@ static void gameport_remove_duplicate_events(struct gameport_event *event) static struct gameport_event *gameport_get_event(void) { - struct gameport_event *event; - struct list_head *node; + struct gameport_event *event = NULL; unsigned long flags; spin_lock_irqsave(&gameport_event_lock, flags); - if (list_empty(&gameport_event_list)) { - spin_unlock_irqrestore(&gameport_event_lock, flags); - return NULL; + if (!list_empty(&gameport_event_list)) { + event = list_first_entry(&gameport_event_list, + struct gameport_event, node); + list_del_init(&event->node); } - node = gameport_event_list.next; - event = list_entry(node, struct gameport_event, node); - list_del_init(node); - spin_unlock_irqrestore(&gameport_event_lock, flags); return event; @@ -385,16 +379,14 @@ static void gameport_handle_event(void) */ static void gameport_remove_pending_events(void *object) { - struct list_head *node, *next; - struct gameport_event *event; + struct gameport_event *event, *next; unsigned long flags; spin_lock_irqsave(&gameport_event_lock, flags); - list_for_each_safe(node, next, &gameport_event_list) { - event = list_entry(node, struct gameport_event, node); + list_for_each_entry_safe(event, next, &gameport_event_list, node) { if (event->object == object) { - list_del_init(node); + list_del_init(&event->node); gameport_free_event(event); } } -- cgit v1.2.3 From fc99ec6f4b6116305bca56a781b8b3b2ac054d27 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:03 -0800 Subject: Input: gameport - switch to using pr_xxx() and dev_xxx() pr_xxx() and dev_xxx() helpers ensure that all messages emitted by the module have consistent prefixes, so let's use them. Also fix some formatting issues. Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/gameport.c | 62 ++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 34 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 953a20bf26e8..7e18bcf05a66 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -11,6 +11,8 @@ * the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -190,9 +192,8 @@ static int gameport_bind_driver(struct gameport *gameport, struct gameport_drive error = device_bind_driver(&gameport->dev); if (error) { - printk(KERN_WARNING - "gameport: device_bind_driver() failed " - "for %s (%s) and %s, error: %d\n", + dev_warn(&gameport->dev, + "device_bind_driver() failed for %s (%s) and %s, error: %d\n", gameport->phys, gameport->name, drv->description, error); drv->disconnect(gameport); @@ -209,9 +210,9 @@ static void gameport_find_driver(struct gameport *gameport) error = device_attach(&gameport->dev); if (error < 0) - printk(KERN_WARNING - "gameport: device_attach() failed for %s (%s), error: %d\n", - gameport->phys, gameport->name, error); + dev_warn(&gameport->dev, + "device_attach() failed for %s (%s), error: %d\n", + gameport->phys, gameport->name, error); } @@ -262,17 +263,14 @@ static int gameport_queue_event(void *object, struct module *owner, event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); if (!event) { - printk(KERN_ERR - "gameport: Not enough memory to queue event %d\n", - event_type); + pr_err("Not enough memory to queue event %d\n", event_type); retval = -ENOMEM; goto out; } if (!try_module_get(owner)) { - printk(KERN_WARNING - "gameport: Can't get module reference, dropping event %d\n", - event_type); + pr_warning("Can't get module reference, dropping event %d\n", + event_type); kfree(event); retval = -EINVAL; goto out; @@ -335,7 +333,6 @@ static struct gameport_event *gameport_get_event(void) } spin_unlock_irqrestore(&gameport_event_lock, flags); - return event; } @@ -354,16 +351,14 @@ static void gameport_handle_event(void) if ((event = gameport_get_event())) { switch (event->type) { - case GAMEPORT_REGISTER_PORT: - gameport_add_port(event->object); - break; - case GAMEPORT_ATTACH_DRIVER: - gameport_attach_driver(event->object); - break; + case GAMEPORT_REGISTER_PORT: + gameport_add_port(event->object); + break; - default: - break; + case GAMEPORT_ATTACH_DRIVER: + gameport_attach_driver(event->object); + break; } gameport_remove_duplicate_events(event); @@ -433,7 +428,6 @@ static int gameport_thread(void *nothing) kthread_should_stop() || !list_empty(&gameport_event_list)); } while (!kthread_should_stop()); - printk(KERN_DEBUG "gameport: kgameportd exiting\n"); return 0; } @@ -445,6 +439,7 @@ static int gameport_thread(void *nothing) static ssize_t gameport_show_description(struct device *dev, struct device_attribute *attr, char *buf) { struct gameport *gameport = to_gameport_port(dev); + return sprintf(buf, "%s\n", gameport->name); } @@ -513,7 +508,8 @@ static void gameport_init_port(struct gameport *gameport) mutex_init(&gameport->drv_mutex); device_initialize(&gameport->dev); - dev_set_name(&gameport->dev, "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1); + dev_set_name(&gameport->dev, "gameport%lu", + (unsigned long)atomic_inc_return(&gameport_no) - 1); gameport->dev.bus = &gameport_bus; gameport->dev.release = gameport_release_port; if (gameport->parent) @@ -542,16 +538,16 @@ static void gameport_add_port(struct gameport *gameport) list_add_tail(&gameport->node, &gameport_list); if (gameport->io) - printk(KERN_INFO "gameport: %s is %s, io %#x, speed %dkHz\n", - gameport->name, gameport->phys, gameport->io, gameport->speed); + dev_info(&gameport->dev, "%s is %s, io %#x, speed %dkHz\n", + gameport->name, gameport->phys, gameport->io, gameport->speed); else - printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n", + dev_info(&gameport->dev, "%s is %s, speed %dkHz\n", gameport->name, gameport->phys, gameport->speed); error = device_add(&gameport->dev); if (error) - printk(KERN_ERR - "gameport: device_add() failed for %s (%s), error: %d\n", + dev_err(&gameport->dev, + "device_add() failed for %s (%s), error: %d\n", gameport->phys, gameport->name, error); } @@ -693,8 +689,7 @@ static void gameport_attach_driver(struct gameport_driver *drv) error = driver_attach(&drv->driver); if (error) - printk(KERN_ERR - "gameport: driver_attach() failed for %s, error: %d\n", + pr_err("driver_attach() failed for %s, error: %d\n", drv->driver.name, error); } @@ -715,8 +710,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner error = driver_register(&drv->driver); if (error) { - printk(KERN_ERR - "gameport: driver_register() failed for %s, error: %d\n", + pr_err("driver_register() failed for %s, error: %d\n", drv->driver.name, error); return error; } @@ -816,7 +810,7 @@ static int __init gameport_init(void) error = bus_register(&gameport_bus); if (error) { - printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error); + pr_err("failed to register gameport bus, error: %d\n", error); return error; } @@ -824,7 +818,7 @@ static int __init gameport_init(void) if (IS_ERR(gameport_task)) { bus_unregister(&gameport_bus); error = PTR_ERR(gameport_task); - printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error); + pr_err("Failed to start kgameportd, error: %d\n", error); return error; } -- cgit v1.2.3 From 4f93df40859cf471774f6ef3ec7f2870c2e8e260 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:00 -0800 Subject: Input: automatically reset KEY_RESERVED bit for all input devices KEY_RESERVED is not supposed to be reported to userspace but rather to mark unused entries in keymaps. Acked-by: Henrique de Moraes Holschuh Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/input.c b/drivers/input/input.c index ab060710688f..910d7be06eff 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -613,12 +613,12 @@ static int input_default_setkeycode(struct input_dev *dev, } } - clear_bit(old_keycode, dev->keybit); - set_bit(keycode, dev->keybit); + __clear_bit(old_keycode, dev->keybit); + __set_bit(keycode, dev->keybit); for (i = 0; i < dev->keycodemax; i++) { if (input_fetch_keycode(dev, i) == old_keycode) { - set_bit(old_keycode, dev->keybit); + __set_bit(old_keycode, dev->keybit); break; /* Setting the bit twice is useless, so break */ } } @@ -676,6 +676,9 @@ int input_set_keycode(struct input_dev *dev, int scancode, int keycode) if (retval) goto out; + /* Make sure KEY_RESERVED did not get enabled. */ + __clear_bit(KEY_RESERVED, dev->keybit); + /* * Simulate keyup event if keycode is not present * in the keymap anymore @@ -1513,13 +1516,16 @@ int input_register_device(struct input_dev *dev) const char *path; int error; + /* Every input device generates EV_SYN/SYN_REPORT events. */ __set_bit(EV_SYN, dev->evbit); + /* KEY_RESERVED is not supposed to be transmitted to userspace. */ + __clear_bit(KEY_RESERVED, dev->keybit); + /* * If delay and period are pre-set by the driver, then autorepeating * is handled by the driver itself and we don't do it in input.c. */ - init_timer(&dev->timer); if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) { dev->timer.data = (long) dev; -- cgit v1.2.3 From 92a3a58788790645c6143b5353ef065fd26110bb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:01 -0800 Subject: Input: cleanse capabilities bits before registering device To avoid showing garbage in capability bits, zero out bitmasks absent from dev->evbit in case driver inadvertently leaves some garbage there. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/input.c b/drivers/input/input.c index 910d7be06eff..a31394c1eca8 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1497,6 +1497,25 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int } EXPORT_SYMBOL(input_set_capability); +#define INPUT_CLEANSE_BITMASK(dev, type, bits) \ + do { \ + if (!test_bit(EV_##type, dev->evbit)) \ + memset(dev->bits##bit, 0, \ + sizeof(dev->bits##bit)); \ + } while (0) + +static void input_cleanse_bitmasks(struct input_dev *dev) +{ + INPUT_CLEANSE_BITMASK(dev, KEY, key); + INPUT_CLEANSE_BITMASK(dev, REL, rel); + INPUT_CLEANSE_BITMASK(dev, ABS, abs); + INPUT_CLEANSE_BITMASK(dev, MSC, msc); + INPUT_CLEANSE_BITMASK(dev, LED, led); + INPUT_CLEANSE_BITMASK(dev, SND, snd); + INPUT_CLEANSE_BITMASK(dev, FF, ff); + INPUT_CLEANSE_BITMASK(dev, SW, sw); +} + /** * input_register_device - register device with input core * @dev: device to be registered @@ -1522,6 +1541,9 @@ int input_register_device(struct input_dev *dev) /* KEY_RESERVED is not supposed to be transmitted to userspace. */ __clear_bit(KEY_RESERVED, dev->keybit); + /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ + input_cleanse_bitmasks(dev); + /* * If delay and period are pre-set by the driver, then autorepeating * is handled by the driver itself and we don't do it in input.c. -- cgit v1.2.3 From 3032458e38b583c92842818871e85c0f936b8645 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 6 Jan 2010 00:33:07 -0800 Subject: Input: psmouse - remove unused 'autocal' parameter from hgpk protocol Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/hgpk.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index b146237266d8..29dc6aade766 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -68,10 +68,6 @@ module_param(post_interrupt_delay, int, 0644); MODULE_PARM_DESC(post_interrupt_delay, "delay (ms) before recal after recal interrupt detected"); -static int autorecal = 1; -module_param(autorecal, int, 0644); -MODULE_PARM_DESC(autorecal, "enable recalibration in the driver"); - /* * When the touchpad gets ultra-sensitive, one can keep their finger 1/2" * above the pad and still have it send packets. This causes a jump cursor -- cgit v1.2.3 From a9a1f9c315c27fe7a260cd453167981cd680dae8 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 6 Jan 2010 23:51:47 -0800 Subject: Input: atkbd - switch to dev_err() and friends dev_err(), dev_warn() and dev_dbg() ensure consistency in driver messages. Also switch to using bool where appropriate and fix some formatting issues. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 283 +++++++++++++++++++++-------------------- 1 file changed, 146 insertions(+), 137 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index a3573570c52f..7c235013dba3 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -40,26 +40,26 @@ module_param_named(set, atkbd_set, int, 0); MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)"); #if defined(__i386__) || defined(__x86_64__) || defined(__hppa__) -static int atkbd_reset; +static bool atkbd_reset; #else -static int atkbd_reset = 1; +static bool atkbd_reset = true; #endif module_param_named(reset, atkbd_reset, bool, 0); MODULE_PARM_DESC(reset, "Reset keyboard during initialization"); -static int atkbd_softrepeat; +static bool atkbd_softrepeat; module_param_named(softrepeat, atkbd_softrepeat, bool, 0); MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat"); -static int atkbd_softraw = 1; +static bool atkbd_softraw = true; module_param_named(softraw, atkbd_softraw, bool, 0); MODULE_PARM_DESC(softraw, "Use software generated rawmode"); -static int atkbd_scroll; +static bool atkbd_scroll; module_param_named(scroll, atkbd_scroll, bool, 0); MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards"); -static int atkbd_extra; +static bool atkbd_extra; module_param_named(extra, atkbd_extra, bool, 0); MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards"); @@ -205,18 +205,18 @@ struct atkbd { unsigned short keycode[ATKBD_KEYMAP_SIZE]; DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE); unsigned char set; - unsigned char translated; - unsigned char extra; - unsigned char write; - unsigned char softrepeat; - unsigned char softraw; - unsigned char scroll; - unsigned char enabled; + bool translated; + bool extra; + bool write; + bool softrepeat; + bool softraw; + bool scroll; + bool enabled; /* Accessed only from interrupt */ unsigned char emul; - unsigned char resend; - unsigned char release; + bool resend; + bool release; unsigned long xl_bit; unsigned int last; unsigned long time; @@ -298,18 +298,18 @@ static const unsigned int xl_table[] = { * Checks if we should mangle the scancode to extract 'release' bit * in translated mode. */ -static int atkbd_need_xlate(unsigned long xl_bit, unsigned char code) +static bool atkbd_need_xlate(unsigned long xl_bit, unsigned char code) { int i; if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1) - return 0; + return false; for (i = 0; i < ARRAY_SIZE(xl_table); i++) if (code == xl_table[i]) return test_bit(i, &xl_bit); - return 1; + return true; } /* @@ -356,7 +356,7 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code */ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, - unsigned int flags) + unsigned int flags) { struct atkbd *atkbd = serio_get_drvdata(serio); struct input_dev *dev = atkbd->dev; @@ -365,20 +365,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, int value; unsigned short keycode; -#ifdef ATKBD_DEBUG - printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags); -#endif + dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags); #if !defined(__i386__) && !defined (__x86_64__) if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) { - printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags); + dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags); serio_write(serio, ATKBD_CMD_RESEND); - atkbd->resend = 1; + atkbd->resend = true; goto out; } if (!flags && data == ATKBD_RET_ACK) - atkbd->resend = 0; + atkbd->resend = false; #endif if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK)) @@ -409,32 +407,32 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, } switch (code) { - case ATKBD_RET_BAT: - atkbd->enabled = 0; - serio_reconnect(atkbd->ps2dev.serio); - goto out; - case ATKBD_RET_EMUL0: - atkbd->emul = 1; - goto out; - case ATKBD_RET_EMUL1: - atkbd->emul = 2; - goto out; - case ATKBD_RET_RELEASE: - atkbd->release = 1; - goto out; - case ATKBD_RET_ACK: - case ATKBD_RET_NAK: - if (printk_ratelimit()) - printk(KERN_WARNING "atkbd.c: Spurious %s on %s. " - "Some program might be trying access hardware directly.\n", - data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); - goto out; - case ATKBD_RET_ERR: - atkbd->err_count++; -#ifdef ATKBD_DEBUG - printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys); -#endif - goto out; + case ATKBD_RET_BAT: + atkbd->enabled = false; + serio_reconnect(atkbd->ps2dev.serio); + goto out; + case ATKBD_RET_EMUL0: + atkbd->emul = 1; + goto out; + case ATKBD_RET_EMUL1: + atkbd->emul = 2; + goto out; + case ATKBD_RET_RELEASE: + atkbd->release = true; + goto out; + case ATKBD_RET_ACK: + case ATKBD_RET_NAK: + if (printk_ratelimit()) + dev_warn(&serio->dev, + "Spurious %s on %s. " + "Some program might be trying access hardware directly.\n", + data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); + goto out; + case ATKBD_RET_ERR: + atkbd->err_count++; + dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n", + serio->phys); + goto out; } code = atkbd_compat_scancode(atkbd, code); @@ -448,71 +446,72 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, input_event(dev, EV_MSC, MSC_SCAN, code); switch (keycode) { - case ATKBD_KEY_NULL: - break; - case ATKBD_KEY_UNKNOWN: - printk(KERN_WARNING - "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n", - atkbd->release ? "released" : "pressed", - atkbd->translated ? "translated" : "raw", - atkbd->set, code, serio->phys); - printk(KERN_WARNING - "atkbd.c: Use 'setkeycodes %s%02x ' to make it known.\n", - code & 0x80 ? "e0" : "", code & 0x7f); - input_sync(dev); - break; - case ATKBD_SCR_1: - scroll = 1 - atkbd->release * 2; - break; - case ATKBD_SCR_2: - scroll = 2 - atkbd->release * 4; - break; - case ATKBD_SCR_4: - scroll = 4 - atkbd->release * 8; - break; - case ATKBD_SCR_8: - scroll = 8 - atkbd->release * 16; - break; - case ATKBD_SCR_CLICK: - click = !atkbd->release; - break; - case ATKBD_SCR_LEFT: - hscroll = -1; - break; - case ATKBD_SCR_RIGHT: - hscroll = 1; - break; - default: - if (atkbd->release) { - value = 0; - atkbd->last = 0; - } else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) { - /* Workaround Toshiba laptop multiple keypress */ - value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2; - } else { - value = 1; - atkbd->last = code; - atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2; - } - - input_event(dev, EV_KEY, keycode, value); - input_sync(dev); + case ATKBD_KEY_NULL: + break; + case ATKBD_KEY_UNKNOWN: + dev_warn(&serio->dev, + "Unknown key %s (%s set %d, code %#x on %s).\n", + atkbd->release ? "released" : "pressed", + atkbd->translated ? "translated" : "raw", + atkbd->set, code, serio->phys); + dev_warn(&serio->dev, + "Use 'setkeycodes %s%02x ' to make it known.\n", + code & 0x80 ? "e0" : "", code & 0x7f); + input_sync(dev); + break; + case ATKBD_SCR_1: + scroll = 1; + break; + case ATKBD_SCR_2: + scroll = 2; + break; + case ATKBD_SCR_4: + scroll = 4; + break; + case ATKBD_SCR_8: + scroll = 8; + break; + case ATKBD_SCR_CLICK: + click = !atkbd->release; + break; + case ATKBD_SCR_LEFT: + hscroll = -1; + break; + case ATKBD_SCR_RIGHT: + hscroll = 1; + break; + default: + if (atkbd->release) { + value = 0; + atkbd->last = 0; + } else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) { + /* Workaround Toshiba laptop multiple keypress */ + value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2; + } else { + value = 1; + atkbd->last = code; + atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2; + } + + input_event(dev, EV_KEY, keycode, value); + input_sync(dev); - if (value && test_bit(code, atkbd->force_release_mask)) { - input_report_key(dev, keycode, 0); - input_sync(dev); - } + if (value && test_bit(code, atkbd->force_release_mask)) { + input_report_key(dev, keycode, 0); + input_sync(dev); + } } if (atkbd->scroll) { if (click != -1) input_report_key(dev, BTN_MIDDLE, click); - input_report_rel(dev, REL_WHEEL, scroll); + input_report_rel(dev, REL_WHEEL, + atkbd->release ? -scroll : scroll); input_report_rel(dev, REL_HWHEEL, hscroll); input_sync(dev); } - atkbd->release = 0; + atkbd->release = false; out: return IRQ_HANDLED; } @@ -631,17 +630,18 @@ static int atkbd_event(struct input_dev *dev, switch (type) { - case EV_LED: - atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT); - return 0; + case EV_LED: + atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT); + return 0; - case EV_REP: - if (!atkbd->softrepeat) - atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT); - return 0; - } + case EV_REP: + if (!atkbd->softrepeat) + atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT); + return 0; - return -1; + default: + return -1; + } } /* @@ -652,7 +652,7 @@ static int atkbd_event(struct input_dev *dev, static inline void atkbd_enable(struct atkbd *atkbd) { serio_pause_rx(atkbd->ps2dev.serio); - atkbd->enabled = 1; + atkbd->enabled = true; serio_continue_rx(atkbd->ps2dev.serio); } @@ -664,7 +664,7 @@ static inline void atkbd_enable(struct atkbd *atkbd) static inline void atkbd_disable(struct atkbd *atkbd) { serio_pause_rx(atkbd->ps2dev.serio); - atkbd->enabled = 0; + atkbd->enabled = false; serio_continue_rx(atkbd->ps2dev.serio); } @@ -685,7 +685,9 @@ static int atkbd_probe(struct atkbd *atkbd) if (atkbd_reset) if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT)) - printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", ps2dev->serio->phys); + dev_warn(&ps2dev->serio->dev, + "keyboard reset failed on %s\n", + ps2dev->serio->phys); /* * Then we check the keyboard ID. We should get 0xab83 under normal conditions. @@ -715,8 +717,9 @@ static int atkbd_probe(struct atkbd *atkbd) atkbd->id = (param[0] << 8) | param[1]; if (atkbd->id == 0xaca1 && atkbd->translated) { - printk(KERN_ERR "atkbd.c: NCD terminal keyboards are only supported on non-translating\n"); - printk(KERN_ERR "atkbd.c: controllers. Use i8042.direct=1 to disable translation.\n"); + dev_err(&ps2dev->serio->dev, + "NCD terminal keyboards are only supported on non-translating controlelrs. " + "Use i8042.direct=1 to disable translation.\n"); return -1; } @@ -734,7 +737,7 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra struct ps2dev *ps2dev = &atkbd->ps2dev; unsigned char param[2]; - atkbd->extra = 0; + atkbd->extra = false; /* * For known special keyboards we can go ahead and set the correct set. * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and @@ -753,7 +756,7 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra if (allow_extra) { param[0] = 0x71; if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) { - atkbd->extra = 1; + atkbd->extra = true; return 2; } } @@ -818,7 +821,8 @@ static int atkbd_activate(struct atkbd *atkbd) */ if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) { - printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n", + dev_err(&ps2dev->serio->dev, + "Failed to enable keyboard on %s\n", ps2dev->serio->phys); return -1; } @@ -1090,12 +1094,14 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) switch (serio->id.type) { - case SERIO_8042_XL: - atkbd->translated = 1; - case SERIO_8042: - if (serio->write) - atkbd->write = 1; - break; + case SERIO_8042_XL: + atkbd->translated = true; + /* Fall through */ + + case SERIO_8042: + if (serio->write) + atkbd->write = true; + break; } atkbd->softraw = atkbd_softraw; @@ -1103,7 +1109,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->scroll = atkbd_scroll; if (atkbd->softrepeat) - atkbd->softraw = 1; + atkbd->softraw = true; serio_set_drvdata(serio, atkbd); @@ -1161,7 +1167,8 @@ static int atkbd_reconnect(struct serio *serio) struct serio_driver *drv = serio->drv; if (!atkbd || !drv) { - printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); + dev_dbg(&serio->dev, + "reconnect request, but serio is disconnected, ignoring...\n"); return -1; } @@ -1288,7 +1295,8 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun struct input_dev *old_dev, *new_dev; unsigned long value; int err; - unsigned char old_extra, old_set; + bool old_extra; + unsigned char old_set; if (!atkbd->write) return -EIO; @@ -1371,7 +1379,7 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou struct input_dev *old_dev, *new_dev; unsigned long value; int err; - unsigned char old_scroll; + bool old_scroll; if (strict_strtoul(buf, 10, &value) || value > 1) return -EINVAL; @@ -1415,7 +1423,8 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) struct input_dev *old_dev, *new_dev; unsigned long value; int err; - unsigned char old_set, old_extra; + unsigned char old_set; + bool old_extra; if (!atkbd->write) return -EIO; @@ -1465,7 +1474,7 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t struct input_dev *old_dev, *new_dev; unsigned long value; int err; - unsigned char old_softrepeat, old_softraw; + bool old_softrepeat, old_softraw; if (!atkbd->write) return -EIO; @@ -1485,7 +1494,7 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t atkbd->dev = new_dev; atkbd->softrepeat = value; if (atkbd->softrepeat) - atkbd->softraw = 1; + atkbd->softraw = true; atkbd_set_device_attrs(atkbd); err = input_register_device(atkbd->dev); @@ -1515,7 +1524,7 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co struct input_dev *old_dev, *new_dev; unsigned long value; int err; - unsigned char old_softraw; + bool old_softraw; if (strict_strtoul(buf, 10, &value) || value > 1) return -EINVAL; -- cgit v1.2.3 From 8cab9ba10493cea164ac8bbbc733c21a528e6fe5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 6 Jan 2010 23:52:12 -0800 Subject: Input: elo - switch to using dev_xxx() when printing messages Also fix formatting of "switch" statements. Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elo.c | 225 +++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 105 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 8f38c5e55ce6..486d31ba9c09 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -72,45 +72,49 @@ static void elo_process_data_10(struct elo *elo, unsigned char data) struct input_dev *dev = elo->dev; elo->data[elo->idx] = data; - switch (elo->idx++) { - case 0: - elo->csum = 0xaa; - if (data != ELO10_LEAD_BYTE) { - pr_debug("elo: unsynchronized data: 0x%02x\n", data); - elo->idx = 0; - } - break; - case 9: + switch (elo->idx++) { + case 0: + elo->csum = 0xaa; + if (data != ELO10_LEAD_BYTE) { + dev_dbg(&elo->serio->dev, + "unsynchronized data: 0x%02x\n", data); elo->idx = 0; - if (data != elo->csum) { - pr_debug("elo: bad checksum: 0x%02x, expected 0x%02x\n", - data, elo->csum); - break; - } - if (elo->data[1] != elo->expected_packet) { - if (elo->data[1] != ELO10_TOUCH_PACKET) - pr_debug("elo: unexpected packet: 0x%02x\n", - elo->data[1]); - break; - } - if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { - input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); - input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); - if (elo->data[2] & ELO10_PRESSURE) - input_report_abs(dev, ABS_PRESSURE, - (elo->data[8] << 8) | elo->data[7]); - input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); - input_sync(dev); - } else if (elo->data[1] == ELO10_ACK_PACKET) { - if (elo->data[2] == '0') - elo->expected_packet = ELO10_TOUCH_PACKET; - complete(&elo->cmd_done); - } else { - memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); - elo->expected_packet = ELO10_ACK_PACKET; - } + } + break; + + case 9: + elo->idx = 0; + if (data != elo->csum) { + dev_dbg(&elo->serio->dev, + "bad checksum: 0x%02x, expected 0x%02x\n", + data, elo->csum); + break; + } + if (elo->data[1] != elo->expected_packet) { + if (elo->data[1] != ELO10_TOUCH_PACKET) + dev_dbg(&elo->serio->dev, + "unexpected packet: 0x%02x\n", + elo->data[1]); break; + } + if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { + input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); + input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); + if (elo->data[2] & ELO10_PRESSURE) + input_report_abs(dev, ABS_PRESSURE, + (elo->data[8] << 8) | elo->data[7]); + input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); + input_sync(dev); + } else if (elo->data[1] == ELO10_ACK_PACKET) { + if (elo->data[2] == '0') + elo->expected_packet = ELO10_TOUCH_PACKET; + complete(&elo->cmd_done); + } else { + memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); + elo->expected_packet = ELO10_ACK_PACKET; + } + break; } elo->csum += data; } @@ -123,42 +127,53 @@ static void elo_process_data_6(struct elo *elo, unsigned char data) switch (elo->idx++) { - case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break; - case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break; - case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break; - - case 3: - if (data & 0xc0) { - elo->idx = 0; - break; - } + case 0: + if ((data & 0xc0) != 0xc0) + elo->idx = 0; + break; - input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f)); - input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f)); + case 1: + if ((data & 0xc0) != 0x80) + elo->idx = 0; + break; - if (elo->id == 2) { - input_report_key(dev, BTN_TOUCH, 1); - input_sync(dev); - elo->idx = 0; - } + case 2: + if ((data & 0xc0) != 0x40) + elo->idx = 0; + break; + case 3: + if (data & 0xc0) { + elo->idx = 0; break; + } - case 4: - if (data) { - input_sync(dev); - elo->idx = 0; - } - break; + input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f)); + input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f)); - case 5: - if ((data & 0xf0) == 0) { - input_report_abs(dev, ABS_PRESSURE, elo->data[5]); - input_report_key(dev, BTN_TOUCH, !!elo->data[5]); - } + if (elo->id == 2) { + input_report_key(dev, BTN_TOUCH, 1); input_sync(dev); elo->idx = 0; - break; + } + + break; + + case 4: + if (data) { + input_sync(dev); + elo->idx = 0; + } + break; + + case 5: + if ((data & 0xf0) == 0) { + input_report_abs(dev, ABS_PRESSURE, elo->data[5]); + input_report_key(dev, BTN_TOUCH, !!elo->data[5]); + } + input_sync(dev); + elo->idx = 0; + break; } } @@ -170,17 +185,17 @@ static void elo_process_data_3(struct elo *elo, unsigned char data) switch (elo->idx++) { - case 0: - if ((data & 0x7f) != 0x01) - elo->idx = 0; - break; - case 2: - input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80)); - input_report_abs(dev, ABS_X, elo->data[1]); - input_report_abs(dev, ABS_Y, elo->data[2]); - input_sync(dev); + case 0: + if ((data & 0x7f) != 0x01) elo->idx = 0; - break; + break; + case 2: + input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80)); + input_report_abs(dev, ABS_X, elo->data[1]); + input_report_abs(dev, ABS_Y, elo->data[2]); + input_sync(dev); + elo->idx = 0; + break; } } @@ -189,19 +204,19 @@ static irqreturn_t elo_interrupt(struct serio *serio, { struct elo *elo = serio_get_drvdata(serio); - switch(elo->id) { - case 0: - elo_process_data_10(elo, data); - break; - - case 1: - case 2: - elo_process_data_6(elo, data); - break; - - case 3: - elo_process_data_3(elo, data); - break; + switch (elo->id) { + case 0: + elo_process_data_10(elo, data); + break; + + case 1: + case 2: + elo_process_data_6(elo, data); + break; + + case 3: + elo_process_data_3(elo, data); + break; } return IRQ_HANDLED; @@ -261,10 +276,10 @@ static int elo_setup_10(struct elo *elo) if (packet[3] & ELO10_PRESSURE) input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); - printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, " - "features: 0x%02x, controller: 0x%02x\n", - elo_types[(packet[1] -'0') & 0x03], - packet[5], packet[4], packet[3], packet[7]); + dev_info(&elo->serio->dev, + "%sTouch touchscreen, fw: %02x.%02x, features: 0x%02x, controller: 0x%02x\n", + elo_types[(packet[1] -'0') & 0x03], + packet[5], packet[4], packet[3], packet[7]); return 0; } @@ -330,24 +345,24 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) switch (elo->id) { - case 0: /* 10-byte protocol */ - if (elo_setup_10(elo)) - goto fail3; + case 0: /* 10-byte protocol */ + if (elo_setup_10(elo)) + goto fail3; - break; + break; - case 1: /* 6-byte protocol */ - input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); + case 1: /* 6-byte protocol */ + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); - case 2: /* 4-byte protocol */ - input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); - break; + case 2: /* 4-byte protocol */ + input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); + break; - case 3: /* 3-byte protocol */ - input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0); - break; + case 3: /* 3-byte protocol */ + input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0); + break; } err = input_register_device(elo->dev); -- cgit v1.2.3 From ce7b39a181571ed5a87f3ca62d4cffe4835c6ae9 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sat, 9 Jan 2010 23:23:02 -0800 Subject: Input: make i2c device ids constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The id_table field of the struct i2c_driver is defined as constant in so it makes sense to mark the initialization data also constant. Signed-off-by: Márton Németh Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/qt2160.c | 2 +- drivers/input/misc/apanel.c | 2 +- drivers/input/touchscreen/tsc2007.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 191cc51d6cf8..31f30087b591 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -362,7 +362,7 @@ static int __devexit qt2160_remove(struct i2c_client *client) return 0; } -static struct i2c_device_id qt2160_idtable[] = { +static const struct i2c_device_id qt2160_idtable[] = { { "qt2160", 0, }, { } }; diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index 71b82434264d..a8d2b8db4e35 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c @@ -149,7 +149,7 @@ static void apanel_shutdown(struct i2c_client *client) apanel_remove(client); } -static struct i2c_device_id apanel_id[] = { +static const struct i2c_device_id apanel_id[] = { { "fujitsu_apanel", 0 }, { } }; diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 7ef0d1420d3c..be23780e8a3e 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -358,7 +358,7 @@ static int __devexit tsc2007_remove(struct i2c_client *client) return 0; } -static struct i2c_device_id tsc2007_idtable[] = { +static const struct i2c_device_id tsc2007_idtable[] = { { "tsc2007", 0 }, { } }; -- cgit v1.2.3 From ef9a16f15dccba6630d8860a964a4adef1a4ab98 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sat, 9 Jan 2010 23:23:02 -0800 Subject: Input: xilinx_ps2 - make Open Firmware device ids constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The match_table field of the struct of_device_id is constant in so it makes sense to mark xps2_of_match also constant. Signed-off-by: Márton Németh Signed-off-by: Dmitry Torokhov --- drivers/input/serio/xilinx_ps2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index ebb22f88c842..78c64fb8a4b0 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -354,7 +354,7 @@ static int __devexit xps2_of_remove(struct of_device *of_dev) } /* Match table for of_platform binding */ -static struct of_device_id xps2_of_match[] __devinitdata = { +static const struct of_device_id xps2_of_match[] __devinitconst = { { .compatible = "xlnx,xps-ps2-1.00.a", }, { /* end of list */ }, }; -- cgit v1.2.3 From a9844b18502bde376284e4ad83b04fa20eb5afa5 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sat, 9 Jan 2010 23:23:58 -0800 Subject: Input: make PCI device ids constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The id_table field of the struct pci_driver is constant in so it makes sense to mark initialization data also constant. Signed-off-by: Márton Németh Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/emu10k1-gp.c | 2 +- drivers/input/gameport/fm801-gp.c | 2 +- drivers/input/serio/pcips2.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index b04930f7ea7d..7392992da424 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c @@ -46,7 +46,7 @@ struct emu { int size; }; -static struct pci_device_id emu_tbl[] = { +static const struct pci_device_id emu_tbl[] = { { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */ { 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */ diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index 8a1810f88b9e..14d3f3e208a2 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c @@ -140,7 +140,7 @@ static void __devexit fm801_gp_remove(struct pci_dev *pci) } } -static struct pci_device_id fm801_gp_id_table[] = { +static const struct pci_device_id fm801_gp_id_table[] = { { PCI_VENDOR_ID_FORTEMEDIA, PCI_DEVICE_ID_FM801_GP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0 } }; diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 1dacbe0d9348..797314be7af2 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c @@ -186,7 +186,7 @@ static void __devexit pcips2_remove(struct pci_dev *dev) pci_disable_device(dev); } -static struct pci_device_id pcips2_ids[] = { +static const struct pci_device_id pcips2_ids[] = { { .vendor = 0x14f2, /* MOBILITY */ .device = 0x0123, /* Keyboard */ -- cgit v1.2.3 From 35c4b918a696f20cb775f1a65955c8ed0fe7c052 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sat, 9 Jan 2010 23:24:48 -0800 Subject: Input: ns558 - make pnp device ids constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The id_table field of the struct pnp_driver is constant in so it makes sense to mark pnp_devids also constant. Signed-off-by: Márton Németh Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/ns558.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index db556b71ddda..7c217848613e 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c @@ -166,7 +166,7 @@ static int ns558_isa_probe(int io) #ifdef CONFIG_PNP -static struct pnp_device_id pnp_devids[] = { +static const struct pnp_device_id pnp_devids[] = { { .id = "@P@0001", .driver_data = 0 }, /* ALS 100 */ { .id = "@P@0020", .driver_data = 0 }, /* ALS 200 */ { .id = "@P@1001", .driver_data = 0 }, /* ALS 100+ */ -- cgit v1.2.3 From c6d5709384090de541158a6bba8d4ae50242ff94 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sat, 9 Jan 2010 23:25:44 -0800 Subject: Input: xen-kbdfront - make xenbus device ids constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ids field of the struct xenbus_device_id is constant in so it makes sense to mark xenkbd_ids also constant. Signed-off-by: Márton Németh Signed-off-by: Dmitry Torokhov --- drivers/input/xen-kbdfront.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c index c721c0a23eb8..d30436fee476 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/xen-kbdfront.c @@ -321,7 +321,7 @@ InitWait: } } -static struct xenbus_device_id xenkbd_ids[] = { +static const struct xenbus_device_id xenkbd_ids[] = { { "vkbd" }, { "" } }; -- cgit v1.2.3 From 9cb3ce52ca45d089d5be90d2f34005296fc5a34e Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sun, 10 Jan 2010 23:59:05 -0800 Subject: Input: make USB device ids constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The id_table field of the struct usb_device_id is constant in so it makes sense to mark the initialization data also constant. Signed-off-by: Márton Németh Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/gtco.c | 2 +- drivers/input/touchscreen/usbtouchscreen.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 3d32d3f4e486..866a9ee1af1a 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -92,7 +92,7 @@ Scott Hill shill@gtcocalcomp.com /* DATA STRUCTURES */ /* Device table */ -static struct usb_device_id gtco_usbid_table [] = { +static const struct usb_device_id gtco_usbid_table[] = { { USB_DEVICE(VENDOR_ID_GTCO, PID_400) }, { USB_DEVICE(VENDOR_ID_GTCO, PID_401) }, { USB_DEVICE(VENDOR_ID_GTCO, PID_1000) }, diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 09a5e7341bd5..b1b99e931f80 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -144,7 +144,7 @@ enum { .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE -static struct usb_device_id usbtouch_devices[] = { +static const struct usb_device_id usbtouch_devices[] = { #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX /* ignore the HID capable devices, handled by usbhid */ {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, -- cgit v1.2.3 From a5abd95cc0b35034186a9f76b0f2b83458425f47 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 13 Jan 2010 00:34:12 -0800 Subject: Input: ep93xx_keypad - cleanup and use matrix_keypad helpers Use struct matrix_keymap_data to supply the keymap from the platform code and matrix_keypad_build_keymap() to initialize the keymap. Signed-off-by: H Hartley Sweeten Signed-off-by: Dmitry Torokhov --- arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h | 14 ++++---- drivers/input/keyboard/ep93xx_keypad.c | 40 +++++++++-------------- 2 files changed, 22 insertions(+), 32 deletions(-) (limited to 'drivers/input') diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h index 62d17421e48c..1e2f4e97f428 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h @@ -5,6 +5,8 @@ #ifndef __ASM_ARCH_EP93XX_KEYPAD_H #define __ASM_ARCH_EP93XX_KEYPAD_H +struct matrix_keymap_data; + /* flags for the ep93xx_keypad driver */ #define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */ #define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */ @@ -15,15 +17,13 @@ /** * struct ep93xx_keypad_platform_data - platform specific device structure - * @matrix_key_map: array of keycodes defining the keypad matrix - * @matrix_key_map_size: ARRAY_SIZE(matrix_key_map) - * @debounce: debounce start count; terminal count is 0xff - * @prescale: row/column counter pre-scaler load value - * @flags: see above + * @keymap_data: pointer to &matrix_keymap_data + * @debounce: debounce start count; terminal count is 0xff + * @prescale: row/column counter pre-scaler load value + * @flags: see above */ struct ep93xx_keypad_platform_data { - unsigned int *matrix_key_map; - int matrix_key_map_size; + struct matrix_keymap_data *keymap_data; unsigned int debounce; unsigned int prescale; unsigned int flags; diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index e45740429f7e..bd25a3af1664 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -69,7 +69,7 @@ struct ep93xx_keypad { void __iomem *mmio_base; - unsigned int matrix_keycodes[EP93XX_MATRIX_SIZE]; + unsigned short keycodes[EP93XX_MATRIX_SIZE]; int key1; int key2; @@ -79,24 +79,6 @@ struct ep93xx_keypad { bool enabled; }; -static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad) -{ - struct ep93xx_keypad_platform_data *pdata = keypad->pdata; - struct input_dev *input_dev = keypad->input_dev; - unsigned int *key; - int i; - - key = &pdata->matrix_key_map[0]; - for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { - int row = KEY_ROW(*key); - int col = KEY_COL(*key); - int code = KEY_VAL(*key); - - keypad->matrix_keycodes[(row << 3) + col] = code; - __set_bit(code, input_dev->keybit); - } -} - static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id) { struct ep93xx_keypad *keypad = dev_id; @@ -107,10 +89,10 @@ static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id) status = __raw_readl(keypad->mmio_base + KEY_REG); keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT; - key1 = keypad->matrix_keycodes[keycode]; + key1 = keypad->keycodes[keycode]; keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT; - key2 = keypad->matrix_keycodes[keycode]; + key2 = keypad->keycodes[keycode]; if (status & KEY_REG_2KEYS) { if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1) @@ -256,6 +238,7 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) { struct ep93xx_keypad *keypad; + const struct matrix_keymap_data *keymap_data; struct input_dev *input_dev; struct resource *res; int err; @@ -270,6 +253,12 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) goto failed_free; } + keymap_data = keypad->pdata->keymap_data; + if (!keymap_data) { + err = -EINVAL; + goto failed_free; + } + keypad->irq = platform_get_irq(pdev, 0); if (!keypad->irq) { err = -ENXIO; @@ -317,9 +306,9 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) input_dev->open = ep93xx_keypad_open; input_dev->close = ep93xx_keypad_close; input_dev->dev.parent = &pdev->dev; - input_dev->keycode = keypad->matrix_keycodes; - input_dev->keycodesize = sizeof(keypad->matrix_keycodes[0]); - input_dev->keycodemax = ARRAY_SIZE(keypad->matrix_keycodes); + input_dev->keycode = keypad->keycodes; + input_dev->keycodesize = sizeof(keypad->keycodes[0]); + input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); input_set_drvdata(input_dev, keypad); @@ -327,7 +316,8 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT) input_dev->evbit[0] |= BIT_MASK(EV_REP); - ep93xx_keypad_build_keycode(keypad); + matrix_keypad_build_keymap(keymap_data, 3, + input_dev->keycode, input_dev->keybit); platform_set_drvdata(pdev, keypad); err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, -- cgit v1.2.3 From 5a9003db1faa34c0560561f66b263f288d623324 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 19 Jan 2010 00:28:44 -0800 Subject: Input: ADP5588 - add support for ADP5587 devices The ADP5587 is quite similar to the ADP5588 but features a greater I/O voltage range and lacks the Dual Light Sensor Interface. This new part is also supported by this driver. Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 4 ++-- drivers/input/keyboard/adp5588-keys.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 02c836e11813..c72283c6916f 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -35,10 +35,10 @@ config KEYBOARD_ADP5520 be called adp5520-keys. config KEYBOARD_ADP5588 - tristate "ADP5588 I2C QWERTY Keypad and IO Expander" + tristate "ADP5588/87 I2C QWERTY Keypad and IO Expander" depends on I2C help - Say Y here if you want to use a ADP5588 attached to your + Say Y here if you want to use a ADP5588/87 attached to your system I2C bus. To compile this driver as a module, choose M here: the diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index d48c808d5928..6737fe4c0f12 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -1,6 +1,7 @@ /* * File: drivers/input/keyboard/adp5588_keys.c - * Description: keypad driver for ADP5588 I2C QWERTY Keypad and IO Expander + * Description: keypad driver for ADP5588 and ADP5587 + * I2C QWERTY Keypad and IO Expander * Bugs: Enter bugs at http://blackfin.uclinux.org/ * * Copyright (C) 2008-2009 Analog Devices Inc. @@ -327,6 +328,7 @@ static struct dev_pm_ops adp5588_dev_pm_ops = { static const struct i2c_device_id adp5588_id[] = { { KBUILD_MODNAME, 0 }, + { "adp5587-keys", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, adp5588_id); @@ -357,5 +359,5 @@ module_exit(adp5588_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("ADP5588 Keypad driver"); +MODULE_DESCRIPTION("ADP5588/87 Keypad driver"); MODULE_ALIAS("platform:adp5588-keys"); -- cgit v1.2.3 From 3bf127637e22ddf95e67e10a23c339cee3d52429 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 21 Jan 2010 00:02:36 -0800 Subject: Input: sh_keysc - add mode 4 and mode 5 support Add Mode 4 and Mode 5 support to the SH_KEYSC driver. These modes allow slightly larger key pad matrixes. While at it, make use of resource_size(). Signed-off-by: Magnus Damm Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/sh_keysc.c | 6 +++--- include/linux/input/sh_keysc.h | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 076111fc72d2..25706f802258 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -36,6 +36,8 @@ static const struct { [SH_KEYSC_MODE_1] = { 0, 6, 5 }, [SH_KEYSC_MODE_2] = { 1, 5, 6 }, [SH_KEYSC_MODE_3] = { 2, 4, 7 }, + [SH_KEYSC_MODE_4] = { 3, 6, 6 }, + [SH_KEYSC_MODE_5] = { 4, 6, 7 }, }; struct sh_keysc_priv { @@ -122,8 +124,6 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id) return IRQ_HANDLED; } -#define res_size(res) ((res)->end - (res)->start + 1) - static int __devinit sh_keysc_probe(struct platform_device *pdev) { struct sh_keysc_priv *priv; @@ -164,7 +164,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata)); pdata = &priv->pdata; - priv->iomem_base = ioremap_nocache(res->start, res_size(res)); + priv->iomem_base = ioremap_nocache(res->start, resource_size(res)); if (priv->iomem_base == NULL) { dev_err(&pdev->dev, "failed to remap I/O memory\n"); error = -ENXIO; diff --git a/include/linux/input/sh_keysc.h b/include/linux/input/sh_keysc.h index c211b5cf08e6..2aff38bcf2ba 100644 --- a/include/linux/input/sh_keysc.h +++ b/include/linux/input/sh_keysc.h @@ -1,10 +1,11 @@ #ifndef __SH_KEYSC_H__ #define __SH_KEYSC_H__ -#define SH_KEYSC_MAXKEYS 30 +#define SH_KEYSC_MAXKEYS 42 struct sh_keysc_info { - enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3 } mode; + enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3, + SH_KEYSC_MODE_4, SH_KEYSC_MODE_5 } mode; int scan_timing; /* 0 -> 7, see KYCR1, SCN[2:0] */ int delay; int kycr2_delay; -- cgit v1.2.3 From ce841b945b84bf7360aa32e60ddaa1e9ccae3e96 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 21 Jan 2010 23:52:37 -0800 Subject: Input: xilinx_ps2 - use resource_size Use the resource_size inline function instead of manually calculating the resource size. Signed-off-by: Tobias Klauser Acked-by: John Linn Signed-off-by: Dmitry Torokhov --- drivers/input/serio/xilinx_ps2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 78c64fb8a4b0..8298e1f68234 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -270,7 +270,7 @@ static int __devinit xps2_of_probe(struct of_device *ofdev, drvdata->irq = r_irq.start; phys_addr = r_mem.start; - remap_size = r_mem.end - r_mem.start + 1; + remap_size = resource_size(&r_mem); if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) { dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", (unsigned long long)phys_addr); @@ -344,7 +344,7 @@ static int __devexit xps2_of_remove(struct of_device *of_dev) if (of_address_to_resource(of_dev->node, 0, &r_mem)) dev_err(dev, "invalid address\n"); else - release_mem_region(r_mem.start, r_mem.end - r_mem.start + 1); + release_mem_region(r_mem.start, resource_size(&r_mem)); kfree(drvdata); -- cgit v1.2.3 From 121873059fbe3b4f1ddb4781b578a2128e78be4a Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 21 Jan 2010 20:19:06 -0800 Subject: Input: xpad - add rumble support for original xbox controller Signed-off-by: Benjamin Valentin Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 53 ++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 16 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 66be6901619d..9b3353b404da 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -530,7 +530,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) struct usb_endpoint_descriptor *ep_irq_out; int error = -ENOMEM; - if (xpad->xtype != XTYPE_XBOX360) + if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) return 0; xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, @@ -560,13 +560,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) static void xpad_stop_output(struct usb_xpad *xpad) { - if (xpad->xtype == XTYPE_XBOX360) + if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) usb_kill_urb(xpad->irq_out); } static void xpad_deinit_output(struct usb_xpad *xpad) { - if (xpad->xtype == XTYPE_XBOX360) { + if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) { usb_free_urb(xpad->irq_out); usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); @@ -579,24 +579,45 @@ static void xpad_stop_output(struct usb_xpad *xpad) {} #endif #ifdef CONFIG_JOYSTICK_XPAD_FF -static int xpad_play_effect(struct input_dev *dev, void *data, - struct ff_effect *effect) +static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { struct usb_xpad *xpad = input_get_drvdata(dev); if (effect->type == FF_RUMBLE) { __u16 strong = effect->u.rumble.strong_magnitude; __u16 weak = effect->u.rumble.weak_magnitude; - xpad->odata[0] = 0x00; - xpad->odata[1] = 0x08; - xpad->odata[2] = 0x00; - xpad->odata[3] = strong / 256; - xpad->odata[4] = weak / 256; - xpad->odata[5] = 0x00; - xpad->odata[6] = 0x00; - xpad->odata[7] = 0x00; - xpad->irq_out->transfer_buffer_length = 8; - usb_submit_urb(xpad->irq_out, GFP_ATOMIC); + + switch (xpad->xtype) { + + case XTYPE_XBOX: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x06; + xpad->odata[2] = 0x00; + xpad->odata[3] = strong / 256; /* left actuator */ + xpad->odata[4] = 0x00; + xpad->odata[5] = weak / 256; /* right actuator */ + xpad->irq_out->transfer_buffer_length = 6; + + return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); + + case XTYPE_XBOX360: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x08; + xpad->odata[2] = 0x00; + xpad->odata[3] = strong / 256; /* left actuator? */ + xpad->odata[4] = weak / 256; /* right actuator? */ + xpad->odata[5] = 0x00; + xpad->odata[6] = 0x00; + xpad->odata[7] = 0x00; + xpad->irq_out->transfer_buffer_length = 8; + + return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); + + default: + dbg("%s - rumble command sent to unsupported xpad type: %d", + __func__, xpad->xtype); + return -1; + } } return 0; @@ -604,7 +625,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, static int xpad_init_ff(struct usb_xpad *xpad) { - if (xpad->xtype != XTYPE_XBOX360) + if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) return 0; input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); -- cgit v1.2.3 From 439913fffd39374c3737186b22d2d56c3a0ae526 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 28 Jan 2010 10:53:19 +0800 Subject: ACPI: replace acpi_integer by u64 acpi_integer is now obsolete and removed from the ACPICA code base, replaced by u64. Signed-off-by: Lin Ming Signed-off-by: Len Brown --- arch/ia64/hp/common/aml_nfw.c | 6 ++--- arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 6 ++--- drivers/acpi/battery.c | 4 +-- drivers/acpi/ec.c | 4 +-- drivers/acpi/glue.c | 4 +-- drivers/acpi/osl.c | 4 +-- drivers/acpi/power_meter.c | 30 +++++++++++----------- drivers/acpi/processor_idle.c | 2 +- drivers/acpi/processor_throttling.c | 24 +++++++++--------- drivers/acpi/utils.c | 16 ++++++------ drivers/acpi/video.c | 2 +- drivers/ata/libata-acpi.c | 4 +-- drivers/ide/ide-acpi.c | 8 +++--- drivers/input/misc/atlas_btns.c | 2 +- drivers/pci/pci-acpi.c | 2 +- drivers/platform/x86/toshiba_bluetooth.c | 4 +-- drivers/platform/x86/wmi.c | 4 +-- include/acpi/acpi_bus.h | 6 ++--- include/acpi/processor.h | 42 +++++++++++++++---------------- 19 files changed, 87 insertions(+), 87 deletions(-) (limited to 'drivers/input') diff --git a/arch/ia64/hp/common/aml_nfw.c b/arch/ia64/hp/common/aml_nfw.c index 4abd2c79bb1d..22078486d35d 100644 --- a/arch/ia64/hp/common/aml_nfw.c +++ b/arch/ia64/hp/common/aml_nfw.c @@ -77,7 +77,7 @@ static void aml_nfw_execute(struct ia64_nfw_context *c) c->arg[4], c->arg[5], c->arg[6], c->arg[7]); } -static void aml_nfw_read_arg(u8 *offset, u32 bit_width, acpi_integer *value) +static void aml_nfw_read_arg(u8 *offset, u32 bit_width, u64 *value) { switch (bit_width) { case 8: @@ -95,7 +95,7 @@ static void aml_nfw_read_arg(u8 *offset, u32 bit_width, acpi_integer *value) } } -static void aml_nfw_write_arg(u8 *offset, u32 bit_width, acpi_integer *value) +static void aml_nfw_write_arg(u8 *offset, u32 bit_width, u64 *value) { switch (bit_width) { case 8: @@ -114,7 +114,7 @@ static void aml_nfw_write_arg(u8 *offset, u32 bit_width, acpi_integer *value) } static acpi_status aml_nfw_handler(u32 function, acpi_physical_address address, - u32 bit_width, acpi_integer *value, void *handler_context, + u32 bit_width, u64 *value, void *handler_context, void *region_context) { struct ia64_nfw_context *context = handler_context; diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index f125e5c551c0..55d42bc443e8 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -806,7 +806,7 @@ static int find_psb_table(struct powernow_k8_data *data) static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index) { - acpi_integer control; + u64 control; if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE)) return; @@ -824,7 +824,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { struct cpufreq_frequency_table *powernow_table; int ret_val = -ENODEV; - acpi_integer control, status; + u64 control, status; if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { dprintk("register performance failed: bad ACPI data\n"); @@ -948,7 +948,7 @@ static int fill_powernow_table_fidvid(struct powernow_k8_data *data, u32 fid; u32 vid; u32 freq, index; - acpi_integer status, control; + u64 status, control; if (data->exttype) { status = data->acpi_data.states[i].status; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index cada73ffdfa7..58d2c91ba62b 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -324,8 +324,8 @@ static int extract_package(struct acpi_battery *battery, strncpy(ptr, element->string.pointer, 32); else if (element->type == ACPI_TYPE_INTEGER) { strncpy(ptr, (u8 *)&element->integer.value, - sizeof(acpi_integer)); - ptr[sizeof(acpi_integer)] = 0; + sizeof(u64)); + ptr[sizeof(u64)] = 0; } else *ptr = 0; /* don't have value */ } else { diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index d6471bb6852f..748ced85dec5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -589,7 +589,7 @@ static u32 acpi_ec_gpe_handler(void *data) static acpi_status acpi_ec_space_handler(u32 function, acpi_physical_address address, - u32 bits, acpi_integer *value, + u32 bits, u64 *value, void *handler_context, void *region_context) { struct acpi_ec *ec = handler_context; @@ -620,7 +620,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, ++address; if (function == ACPI_READ) { result = acpi_ec_read(ec, address, &temp); - (*value) |= ((acpi_integer)temp) << i; + (*value) |= ((u64)temp) << i; } else { temp = 0xff & ((*value) >> i); result = acpi_ec_write(ec, address, temp); diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 4c8fcff662cf..6d5b64b7d526 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -87,7 +87,7 @@ static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) /* Get device's handler per its address under its parent */ struct acpi_find_child { acpi_handle handle; - acpi_integer address; + u64 address; }; static acpi_status @@ -106,7 +106,7 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -acpi_handle acpi_get_child(acpi_handle parent, acpi_integer address) +acpi_handle acpi_get_child(acpi_handle parent, u64 address) { struct acpi_find_child find = { NULL, address }; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 02e8464e480f..8e6d8665f0ae 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -436,7 +436,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) * Running in interpreter thread context, safe to sleep */ -void acpi_os_sleep(acpi_integer ms) +void acpi_os_sleep(u64 ms) { schedule_timeout_interruptible(msecs_to_jiffies(ms)); } @@ -603,7 +603,7 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, acpi_status acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, - acpi_integer value, u32 width) + u64 value, u32 width) { int result, size; diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index dc4ffadf8122..834c5af0de4b 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -71,17 +71,17 @@ static const struct acpi_device_id power_meter_ids[] = { MODULE_DEVICE_TABLE(acpi, power_meter_ids); struct acpi_power_meter_capabilities { - acpi_integer flags; - acpi_integer units; - acpi_integer type; - acpi_integer accuracy; - acpi_integer sampling_time; - acpi_integer min_avg_interval; - acpi_integer max_avg_interval; - acpi_integer hysteresis; - acpi_integer configurable_cap; - acpi_integer min_cap; - acpi_integer max_cap; + u64 flags; + u64 units; + u64 type; + u64 accuracy; + u64 sampling_time; + u64 min_avg_interval; + u64 max_avg_interval; + u64 hysteresis; + u64 configurable_cap; + u64 min_cap; + u64 max_cap; }; struct acpi_power_meter_resource { @@ -93,9 +93,9 @@ struct acpi_power_meter_resource { acpi_string model_number; acpi_string serial_number; acpi_string oem_info; - acpi_integer power; - acpi_integer cap; - acpi_integer avg_interval; + u64 power; + u64 cap; + u64 avg_interval; int sensors_valid; unsigned long sensors_last_updated; struct sensor_device_attribute sensors[NUM_SENSORS]; @@ -402,7 +402,7 @@ static ssize_t show_val(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - acpi_integer val = 0; + u64 val = 0; switch (attr->index) { case 0: diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 7c0441f63b39..3455d7abf5f3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -352,7 +352,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) { acpi_status status = 0; - acpi_integer count; + u64 count; int current_count; int i; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 1c5d7a8b2fdf..7ded7542fc9d 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -660,7 +660,7 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) #ifdef CONFIG_X86 static int acpi_throttling_rdmsr(struct acpi_processor *pr, - acpi_integer * value) + u64 *value) { struct cpuinfo_x86 *c; u64 msr_high, msr_low; @@ -681,13 +681,13 @@ static int acpi_throttling_rdmsr(struct acpi_processor *pr, rdmsr_safe(MSR_IA32_THERM_CONTROL, (u32 *)&msr_low , (u32 *) &msr_high); msr = (msr_high << 32) | msr_low; - *value = (acpi_integer) msr; + *value = (u64) msr; ret = 0; } return ret; } -static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) +static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value) { struct cpuinfo_x86 *c; unsigned int cpu; @@ -711,14 +711,14 @@ static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) } #else static int acpi_throttling_rdmsr(struct acpi_processor *pr, - acpi_integer * value) + u64 *value) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); return -1; } -static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) +static int acpi_throttling_wrmsr(struct acpi_processor *pr, u64 value) { printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); @@ -727,7 +727,7 @@ static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) #endif static int acpi_read_throttling_status(struct acpi_processor *pr, - acpi_integer *value) + u64 *value) { u32 bit_width, bit_offset; u64 ptc_value; @@ -746,7 +746,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, address, (u32 *) &ptc_value, (u32) (bit_width + bit_offset)); ptc_mask = (1 << bit_width) - 1; - *value = (acpi_integer) ((ptc_value >> bit_offset) & ptc_mask); + *value = (u64) ((ptc_value >> bit_offset) & ptc_mask); ret = 0; break; case ACPI_ADR_SPACE_FIXED_HARDWARE: @@ -760,7 +760,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, } static int acpi_write_throttling_state(struct acpi_processor *pr, - acpi_integer value) + u64 value) { u32 bit_width, bit_offset; u64 ptc_value; @@ -793,7 +793,7 @@ static int acpi_write_throttling_state(struct acpi_processor *pr, } static int acpi_get_throttling_state(struct acpi_processor *pr, - acpi_integer value) + u64 value) { int i; @@ -808,7 +808,7 @@ static int acpi_get_throttling_state(struct acpi_processor *pr, } static int acpi_get_throttling_value(struct acpi_processor *pr, - int state, acpi_integer *value) + int state, u64 *value) { int ret = -1; @@ -826,7 +826,7 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) { int state = 0; int ret; - acpi_integer value; + u64 value; if (!pr) return -EINVAL; @@ -993,7 +993,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, int state, bool force) { int ret; - acpi_integer value; + u64 value; if (!pr) return -EINVAL; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 811fec10462b..11882dbe2094 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -107,12 +107,12 @@ acpi_extract_package(union acpi_object *package, case ACPI_TYPE_INTEGER: switch (format_string[i]) { case 'N': - size_required += sizeof(acpi_integer); - tail_offset += sizeof(acpi_integer); + size_required += sizeof(u64); + tail_offset += sizeof(u64); break; case 'S': size_required += - sizeof(char *) + sizeof(acpi_integer) + + sizeof(char *) + sizeof(u64) + sizeof(char); tail_offset += sizeof(char *); break; @@ -193,17 +193,17 @@ acpi_extract_package(union acpi_object *package, case ACPI_TYPE_INTEGER: switch (format_string[i]) { case 'N': - *((acpi_integer *) head) = + *((u64 *) head) = element->integer.value; - head += sizeof(acpi_integer); + head += sizeof(u64); break; case 'S': pointer = (u8 **) head; *pointer = tail; - *((acpi_integer *) tail) = + *((u64 *) tail) = element->integer.value; - head += sizeof(acpi_integer *); - tail += sizeof(acpi_integer); + head += sizeof(u64 *); + tail += sizeof(u64); /* NULL terminate string */ *tail = (char)0; tail += sizeof(char); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index b765790b32be..6e9b49149fce 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -759,7 +759,7 @@ acpi_video_bus_POST_options(struct acpi_video_bus *video, static int acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) { - acpi_integer status = 0; + u64 status = 0; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 1245838ac13d..292fdbc0431a 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -64,7 +64,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap) WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA)); if (!sata_pmp_attached(ap)) { - acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT); + u64 adr = SATA_ADR(ap->port_no, NO_PORT_MULT); ap->link.device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr); @@ -74,7 +74,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap) ap->link.device->acpi_handle = NULL; ata_for_each_link(link, ap, EDGE) { - acpi_integer adr = SATA_ADR(ap->port_no, link->pmp); + u64 adr = SATA_ADR(ap->port_no, link->pmp); link->device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr); diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index c0cf45a11b93..5cb01e5c323c 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -108,11 +108,11 @@ bool ide_port_acpi(ide_hwif_t *hwif) * Returns 0 on success, <0 on error. */ static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, - acpi_integer *pcidevfn) + u64 *pcidevfn) { struct pci_dev *pdev = to_pci_dev(dev); unsigned int bus, devnum, func; - acpi_integer addr; + u64 addr; acpi_handle dev_handle; acpi_status status; struct acpi_device_info *dinfo = NULL; @@ -122,7 +122,7 @@ static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, devnum = PCI_SLOT(pdev->devfn); func = PCI_FUNC(pdev->devfn); /* ACPI _ADR encoding for PCI bus: */ - addr = (acpi_integer)(devnum << 16 | func); + addr = (u64)(devnum << 16 | func); DEBPRINT("ENTER: pci %02x:%02x.%01x\n", bus, devnum, func); @@ -169,7 +169,7 @@ static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif) { struct device *dev = hwif->gendev.parent; acpi_handle uninitialized_var(dev_handle); - acpi_integer pcidevfn; + u64 pcidevfn; acpi_handle chan_handle; int err; diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 1b871917340a..dfaa9a045ed8 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -47,7 +47,7 @@ static acpi_status acpi_atlas_button_setup(acpi_handle region_handle, static acpi_status acpi_atlas_button_handler(u32 function, acpi_physical_address address, - u32 bit_width, acpi_integer *value, + u32 bit_width, u64 *value, void *handler_context, void *region_context) { acpi_status status; diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 7e2829538a4c..441326c44138 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -143,7 +143,7 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = { static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) { struct pci_dev * pci_dev; - acpi_integer addr; + u64 addr; pci_dev = to_pci_dev(dev); /* Please ref to ACPI spec for the syntax of _ADR */ diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index a350418e87ea..944068611919 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c @@ -57,7 +57,7 @@ static struct acpi_driver toshiba_bt_rfkill_driver = { static int toshiba_bluetooth_enable(acpi_handle handle) { acpi_status res1, res2; - acpi_integer result; + u64 result; /* * Query ACPI to verify RFKill switch is set to 'on'. @@ -95,7 +95,7 @@ static int toshiba_bt_resume(struct acpi_device *device) static int toshiba_bt_rfkill_add(struct acpi_device *device) { acpi_status status; - acpi_integer bt_present; + u64 bt_present; int result = -ENODEV; /* diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index b104302fea0a..09e9918c69c1 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -796,7 +796,7 @@ static __init acpi_status parse_wdg(acpi_handle handle) */ static acpi_status acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, - u32 bits, acpi_integer * value, + u32 bits, u64 *value, void *handler_context, void *region_context) { int result = 0, i = 0; @@ -813,7 +813,7 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, if (function == ACPI_READ) { result = ec_read(address, &temp); - (*value) |= ((acpi_integer)temp) << i; + (*value) |= ((u64)temp) << i; } else { temp = 0xff & ((*value) >> i); result = ec_write(address, temp); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 3cd9ccdcbd8f..71c105c9b0ee 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -250,8 +250,8 @@ struct acpi_device_wakeup_state { struct acpi_device_wakeup { acpi_handle gpe_device; - acpi_integer gpe_number; - acpi_integer sleep_state; + u64 gpe_number; + u64 sleep_state; struct acpi_handle_list resources; struct acpi_device_wakeup_state state; struct acpi_device_wakeup_flags flags; @@ -380,7 +380,7 @@ struct acpi_pci_root { }; /* helper */ -acpi_handle acpi_get_child(acpi_handle, acpi_integer); +acpi_handle acpi_get_child(acpi_handle, u64); int acpi_is_root_bridge(acpi_handle); acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 0ea5ef4eb6a9..29831768c0e6 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -92,11 +92,11 @@ struct acpi_processor_power { /* Performance Management */ struct acpi_psd_package { - acpi_integer num_entries; - acpi_integer revision; - acpi_integer domain; - acpi_integer coord_type; - acpi_integer num_processors; + u64 num_entries; + u64 revision; + u64 domain; + u64 coord_type; + u64 num_processors; } __attribute__ ((packed)); struct acpi_pct_register { @@ -110,12 +110,12 @@ struct acpi_pct_register { } __attribute__ ((packed)); struct acpi_processor_px { - acpi_integer core_frequency; /* megahertz */ - acpi_integer power; /* milliWatts */ - acpi_integer transition_latency; /* microseconds */ - acpi_integer bus_master_latency; /* microseconds */ - acpi_integer control; /* control value */ - acpi_integer status; /* success indicator */ + u64 core_frequency; /* megahertz */ + u64 power; /* milliWatts */ + u64 transition_latency; /* microseconds */ + u64 bus_master_latency; /* microseconds */ + u64 control; /* control value */ + u64 status; /* success indicator */ }; struct acpi_processor_performance { @@ -133,11 +133,11 @@ struct acpi_processor_performance { /* Throttling Control */ struct acpi_tsd_package { - acpi_integer num_entries; - acpi_integer revision; - acpi_integer domain; - acpi_integer coord_type; - acpi_integer num_processors; + u64 num_entries; + u64 revision; + u64 domain; + u64 coord_type; + u64 num_processors; } __attribute__ ((packed)); struct acpi_ptc_register { @@ -151,11 +151,11 @@ struct acpi_ptc_register { } __attribute__ ((packed)); struct acpi_processor_tx_tss { - acpi_integer freqpercentage; /* */ - acpi_integer power; /* milliWatts */ - acpi_integer transition_latency; /* microseconds */ - acpi_integer control; /* control value */ - acpi_integer status; /* success indicator */ + u64 freqpercentage; /* */ + u64 power; /* milliWatts */ + u64 transition_latency; /* microseconds */ + u64 control; /* control value */ + u64 status; /* success indicator */ }; struct acpi_processor_tx { u16 power; -- cgit v1.2.3 From dcfc32babbece923381bd3bffaf17373b5d97568 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 28 Jan 2010 22:37:39 -0800 Subject: Input: wm97xx - provide coordinate logs for accelerated I/O This aids debug of problematic systems. Signed-off-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/mainstone-wm97xx.c | 3 +++ drivers/input/touchscreen/zylonite-wm97xx.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 6cdcf2a6e036..b6b8b1c7ecea 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c @@ -153,6 +153,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) if (pressure) p = MODR; + dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n", + x, y, p); + /* are samples valid */ if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c index eca54dbdf493..048849867643 100644 --- a/drivers/input/touchscreen/zylonite-wm97xx.c +++ b/drivers/input/touchscreen/zylonite-wm97xx.c @@ -118,6 +118,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) if (pressure) p = MODR; + dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n", + x, y, p); + /* are samples valid */ if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || -- cgit v1.2.3 From 45cdba4d376adfd30cfbda1b7d43110818d967cc Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Fri, 29 Jan 2010 23:53:57 -0800 Subject: Input: uinput - remove BKL from uinput_open function Commit 8702965848ed4bee27486a3e3d2ae34ebba6dd83 pushed down the BKL into uinput open function. However, there's nothing that needs locking in there. Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Dmitry Torokhov --- drivers/input/misc/uinput.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index d3f57245420a..18206e18d1b1 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -284,7 +283,6 @@ static int uinput_open(struct inode *inode, struct file *file) if (!newdev) return -ENOMEM; - lock_kernel(); mutex_init(&newdev->mutex); spin_lock_init(&newdev->requests_lock); init_waitqueue_head(&newdev->requests_waitq); @@ -292,7 +290,6 @@ static int uinput_open(struct inode *inode, struct file *file) newdev->state = UIST_NEW_DEVICE; file->private_data = newdev; - unlock_kernel(); return 0; } -- cgit v1.2.3 From ef7995f4e46b1677f3eaaf547316e1a910b38dcb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 29 Jan 2010 23:59:12 -0800 Subject: Input: implement input filters Sometimes it is desirable to suppress certain events from reaching input handlers and thus user space. One such example is Mac mouse button emulation code which catches certain key presses and converts them into button clicks as if they were emitted by a virtual mouse. The original key press events should be completely suppressed, otherwise user space will be confused, and while keyboard driver does it on its own evdev is blissfully unaware of this arrangement. This patch adds notion of 'filter' to the standard input handlers, which may flag event as filtered thus preventing it from reaching other input handlers. Filters don't (nor will they ever) have a notion of priority relative to each other, input core will run all of them first and any one of them may mark event as filtered. This patch is inspired by similar patch by Matthew Garret but the implementation and intended usage are quite different. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 41 ++++++++++++++++++++++++++++++++++------- include/linux/input.h | 8 ++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/input.c b/drivers/input/input.c index 6c161e220868..7080a9d4b840 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -86,12 +86,14 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) } /* - * Pass event through all open handles. This function is called with + * Pass event first through all filters and then, if event has not been + * filtered out, through all open handles. This function is called with * dev->event_lock held and interrupts disabled. */ static void input_pass_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { + struct input_handler *handler; struct input_handle *handle; rcu_read_lock(); @@ -99,11 +101,25 @@ static void input_pass_event(struct input_dev *dev, handle = rcu_dereference(dev->grab); if (handle) handle->handler->event(handle, type, code, value); - else - list_for_each_entry_rcu(handle, &dev->h_list, d_node) - if (handle->open) - handle->handler->event(handle, - type, code, value); + else { + bool filtered = false; + + list_for_each_entry_rcu(handle, &dev->h_list, d_node) { + if (!handle->open) + continue; + + handler = handle->handler; + if (!handler->filter) { + if (filtered) + break; + + handler->event(handle, type, code, value); + + } else if (handler->filter(handle, type, code, value)) + filtered = true; + } + } + rcu_read_unlock(); } @@ -990,6 +1006,8 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v) union input_seq_state *state = (union input_seq_state *)&seq->private; seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); + if (handler->filter) + seq_puts(seq, " (filter)"); if (handler->fops) seq_printf(seq, " Minor=%d", handler->minor); seq_putc(seq, '\n'); @@ -1803,7 +1821,16 @@ int input_register_handle(struct input_handle *handle) error = mutex_lock_interruptible(&dev->mutex); if (error) return error; - list_add_tail_rcu(&handle->d_node, &dev->h_list); + + /* + * Filters go to the head of the list, normal handlers + * to the tail. + */ + if (handler->filter) + list_add_rcu(&handle->d_node, &dev->h_list); + else + list_add_tail_rcu(&handle->d_node, &dev->h_list); + mutex_unlock(&dev->mutex); /* diff --git a/include/linux/input.h b/include/linux/input.h index 7be8a6537b57..6c9d3d49fa91 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1198,6 +1198,8 @@ struct input_handle; * @event: event handler. This method is being called by input core with * interrupts disabled and dev->event_lock spinlock held and so * it may not sleep + * @filter: similar to @event; separates normal event handlers from + * "filters". * @connect: called when attaching a handler to an input device * @disconnect: disconnects a handler from input device * @start: starts handler for given handle. This function is called by @@ -1219,6 +1221,11 @@ struct input_handle; * same time. All of them will get their copy of input event generated by * the device. * + * The very same structure is used to implement input filters. Input core + * allows filters to run first and will not pass event to regular handlers + * if any of the filters indicate that the event should be filtered (by + * returning %true from their filter() method). + * * Note that input core serializes calls to connect() and disconnect() * methods. */ @@ -1227,6 +1234,7 @@ struct input_handler { void *private; void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); + bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value); int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); void (*disconnect)(struct input_handle *handle); void (*start)(struct input_handle *handle); -- cgit v1.2.3 From 76cdc083f4d1a2a12a961634672fb9ca7adca29c Mon Sep 17 00:00:00 2001 From: Alberto Panizzo Date: Sun, 31 Jan 2010 17:52:07 -0800 Subject: Input: add imx-keypad driver to support the IMX Keypad Port The IMX family of Application Processors is shipped with a Keypad Port supported by this driver. The peripheral can control up to an 8x8 matrix key pad where all the scanning is done via software. The hardware provides two interrupts: one for key presses (KDI) and one for all key releases (KRI). There is also a simple circuit for glitch reduction (said for synchronization) made by two series of 3 D-latches clocked by the keypad-clock that stabilize the interrupts sources. KDI and KRI are fired only if the respective conditions are maintained for at last 4 keypad-clock cycle. Since those circuits are poor for a correct debounce process (the keypad-clock frequency is 32K and bounces longer than 94us are not masked) the driver, when an interrupt arrives, samples the matrix with a period of 10ms until the readins are stable for IMX_KEYPAD_SCANS_FOR_STABILITY times (currently set at 3). After getting stable result appropriate events are sent through the input stack. If some keys are maintained pressed, the driver continues to scan the matrix with a longer period (60ms) to catch possible multiple key presses without overloading the cpu. This process ends when all keys are released. This driver is tested to build in kernel or as a module and follow the specification of Freescale Application processors: i.MX25 i.MX27 i.MX31 i.MX35 i.MX51 especially tested on i.MX31. Signed-off-by: Alberto Panizzo Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 9 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/imx_keypad.c | 594 ++++++++++++++++++++++++++++++++++++ 3 files changed, 604 insertions(+) create mode 100644 drivers/input/keyboard/imx_keypad.c (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c72283c6916f..616a3916d187 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -292,6 +292,15 @@ config KEYBOARD_MAX7359 To compile this driver as a module, choose M here: the module will be called max7359_keypad. +config KEYBOARD_IMX + tristate "IMX keypad support" + depends on ARCH_MXC + help + Enable support for IMX keypad port. + + To compile this driver as a module, choose M here: the + module will be called imx_keypad. + config KEYBOARD_NEWTON tristate "Newton keyboard" select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 78654ef65206..706c6b5ed5f4 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o +obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c new file mode 100644 index 000000000000..2ee5b798024d --- /dev/null +++ b/drivers/input/keyboard/imx_keypad.c @@ -0,0 +1,594 @@ +/* + * Driver for the IMX keypad port. + * Copyright (C) 2009 Alberto Panizzo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * <>. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Keypad Controller registers (halfword) + */ +#define KPCR 0x00 /* Keypad Control Register */ + +#define KPSR 0x02 /* Keypad Status Register */ +#define KBD_STAT_KPKD (0x1 << 0) /* Key Press Interrupt Status bit (w1c) */ +#define KBD_STAT_KPKR (0x1 << 1) /* Key Release Interrupt Status bit (w1c) */ +#define KBD_STAT_KDSC (0x1 << 2) /* Key Depress Synch Chain Status bit (w1c)*/ +#define KBD_STAT_KRSS (0x1 << 3) /* Key Release Synch Status bit (w1c)*/ +#define KBD_STAT_KDIE (0x1 << 8) /* Key Depress Interrupt Enable Status bit */ +#define KBD_STAT_KRIE (0x1 << 9) /* Key Release Interrupt Enable */ +#define KBD_STAT_KPPEN (0x1 << 10) /* Keypad Clock Enable */ + +#define KDDR 0x04 /* Keypad Data Direction Register */ +#define KPDR 0x06 /* Keypad Data Register */ + +#define MAX_MATRIX_KEY_ROWS 8 +#define MAX_MATRIX_KEY_COLS 8 +#define MATRIX_ROW_SHIFT 3 + +#define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS) + +struct imx_keypad { + + struct clk *clk; + struct input_dev *input_dev; + void __iomem *mmio_base; + + int irq; + struct timer_list check_matrix_timer; + + /* + * The matrix is stable only if no changes are detected after + * IMX_KEYPAD_SCANS_FOR_STABILITY scans + */ +#define IMX_KEYPAD_SCANS_FOR_STABILITY 3 + int stable_count; + + bool enabled; + + /* Masks for enabled rows/cols */ + unsigned short rows_en_mask; + unsigned short cols_en_mask; + + unsigned short keycodes[MAX_MATRIX_KEY_NUM]; + + /* + * Matrix states: + * -stable: achieved after a complete debounce process. + * -unstable: used in the debouncing process. + */ + unsigned short matrix_stable_state[MAX_MATRIX_KEY_COLS]; + unsigned short matrix_unstable_state[MAX_MATRIX_KEY_COLS]; +}; + +/* Scan the matrix and return the new state in *matrix_volatile_state. */ +static void imx_keypad_scan_matrix(struct imx_keypad *keypad, + unsigned short *matrix_volatile_state) +{ + int col; + unsigned short reg_val; + + for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) { + if ((keypad->cols_en_mask & (1 << col)) == 0) + continue; + /* + * Discharge keypad capacitance: + * 2. write 1s on column data. + * 3. configure columns as totem-pole to discharge capacitance. + * 4. configure columns as open-drain. + */ + reg_val = readw(keypad->mmio_base + KPDR); + reg_val |= 0xff00; + writew(reg_val, keypad->mmio_base + KPDR); + + reg_val = readw(keypad->mmio_base + KPCR); + reg_val &= ~((keypad->cols_en_mask & 0xff) << 8); + writew(reg_val, keypad->mmio_base + KPCR); + + udelay(2); + + reg_val = readw(keypad->mmio_base + KPCR); + reg_val |= (keypad->cols_en_mask & 0xff) << 8; + writew(reg_val, keypad->mmio_base + KPCR); + + /* + * 5. Write a single column to 0, others to 1. + * 6. Sample row inputs and save data. + * 7. Repeat steps 2 - 6 for remaining columns. + */ + reg_val = readw(keypad->mmio_base + KPDR); + reg_val &= ~(1 << (8 + col)); + writew(reg_val, keypad->mmio_base + KPDR); + + /* + * Delay added to avoid propagating the 0 from column to row + * when scanning. + */ + udelay(5); + + /* + * 1s in matrix_volatile_state[col] means key pressures + * throw data from non enabled rows. + */ + reg_val = readw(keypad->mmio_base + KPDR); + matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask; + } + + /* + * Return in standby mode: + * 9. write 0s to columns + */ + reg_val = readw(keypad->mmio_base + KPDR); + reg_val &= 0x00ff; + writew(reg_val, keypad->mmio_base + KPDR); +} + +/* + * Compare the new matrix state (volatile) with the stable one stored in + * keypad->matrix_stable_state and fire events if changes are detected. + */ +static void imx_keypad_fire_events(struct imx_keypad *keypad, + unsigned short *matrix_volatile_state) +{ + struct input_dev *input_dev = keypad->input_dev; + int row, col; + + for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) { + unsigned short bits_changed; + int code; + + if ((keypad->cols_en_mask & (1 << col)) == 0) + continue; /* Column is not enabled */ + + bits_changed = keypad->matrix_stable_state[col] ^ + matrix_volatile_state[col]; + + if (bits_changed == 0) + continue; /* Column does not contain changes */ + + for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) { + if ((keypad->rows_en_mask & (1 << row)) == 0) + continue; /* Row is not enabled */ + if ((bits_changed & (1 << row)) == 0) + continue; /* Row does not contain changes */ + + code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT); + input_event(input_dev, EV_MSC, MSC_SCAN, code); + input_report_key(input_dev, keypad->keycodes[code], + matrix_volatile_state[col] & (1 << row)); + dev_dbg(&input_dev->dev, "Event code: %d, val: %d", + keypad->keycodes[code], + matrix_volatile_state[col] & (1 << row)); + } + } + input_sync(input_dev); +} + +/* + * imx_keypad_check_for_events is the timer handler. + */ +static void imx_keypad_check_for_events(unsigned long data) +{ + struct imx_keypad *keypad = (struct imx_keypad *) data; + unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS]; + unsigned short reg_val; + bool state_changed, is_zero_matrix; + int i; + + memset(matrix_volatile_state, 0, sizeof(matrix_volatile_state)); + + imx_keypad_scan_matrix(keypad, matrix_volatile_state); + + state_changed = false; + for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) { + if ((keypad->cols_en_mask & (1 << i)) == 0) + continue; + + if (keypad->matrix_unstable_state[i] ^ matrix_volatile_state[i]) { + state_changed = true; + break; + } + } + + /* + * If the matrix state is changed from the previous scan + * (Re)Begin the debouncing process, saving the new state in + * keypad->matrix_unstable_state. + * else + * Increase the count of number of scans with a stable state. + */ + if (state_changed) { + memcpy(keypad->matrix_unstable_state, matrix_volatile_state, + sizeof(matrix_volatile_state)); + keypad->stable_count = 0; + } else + keypad->stable_count++; + + /* + * If the matrix is not as stable as we want reschedule scan + * in the near future. + */ + if (keypad->stable_count < IMX_KEYPAD_SCANS_FOR_STABILITY) { + mod_timer(&keypad->check_matrix_timer, + jiffies + msecs_to_jiffies(10)); + return; + } + + /* + * If the matrix state is stable, fire the events and save the new + * stable state. Note, if the matrix is kept stable for longer + * (keypad->stable_count > IMX_KEYPAD_SCANS_FOR_STABILITY) all + * events have already been generated. + */ + if (keypad->stable_count == IMX_KEYPAD_SCANS_FOR_STABILITY) { + imx_keypad_fire_events(keypad, matrix_volatile_state); + + memcpy(keypad->matrix_stable_state, matrix_volatile_state, + sizeof(matrix_volatile_state)); + } + + is_zero_matrix = true; + for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) { + if (matrix_volatile_state[i] != 0) { + is_zero_matrix = false; + break; + } + } + + + if (is_zero_matrix) { + /* + * All keys have been released. Enable only the KDI + * interrupt for future key presses (clear the KDI + * status bit and its sync chain before that). + */ + reg_val = readw(keypad->mmio_base + KPSR); + reg_val |= KBD_STAT_KPKD | KBD_STAT_KDSC; + writew(reg_val, keypad->mmio_base + KPSR); + + reg_val = readw(keypad->mmio_base + KPSR); + reg_val |= KBD_STAT_KDIE; + reg_val &= ~KBD_STAT_KRIE; + writew(reg_val, keypad->mmio_base + KPSR); + } else { + /* + * Some keys are still pressed. Schedule a rescan in + * attempt to detect multiple key presses and enable + * the KRI interrupt to react quickly to key release + * event. + */ + mod_timer(&keypad->check_matrix_timer, + jiffies + msecs_to_jiffies(60)); + + reg_val = readw(keypad->mmio_base + KPSR); + reg_val |= KBD_STAT_KPKR | KBD_STAT_KRSS; + writew(reg_val, keypad->mmio_base + KPSR); + + reg_val = readw(keypad->mmio_base + KPSR); + reg_val |= KBD_STAT_KRIE; + reg_val &= ~KBD_STAT_KDIE; + writew(reg_val, keypad->mmio_base + KPSR); + } +} + +static irqreturn_t imx_keypad_irq_handler(int irq, void *dev_id) +{ + struct imx_keypad *keypad = dev_id; + unsigned short reg_val; + + reg_val = readw(keypad->mmio_base + KPSR); + + /* Disable both interrupt types */ + reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE); + /* Clear interrupts status bits */ + reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD; + writew(reg_val, keypad->mmio_base + KPSR); + + if (keypad->enabled) { + /* The matrix is supposed to be changed */ + keypad->stable_count = 0; + + /* Schedule the scanning procedure near in the future */ + mod_timer(&keypad->check_matrix_timer, + jiffies + msecs_to_jiffies(2)); + } + + return IRQ_HANDLED; +} + +static void imx_keypad_config(struct imx_keypad *keypad) +{ + unsigned short reg_val; + + /* + * Include enabled rows in interrupt generation (KPCR[7:0]) + * Configure keypad columns as open-drain (KPCR[15:8]) + */ + reg_val = readw(keypad->mmio_base + KPCR); + reg_val |= keypad->rows_en_mask & 0xff; /* rows */ + reg_val |= (keypad->cols_en_mask & 0xff) << 8; /* cols */ + writew(reg_val, keypad->mmio_base + KPCR); + + /* Write 0's to KPDR[15:8] (Colums) */ + reg_val = readw(keypad->mmio_base + KPDR); + reg_val &= 0x00ff; + writew(reg_val, keypad->mmio_base + KPDR); + + /* Configure columns as output, rows as input (KDDR[15:0]) */ + writew(0xff00, keypad->mmio_base + KDDR); + + /* + * Clear Key Depress and Key Release status bit. + * Clear both synchronizer chain. + */ + reg_val = readw(keypad->mmio_base + KPSR); + reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD | + KBD_STAT_KDSC | KBD_STAT_KRSS; + writew(reg_val, keypad->mmio_base + KPSR); + + /* Enable KDI and disable KRI (avoid false release events). */ + reg_val |= KBD_STAT_KDIE; + reg_val &= ~KBD_STAT_KRIE; + writew(reg_val, keypad->mmio_base + KPSR); +} + +static void imx_keypad_inhibit(struct imx_keypad *keypad) +{ + unsigned short reg_val; + + /* Inhibit KDI and KRI interrupts. */ + reg_val = readw(keypad->mmio_base + KPSR); + reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE); + writew(reg_val, keypad->mmio_base + KPSR); + + /* Colums as open drain and disable all rows */ + writew(0xff00, keypad->mmio_base + KPCR); +} + +static void imx_keypad_close(struct input_dev *dev) +{ + struct imx_keypad *keypad = input_get_drvdata(dev); + + dev_dbg(&dev->dev, ">%s\n", __func__); + + /* Mark keypad as being inactive */ + keypad->enabled = false; + synchronize_irq(keypad->irq); + del_timer_sync(&keypad->check_matrix_timer); + + imx_keypad_inhibit(keypad); + + /* Disable clock unit */ + clk_disable(keypad->clk); +} + +static int imx_keypad_open(struct input_dev *dev) +{ + struct imx_keypad *keypad = input_get_drvdata(dev); + + dev_dbg(&dev->dev, ">%s\n", __func__); + + /* We became active from now */ + keypad->enabled = true; + + /* Enable the kpp clock */ + clk_enable(keypad->clk); + imx_keypad_config(keypad); + + /* Sanity control, not all the rows must be actived now. */ + if ((readw(keypad->mmio_base + KPDR) & keypad->rows_en_mask) == 0) { + dev_err(&dev->dev, + "too many keys pressed, control pins initialisation\n"); + goto open_err; + } + + return 0; + +open_err: + imx_keypad_close(dev); + return -EIO; +} + +static int __devinit imx_keypad_probe(struct platform_device *pdev) +{ + const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data; + struct imx_keypad *keypad; + struct input_dev *input_dev; + struct resource *res; + int irq, error, i; + + if (keymap_data == NULL) { + dev_err(&pdev->dev, "no keymap defined\n"); + return -EINVAL; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq defined in platform data\n"); + return -EINVAL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no I/O memory defined in platform data\n"); + return -EINVAL; + } + + res = request_mem_region(res->start, resource_size(res), pdev->name); + if (res == NULL) { + dev_err(&pdev->dev, "failed to request I/O memory\n"); + return -EBUSY; + } + + input_dev = input_allocate_device(); + if (!input_dev) { + dev_err(&pdev->dev, "failed to allocate the input device\n"); + error = -ENOMEM; + goto failed_rel_mem; + } + + keypad = kzalloc(sizeof(struct imx_keypad), GFP_KERNEL); + if (!keypad) { + dev_err(&pdev->dev, "not enough memory for driver data\n"); + error = -ENOMEM; + goto failed_free_input; + } + + keypad->input_dev = input_dev; + keypad->irq = irq; + keypad->stable_count = 0; + + setup_timer(&keypad->check_matrix_timer, + imx_keypad_check_for_events, (unsigned long) keypad); + + keypad->mmio_base = ioremap(res->start, resource_size(res)); + if (keypad->mmio_base == NULL) { + dev_err(&pdev->dev, "failed to remap I/O memory\n"); + error = -ENOMEM; + goto failed_free_priv; + } + + keypad->clk = clk_get(&pdev->dev, "kpp"); + if (IS_ERR(keypad->clk)) { + dev_err(&pdev->dev, "failed to get keypad clock\n"); + error = PTR_ERR(keypad->clk); + goto failed_unmap; + } + + /* Search for rows and cols enabled */ + for (i = 0; i < keymap_data->keymap_size; i++) { + keypad->rows_en_mask |= 1 << KEY_ROW(keymap_data->keymap[i]); + keypad->cols_en_mask |= 1 << KEY_COL(keymap_data->keymap[i]); + } + + if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) || + keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) { + dev_err(&pdev->dev, + "invalid key data (too many rows or colums)\n"); + error = -EINVAL; + goto failed_clock_put; + } + dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask); + dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask); + + /* Init the Input device */ + input_dev->name = pdev->name; + input_dev->id.bustype = BUS_HOST; + input_dev->dev.parent = &pdev->dev; + input_dev->open = imx_keypad_open; + input_dev->close = imx_keypad_close; + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + input_dev->keycode = keypad->keycodes; + input_dev->keycodesize = sizeof(keypad->keycodes[0]); + input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); + + matrix_keypad_build_keymap(keymap_data, MATRIX_ROW_SHIFT, + keypad->keycodes, input_dev->keybit); + + input_set_capability(input_dev, EV_MSC, MSC_SCAN); + input_set_drvdata(input_dev, keypad); + + /* Ensure that the keypad will stay dormant until opened */ + imx_keypad_inhibit(keypad); + + error = request_irq(irq, imx_keypad_irq_handler, IRQF_DISABLED, + pdev->name, keypad); + if (error) { + dev_err(&pdev->dev, "failed to request IRQ\n"); + goto failed_clock_put; + } + + /* Register the input device */ + error = input_register_device(input_dev); + if (error) { + dev_err(&pdev->dev, "failed to register input device\n"); + goto failed_free_irq; + } + + platform_set_drvdata(pdev, keypad); + device_init_wakeup(&pdev->dev, 1); + + return 0; + +failed_free_irq: + free_irq(irq, pdev); +failed_clock_put: + clk_put(keypad->clk); +failed_unmap: + iounmap(keypad->mmio_base); +failed_free_priv: + kfree(keypad); +failed_free_input: + input_free_device(input_dev); +failed_rel_mem: + release_mem_region(res->start, resource_size(res)); + return error; +} + +static int __devexit imx_keypad_remove(struct platform_device *pdev) +{ + struct imx_keypad *keypad = platform_get_drvdata(pdev); + struct resource *res; + + dev_dbg(&pdev->dev, ">%s\n", __func__); + + platform_set_drvdata(pdev, NULL); + + input_unregister_device(keypad->input_dev); + + free_irq(keypad->irq, keypad); + clk_put(keypad->clk); + + iounmap(keypad->mmio_base); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + + kfree(keypad); + + return 0; +} + +static struct platform_driver imx_keypad_driver = { + .driver = { + .name = "imx-keypad", + .owner = THIS_MODULE, + }, + .probe = imx_keypad_probe, + .remove = __devexit_p(imx_keypad_remove), +}; + +static int __init imx_keypad_init(void) +{ + return platform_driver_register(&imx_keypad_driver); +} + +static void __exit imx_keypad_exit(void) +{ + platform_driver_unregister(&imx_keypad_driver); +} + +module_init(imx_keypad_init); +module_exit(imx_keypad_exit); + +MODULE_AUTHOR("Alberto Panizzo "); +MODULE_DESCRIPTION("IMX Keypad Port Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:imx-keypad"); -- cgit v1.2.3 From fea4d14b69567e134e1838155a5dc857ebca70cb Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Wed, 3 Feb 2010 23:46:48 -0800 Subject: Input: usbtouchscreen - convert from usb_device to usb_interface Convert usbtouchscreen from storing usb_device to usb_interface. This is needed for multi-interface touchscreen devices such as iNexio. Signed-off-by: Ondrej Zary Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/usbtouchscreen.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index b1b99e931f80..69be77118884 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -104,7 +104,7 @@ struct usbtouch_usb { unsigned char *buffer; int buf_len; struct urb *irq; - struct usb_device *udev; + struct usb_interface *interface; struct input_dev *input; struct usbtouch_device_info *type; char name[128]; @@ -234,8 +234,9 @@ static const struct usb_device_id usbtouch_devices[] = { static int e2i_init(struct usbtouch_usb *usbtouch) { int ret; + struct usb_device *udev = interface_to_usbdev(usbtouch->interface); - ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x01, 0x02, 0x0000, 0x0081, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -344,8 +345,9 @@ static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) static int mtouch_init(struct usbtouch_usb *usbtouch) { int ret, i; + struct usb_device *udev = interface_to_usbdev(usbtouch->interface); - ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), MTOUCHUSB_RESET, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -356,7 +358,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) msleep(150); for (i = 0; i < 3; i++) { - ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), MTOUCHUSB_ASYNC_REPORT, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -489,7 +491,7 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) { - struct usb_device *dev = usbtouch->udev; + struct usb_device *dev = interface_to_usbdev(usbtouch->interface); int ret = -ENOMEM; unsigned char *buf; @@ -1021,7 +1023,7 @@ static int usbtouch_open(struct input_dev *input) { struct usbtouch_usb *usbtouch = input_get_drvdata(input); - usbtouch->irq->dev = usbtouch->udev; + usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); if (!usbtouch->type->irq_always) { if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) @@ -1094,7 +1096,7 @@ static int usbtouch_probe(struct usb_interface *intf, goto out_free_buffers; } - usbtouch->udev = udev; + usbtouch->interface = intf; usbtouch->input = input_dev; if (udev->manufacturer) @@ -1133,12 +1135,12 @@ static int usbtouch_probe(struct usb_interface *intf, input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, type->max_press, 0, 0); - usb_fill_int_urb(usbtouch->irq, usbtouch->udev, - usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress), + usb_fill_int_urb(usbtouch->irq, udev, + usb_rcvintpipe(udev, endpoint->bEndpointAddress), usbtouch->data, type->rept_size, usbtouch_irq, usbtouch, endpoint->bInterval); - usbtouch->irq->dev = usbtouch->udev; + usbtouch->irq->dev = udev; usbtouch->irq->transfer_dma = usbtouch->data_dma; usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -- cgit v1.2.3 From f4a5e359c4bafc2269766ccd74256024160ed7ac Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Wed, 3 Feb 2010 23:54:59 -0800 Subject: Input: usbtouchscreen - find input endpoint automatically Find input enpoint automatically instead of assuming that the first one is OK. This is needed for devices with multiple endpoints such as iNexio where the first endpoint might be output. Signed-off-by: Ondrej Zary Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/usbtouchscreen.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 69be77118884..a2a82351a42f 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -1050,13 +1050,23 @@ static void usbtouch_free_buffers(struct usb_device *udev, kfree(usbtouch->buffer); } +static struct usb_endpoint_descriptor * +usbtouch_get_input_endpoint(struct usb_host_interface *interface) +{ + int i; + + for (i = 0; i < interface->desc.bNumEndpoints; i++) + if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) + return &interface->endpoint[i].desc; + + return NULL; +} static int usbtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usbtouch_usb *usbtouch; struct input_dev *input_dev; - struct usb_host_interface *interface; struct usb_endpoint_descriptor *endpoint; struct usb_device *udev = interface_to_usbdev(intf); struct usbtouch_device_info *type; @@ -1066,8 +1076,9 @@ static int usbtouch_probe(struct usb_interface *intf, if (id->driver_info == DEVTYPE_IGNORE) return -ENODEV; - interface = intf->cur_altsetting; - endpoint = &interface->endpoint[0].desc; + endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); + if (!endpoint) + return -ENXIO; usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); input_dev = input_allocate_device(); -- cgit v1.2.3 From 5197424cdcccd2b0b1922babb93969b2515c43ce Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 4 Feb 2010 00:17:18 -0800 Subject: Input: usbtouchscreen - add NEXIO (or iNexio) support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for NEXIO (or iNexio) USB touchscreens to usbtouchscreen driver. Tested with NEX170MRT 17" LCD monitor with integrated touchscreen (with xserver-xorg-input-evtouch 0.8.8-1): T:  Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 54 Spd=12  MxCh= 0 D:  Ver= 1.10 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1 P:  Vendor=1870 ProdID=0001 Rev= 1.00 S:  Manufacturer=iNexio S:  Product=iNexio USB C:* #Ifs= 2 Cfg#= 1 Atr=c0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=00 Driver=(none) E:  Ad=83(I) Atr=03(Int.) MxPS=   8 Ivl=255ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=(none) E:  Ad=01(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms No datasheet is available, this was written by capturing some data with SniffUSB in Windows: http://www.rainbow-software.org/linux_files/nexio/ Signed-off-by: Ondrej Zary Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 5 + drivers/input/touchscreen/usbtouchscreen.c | 261 ++++++++++++++++++++++++++++- 2 files changed, 264 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index dfafc76da4fb..a1e2d845f680 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -537,6 +537,11 @@ config TOUCHSCREEN_USB_ETT_TC5UH bool "ET&T TC5UH touchscreen controler support" if EMBEDDED depends on TOUCHSCREEN_USB_COMPOSITE +config TOUCHSCREEN_USB_NEXIO + default y + bool "NEXIO/iNexio device support" if EMBEDDED + depends on TOUCHSCREEN_USB_COMPOSITE + config TOUCHSCREEN_TOUCHIT213 tristate "Sahara TouchIT-213 touchscreen" select SERIO diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index a2a82351a42f..07656efee654 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -15,6 +15,7 @@ * - GoTop Super_Q2/GogoPen/PenPower tablets * - JASTEC USB touch controller/DigiTech DTR-02U * - Zytronic capacitive touchscreen + * - NEXIO/iNexio * * Copyright (C) 2004-2007 by Daniel Ritz * Copyright (C) by Todd E. Johnson (mtouchusb.c) @@ -95,6 +96,7 @@ struct usbtouch_device_info { int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); int (*init) (struct usbtouch_usb *usbtouch); + void (*exit) (struct usbtouch_usb *usbtouch); }; /* a usbtouch device */ @@ -109,6 +111,7 @@ struct usbtouch_usb { struct usbtouch_device_info *type; char name[128]; char phys[64]; + void *priv; int x, y; int touch, press; @@ -133,6 +136,7 @@ enum { DEVTYPE_E2I, DEVTYPE_ZYTRONIC, DEVTYPE_TC5UH, + DEVTYPE_NEXIO, }; #define USB_DEVICE_HID_CLASS(vend, prod) \ @@ -222,6 +226,14 @@ static const struct usb_device_id usbtouch_devices[] = { {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC5UH}, #endif +#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO + /* data interface only */ + {USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), + .driver_info = DEVTYPE_NEXIO}, + {USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), + .driver_info = DEVTYPE_NEXIO}, +#endif + {} }; @@ -691,6 +703,229 @@ static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) } #endif +/***************************************************************************** + * NEXIO Part + */ +#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO + +#define NEXIO_TIMEOUT 5000 +#define NEXIO_BUFSIZE 1024 +#define NEXIO_THRESHOLD 50 + +struct nexio_priv { + struct urb *ack; + unsigned char *ack_buf; +}; + +struct nexio_touch_packet { + u8 flags; /* 0xe1 = touch, 0xe1 = release */ + __be16 data_len; /* total bytes of touch data */ + __be16 x_len; /* bytes for X axis */ + __be16 y_len; /* bytes for Y axis */ + u8 data[]; +} __attribute__ ((packed)); + +static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 }; +static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f }; + +static void nexio_ack_complete(struct urb *urb) +{ +} + +static int nexio_init(struct usbtouch_usb *usbtouch) +{ + struct usb_device *dev = interface_to_usbdev(usbtouch->interface); + struct usb_host_interface *interface = usbtouch->interface->cur_altsetting; + struct nexio_priv *priv; + int ret = -ENOMEM; + int actual_len, i; + unsigned char *buf; + char *firmware_ver = NULL, *device_name = NULL; + int input_ep = 0, output_ep = 0; + + /* find first input and output endpoint */ + for (i = 0; i < interface->desc.bNumEndpoints; i++) { + if (!input_ep && + usb_endpoint_dir_in(&interface->endpoint[i].desc)) + input_ep = interface->endpoint[i].desc.bEndpointAddress; + if (!output_ep && + usb_endpoint_dir_out(&interface->endpoint[i].desc)) + output_ep = interface->endpoint[i].desc.bEndpointAddress; + } + if (!input_ep || !output_ep) + return -ENXIO; + + buf = kmalloc(NEXIO_BUFSIZE, GFP_KERNEL); + if (!buf) + goto out_buf; + + /* two empty reads */ + for (i = 0; i < 2; i++) { + ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), + buf, NEXIO_BUFSIZE, &actual_len, + NEXIO_TIMEOUT); + if (ret < 0) + goto out_buf; + } + + /* send init command */ + memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt)); + ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep), + buf, sizeof(nexio_init_pkt), &actual_len, + NEXIO_TIMEOUT); + if (ret < 0) + goto out_buf; + + /* read replies */ + for (i = 0; i < 3; i++) { + memset(buf, 0, NEXIO_BUFSIZE); + ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), + buf, NEXIO_BUFSIZE, &actual_len, + NEXIO_TIMEOUT); + if (ret < 0 || actual_len < 1 || buf[1] != actual_len) + continue; + switch (buf[0]) { + case 0x83: /* firmware version */ + if (!firmware_ver) + firmware_ver = kstrdup(&buf[2], GFP_KERNEL); + break; + case 0x84: /* device name */ + if (!device_name) + device_name = kstrdup(&buf[2], GFP_KERNEL); + break; + } + } + + printk(KERN_INFO "Nexio device: %s, firmware version: %s\n", + device_name, firmware_ver); + + kfree(firmware_ver); + kfree(device_name); + + /* prepare ACK URB */ + ret = -ENOMEM; + + usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); + if (!usbtouch->priv) + goto out_buf; + + priv = usbtouch->priv; + + priv->ack_buf = kmalloc(sizeof(nexio_ack_pkt), GFP_KERNEL); + if (!priv->ack_buf) + goto err_priv; + + memcpy(priv->ack_buf, nexio_ack_pkt, sizeof(nexio_ack_pkt)); + + priv->ack = usb_alloc_urb(0, GFP_KERNEL); + if (!priv->ack) { + dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); + goto err_ack_buf; + } + + usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), + priv->ack_buf, sizeof(nexio_ack_pkt), + nexio_ack_complete, usbtouch); + ret = 0; + goto out_buf; + +err_ack_buf: + kfree(priv->ack_buf); +err_priv: + kfree(priv); +out_buf: + kfree(buf); + return ret; +} + +static void nexio_exit(struct usbtouch_usb *usbtouch) +{ + struct nexio_priv *priv = usbtouch->priv; + + usb_kill_urb(priv->ack); + usb_free_urb(priv->ack); + kfree(priv->ack_buf); + kfree(priv); +} + +static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) +{ + int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; + struct nexio_touch_packet *packet = (void *) pkt; + struct nexio_priv *priv = usbtouch->priv; + + /* got touch data? */ + if ((pkt[0] & 0xe0) != 0xe0) + return 0; + + /* send ACK */ + ret = usb_submit_urb(priv->ack, GFP_ATOMIC); + + if (!usbtouch->type->max_xc) { + usbtouch->type->max_xc = 2 * be16_to_cpu(packet->x_len); + input_set_abs_params(usbtouch->input, ABS_X, 0, + 2 * be16_to_cpu(packet->x_len), 0, 0); + usbtouch->type->max_yc = 2 * be16_to_cpu(packet->y_len); + input_set_abs_params(usbtouch->input, ABS_Y, 0, + 2 * be16_to_cpu(packet->y_len), 0, 0); + } + /* + * The device reports state of IR sensors on X and Y axes. + * Each byte represents "darkness" percentage (0-100) of one element. + * 17" touchscreen reports only 64 x 52 bytes so the resolution is low. + * This also means that there's a limited multi-touch capability but + * it's disabled (and untested) here as there's no X driver for that. + */ + begin_x = end_x = begin_y = end_y = -1; + for (x = 0; x < be16_to_cpu(packet->x_len); x++) { + if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { + begin_x = x; + continue; + } + if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { + end_x = x - 1; + for (y = be16_to_cpu(packet->x_len); + y < be16_to_cpu(packet->data_len); y++) { + if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { + begin_y = y - be16_to_cpu(packet->x_len); + continue; + } + if (end_y == -1 && + begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { + end_y = y - 1 - be16_to_cpu(packet->x_len); + w = end_x - begin_x; + h = end_y - begin_y; +#if 0 + /* multi-touch */ + input_report_abs(usbtouch->input, + ABS_MT_TOUCH_MAJOR, max(w,h)); + input_report_abs(usbtouch->input, + ABS_MT_TOUCH_MINOR, min(x,h)); + input_report_abs(usbtouch->input, + ABS_MT_POSITION_X, 2*begin_x+w); + input_report_abs(usbtouch->input, + ABS_MT_POSITION_Y, 2*begin_y+h); + input_report_abs(usbtouch->input, + ABS_MT_ORIENTATION, w > h); + input_mt_sync(usbtouch->input); +#endif + /* single touch */ + usbtouch->x = 2 * begin_x + w; + usbtouch->y = 2 * begin_y + h; + usbtouch->touch = packet->flags & 0x01; + begin_y = end_y = -1; + return 1; + } + } + begin_x = end_x = -1; + } + + } + return 0; +} +#endif + + /***************************************************************************** * the different device descriptors */ @@ -875,6 +1110,16 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { .read_data = tc5uh_read_data, }, #endif + +#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO + [DEVTYPE_NEXIO] = { + .rept_size = 128, + .irq_always = true, + .read_data = nexio_read_data, + .init = nexio_init, + .exit = nexio_exit, + }, +#endif }; @@ -1000,6 +1245,7 @@ static void usbtouch_irq(struct urb *urb) case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: + case -EPIPE: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __func__, urb->status); @@ -1146,10 +1392,16 @@ static int usbtouch_probe(struct usb_interface *intf, input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, type->max_press, 0, 0); - usb_fill_int_urb(usbtouch->irq, udev, + if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) + usb_fill_int_urb(usbtouch->irq, udev, usb_rcvintpipe(udev, endpoint->bEndpointAddress), usbtouch->data, type->rept_size, usbtouch_irq, usbtouch, endpoint->bInterval); + else + usb_fill_bulk_urb(usbtouch->irq, udev, + usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), + usbtouch->data, type->rept_size, + usbtouch_irq, usbtouch); usbtouch->irq->dev = udev; usbtouch->irq->transfer_dma = usbtouch->data_dma; @@ -1167,7 +1419,7 @@ static int usbtouch_probe(struct usb_interface *intf, err = input_register_device(usbtouch->input); if (err) { dbg("%s - input_register_device failed, err: %d", __func__, err); - goto out_free_buffers; + goto out_do_exit; } usb_set_intfdata(intf, usbtouch); @@ -1177,6 +1429,9 @@ static int usbtouch_probe(struct usb_interface *intf, return 0; +out_do_exit: + if (type->exit) + type->exit(usbtouch); out_free_buffers: usbtouch_free_buffers(udev, usbtouch); out_free: @@ -1199,6 +1454,8 @@ static void usbtouch_disconnect(struct usb_interface *intf) /* this will stop IO via close */ input_unregister_device(usbtouch->input); usb_free_urb(usbtouch->irq); + if (usbtouch->type->exit) + usbtouch->type->exit(usbtouch); usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); kfree(usbtouch); } -- cgit v1.2.3 From 1e87a43080a259a0e9739377708ece163b08de8d Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Thu, 4 Feb 2010 00:20:35 -0800 Subject: Input: usbtouchscreen - fix leaks and check return value of usb_submit_urb() Fix urb leak in error path of initialization and make sure we handle errors from initial usb_submit_urb(). Signed-off-by: Ondrej Zary Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/usbtouchscreen.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 07656efee654..7a2d39abc586 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -1412,7 +1412,7 @@ static int usbtouch_probe(struct usb_interface *intf, err = type->init(usbtouch); if (err) { dbg("%s - type->init() failed, err: %d", __func__, err); - goto out_free_buffers; + goto out_free_urb; } } @@ -1424,14 +1424,25 @@ static int usbtouch_probe(struct usb_interface *intf, usb_set_intfdata(intf, usbtouch); - if (usbtouch->type->irq_always) - usb_submit_urb(usbtouch->irq, GFP_KERNEL); + if (usbtouch->type->irq_always) { + err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); + if (err) { + err("%s - usb_submit_urb failed with result: %d", + __func__, err); + goto out_unregister_input; + } + } return 0; +out_unregister_input: + input_unregister_device(input_dev); + input_dev = NULL; out_do_exit: if (type->exit) type->exit(usbtouch); +out_free_urb: + usb_free_urb(usbtouch->irq); out_free_buffers: usbtouch_free_buffers(udev, usbtouch); out_free: -- cgit v1.2.3 From 0b7024ac4df5821347141c18e680b7166bc1cb20 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 2 Feb 2010 21:08:26 -0800 Subject: Input: add match() method to input hanlders Get rid of blacklist in input handler structure and instead allow handlers to define their own match() method to perform fine-grained filtering of supported devices. Signed-off-by: Dmitry Torokhov --- drivers/char/keyboard.c | 24 ++++++++++++++++-------- drivers/input/input.c | 13 ++++++------- drivers/input/joydev.c | 32 +++++++++++++++----------------- include/linux/input.h | 6 +++--- 4 files changed, 40 insertions(+), 35 deletions(-) (limited to 'drivers/input') diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index cbf64b985ef4..ada25bb8941e 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -1323,6 +1323,21 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type, schedule_console_callback(); } +static bool kbd_match(struct input_handler *handler, struct input_dev *dev) +{ + int i; + + if (test_bit(EV_SND, dev->evbit)) + return true; + + if (test_bit(EV_KEY, dev->evbit)) + for (i = KEY_RESERVED; i < BTN_MISC; i++) + if (test_bit(i, dev->keybit)) + return true; + + return false; +} + /* * When a keyboard (or other input device) is found, the kbd_connect * function is called. The function then looks at the device, and if it @@ -1334,14 +1349,6 @@ static int kbd_connect(struct input_handler *handler, struct input_dev *dev, { struct input_handle *handle; int error; - int i; - - for (i = KEY_RESERVED; i < BTN_MISC; i++) - if (test_bit(i, dev->keybit)) - break; - - if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) - return -ENODEV; handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); if (!handle) @@ -1407,6 +1414,7 @@ MODULE_DEVICE_TABLE(input, kbd_ids); static struct input_handler kbd_handler = { .event = kbd_event, + .match = kbd_match, .connect = kbd_connect, .disconnect = kbd_disconnect, .start = kbd_start, diff --git a/drivers/input/input.c b/drivers/input/input.c index 7080a9d4b840..dae49eba6ccd 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -723,12 +723,13 @@ EXPORT_SYMBOL(input_set_keycode); if (i != BITS_TO_LONGS(max)) \ continue; -static const struct input_device_id *input_match_device(const struct input_device_id *id, +static const struct input_device_id *input_match_device(struct input_handler *handler, struct input_dev *dev) { + const struct input_device_id *id; int i; - for (; id->flags || id->driver_info; id++) { + for (id = handler->id_table; id->flags || id->driver_info; id++) { if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) if (id->bustype != dev->id.bustype) @@ -756,7 +757,8 @@ static const struct input_device_id *input_match_device(const struct input_devic MATCH_BIT(ffbit, FF_MAX); MATCH_BIT(swbit, SW_MAX); - return id; + if (!handler->match || handler->match(handler, dev)) + return id; } return NULL; @@ -767,10 +769,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han const struct input_device_id *id; int error; - if (handler->blacklist && input_match_device(handler->blacklist, dev)) - return -ENODEV; - - id = input_match_device(handler->id_table, dev); + id = input_match_device(handler, dev); if (!id) return -ENODEV; diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index b1bd6dd32286..63e71f2a7acc 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -775,6 +775,20 @@ static void joydev_cleanup(struct joydev *joydev) input_close_device(handle); } + +static bool joydev_match(struct input_handler *handler, struct input_dev *dev) +{ + /* Avoid touchpads and touchscreens */ + if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit)) + return false; + + /* Avoid tablets, digitisers and similar devices */ + if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_DIGI, dev->keybit)) + return false; + + return true; +} + static int joydev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { @@ -894,22 +908,6 @@ static void joydev_disconnect(struct input_handle *handle) put_device(&joydev->dev); } -static const struct input_device_id joydev_blacklist[] = { - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_KEYBIT, - .evbit = { BIT_MASK(EV_KEY) }, - .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, - }, /* Avoid itouchpads and touchscreens */ - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | - INPUT_DEVICE_ID_MATCH_KEYBIT, - .evbit = { BIT_MASK(EV_KEY) }, - .keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) }, - }, /* Avoid tablets, digitisers and similar devices */ - { } /* Terminating entry */ -}; - static const struct input_device_id joydev_ids[] = { { .flags = INPUT_DEVICE_ID_MATCH_EVBIT | @@ -936,13 +934,13 @@ MODULE_DEVICE_TABLE(input, joydev_ids); static struct input_handler joydev_handler = { .event = joydev_event, + .match = joydev_match, .connect = joydev_connect, .disconnect = joydev_disconnect, .fops = &joydev_fops, .minor = JOYDEV_MINOR_BASE, .name = "joydev", .id_table = joydev_ids, - .blacklist = joydev_blacklist, }; static int __init joydev_init(void) diff --git a/include/linux/input.h b/include/linux/input.h index 6c9d3d49fa91..8dc5d724c703 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1200,6 +1200,8 @@ struct input_handle; * it may not sleep * @filter: similar to @event; separates normal event handlers from * "filters". + * @match: called after comparing device's id with handler's id_table + * to perform fine-grained matching between device and handler * @connect: called when attaching a handler to an input device * @disconnect: disconnects a handler from input device * @start: starts handler for given handle. This function is called by @@ -1211,8 +1213,6 @@ struct input_handle; * @name: name of the handler, to be shown in /proc/bus/input/handlers * @id_table: pointer to a table of input_device_ids this driver can * handle - * @blacklist: pointer to a table of input_device_ids this driver should - * ignore even if they match @id_table * @h_list: list of input handles associated with the handler * @node: for placing the driver onto input_handler_list * @@ -1235,6 +1235,7 @@ struct input_handler { void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value); + bool (*match)(struct input_handler *handler, struct input_dev *dev); int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); void (*disconnect)(struct input_handle *handle); void (*start)(struct input_handle *handle); @@ -1244,7 +1245,6 @@ struct input_handler { const char *name; const struct input_device_id *id_table; - const struct input_device_id *blacklist; struct list_head h_list; struct list_head node; -- cgit v1.2.3 From daf8a96b2d4a5d4d1d288831be43457c84c55a2f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 4 Feb 2010 00:30:39 -0800 Subject: Input: uinput - mark as non-seekable Seeking does not make sense for uinput so let's use nonseekable_open to mark the device non-seekable. Signed-off-by: Dmitry Torokhov --- drivers/input/misc/uinput.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 18206e18d1b1..1477466076ad 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -290,6 +290,7 @@ static int uinput_open(struct inode *inode, struct file *file) newdev->state = UIST_NEW_DEVICE; file->private_data = newdev; + nonseekable_open(inode, file); return 0; } -- cgit v1.2.3 From 3d7bbd4575cfb23e6ef7368fff1f7d7e198b7930 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 4 Feb 2010 00:30:42 -0800 Subject: Input: mark input interfaces as non-seekable Seeking does not make sense for input interfaces such as evdev and joydev so let's use nonseekable_open to mark them non-seekable. Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 2 ++ drivers/input/joydev.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 258c639571b5..9f9816baeb97 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -278,6 +278,8 @@ static int evdev_open(struct inode *inode, struct file *file) goto err_free_client; file->private_data = client; + nonseekable_open(inode, file); + return 0; err_free_client: diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 63e71f2a7acc..c52bec4d0530 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -286,6 +286,8 @@ static int joydev_open(struct inode *inode, struct file *file) goto err_free_client; file->private_data = client; + nonseekable_open(inode, file); + return 0; err_free_client: -- cgit v1.2.3 From 9e3af04f8787315f63f55b191bb9a06741dbf183 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 4 Feb 2010 00:48:00 -0800 Subject: Input: gpio-keys - add support for disabling gpios through sysfs Now gpio-keys input driver exports 4 new attributes to userland through sysfs: /sys/devices/platform/gpio-keys/keys [ro] /sys/devices/platform/gpio-keys/switches [ro] /sys/devices/platform/gpio-keys/disabled_keys [rw] /sys/devices/platform/gpio-keys/disables_switches [rw] With these attributes, userland program can read which keys and switches can be disabled and then disable/enable them as needed. Keys and switches are exported as stringified bitmap of codes (keycodes or switch codes). For example keys 15, 89, 100, 101, 102 are exported as: '15,89,100-102'. Description of the attributes: keys - bitmap of keys which can be disabled switches - bitmap of switches which can be disabled disabled_keys - bitmap of currently disabled keys (bit 1 means disabled, 0 enabled) disabled_switches - bitmap of currently disabled switches (bit 1 means disabled, 0 enabled) Signed-off-by: Mika Westerberg Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 318 +++++++++++++++++++++++++++++++++++-- include/linux/gpio_keys.h | 1 + 2 files changed, 308 insertions(+), 11 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 1aff3b76effd..2b708aa85553 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -30,13 +30,289 @@ struct gpio_button_data { struct input_dev *input; struct timer_list timer; struct work_struct work; + bool disabled; }; struct gpio_keys_drvdata { struct input_dev *input; + struct mutex disable_lock; + unsigned int n_buttons; struct gpio_button_data data[0]; }; +/* + * SYSFS interface for enabling/disabling keys and switches: + * + * There are 4 attributes under /sys/devices/platform/gpio-keys/ + * keys [ro] - bitmap of keys (EV_KEY) which can be + * disabled + * switches [ro] - bitmap of switches (EV_SW) which can be + * disabled + * disabled_keys [rw] - bitmap of keys currently disabled + * disabled_switches [rw] - bitmap of switches currently disabled + * + * Userland can change these values and hence disable event generation + * for each key (or switch). Disabling a key means its interrupt line + * is disabled. + * + * For example, if we have following switches set up as gpio-keys: + * SW_DOCK = 5 + * SW_CAMERA_LENS_COVER = 9 + * SW_KEYPAD_SLIDE = 10 + * SW_FRONT_PROXIMITY = 11 + * This is read from switches: + * 11-9,5 + * Next we want to disable proximity (11) and dock (5), we write: + * 11,5 + * to file disabled_switches. Now proximity and dock IRQs are disabled. + * This can be verified by reading the file disabled_switches: + * 11,5 + * If we now want to enable proximity (11) switch we write: + * 5 + * to disabled_switches. + * + * We can disable only those keys which don't allow sharing the irq. + */ + +/** + * get_n_events_by_type() - returns maximum number of events per @type + * @type: type of button (%EV_KEY, %EV_SW) + * + * Return value of this function can be used to allocate bitmap + * large enough to hold all bits for given type. + */ +static inline int get_n_events_by_type(int type) +{ + BUG_ON(type != EV_SW && type != EV_KEY); + + return (type == EV_KEY) ? KEY_CNT : SW_CNT; +} + +/** + * gpio_keys_disable_button() - disables given GPIO button + * @bdata: button data for button to be disabled + * + * Disables button pointed by @bdata. This is done by masking + * IRQ line. After this function is called, button won't generate + * input events anymore. Note that one can only disable buttons + * that don't share IRQs. + * + * Make sure that @bdata->disable_lock is locked when entering + * this function to avoid races when concurrent threads are + * disabling buttons at the same time. + */ +static void gpio_keys_disable_button(struct gpio_button_data *bdata) +{ + if (!bdata->disabled) { + /* + * Disable IRQ and possible debouncing timer. + */ + disable_irq(gpio_to_irq(bdata->button->gpio)); + if (bdata->button->debounce_interval) + del_timer_sync(&bdata->timer); + + bdata->disabled = true; + } +} + +/** + * gpio_keys_enable_button() - enables given GPIO button + * @bdata: button data for button to be disabled + * + * Enables given button pointed by @bdata. + * + * Make sure that @bdata->disable_lock is locked when entering + * this function to avoid races with concurrent threads trying + * to enable the same button at the same time. + */ +static void gpio_keys_enable_button(struct gpio_button_data *bdata) +{ + if (bdata->disabled) { + enable_irq(gpio_to_irq(bdata->button->gpio)); + bdata->disabled = false; + } +} + +/** + * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons + * @ddata: pointer to drvdata + * @buf: buffer where stringified bitmap is written + * @type: button type (%EV_KEY, %EV_SW) + * @only_disabled: does caller want only those buttons that are + * currently disabled or all buttons that can be + * disabled + * + * This function writes buttons that can be disabled to @buf. If + * @only_disabled is true, then @buf contains only those buttons + * that are currently disabled. Returns 0 on success or negative + * errno on failure. + */ +static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, + char *buf, unsigned int type, + bool only_disabled) +{ + int n_events = get_n_events_by_type(type); + unsigned long *bits; + ssize_t ret; + int i; + + bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); + if (!bits) + return -ENOMEM; + + for (i = 0; i < ddata->n_buttons; i++) { + struct gpio_button_data *bdata = &ddata->data[i]; + + if (bdata->button->type != type) + continue; + + if (only_disabled && !bdata->disabled) + continue; + + __set_bit(bdata->button->code, bits); + } + + ret = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, bits, n_events); + buf[ret++] = '\n'; + buf[ret] = '\0'; + + kfree(bits); + + return ret; +} + +/** + * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap + * @ddata: pointer to drvdata + * @buf: buffer from userspace that contains stringified bitmap + * @type: button type (%EV_KEY, %EV_SW) + * + * This function parses stringified bitmap from @buf and disables/enables + * GPIO buttons accordinly. Returns 0 on success and negative error + * on failure. + */ +static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, + const char *buf, unsigned int type) +{ + int n_events = get_n_events_by_type(type); + unsigned long *bits; + ssize_t error; + int i; + + bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); + if (!bits) + return -ENOMEM; + + error = bitmap_parselist(buf, bits, n_events); + if (error) + goto out; + + /* First validate */ + for (i = 0; i < ddata->n_buttons; i++) { + struct gpio_button_data *bdata = &ddata->data[i]; + + if (bdata->button->type != type) + continue; + + if (test_bit(bdata->button->code, bits) && + !bdata->button->can_disable) { + error = -EINVAL; + goto out; + } + } + + mutex_lock(&ddata->disable_lock); + + for (i = 0; i < ddata->n_buttons; i++) { + struct gpio_button_data *bdata = &ddata->data[i]; + + if (bdata->button->type != type) + continue; + + if (test_bit(bdata->button->code, bits)) + gpio_keys_disable_button(bdata); + else + gpio_keys_enable_button(bdata); + } + + mutex_unlock(&ddata->disable_lock); + +out: + kfree(bits); + return error; +} + +#define ATTR_SHOW_FN(name, type, only_disabled) \ +static ssize_t gpio_keys_show_##name(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct platform_device *pdev = to_platform_device(dev); \ + struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ + \ + return gpio_keys_attr_show_helper(ddata, buf, \ + type, only_disabled); \ +} + +ATTR_SHOW_FN(keys, EV_KEY, false); +ATTR_SHOW_FN(switches, EV_SW, false); +ATTR_SHOW_FN(disabled_keys, EV_KEY, true); +ATTR_SHOW_FN(disabled_switches, EV_SW, true); + +/* + * ATTRIBUTES: + * + * /sys/devices/platform/gpio-keys/keys [ro] + * /sys/devices/platform/gpio-keys/switches [ro] + */ +static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL); +static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL); + +#define ATTR_STORE_FN(name, type) \ +static ssize_t gpio_keys_store_##name(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, \ + size_t count) \ +{ \ + struct platform_device *pdev = to_platform_device(dev); \ + struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ + ssize_t error; \ + \ + error = gpio_keys_attr_store_helper(ddata, buf, type); \ + if (error) \ + return error; \ + \ + return count; \ +} + +ATTR_STORE_FN(disabled_keys, EV_KEY); +ATTR_STORE_FN(disabled_switches, EV_SW); + +/* + * ATTRIBUTES: + * + * /sys/devices/platform/gpio-keys/disabled_keys [rw] + * /sys/devices/platform/gpio-keys/disables_switches [rw] + */ +static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO, + gpio_keys_show_disabled_keys, + gpio_keys_store_disabled_keys); +static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO, + gpio_keys_show_disabled_switches, + gpio_keys_store_disabled_switches); + +static struct attribute *gpio_keys_attrs[] = { + &dev_attr_keys.attr, + &dev_attr_switches.attr, + &dev_attr_disabled_keys.attr, + &dev_attr_disabled_switches.attr, + NULL, +}; + +static struct attribute_group gpio_keys_attr_group = { + .attrs = gpio_keys_attrs, +}; + static void gpio_keys_report_event(struct gpio_button_data *bdata) { struct gpio_keys_button *button = bdata->button; @@ -79,11 +355,13 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit gpio_keys_setup_key(struct device *dev, +static int __devinit gpio_keys_setup_key(struct platform_device *pdev, struct gpio_button_data *bdata, struct gpio_keys_button *button) { char *desc = button->desc ? button->desc : "gpio_keys"; + struct device *dev = &pdev->dev; + unsigned long irqflags; int irq, error; setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata); @@ -112,10 +390,15 @@ static int __devinit gpio_keys_setup_key(struct device *dev, goto fail3; } - error = request_irq(irq, gpio_keys_isr, - IRQF_SHARED | - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - desc, bdata); + irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + /* + * If platform has specified that the button can be disabled, + * we don't want it to share the interrupt line. + */ + if (!button->can_disable) + irqflags |= IRQF_SHARED; + + error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata); if (error) { dev_err(dev, "Unable to claim irq %d; error %d\n", irq, error); @@ -149,6 +432,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) goto fail1; } + ddata->input = input; + ddata->n_buttons = pdata->nbuttons; + mutex_init(&ddata->disable_lock); + platform_set_drvdata(pdev, ddata); input->name = pdev->name; @@ -164,8 +451,6 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) if (pdata->rep) __set_bit(EV_REP, input->evbit); - ddata->input = input; - for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_button_data *bdata = &ddata->data[i]; @@ -174,7 +459,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) bdata->input = input; bdata->button = button; - error = gpio_keys_setup_key(dev, bdata, button); + error = gpio_keys_setup_key(pdev, bdata, button); if (error) goto fail2; @@ -184,13 +469,20 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) input_set_capability(input, type, button->code); } - error = input_register_device(input); + error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); if (error) { - dev_err(dev, "Unable to register input device, " - "error: %d\n", error); + dev_err(dev, "Unable to export keys/switches, error: %d\n", + error); goto fail2; } + error = input_register_device(input); + if (error) { + dev_err(dev, "Unable to register input device, error: %d\n", + error); + goto fail3; + } + /* get current state of buttons */ for (i = 0; i < pdata->nbuttons; i++) gpio_keys_report_event(&ddata->data[i]); @@ -200,6 +492,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) return 0; + fail3: + sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); fail2: while (--i >= 0) { free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); @@ -224,6 +518,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) struct input_dev *input = ddata->input; int i; + sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); + device_init_wakeup(&pdev->dev, 0); for (i = 0; i < pdata->nbuttons; i++) { diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h index 1289fa7623ca..cd0b3f30f48e 100644 --- a/include/linux/gpio_keys.h +++ b/include/linux/gpio_keys.h @@ -10,6 +10,7 @@ struct gpio_keys_button { int type; /* input event type (EV_KEY, EV_SW) */ int wakeup; /* configure the button as a wake-up source */ int debounce_interval; /* debounce ticks interval in msecs */ + bool can_disable; }; struct gpio_keys_platform_data { -- cgit v1.2.3 From 32974ad4907cdde6c9de612cd1b2ee0568fb9409 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Mon, 8 Feb 2010 10:42:17 -0800 Subject: [IA64] Remove COMPAT_IA32 support This has been broken since May 2008 when Al Viro killed altroot support. Since nobody has complained, it would appear that there are no users of this code (A plausible theory since the main OSVs that support ia64 prefer to use the IA32-EL software emulation). Signed-off-by: Tony Luck --- arch/ia64/Kconfig | 17 - arch/ia64/Makefile | 1 - arch/ia64/configs/bigsur_defconfig | 2 - arch/ia64/configs/generic_defconfig | 2 - arch/ia64/configs/gensparse_defconfig | 2 - arch/ia64/configs/sim_defconfig | 2 - arch/ia64/configs/tiger_defconfig | 1 - arch/ia64/configs/xen_domu_defconfig | 2 - arch/ia64/configs/zx1_defconfig | 2 - arch/ia64/ia32/Makefile | 11 - arch/ia64/ia32/audit.c | 42 - arch/ia64/ia32/binfmt_elf32.c | 245 --- arch/ia64/ia32/elfcore32.h | 148 -- arch/ia64/ia32/ia32_entry.S | 468 ------ arch/ia64/ia32/ia32_ldt.c | 146 -- arch/ia64/ia32/ia32_signal.c | 1010 ------------ arch/ia64/ia32/ia32_support.c | 253 --- arch/ia64/ia32/ia32_traps.c | 156 -- arch/ia64/ia32/ia32priv.h | 532 ------- arch/ia64/ia32/sys_ia32.c | 2765 --------------------------------- arch/ia64/include/asm/ia32.h | 40 - arch/ia64/include/asm/processor.h | 46 - arch/ia64/include/asm/syscall.h | 81 - arch/ia64/include/asm/system.h | 11 +- arch/ia64/include/asm/unistd.h | 14 - arch/ia64/kernel/audit.c | 21 - arch/ia64/kernel/entry.S | 39 - arch/ia64/kernel/ivt.S | 114 -- arch/ia64/kernel/process.c | 55 +- arch/ia64/kernel/ptrace.c | 14 +- arch/ia64/kernel/setup.c | 5 - arch/ia64/kernel/signal.c | 54 +- arch/ia64/kernel/smpboot.c | 5 - arch/ia64/kernel/traps.c | 9 - arch/ia64/mm/init.c | 5 - arch/ia64/xen/hypercall.S | 5 - arch/ia64/xen/xen_pv_ops.c | 16 - drivers/input/input-compat.h | 2 - 38 files changed, 20 insertions(+), 6323 deletions(-) delete mode 100644 arch/ia64/ia32/Makefile delete mode 100644 arch/ia64/ia32/audit.c delete mode 100644 arch/ia64/ia32/binfmt_elf32.c delete mode 100644 arch/ia64/ia32/elfcore32.h delete mode 100644 arch/ia64/ia32/ia32_entry.S delete mode 100644 arch/ia64/ia32/ia32_ldt.c delete mode 100644 arch/ia64/ia32/ia32_signal.c delete mode 100644 arch/ia64/ia32/ia32_support.c delete mode 100644 arch/ia64/ia32/ia32_traps.c delete mode 100644 arch/ia64/ia32/ia32priv.h delete mode 100644 arch/ia64/ia32/sys_ia32.c delete mode 100644 arch/ia64/include/asm/ia32.h (limited to 'drivers/input') diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 2d7f56a98e0f..9a50d7dd2a0b 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -499,23 +499,6 @@ config ARCH_PROC_KCORE_TEXT def_bool y depends on PROC_KCORE -config IA32_SUPPORT - bool "Support for Linux/x86 binaries" - help - IA-64 processors can execute IA-32 (X86) instructions. By - saying Y here, the kernel will include IA-32 system call - emulation support which makes it possible to transparently - run IA-32 Linux binaries on an IA-64 Linux system. - If in doubt, say Y. - -config COMPAT - bool - depends on IA32_SUPPORT - default y - -config COMPAT_FOR_U64_ALIGNMENT - def_bool COMPAT - config IA64_MCA_RECOVERY tristate "MCA recovery from errors other than TLB." diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 475e2725fbde..8ae0d2604ce1 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -46,7 +46,6 @@ head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o libs-y += arch/ia64/lib/ core-y += arch/ia64/kernel/ arch/ia64/mm/ -core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig index ace41096b47b..312b12094a1d 100644 --- a/arch/ia64/configs/bigsur_defconfig +++ b/arch/ia64/configs/bigsur_defconfig @@ -131,8 +131,6 @@ CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y # CONFIG_VIRTUAL_MEM_MAP is not set -CONFIG_IA32_SUPPORT=y -CONFIG_COMPAT=y # CONFIG_IA64_MCA_RECOVERY is not set CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig index 75645495c2dd..6a4cc506fb5f 100644 --- a/arch/ia64/configs/generic_defconfig +++ b/arch/ia64/configs/generic_defconfig @@ -205,8 +205,6 @@ CONFIG_VIRTUAL_MEM_MAP=y CONFIG_HOLES_IN_ZONE=y CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y -CONFIG_IA32_SUPPORT=y -CONFIG_COMPAT=y CONFIG_COMPAT_FOR_U64_ALIGNMENT=y CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig index e86fbd39c795..2dc185b0f9a3 100644 --- a/arch/ia64/configs/gensparse_defconfig +++ b/arch/ia64/configs/gensparse_defconfig @@ -139,8 +139,6 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y CONFIG_NUMA=y CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y -CONFIG_IA32_SUPPORT=y -CONFIG_COMPAT=y CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y diff --git a/arch/ia64/configs/sim_defconfig b/arch/ia64/configs/sim_defconfig index 546a772f438e..21a23cdfd41c 100644 --- a/arch/ia64/configs/sim_defconfig +++ b/arch/ia64/configs/sim_defconfig @@ -130,8 +130,6 @@ CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y # CONFIG_VIRTUAL_MEM_MAP is not set -CONFIG_IA32_SUPPORT=y -CONFIG_COMPAT=y # CONFIG_IA64_MCA_RECOVERY is not set # CONFIG_PERFMON is not set CONFIG_IA64_PALINFO=m diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig index c522edf23c62..c5a5ea9d54ae 100644 --- a/arch/ia64/configs/tiger_defconfig +++ b/arch/ia64/configs/tiger_defconfig @@ -154,7 +154,6 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_VIRTUAL_MEM_MAP=y CONFIG_HOLES_IN_ZONE=y -# CONFIG_IA32_SUPPORT is not set CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y diff --git a/arch/ia64/configs/xen_domu_defconfig b/arch/ia64/configs/xen_domu_defconfig index 0bb0714dc19d..c67eafc4bb38 100644 --- a/arch/ia64/configs/xen_domu_defconfig +++ b/arch/ia64/configs/xen_domu_defconfig @@ -200,8 +200,6 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_VIRTUAL_MEM_MAP=y CONFIG_HOLES_IN_ZONE=y -# CONFIG_IA32_SUPPORT is not set -# CONFIG_COMPAT_FOR_U64_ALIGNMENT is not set CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig index 514f0635dafe..3cec65b534c2 100644 --- a/arch/ia64/configs/zx1_defconfig +++ b/arch/ia64/configs/zx1_defconfig @@ -150,8 +150,6 @@ CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_VIRTUAL_MEM_MAP=y CONFIG_HOLES_IN_ZONE=y -CONFIG_IA32_SUPPORT=y -CONFIG_COMPAT=y CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y diff --git a/arch/ia64/ia32/Makefile b/arch/ia64/ia32/Makefile deleted file mode 100644 index baad8c7699c0..000000000000 --- a/arch/ia64/ia32/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for the ia32 kernel emulation subsystem. -# - -obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \ - ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o -obj-$(CONFIG_AUDIT) += audit.o - -# Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and -# restore_ia32_fpstate_live() can be sure the live register contain user-level state. -CFLAGS_ia32_signal.o += -mfixed-range=f16-f31 diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c deleted file mode 100644 index 5c93ddd1e42d..000000000000 --- a/arch/ia64/ia32/audit.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "../../x86/include/asm/unistd_32.h" - -unsigned ia32_dir_class[] = { -#include -~0U -}; - -unsigned ia32_chattr_class[] = { -#include -~0U -}; - -unsigned ia32_write_class[] = { -#include -~0U -}; - -unsigned ia32_read_class[] = { -#include -~0U -}; - -unsigned ia32_signal_class[] = { -#include -~0U -}; - -int ia32_classify_syscall(unsigned syscall) -{ - switch(syscall) { - case __NR_open: - return 2; - case __NR_openat: - return 3; - case __NR_socketcall: - return 4; - case __NR_execve: - return 5; - default: - return 1; - } -} diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c deleted file mode 100644 index c69552bf893e..000000000000 --- a/arch/ia64/ia32/binfmt_elf32.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * IA-32 ELF support. - * - * Copyright (C) 1999 Arun Sharma - * Copyright (C) 2001 Hewlett-Packard Co - * David Mosberger-Tang - * - * 06/16/00 A. Mallick initialize csd/ssd/tssd/cflg for ia32_load_state - * 04/13/01 D. Mosberger dropped saving tssd in ar.k1---it's not needed - * 09/14/01 D. Mosberger fixed memory management for gdt/tss page - */ - -#include -#include -#include - -#include -#include - -#include "ia32priv.h" -#include "elfcore32.h" - -/* Override some function names */ -#undef start_thread -#define start_thread ia32_start_thread -#define elf_format elf32_format -#define init_elf_binfmt init_elf32_binfmt -#define exit_elf_binfmt exit_elf32_binfmt - -#undef CLOCKS_PER_SEC -#define CLOCKS_PER_SEC IA32_CLOCKS_PER_SEC - -extern void ia64_elf32_init (struct pt_regs *regs); - -static void elf32_set_personality (void); - -static unsigned long __attribute ((unused)) -randomize_stack_top(unsigned long stack_top); - -#define setup_arg_pages(bprm,tos,exec) ia32_setup_arg_pages(bprm,exec) -#define elf_map elf32_map - -#undef SET_PERSONALITY -#define SET_PERSONALITY(ex) elf32_set_personality() - -#define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack)) - -/* Ugly but avoids duplication */ -#include "../../../fs/binfmt_elf.c" - -extern struct page *ia32_shared_page[]; -extern unsigned long *ia32_gdt; -extern struct page *ia32_gate_page; - -int -ia32_install_shared_page (struct vm_area_struct *vma, struct vm_fault *vmf) -{ - vmf->page = ia32_shared_page[smp_processor_id()]; - get_page(vmf->page); - return 0; -} - -int -ia32_install_gate_page (struct vm_area_struct *vma, struct vm_fault *vmf) -{ - vmf->page = ia32_gate_page; - get_page(vmf->page); - return 0; -} - - -static const struct vm_operations_struct ia32_shared_page_vm_ops = { - .fault = ia32_install_shared_page -}; - -static const struct vm_operations_struct ia32_gate_page_vm_ops = { - .fault = ia32_install_gate_page -}; - -void -ia64_elf32_init (struct pt_regs *regs) -{ - struct vm_area_struct *vma; - - /* - * Map GDT below 4GB, where the processor can find it. We need to map - * it with privilege level 3 because the IVE uses non-privileged accesses to these - * tables. IA-32 segmentation is used to protect against IA-32 accesses to them. - */ - vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); - if (vma) { - vma->vm_mm = current->mm; - vma->vm_start = IA32_GDT_OFFSET; - vma->vm_end = vma->vm_start + PAGE_SIZE; - vma->vm_page_prot = PAGE_SHARED; - vma->vm_flags = VM_READ|VM_MAYREAD|VM_RESERVED; - vma->vm_ops = &ia32_shared_page_vm_ops; - down_write(¤t->mm->mmap_sem); - { - if (insert_vm_struct(current->mm, vma)) { - kmem_cache_free(vm_area_cachep, vma); - up_write(¤t->mm->mmap_sem); - BUG(); - } - } - up_write(¤t->mm->mmap_sem); - } - - /* - * When user stack is not executable, push sigreturn code to stack makes - * segmentation fault raised when returning to kernel. So now sigreturn - * code is locked in specific gate page, which is pointed by pretcode - * when setup_frame_ia32 - */ - vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); - if (vma) { - vma->vm_mm = current->mm; - vma->vm_start = IA32_GATE_OFFSET; - vma->vm_end = vma->vm_start + PAGE_SIZE; - vma->vm_page_prot = PAGE_COPY_EXEC; - vma->vm_flags = VM_READ | VM_MAYREAD | VM_EXEC - | VM_MAYEXEC | VM_RESERVED; - vma->vm_ops = &ia32_gate_page_vm_ops; - down_write(¤t->mm->mmap_sem); - { - if (insert_vm_struct(current->mm, vma)) { - kmem_cache_free(vm_area_cachep, vma); - up_write(¤t->mm->mmap_sem); - BUG(); - } - } - up_write(¤t->mm->mmap_sem); - } - - /* - * Install LDT as anonymous memory. This gives us all-zero segment descriptors - * until a task modifies them via modify_ldt(). - */ - vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); - if (vma) { - vma->vm_mm = current->mm; - vma->vm_start = IA32_LDT_OFFSET; - vma->vm_end = vma->vm_start + PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE); - vma->vm_page_prot = PAGE_SHARED; - vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE; - down_write(¤t->mm->mmap_sem); - { - if (insert_vm_struct(current->mm, vma)) { - kmem_cache_free(vm_area_cachep, vma); - up_write(¤t->mm->mmap_sem); - BUG(); - } - } - up_write(¤t->mm->mmap_sem); - } - - ia64_psr(regs)->ac = 0; /* turn off alignment checking */ - regs->loadrs = 0; - /* - * According to the ABI %edx points to an `atexit' handler. Since we don't have - * one we'll set it to 0 and initialize all the other registers just to make - * things more deterministic, ala the i386 implementation. - */ - regs->r8 = 0; /* %eax */ - regs->r11 = 0; /* %ebx */ - regs->r9 = 0; /* %ecx */ - regs->r10 = 0; /* %edx */ - regs->r13 = 0; /* %ebp */ - regs->r14 = 0; /* %esi */ - regs->r15 = 0; /* %edi */ - - current->thread.eflag = IA32_EFLAG; - current->thread.fsr = IA32_FSR_DEFAULT; - current->thread.fcr = IA32_FCR_DEFAULT; - current->thread.fir = 0; - current->thread.fdr = 0; - - /* - * Setup GDTD. Note: GDTD is the descrambled version of the pseudo-descriptor - * format defined by Figure 3-11 "Pseudo-Descriptor Format" in the IA-32 - * architecture manual. Also note that the only fields that are not ignored are - * `base', `limit', 'G', `P' (must be 1) and `S' (must be 0). - */ - regs->r31 = IA32_SEG_UNSCRAMBLE(IA32_SEG_DESCRIPTOR(IA32_GDT_OFFSET, IA32_PAGE_SIZE - 1, - 0, 0, 0, 1, 0, 0, 0)); - /* Setup the segment selectors */ - regs->r16 = (__USER_DS << 16) | __USER_DS; /* ES == DS, GS, FS are zero */ - regs->r17 = (__USER_DS << 16) | __USER_CS; /* SS, CS; ia32_load_state() sets TSS and LDT */ - - ia32_load_segment_descriptors(current); - ia32_load_state(current); -} - -/* - * Undo the override of setup_arg_pages() without this ia32_setup_arg_pages() - * will suffer infinite self recursion. - */ -#undef setup_arg_pages - -int -ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) -{ - int ret; - - ret = setup_arg_pages(bprm, IA32_STACK_TOP, executable_stack); - if (!ret) { - /* - * Can't do it in ia64_elf32_init(). Needs to be done before - * calls to elf32_map() - */ - current->thread.ppl = ia32_init_pp_list(); - } - - return ret; -} - -static void -elf32_set_personality (void) -{ - set_personality(PER_LINUX32); - current->thread.map_base = IA32_PAGE_OFFSET/3; -} - -static unsigned long -elf32_map(struct file *filep, unsigned long addr, struct elf_phdr *eppnt, - int prot, int type, unsigned long unused) -{ - unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK; - - return ia32_do_mmap(filep, (addr & IA32_PAGE_MASK), eppnt->p_filesz + pgoff, prot, type, - eppnt->p_offset - pgoff); -} - -#define cpu_uses_ia32el() (local_cpu_data->family > 0x1f) - -static int __init check_elf32_binfmt(void) -{ - if (cpu_uses_ia32el()) { - printk("Please use IA-32 EL for executing IA-32 binaries\n"); - unregister_binfmt(&elf_format); - } - return 0; -} - -module_init(check_elf32_binfmt) diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h deleted file mode 100644 index 657725742617..000000000000 --- a/arch/ia64/ia32/elfcore32.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * IA-32 ELF core dump support. - * - * Copyright (C) 2003 Arun Sharma - * - * Derived from the x86_64 version - */ -#ifndef _ELFCORE32_H_ -#define _ELFCORE32_H_ - -#include -#include - -/* Override elfcore.h */ -#define _LINUX_ELFCORE_H 1 -typedef unsigned int elf_greg_t; - -#define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t)) -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef struct ia32_user_i387_struct elf_fpregset_t; -typedef struct ia32_user_fxsr_struct elf_fpxregset_t; - -struct elf_siginfo -{ - int si_signo; /* signal number */ - int si_code; /* extra code */ - int si_errno; /* errno */ -}; - -#ifdef CONFIG_VIRT_CPU_ACCOUNTING -/* - * Hacks are here since types between compat_timeval (= pair of s32) and - * ia64-native timeval (= pair of s64) are not compatible, at least a file - * arch/ia64/ia32/../../../fs/binfmt_elf.c will get warnings from compiler on - * use of cputime_to_timeval(), which usually an alias of jiffies_to_timeval(). - */ -#define cputime_to_timeval(a,b) \ - do { (b)->tv_usec = 0; (b)->tv_sec = (a)/NSEC_PER_SEC; } while(0) -#else -#define jiffies_to_timeval(a,b) \ - do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; } while(0) -#endif - -struct elf_prstatus -{ - struct elf_siginfo pr_info; /* Info associated with signal */ - short pr_cursig; /* Current signal */ - unsigned int pr_sigpend; /* Set of pending signals */ - unsigned int pr_sighold; /* Set of held signals */ - pid_t pr_pid; - pid_t pr_ppid; - pid_t pr_pgrp; - pid_t pr_sid; - struct compat_timeval pr_utime; /* User time */ - struct compat_timeval pr_stime; /* System time */ - struct compat_timeval pr_cutime; /* Cumulative user time */ - struct compat_timeval pr_cstime; /* Cumulative system time */ - elf_gregset_t pr_reg; /* GP registers */ - int pr_fpvalid; /* True if math co-processor being used. */ -}; - -#define ELF_PRARGSZ (80) /* Number of chars for args */ - -struct elf_prpsinfo -{ - char pr_state; /* numeric process state */ - char pr_sname; /* char for pr_state */ - char pr_zomb; /* zombie */ - char pr_nice; /* nice val */ - unsigned int pr_flag; /* flags */ - __u16 pr_uid; - __u16 pr_gid; - pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; - /* Lots missing */ - char pr_fname[16]; /* filename of executable */ - char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ -}; - -#define ELF_CORE_COPY_REGS(pr_reg, regs) \ - pr_reg[0] = regs->r11; \ - pr_reg[1] = regs->r9; \ - pr_reg[2] = regs->r10; \ - pr_reg[3] = regs->r14; \ - pr_reg[4] = regs->r15; \ - pr_reg[5] = regs->r13; \ - pr_reg[6] = regs->r8; \ - pr_reg[7] = regs->r16 & 0xffff; \ - pr_reg[8] = (regs->r16 >> 16) & 0xffff; \ - pr_reg[9] = (regs->r16 >> 32) & 0xffff; \ - pr_reg[10] = (regs->r16 >> 48) & 0xffff; \ - pr_reg[11] = regs->r1; \ - pr_reg[12] = regs->cr_iip; \ - pr_reg[13] = regs->r17 & 0xffff; \ - pr_reg[14] = ia64_getreg(_IA64_REG_AR_EFLAG); \ - pr_reg[15] = regs->r12; \ - pr_reg[16] = (regs->r17 >> 16) & 0xffff; - -static inline void elf_core_copy_regs(elf_gregset_t *elfregs, - struct pt_regs *regs) -{ - ELF_CORE_COPY_REGS((*elfregs), regs) -} - -static inline int elf_core_copy_task_regs(struct task_struct *t, - elf_gregset_t* elfregs) -{ - ELF_CORE_COPY_REGS((*elfregs), task_pt_regs(t)); - return 1; -} - -static inline int -elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpregset_t *fpu) -{ - struct ia32_user_i387_struct *fpstate = (void*)fpu; - mm_segment_t old_fs; - - if (!tsk_used_math(tsk)) - return 0; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - save_ia32_fpstate(tsk, (struct ia32_user_i387_struct __user *) fpstate); - set_fs(old_fs); - - return 1; -} - -#define ELF_CORE_COPY_XFPREGS 1 -#define ELF_CORE_XFPREG_TYPE NT_PRXFPREG -static inline int -elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu) -{ - struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu; - mm_segment_t old_fs; - - if (!tsk_used_math(tsk)) - return 0; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - save_ia32_fpxstate(tsk, (struct ia32_user_fxsr_struct __user *) fpxstate); - set_fs(old_fs); - - return 1; -} - -#endif /* _ELFCORE32_H_ */ diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S deleted file mode 100644 index 2fd7479aa216..000000000000 --- a/arch/ia64/ia32/ia32_entry.S +++ /dev/null @@ -1,468 +0,0 @@ -#include -#include -#include -#include -#include - -#include "../kernel/minstate.h" - - /* - * execve() is special because in case of success, we need to - * setup a null register window frame (in case an IA-32 process - * is exec'ing an IA-64 program). - */ -ENTRY(ia32_execve) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3) - alloc loc1=ar.pfs,3,2,4,0 - mov loc0=rp - .body - zxt4 out0=in0 // filename - ;; // stop bit between alloc and call - zxt4 out1=in1 // argv - zxt4 out2=in2 // envp - add out3=16,sp // regs - br.call.sptk.few rp=sys32_execve -1: cmp.ge p6,p0=r8,r0 - mov ar.pfs=loc1 // restore ar.pfs - ;; -(p6) mov ar.pfs=r0 // clear ar.pfs in case of success - sxt4 r8=r8 // return 64-bit result - mov rp=loc0 - br.ret.sptk.few rp -END(ia32_execve) - -ENTRY(ia32_clone) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5) - alloc r16=ar.pfs,5,2,6,0 - DO_SAVE_SWITCH_STACK - mov loc0=rp - mov loc1=r16 // save ar.pfs across do_fork - .body - zxt4 out1=in1 // newsp - mov out3=16 // stacksize (compensates for 16-byte scratch area) - adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s - mov out0=in0 // out0 = clone_flags - zxt4 out4=in2 // out4 = parent_tidptr - zxt4 out5=in4 // out5 = child_tidptr - br.call.sptk.many rp=do_fork -.ret0: .restore sp - adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack - mov ar.pfs=loc1 - mov rp=loc0 - br.ret.sptk.many rp -END(ia32_clone) - -GLOBAL_ENTRY(ia32_ret_from_clone) - PT_REGS_UNWIND_INFO(0) -{ /* - * Some versions of gas generate bad unwind info if the first instruction of a - * procedure doesn't go into the first slot of a bundle. This is a workaround. - */ - nop.m 0 - nop.i 0 - /* - * We need to call schedule_tail() to complete the scheduling process. - * Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the - * address of the previously executing task. - */ - br.call.sptk.many rp=ia64_invoke_schedule_tail -} -.ret1: - adds r2=TI_FLAGS+IA64_TASK_SIZE,r13 - ;; - ld4 r2=[r2] - ;; - mov r8=0 - and r2=_TIF_SYSCALL_TRACEAUDIT,r2 - ;; - cmp.ne p6,p0=r2,r0 -(p6) br.cond.spnt .ia32_strace_check_retval - ;; // prevent RAW on r8 -END(ia32_ret_from_clone) - // fall through -GLOBAL_ENTRY(ia32_ret_from_syscall) - PT_REGS_UNWIND_INFO(0) - - cmp.ge p6,p7=r8,r0 // syscall executed successfully? - adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 - ;; - alloc r3=ar.pfs,0,0,0,0 // drop the syscall argument frame - st8 [r2]=r8 // store return value in slot for r8 - br.cond.sptk.many ia64_leave_kernel -END(ia32_ret_from_syscall) - - // - // Invoke a system call, but do some tracing before and after the call. - // We MUST preserve the current register frame throughout this routine - // because some system calls (such as ia64_execve) directly - // manipulate ar.pfs. - // - // Input: - // r8 = syscall number - // b6 = syscall entry point - // -GLOBAL_ENTRY(ia32_trace_syscall) - PT_REGS_UNWIND_INFO(0) - mov r3=-38 - adds r2=IA64_PT_REGS_R8_OFFSET+16,sp - ;; - st8 [r2]=r3 // initialize return code to -ENOSYS - br.call.sptk.few rp=syscall_trace_enter // give parent a chance to catch syscall args - cmp.lt p6,p0=r8,r0 // check tracehook - adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 - ;; -(p6) st8.spill [r2]=r8 // store return value in slot for r8 -(p6) br.spnt.few .ret4 -.ret2: // Need to reload arguments (they may be changed by the tracing process) - adds r2=IA64_PT_REGS_R1_OFFSET+16,sp // r2 = &pt_regs.r1 - adds r3=IA64_PT_REGS_R13_OFFSET+16,sp // r3 = &pt_regs.r13 - mov r15=IA32_NR_syscalls - ;; - ld4 r8=[r2],IA64_PT_REGS_R9_OFFSET-IA64_PT_REGS_R1_OFFSET - movl r16=ia32_syscall_table - ;; - ld4 r33=[r2],8 // r9 == ecx - ld4 r37=[r3],16 // r13 == ebp - cmp.ltu.unc p6,p7=r8,r15 - ;; - ld4 r34=[r2],8 // r10 == edx - ld4 r36=[r3],8 // r15 == edi -(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number - ;; - ld8 r16=[r16] - ;; - ld4 r32=[r2],8 // r11 == ebx - mov b6=r16 - ld4 r35=[r3],8 // r14 == esi - br.call.sptk.few rp=b6 // do the syscall -.ia32_strace_check_retval: - cmp.lt p6,p0=r8,r0 // syscall failed? - adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 - ;; - st8.spill [r2]=r8 // store return value in slot for r8 - br.call.sptk.few rp=syscall_trace_leave // give parent a chance to catch return value -.ret4: alloc r2=ar.pfs,0,0,0,0 // drop the syscall argument frame - br.cond.sptk.many ia64_leave_kernel -END(ia32_trace_syscall) - -GLOBAL_ENTRY(sys32_vfork) - alloc r16=ar.pfs,2,2,4,0;; - mov out0=IA64_CLONE_VFORK|IA64_CLONE_VM|SIGCHLD // out0 = clone_flags - br.cond.sptk.few .fork1 // do the work -END(sys32_vfork) - -GLOBAL_ENTRY(sys32_fork) - .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) - alloc r16=ar.pfs,2,2,4,0 - mov out0=SIGCHLD // out0 = clone_flags - ;; -.fork1: - mov loc0=rp - mov loc1=r16 // save ar.pfs across do_fork - DO_SAVE_SWITCH_STACK - - .body - - mov out1=0 - mov out3=0 - adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s - br.call.sptk.few rp=do_fork -.ret5: .restore sp - adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack - mov ar.pfs=loc1 - mov rp=loc0 - br.ret.sptk.many rp -END(sys32_fork) - - .rodata - .align 8 - .globl ia32_syscall_table -ia32_syscall_table: - data8 sys_ni_syscall /* 0 - old "setup(" system call*/ - data8 sys_exit - data8 sys32_fork - data8 sys_read - data8 sys_write - data8 compat_sys_open /* 5 */ - data8 sys_close - data8 sys32_waitpid - data8 sys_creat - data8 sys_link - data8 sys_unlink /* 10 */ - data8 ia32_execve - data8 sys_chdir - data8 compat_sys_time - data8 sys_mknod - data8 sys_chmod /* 15 */ - data8 sys_lchown /* 16-bit version */ - data8 sys_ni_syscall /* old break syscall holder */ - data8 sys_ni_syscall - data8 sys32_lseek - data8 sys_getpid /* 20 */ - data8 compat_sys_mount - data8 sys_oldumount - data8 sys_setuid /* 16-bit version */ - data8 sys_getuid /* 16-bit version */ - data8 compat_sys_stime /* 25 */ - data8 compat_sys_ptrace - data8 sys32_alarm - data8 sys_ni_syscall - data8 sys_pause - data8 compat_sys_utime /* 30 */ - data8 sys_ni_syscall /* old stty syscall holder */ - data8 sys_ni_syscall /* old gtty syscall holder */ - data8 sys_access - data8 sys_nice - data8 sys_ni_syscall /* 35 */ /* old ftime syscall holder */ - data8 sys_sync - data8 sys_kill - data8 sys_rename - data8 sys_mkdir - data8 sys_rmdir /* 40 */ - data8 sys_dup - data8 sys_ia64_pipe - data8 compat_sys_times - data8 sys_ni_syscall /* old prof syscall holder */ - data8 sys32_brk /* 45 */ - data8 sys_setgid /* 16-bit version */ - data8 sys_getgid /* 16-bit version */ - data8 sys32_signal - data8 sys_geteuid /* 16-bit version */ - data8 sys_getegid /* 16-bit version */ /* 50 */ - data8 sys_acct - data8 sys_umount /* recycled never used phys( */ - data8 sys_ni_syscall /* old lock syscall holder */ - data8 compat_sys_ioctl - data8 compat_sys_fcntl /* 55 */ - data8 sys_ni_syscall /* old mpx syscall holder */ - data8 sys_setpgid - data8 sys_ni_syscall /* old ulimit syscall holder */ - data8 sys_ni_syscall - data8 sys_umask /* 60 */ - data8 sys_chroot - data8 compat_sys_ustat - data8 sys_dup2 - data8 sys_getppid - data8 sys_getpgrp /* 65 */ - data8 sys_setsid - data8 sys32_sigaction - data8 sys_ni_syscall - data8 sys_ni_syscall - data8 sys_setreuid /* 16-bit version */ /* 70 */ - data8 sys_setregid /* 16-bit version */ - data8 sys32_sigsuspend - data8 compat_sys_sigpending - data8 sys_sethostname - data8 compat_sys_setrlimit /* 75 */ - data8 compat_sys_old_getrlimit - data8 compat_sys_getrusage - data8 compat_sys_gettimeofday - data8 compat_sys_settimeofday - data8 sys32_getgroups16 /* 80 */ - data8 sys32_setgroups16 - data8 sys32_old_select - data8 sys_symlink - data8 sys_ni_syscall - data8 sys_readlink /* 85 */ - data8 sys_uselib - data8 sys_swapon - data8 sys_reboot - data8 compat_sys_old_readdir - data8 sys32_mmap /* 90 */ - data8 sys32_munmap - data8 sys_truncate - data8 sys_ftruncate - data8 sys_fchmod - data8 sys_fchown /* 16-bit version */ /* 95 */ - data8 sys_getpriority - data8 sys_setpriority - data8 sys_ni_syscall /* old profil syscall holder */ - data8 compat_sys_statfs - data8 compat_sys_fstatfs /* 100 */ - data8 sys_ni_syscall /* ioperm */ - data8 compat_sys_socketcall - data8 sys_syslog - data8 compat_sys_setitimer - data8 compat_sys_getitimer /* 105 */ - data8 compat_sys_newstat - data8 compat_sys_newlstat - data8 compat_sys_newfstat - data8 sys_ni_syscall - data8 sys_ni_syscall /* iopl */ /* 110 */ - data8 sys_vhangup - data8 sys_ni_syscall /* used to be sys_idle */ - data8 sys_ni_syscall - data8 compat_sys_wait4 - data8 sys_swapoff /* 115 */ - data8 compat_sys_sysinfo - data8 sys32_ipc - data8 sys_fsync - data8 sys32_sigreturn - data8 ia32_clone /* 120 */ - data8 sys_setdomainname - data8 sys32_newuname - data8 sys32_modify_ldt - data8 compat_sys_adjtimex - data8 sys32_mprotect /* 125 */ - data8 compat_sys_sigprocmask - data8 sys_ni_syscall /* create_module */ - data8 sys_ni_syscall /* init_module */ - data8 sys_ni_syscall /* delete_module */ - data8 sys_ni_syscall /* get_kernel_syms */ /* 130 */ - data8 sys32_quotactl - data8 sys_getpgid - data8 sys_fchdir - data8 sys_ni_syscall /* sys_bdflush */ - data8 sys_sysfs /* 135 */ - data8 sys32_personality - data8 sys_ni_syscall /* for afs_syscall */ - data8 sys_setfsuid /* 16-bit version */ - data8 sys_setfsgid /* 16-bit version */ - data8 sys_llseek /* 140 */ - data8 compat_sys_getdents - data8 compat_sys_select - data8 sys_flock - data8 sys32_msync - data8 compat_sys_readv /* 145 */ - data8 compat_sys_writev - data8 sys_getsid - data8 sys_fdatasync - data8 compat_sys_sysctl - data8 sys_mlock /* 150 */ - data8 sys_munlock - data8 sys_mlockall - data8 sys_munlockall - data8 sys_sched_setparam - data8 sys_sched_getparam /* 155 */ - data8 sys_sched_setscheduler - data8 sys_sched_getscheduler - data8 sys_sched_yield - data8 sys_sched_get_priority_max - data8 sys_sched_get_priority_min /* 160 */ - data8 sys32_sched_rr_get_interval - data8 compat_sys_nanosleep - data8 sys32_mremap - data8 sys_setresuid /* 16-bit version */ - data8 sys32_getresuid16 /* 16-bit version */ /* 165 */ - data8 sys_ni_syscall /* vm86 */ - data8 sys_ni_syscall /* sys_query_module */ - data8 sys_poll - data8 sys_ni_syscall /* nfsservctl */ - data8 sys_setresgid /* 170 */ - data8 sys32_getresgid16 - data8 sys_prctl - data8 sys32_rt_sigreturn - data8 sys32_rt_sigaction - data8 sys32_rt_sigprocmask /* 175 */ - data8 sys_rt_sigpending - data8 compat_sys_rt_sigtimedwait - data8 sys32_rt_sigqueueinfo - data8 compat_sys_rt_sigsuspend - data8 sys32_pread /* 180 */ - data8 sys32_pwrite - data8 sys_chown /* 16-bit version */ - data8 sys_getcwd - data8 sys_capget - data8 sys_capset /* 185 */ - data8 sys32_sigaltstack - data8 sys32_sendfile - data8 sys_ni_syscall /* streams1 */ - data8 sys_ni_syscall /* streams2 */ - data8 sys32_vfork /* 190 */ - data8 compat_sys_getrlimit - data8 sys32_mmap2 - data8 sys32_truncate64 - data8 sys32_ftruncate64 - data8 sys32_stat64 /* 195 */ - data8 sys32_lstat64 - data8 sys32_fstat64 - data8 sys_lchown - data8 sys_getuid - data8 sys_getgid /* 200 */ - data8 sys_geteuid - data8 sys_getegid - data8 sys_setreuid - data8 sys_setregid - data8 sys_getgroups /* 205 */ - data8 sys_setgroups - data8 sys_fchown - data8 sys_setresuid - data8 sys_getresuid - data8 sys_setresgid /* 210 */ - data8 sys_getresgid - data8 sys_chown - data8 sys_setuid - data8 sys_setgid - data8 sys_setfsuid /* 215 */ - data8 sys_setfsgid - data8 sys_pivot_root - data8 sys_mincore - data8 sys_madvise - data8 compat_sys_getdents64 /* 220 */ - data8 compat_sys_fcntl64 - data8 sys_ni_syscall /* reserved for TUX */ - data8 sys_ni_syscall /* reserved for Security */ - data8 sys_gettid - data8 sys_readahead /* 225 */ - data8 sys_setxattr - data8 sys_lsetxattr - data8 sys_fsetxattr - data8 sys_getxattr - data8 sys_lgetxattr /* 230 */ - data8 sys_fgetxattr - data8 sys_listxattr - data8 sys_llistxattr - data8 sys_flistxattr - data8 sys_removexattr /* 235 */ - data8 sys_lremovexattr - data8 sys_fremovexattr - data8 sys_tkill - data8 sys_sendfile64 - data8 compat_sys_futex /* 240 */ - data8 compat_sys_sched_setaffinity - data8 compat_sys_sched_getaffinity - data8 sys32_set_thread_area - data8 sys32_get_thread_area - data8 compat_sys_io_setup /* 245 */ - data8 sys_io_destroy - data8 compat_sys_io_getevents - data8 compat_sys_io_submit - data8 sys_io_cancel - data8 sys_fadvise64 /* 250 */ - data8 sys_ni_syscall - data8 sys_exit_group - data8 sys_lookup_dcookie - data8 sys_epoll_create - data8 sys32_epoll_ctl /* 255 */ - data8 sys32_epoll_wait - data8 sys_remap_file_pages - data8 sys_set_tid_address - data8 compat_sys_timer_create - data8 compat_sys_timer_settime /* 260 */ - data8 compat_sys_timer_gettime - data8 sys_timer_getoverrun - data8 sys_timer_delete - data8 compat_sys_clock_settime - data8 compat_sys_clock_gettime /* 265 */ - data8 compat_sys_clock_getres - data8 compat_sys_clock_nanosleep - data8 compat_sys_statfs64 - data8 compat_sys_fstatfs64 - data8 sys_tgkill /* 270 */ - data8 compat_sys_utimes - data8 sys32_fadvise64_64 - data8 sys_ni_syscall - data8 sys_ni_syscall - data8 sys_ni_syscall /* 275 */ - data8 sys_ni_syscall - data8 compat_sys_mq_open - data8 sys_mq_unlink - data8 compat_sys_mq_timedsend - data8 compat_sys_mq_timedreceive /* 280 */ - data8 compat_sys_mq_notify - data8 compat_sys_mq_getsetattr - data8 sys_ni_syscall /* reserved for kexec */ - data8 compat_sys_waitid - - // guard against failures to increase IA32_NR_syscalls - .org ia32_syscall_table + 8*IA32_NR_syscalls diff --git a/arch/ia64/ia32/ia32_ldt.c b/arch/ia64/ia32/ia32_ldt.c deleted file mode 100644 index 16d51c146849..000000000000 --- a/arch/ia64/ia32/ia32_ldt.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2001, 2004 Hewlett-Packard Co - * David Mosberger-Tang - * - * Adapted from arch/i386/kernel/ldt.c - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "ia32priv.h" - -/* - * read_ldt() is not really atomic - this is not a problem since synchronization of reads - * and writes done to the LDT has to be assured by user-space anyway. Writes are atomic, - * to protect the security checks done on new descriptors. - */ -static int -read_ldt (void __user *ptr, unsigned long bytecount) -{ - unsigned long bytes_left, n; - char __user *src, *dst; - char buf[256]; /* temporary buffer (don't overflow kernel stack!) */ - - if (bytecount > IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE) - bytecount = IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE; - - bytes_left = bytecount; - - src = (void __user *) IA32_LDT_OFFSET; - dst = ptr; - - while (bytes_left) { - n = sizeof(buf); - if (n > bytes_left) - n = bytes_left; - - /* - * We know we're reading valid memory, but we still must guard against - * running out of memory. - */ - if (__copy_from_user(buf, src, n)) - return -EFAULT; - - if (copy_to_user(dst, buf, n)) - return -EFAULT; - - src += n; - dst += n; - bytes_left -= n; - } - return bytecount; -} - -static int -read_default_ldt (void __user * ptr, unsigned long bytecount) -{ - unsigned long size; - int err; - - /* XXX fix me: should return equivalent of default_ldt[0] */ - err = 0; - size = 8; - if (size > bytecount) - size = bytecount; - - err = size; - if (clear_user(ptr, size)) - err = -EFAULT; - - return err; -} - -static int -write_ldt (void __user * ptr, unsigned long bytecount, int oldmode) -{ - struct ia32_user_desc ldt_info; - __u64 entry; - int ret; - - if (bytecount != sizeof(ldt_info)) - return -EINVAL; - if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) - return -EFAULT; - - if (ldt_info.entry_number >= IA32_LDT_ENTRIES) - return -EINVAL; - if (ldt_info.contents == 3) { - if (oldmode) - return -EINVAL; - if (ldt_info.seg_not_present == 0) - return -EINVAL; - } - - if (ldt_info.base_addr == 0 && ldt_info.limit == 0 - && (oldmode || (ldt_info.contents == 0 && ldt_info.read_exec_only == 1 - && ldt_info.seg_32bit == 0 && ldt_info.limit_in_pages == 0 - && ldt_info.seg_not_present == 1 && ldt_info.useable == 0))) - /* allow LDTs to be cleared by the user */ - entry = 0; - else - /* we must set the "Accessed" bit as IVE doesn't emulate it */ - entry = IA32_SEG_DESCRIPTOR(ldt_info.base_addr, ldt_info.limit, - (((ldt_info.read_exec_only ^ 1) << 1) - | (ldt_info.contents << 2)) | 1, - 1, 3, ldt_info.seg_not_present ^ 1, - (oldmode ? 0 : ldt_info.useable), - ldt_info.seg_32bit, - ldt_info.limit_in_pages); - /* - * Install the new entry. We know we're accessing valid (mapped) user-level - * memory, but we still need to guard against out-of-memory, hence we must use - * put_user(). - */ - ret = __put_user(entry, (__u64 __user *) IA32_LDT_OFFSET + ldt_info.entry_number); - ia32_load_segment_descriptors(current); - return ret; -} - -asmlinkage int -sys32_modify_ldt (int func, unsigned int ptr, unsigned int bytecount) -{ - int ret = -ENOSYS; - - switch (func) { - case 0: - ret = read_ldt(compat_ptr(ptr), bytecount); - break; - case 1: - ret = write_ldt(compat_ptr(ptr), bytecount, 1); - break; - case 2: - ret = read_default_ldt(compat_ptr(ptr), bytecount); - break; - case 0x11: - ret = write_ldt(compat_ptr(ptr), bytecount, 0); - break; - } - return ret; -} diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c deleted file mode 100644 index b763ca19ef17..000000000000 --- a/arch/ia64/ia32/ia32_signal.c +++ /dev/null @@ -1,1010 +0,0 @@ -/* - * IA32 Architecture-specific signal handling support. - * - * Copyright (C) 1999, 2001-2002, 2005 Hewlett-Packard Co - * David Mosberger-Tang - * Copyright (C) 1999 Arun Sharma - * Copyright (C) 2000 VA Linux Co - * Copyright (C) 2000 Don Dugger - * - * Derived from i386 and Alpha versions. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "ia32priv.h" - -#include "../kernel/sigframe.h" - -#define A(__x) ((unsigned long)(__x)) - -#define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -#define __IA32_NR_sigreturn 119 -#define __IA32_NR_rt_sigreturn 173 - -struct sigframe_ia32 -{ - int pretcode; - int sig; - struct sigcontext_ia32 sc; - struct _fpstate_ia32 fpstate; - unsigned int extramask[_COMPAT_NSIG_WORDS-1]; - char retcode[8]; -}; - -struct rt_sigframe_ia32 -{ - int pretcode; - int sig; - int pinfo; - int puc; - compat_siginfo_t info; - struct ucontext_ia32 uc; - struct _fpstate_ia32 fpstate; - char retcode[8]; -}; - -int -copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from) -{ - unsigned long tmp; - int err; - - if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) - return -EFAULT; - - err = __get_user(to->si_signo, &from->si_signo); - err |= __get_user(to->si_errno, &from->si_errno); - err |= __get_user(to->si_code, &from->si_code); - - if (to->si_code < 0) - err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); - else { - switch (to->si_code >> 16) { - case __SI_CHLD >> 16: - err |= __get_user(to->si_utime, &from->si_utime); - err |= __get_user(to->si_stime, &from->si_stime); - err |= __get_user(to->si_status, &from->si_status); - default: - err |= __get_user(to->si_pid, &from->si_pid); - err |= __get_user(to->si_uid, &from->si_uid); - break; - case __SI_FAULT >> 16: - err |= __get_user(tmp, &from->si_addr); - to->si_addr = (void __user *) tmp; - break; - case __SI_POLL >> 16: - err |= __get_user(to->si_band, &from->si_band); - err |= __get_user(to->si_fd, &from->si_fd); - break; - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: - err |= __get_user(to->si_pid, &from->si_pid); - err |= __get_user(to->si_uid, &from->si_uid); - err |= __get_user(to->si_int, &from->si_int); - break; - } - } - return err; -} - -int -copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from) -{ - unsigned int addr; - int err; - - if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) - return -EFAULT; - - /* If you change siginfo_t structure, please be sure - this code is fixed accordingly. - It should never copy any pad contained in the structure - to avoid security leaks, but must copy the generic - 3 ints plus the relevant union member. - This routine must convert siginfo from 64bit to 32bit as well - at the same time. */ - err = __put_user(from->si_signo, &to->si_signo); - err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); - if (from->si_code < 0) - err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); - else { - switch (from->si_code >> 16) { - case __SI_CHLD >> 16: - err |= __put_user(from->si_utime, &to->si_utime); - err |= __put_user(from->si_stime, &to->si_stime); - err |= __put_user(from->si_status, &to->si_status); - default: - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - break; - case __SI_FAULT >> 16: - /* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */ - err |= __put_user(from->_sifields._pad[0], &to->si_addr); - break; - case __SI_POLL >> 16: - err |= __put_user(from->si_band, &to->si_band); - err |= __put_user(from->si_fd, &to->si_fd); - break; - case __SI_TIMER >> 16: - err |= __put_user(from->si_tid, &to->si_tid); - err |= __put_user(from->si_overrun, &to->si_overrun); - addr = (unsigned long) from->si_ptr; - err |= __put_user(addr, &to->si_ptr); - break; - case __SI_RT >> 16: /* Not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: - err |= __put_user(from->si_uid, &to->si_uid); - err |= __put_user(from->si_pid, &to->si_pid); - addr = (unsigned long) from->si_ptr; - err |= __put_user(addr, &to->si_ptr); - break; - } - } - return err; -} - - -/* - * SAVE and RESTORE of ia32 fpstate info, from ia64 current state - * Used in exception handler to pass the fpstate to the user, and restore - * the fpstate while returning from the exception handler. - * - * fpstate info and their mapping to IA64 regs: - * fpstate REG(BITS) Attribute Comments - * cw ar.fcr(0:12) with bits 7 and 6 not used - * sw ar.fsr(0:15) - * tag ar.fsr(16:31) with odd numbered bits not used - * (read returns 0, writes ignored) - * ipoff ar.fir(0:31) - * cssel ar.fir(32:47) - * dataoff ar.fdr(0:31) - * datasel ar.fdr(32:47) - * - * _st[(0+TOS)%8] f8 - * _st[(1+TOS)%8] f9 - * _st[(2+TOS)%8] f10 - * _st[(3+TOS)%8] f11 (f8..f11 from ptregs) - * : : : (f12..f15 from live reg) - * : : : - * _st[(7+TOS)%8] f15 TOS=sw.top(bits11:13) - * - * status Same as sw RO - * magic 0 as X86_FXSR_MAGIC in ia32 - * mxcsr Bits(7:15)=ar.fcr(39:47) - * Bits(0:5) =ar.fsr(32:37) with bit 6 reserved - * _xmm[0..7] f16..f31 (live registers) - * with _xmm[0] - * Bit(64:127)=f17(0:63) - * Bit(0:63)=f16(0:63) - * All other fields unused... - */ - -static int -save_ia32_fpstate_live (struct _fpstate_ia32 __user *save) -{ - struct task_struct *tsk = current; - struct pt_regs *ptp; - struct _fpreg_ia32 *fpregp; - char buf[32]; - unsigned long fsr, fcr, fir, fdr; - unsigned long new_fsr; - unsigned long num128[2]; - unsigned long mxcsr=0; - int fp_tos, fr8_st_map; - - if (!access_ok(VERIFY_WRITE, save, sizeof(*save))) - return -EFAULT; - - /* Read in fsr, fcr, fir, fdr and copy onto fpstate */ - fsr = ia64_getreg(_IA64_REG_AR_FSR); - fcr = ia64_getreg(_IA64_REG_AR_FCR); - fir = ia64_getreg(_IA64_REG_AR_FIR); - fdr = ia64_getreg(_IA64_REG_AR_FDR); - - /* - * We need to clear the exception state before calling the signal handler. Clear - * the bits 15, bits 0-7 in fp status word. Similar to the functionality of fnclex - * instruction. - */ - new_fsr = fsr & ~0x80ff; - ia64_setreg(_IA64_REG_AR_FSR, new_fsr); - - __put_user(fcr & 0xffff, &save->cw); - __put_user(fsr & 0xffff, &save->sw); - __put_user((fsr>>16) & 0xffff, &save->tag); - __put_user(fir, &save->ipoff); - __put_user((fir>>32) & 0xffff, &save->cssel); - __put_user(fdr, &save->dataoff); - __put_user((fdr>>32) & 0xffff, &save->datasel); - __put_user(fsr & 0xffff, &save->status); - - mxcsr = ((fcr>>32) & 0xff80) | ((fsr>>32) & 0x3f); - __put_user(mxcsr & 0xffff, &save->mxcsr); - __put_user( 0, &save->magic); //#define X86_FXSR_MAGIC 0x0000 - - /* - * save f8..f11 from pt_regs - * save f12..f15 from live register set - */ - /* - * Find the location where f8 has to go in fp reg stack. This depends on - * TOP(11:13) field of sw. Other f reg continue sequentially from where f8 maps - * to. - */ - fp_tos = (fsr>>11)&0x7; - fr8_st_map = (8-fp_tos)&0x7; - ptp = task_pt_regs(tsk); - fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); - ia64f2ia32f(fpregp, &ptp->f8); - copy_to_user(&save->_st[(0+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); - ia64f2ia32f(fpregp, &ptp->f9); - copy_to_user(&save->_st[(1+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); - ia64f2ia32f(fpregp, &ptp->f10); - copy_to_user(&save->_st[(2+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); - ia64f2ia32f(fpregp, &ptp->f11); - copy_to_user(&save->_st[(3+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); - - ia64_stfe(fpregp, 12); - copy_to_user(&save->_st[(4+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); - ia64_stfe(fpregp, 13); - copy_to_user(&save->_st[(5+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); - ia64_stfe(fpregp, 14); - copy_to_user(&save->_st[(6+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); - ia64_stfe(fpregp, 15); - copy_to_user(&save->_st[(7+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); - - ia64_stf8(&num128[0], 16); - ia64_stf8(&num128[1], 17); - copy_to_user(&save->_xmm[0], num128, sizeof(struct _xmmreg_ia32)); - - ia64_stf8(&num128[0], 18); - ia64_stf8(&num128[1], 19); - copy_to_user(&save->_xmm[1], num128, sizeof(struct _xmmreg_ia32)); - - ia64_stf8(&num128[0], 20); - ia64_stf8(&num128[1], 21); - copy_to_user(&save->_xmm[2], num128, sizeof(struct _xmmreg_ia32)); - - ia64_stf8(&num128[0], 22); - ia64_stf8(&num128[1], 23); - copy_to_user(&save->_xmm[3], num128, sizeof(struct _xmmreg_ia32)); - - ia64_stf8(&num128[0], 24); - ia64_stf8(&num128[1], 25); - copy_to_user(&save->_xmm[4], num128, sizeof(struct _xmmreg_ia32)); - - ia64_stf8(&num128[0], 26); - ia64_stf8(&num128[1], 27); - copy_to_user(&save->_xmm[5], num128, sizeof(struct _xmmreg_ia32)); - - ia64_stf8(&num128[0], 28); - ia64_stf8(&num128[1], 29); - copy_to_user(&save->_xmm[6], num128, sizeof(struct _xmmreg_ia32)); - - ia64_stf8(&num128[0], 30); - ia64_stf8(&num128[1], 31); - copy_to_user(&save->_xmm[7], num128, sizeof(struct _xmmreg_ia32)); - return 0; -} - -static int -restore_ia32_fpstate_live (struct _fpstate_ia32 __user *save) -{ - struct task_struct *tsk = current; - struct pt_regs *ptp; - unsigned int lo, hi; - unsigned long num128[2]; - unsigned long num64, mxcsr; - struct _fpreg_ia32 *fpregp; - char buf[32]; - unsigned long fsr, fcr, fir, fdr; - int fp_tos, fr8_st_map; - - if (!access_ok(VERIFY_READ, save, sizeof(*save))) - return(-EFAULT); - - /* - * Updating fsr, fcr, fir, fdr. - * Just a bit more complicated than save. - * - Need to make sure that we don't write any value other than the - * specific fpstate info - * - Need to make sure that the untouched part of frs, fdr, fir, fcr - * should remain same while writing. - * So, we do a read, change specific fields and write. - */ - fsr = ia64_getreg(_IA64_REG_AR_FSR); - fcr = ia64_getreg(_IA64_REG_AR_FCR); - fir = ia64_getreg(_IA64_REG_AR_FIR); - fdr = ia64_getreg(_IA64_REG_AR_FDR); - - __get_user(mxcsr, (unsigned int __user *)&save->mxcsr); - /* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */ - __get_user(lo, (unsigned int __user *)&save->cw); - num64 = mxcsr & 0xff10; - num64 = (num64 << 32) | (lo & 0x1f3f); - fcr = (fcr & (~0xff1000001f3fUL)) | num64; - - /* setting bits 0..31 with sw and tag and 32..37 from mxcsr */ - __get_user(lo, (unsigned int __user *)&save->sw); - /* set bits 15,7 (fsw.b, fsw.es) to reflect the current error status */ - if ( !(lo & 0x7f) ) - lo &= (~0x8080); - __get_user(hi, (unsigned int __user *)&save->tag); - num64 = mxcsr & 0x3f; - num64 = (num64 << 16) | (hi & 0xffff); - num64 = (num64 << 16) | (lo & 0xffff); - fsr = (fsr & (~0x3fffffffffUL)) | num64; - - /* setting bits 0..47 with cssel and ipoff */ - __get_user(lo, (unsigned int __user *)&save->ipoff); - __get_user(hi, (unsigned int __user *)&save->cssel); - num64 = hi & 0xffff; - num64 = (num64 << 32) | lo; - fir = (fir & (~0xffffffffffffUL)) | num64; - - /* setting bits 0..47 with datasel and dataoff */ - __get_user(lo, (unsigned int __user *)&save->dataoff); - __get_user(hi, (unsigned int __user *)&save->datasel); - num64 = hi & 0xffff; - num64 = (num64 << 32) | lo; - fdr = (fdr & (~0xffffffffffffUL)) | num64; - - ia64_setreg(_IA64_REG_AR_FSR, fsr); - ia64_setreg(_IA64_REG_AR_FCR, fcr); - ia64_setreg(_IA64_REG_AR_FIR, fir); - ia64_setreg(_IA64_REG_AR_FDR, fdr); - - /* - * restore f8..f11 onto pt_regs - * restore f12..f15 onto live registers - */ - /* - * Find the location where f8 has to go in fp reg stack. This depends on - * TOP(11:13) field of sw. Other f reg continue sequentially from where f8 maps - * to. - */ - fp_tos = (fsr>>11)&0x7; - fr8_st_map = (8-fp_tos)&0x7; - fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); - - ptp = task_pt_regs(tsk); - copy_from_user(fpregp, &save->_st[(0+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); - ia32f2ia64f(&ptp->f8, fpregp); - copy_from_user(fpregp, &save->_st[(1+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); - ia32f2ia64f(&ptp->f9, fpregp); - copy_from_user(fpregp, &save->_st[(2+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); - ia32f2ia64f(&ptp->f10, fpregp); - copy_from_user(fpregp, &save->_st[(3+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); - ia32f2ia64f(&ptp->f11, fpregp); - - copy_from_user(fpregp, &save->_st[(4+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); - ia64_ldfe(12, fpregp); - copy_from_user(fpregp, &save->_st[(5+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); - ia64_ldfe(13, fpregp); - copy_from_user(fpregp, &save->_st[(6+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); - ia64_ldfe(14, fpregp); - copy_from_user(fpregp, &save->_st[(7+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); - ia64_ldfe(15, fpregp); - - copy_from_user(num128, &save->_xmm[0], sizeof(struct _xmmreg_ia32)); - ia64_ldf8(16, &num128[0]); - ia64_ldf8(17, &num128[1]); - - copy_from_user(num128, &save->_xmm[1], sizeof(struct _xmmreg_ia32)); - ia64_ldf8(18, &num128[0]); - ia64_ldf8(19, &num128[1]); - - copy_from_user(num128, &save->_xmm[2], sizeof(struct _xmmreg_ia32)); - ia64_ldf8(20, &num128[0]); - ia64_ldf8(21, &num128[1]); - - copy_from_user(num128, &save->_xmm[3], sizeof(struct _xmmreg_ia32)); - ia64_ldf8(22, &num128[0]); - ia64_ldf8(23, &num128[1]); - - copy_from_user(num128, &save->_xmm[4], sizeof(struct _xmmreg_ia32)); - ia64_ldf8(24, &num128[0]); - ia64_ldf8(25, &num128[1]); - - copy_from_user(num128, &save->_xmm[5], sizeof(struct _xmmreg_ia32)); - ia64_ldf8(26, &num128[0]); - ia64_ldf8(27, &num128[1]); - - copy_from_user(num128, &save->_xmm[6], sizeof(struct _xmmreg_ia32)); - ia64_ldf8(28, &num128[0]); - ia64_ldf8(29, &num128[1]); - - copy_from_user(num128, &save->_xmm[7], sizeof(struct _xmmreg_ia32)); - ia64_ldf8(30, &num128[0]); - ia64_ldf8(31, &num128[1]); - return 0; -} - -static inline void -sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int restorer) -{ - if (handler + 1 <= 2) - /* SIG_DFL, SIG_IGN, or SIG_ERR: must sign-extend to 64-bits */ - sa->sa.sa_handler = (__sighandler_t) A((int) handler); - else - sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); -} - -asmlinkage long -sys32_sigsuspend (int history0, int history1, old_sigset_t mask) -{ - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_restore_sigmask(); - return -ERESTARTNOHAND; -} - -asmlinkage long -sys32_signal (int sig, unsigned int handler) -{ - struct k_sigaction new_sa, old_sa; - int ret; - - sigact_set_handler(&new_sa, handler, 0); - new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK; - sigemptyset(&new_sa.sa.sa_mask); - - ret = do_sigaction(sig, &new_sa, &old_sa); - - return ret ? ret : IA32_SA_HANDLER(&old_sa); -} - -asmlinkage long -sys32_rt_sigaction (int sig, struct sigaction32 __user *act, - struct sigaction32 __user *oact, unsigned int sigsetsize) -{ - struct k_sigaction new_ka, old_ka; - unsigned int handler, restorer; - int ret; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(compat_sigset_t)) - return -EINVAL; - - if (act) { - ret = get_user(handler, &act->sa_handler); - ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); - ret |= get_user(restorer, &act->sa_restorer); - ret |= copy_from_user(&new_ka.sa.sa_mask, &act->sa_mask, sizeof(compat_sigset_t)); - if (ret) - return -EFAULT; - - sigact_set_handler(&new_ka, handler, restorer); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler); - ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); - ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer); - ret |= copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask, sizeof(compat_sigset_t)); - } - return ret; -} - - -asmlinkage long -sys32_rt_sigprocmask (int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, - unsigned int sigsetsize) -{ - mm_segment_t old_fs = get_fs(); - sigset_t s; - long ret; - - if (sigsetsize > sizeof(s)) - return -EINVAL; - - if (set) { - memset(&s, 0, sizeof(s)); - if (copy_from_user(&s.sig, set, sigsetsize)) - return -EFAULT; - } - set_fs(KERNEL_DS); - ret = sys_rt_sigprocmask(how, - set ? (sigset_t __user *) &s : NULL, - oset ? (sigset_t __user *) &s : NULL, sizeof(s)); - set_fs(old_fs); - if (ret) - return ret; - if (oset) { - if (copy_to_user(oset, &s.sig, sigsetsize)) - return -EFAULT; - } - return 0; -} - -asmlinkage long -sys32_rt_sigqueueinfo (int pid, int sig, compat_siginfo_t __user *uinfo) -{ - mm_segment_t old_fs = get_fs(); - siginfo_t info; - int ret; - - if (copy_siginfo_from_user32(&info, uinfo)) - return -EFAULT; - set_fs(KERNEL_DS); - ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); - set_fs(old_fs); - return ret; -} - -asmlinkage long -sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact) -{ - struct k_sigaction new_ka, old_ka; - unsigned int handler, restorer; - int ret; - - if (act) { - compat_old_sigset_t mask; - - ret = get_user(handler, &act->sa_handler); - ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); - ret |= get_user(restorer, &act->sa_restorer); - ret |= get_user(mask, &act->sa_mask); - if (ret) - return ret; - - sigact_set_handler(&new_ka, handler, restorer); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler); - ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); - ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer); - ret |= put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -static int -setup_sigcontext_ia32 (struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __user *fpstate, - struct pt_regs *regs, unsigned long mask) -{ - int err = 0; - unsigned long flag; - - if (!access_ok(VERIFY_WRITE, sc, sizeof(*sc))) - return -EFAULT; - - err |= __put_user((regs->r16 >> 32) & 0xffff, (unsigned int __user *)&sc->fs); - err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int __user *)&sc->gs); - err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int __user *)&sc->es); - err |= __put_user(regs->r16 & 0xffff, (unsigned int __user *)&sc->ds); - err |= __put_user(regs->r15, &sc->edi); - err |= __put_user(regs->r14, &sc->esi); - err |= __put_user(regs->r13, &sc->ebp); - err |= __put_user(regs->r12, &sc->esp); - err |= __put_user(regs->r11, &sc->ebx); - err |= __put_user(regs->r10, &sc->edx); - err |= __put_user(regs->r9, &sc->ecx); - err |= __put_user(regs->r8, &sc->eax); -#if 0 - err |= __put_user(current->tss.trap_no, &sc->trapno); - err |= __put_user(current->tss.error_code, &sc->err); -#endif - err |= __put_user(regs->cr_iip, &sc->eip); - err |= __put_user(regs->r17 & 0xffff, (unsigned int __user *)&sc->cs); - /* - * `eflags' is in an ar register for this context - */ - flag = ia64_getreg(_IA64_REG_AR_EFLAG); - err |= __put_user((unsigned int)flag, &sc->eflags); - err |= __put_user(regs->r12, &sc->esp_at_signal); - err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int __user *)&sc->ss); - - if ( save_ia32_fpstate_live(fpstate) < 0 ) - err = -EFAULT; - else - err |= __put_user((u32)(u64)fpstate, &sc->fpstate); - -#if 0 - tmp = save_i387(fpstate); - if (tmp < 0) - err = 1; - else - err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate); - - /* non-iBCS2 extensions.. */ -#endif - err |= __put_user(mask, &sc->oldmask); -#if 0 - err |= __put_user(current->tss.cr2, &sc->cr2); -#endif - return err; -} - -static int -restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 __user *sc, int *peax) -{ - unsigned int err = 0; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - if (!access_ok(VERIFY_READ, sc, sizeof(*sc))) - return(-EFAULT); - -#define COPY(ia64x, ia32x) err |= __get_user(regs->ia64x, &sc->ia32x) - -#define copyseg_gs(tmp) (regs->r16 |= (unsigned long) (tmp) << 48) -#define copyseg_fs(tmp) (regs->r16 |= (unsigned long) (tmp) << 32) -#define copyseg_cs(tmp) (regs->r17 |= tmp) -#define copyseg_ss(tmp) (regs->r17 |= (unsigned long) (tmp) << 16) -#define copyseg_es(tmp) (regs->r16 |= (unsigned long) (tmp) << 16) -#define copyseg_ds(tmp) (regs->r16 |= tmp) - -#define COPY_SEG(seg) \ - { \ - unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ - copyseg_##seg(tmp); \ - } -#define COPY_SEG_STRICT(seg) \ - { \ - unsigned short tmp; \ - err |= __get_user(tmp, &sc->seg); \ - copyseg_##seg(tmp|3); \ - } - - /* To make COPY_SEGs easier, we zero r16, r17 */ - regs->r16 = 0; - regs->r17 = 0; - - COPY_SEG(gs); - COPY_SEG(fs); - COPY_SEG(es); - COPY_SEG(ds); - COPY(r15, edi); - COPY(r14, esi); - COPY(r13, ebp); - COPY(r12, esp); - COPY(r11, ebx); - COPY(r10, edx); - COPY(r9, ecx); - COPY(cr_iip, eip); - COPY_SEG_STRICT(cs); - COPY_SEG_STRICT(ss); - ia32_load_segment_descriptors(current); - { - unsigned int tmpflags; - unsigned long flag; - - /* - * IA32 `eflags' is not part of `pt_regs', it's in an ar register which - * is part of the thread context. Fortunately, we are executing in the - * IA32 process's context. - */ - err |= __get_user(tmpflags, &sc->eflags); - flag = ia64_getreg(_IA64_REG_AR_EFLAG); - flag &= ~0x40DD5; - flag |= (tmpflags & 0x40DD5); - ia64_setreg(_IA64_REG_AR_EFLAG, flag); - - regs->r1 = -1; /* disable syscall checks, r1 is orig_eax */ - } - - { - struct _fpstate_ia32 __user *buf = NULL; - u32 fpstate_ptr; - err |= get_user(fpstate_ptr, &(sc->fpstate)); - buf = compat_ptr(fpstate_ptr); - if (buf) { - err |= restore_ia32_fpstate_live(buf); - } - } - -#if 0 - { - struct _fpstate * buf; - err |= __get_user(buf, &sc->fpstate); - if (buf) { - if (!access_ok(VERIFY_READ, buf, sizeof(*buf))) - goto badframe; - err |= restore_i387(buf); - } - } -#endif - - err |= __get_user(*peax, &sc->eax); - return err; - -#if 0 - badframe: - return 1; -#endif -} - -/* - * Determine which stack to use.. - */ -static inline void __user * -get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) -{ - unsigned long esp; - - /* Default to using normal stack (truncate off sign-extension of bit 31: */ - esp = (unsigned int) regs->r12; - - /* This is the X/Open sanctioned signal stack switching. */ - if (ka->sa.sa_flags & SA_ONSTACK) { - int onstack = sas_ss_flags(esp); - - if (onstack == 0) - esp = current->sas_ss_sp + current->sas_ss_size; - else if (onstack == SS_ONSTACK) { - /* - * If we are on the alternate signal stack and would - * overflow it, don't. Return an always-bogus address - * instead so we will die with SIGSEGV. - */ - if (!likely(on_sig_stack(esp - frame_size))) - return (void __user *) -1L; - } - } - /* Legacy stack switching not supported */ - - esp -= frame_size; - /* Align the stack pointer according to the i386 ABI, - * i.e. so that on function entry ((sp + 4) & 15) == 0. */ - esp = ((esp + 4) & -16ul) - 4; - return (void __user *) esp; -} - -static int -setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) -{ - struct exec_domain *ed = current_thread_info()->exec_domain; - struct sigframe_ia32 __user *frame; - int err = 0; - - frame = get_sigframe(ka, regs, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - err |= __put_user((ed && ed->signal_invmap && sig < 32 - ? (int)(ed->signal_invmap[sig]) : sig), &frame->sig); - - err |= setup_sigcontext_ia32(&frame->sc, &frame->fpstate, regs, set->sig[0]); - - if (_COMPAT_NSIG_WORDS > 1) - err |= __copy_to_user(frame->extramask, (char *) &set->sig + 4, - sizeof(frame->extramask)); - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - unsigned int restorer = IA32_SA_RESTORER(ka); - err |= __put_user(restorer, &frame->pretcode); - } else { - /* Pointing to restorer in ia32 gate page */ - err |= __put_user(IA32_GATE_OFFSET, &frame->pretcode); - } - - /* This is popl %eax ; movl $,%eax ; int $0x80 - * and there for historical reasons only. - * See arch/i386/kernel/signal.c - */ - - err |= __put_user(0xb858, (short __user *)(frame->retcode+0)); - err |= __put_user(__IA32_NR_sigreturn, (int __user *)(frame->retcode+2)); - err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); - - if (err) - goto give_sigsegv; - - /* Set up registers for signal handler */ - regs->r12 = (unsigned long) frame; - regs->cr_iip = IA32_SA_HANDLER(ka); - - set_fs(USER_DS); - -#if 0 - regs->eflags &= ~TF_MASK; -#endif - -#if 0 - printk("SIG deliver (%s:%d): sig=%d sp=%p pc=%lx ra=%x\n", - current->comm, current->pid, sig, (void *) frame, regs->cr_iip, frame->pretcode); -#endif - - return 1; - - give_sigsegv: - force_sigsegv(sig, current); - return 0; -} - -static int -setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs * regs) -{ - struct exec_domain *ed = current_thread_info()->exec_domain; - compat_uptr_t pinfo, puc; - struct rt_sigframe_ia32 __user *frame; - int err = 0; - - frame = get_sigframe(ka, regs, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - err |= __put_user((ed && ed->signal_invmap - && sig < 32 ? ed->signal_invmap[sig] : sig), &frame->sig); - - pinfo = (long __user) &frame->info; - puc = (long __user) &frame->uc; - err |= __put_user(pinfo, &frame->pinfo); - err |= __put_user(puc, &frame->puc); - err |= copy_siginfo_to_user32(&frame->info, info); - - /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->r12), &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext_ia32(&frame->uc.uc_mcontext, &frame->fpstate, regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - if (err) - goto give_sigsegv; - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - unsigned int restorer = IA32_SA_RESTORER(ka); - err |= __put_user(restorer, &frame->pretcode); - } else { - /* Pointing to rt_restorer in ia32 gate page */ - err |= __put_user(IA32_GATE_OFFSET + 8, &frame->pretcode); - } - - /* This is movl $,%eax ; int $0x80 - * and there for historical reasons only. - * See arch/i386/kernel/signal.c - */ - - err |= __put_user(0xb8, (char __user *)(frame->retcode+0)); - err |= __put_user(__IA32_NR_rt_sigreturn, (int __user *)(frame->retcode+1)); - err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); - - if (err) - goto give_sigsegv; - - /* Set up registers for signal handler */ - regs->r12 = (unsigned long) frame; - regs->cr_iip = IA32_SA_HANDLER(ka); - - set_fs(USER_DS); - -#if 0 - regs->eflags &= ~TF_MASK; -#endif - -#if 0 - printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n", - current->comm, current->pid, (void *) frame, regs->cr_iip, frame->pretcode); -#endif - - return 1; - -give_sigsegv: - force_sigsegv(sig, current); - return 0; -} - -int -ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) -{ - /* Set up the stack frame */ - if (ka->sa.sa_flags & SA_SIGINFO) - return setup_rt_frame_ia32(sig, ka, info, set, regs); - else - return setup_frame_ia32(sig, ka, set, regs); -} - -asmlinkage long -sys32_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, - int arg6, int arg7, struct pt_regs regs) -{ - unsigned long esp = (unsigned int) regs.r12; - struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(esp - 8); - sigset_t set; - int eax; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_COMPAT_NSIG_WORDS > 1 && __copy_from_user((char *) &set.sig + 4, &frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext_ia32(®s, &frame->sc, &eax)) - goto badframe; - return eax; - - badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage long -sys32_rt_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, - int arg5, int arg6, int arg7, struct pt_regs regs) -{ - unsigned long esp = (unsigned int) regs.r12; - struct rt_sigframe_ia32 __user *frame = (struct rt_sigframe_ia32 __user *)(esp - 4); - sigset_t set; - int eax; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) - goto badframe; - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext_ia32(®s, &frame->uc.uc_mcontext, &eax)) - goto badframe; - - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - do_sigaltstack((stack_t __user *) &frame->uc.uc_stack, NULL, esp); - - return eax; - - badframe: - force_sig(SIGSEGV, current); - return 0; -} diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c deleted file mode 100644 index a6965ddafc46..000000000000 --- a/arch/ia64/ia32/ia32_support.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * IA32 helper functions - * - * Copyright (C) 1999 Arun Sharma - * Copyright (C) 2000 Asit K. Mallick - * Copyright (C) 2001-2002 Hewlett-Packard Co - * David Mosberger-Tang - * - * 06/16/00 A. Mallick added csd/ssd/tssd for ia32 thread context - * 02/19/01 D. Mosberger dropped tssd; it's not needed - * 09/14/01 D. Mosberger fixed memory management for gdt/tss page - * 09/29/01 D. Mosberger added ia32_load_segment_descriptors() - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "ia32priv.h" - -extern int die_if_kernel (char *str, struct pt_regs *regs, long err); - -struct page *ia32_shared_page[NR_CPUS]; -unsigned long *ia32_boot_gdt; -unsigned long *cpu_gdt_table[NR_CPUS]; -struct page *ia32_gate_page; - -static unsigned long -load_desc (u16 selector) -{ - unsigned long *table, limit, index; - - if (!selector) - return 0; - if (selector & IA32_SEGSEL_TI) { - table = (unsigned long *) IA32_LDT_OFFSET; - limit = IA32_LDT_ENTRIES; - } else { - table = cpu_gdt_table[smp_processor_id()]; - limit = IA32_PAGE_SIZE / sizeof(ia32_boot_gdt[0]); - } - index = selector >> IA32_SEGSEL_INDEX_SHIFT; - if (index >= limit) - return 0; - return IA32_SEG_UNSCRAMBLE(table[index]); -} - -void -ia32_load_segment_descriptors (struct task_struct *task) -{ - struct pt_regs *regs = task_pt_regs(task); - - /* Setup the segment descriptors */ - regs->r24 = load_desc(regs->r16 >> 16); /* ESD */ - regs->r27 = load_desc(regs->r16 >> 0); /* DSD */ - regs->r28 = load_desc(regs->r16 >> 32); /* FSD */ - regs->r29 = load_desc(regs->r16 >> 48); /* GSD */ - regs->ar_csd = load_desc(regs->r17 >> 0); /* CSD */ - regs->ar_ssd = load_desc(regs->r17 >> 16); /* SSD */ -} - -int -ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs) -{ - struct desc_struct *desc; - struct ia32_user_desc info; - int idx; - - if (copy_from_user(&info, (void __user *)(childregs->r14 & 0xffffffff), sizeof(info))) - return -EFAULT; - if (LDT_empty(&info)) - return -EINVAL; - - idx = info.entry_number; - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; - desc->a = LDT_entry_a(&info); - desc->b = LDT_entry_b(&info); - - /* XXX: can this be done in a cleaner way ? */ - load_TLS(&child->thread, smp_processor_id()); - ia32_load_segment_descriptors(child); - load_TLS(¤t->thread, smp_processor_id()); - - return 0; -} - -void -ia32_save_state (struct task_struct *t) -{ - t->thread.eflag = ia64_getreg(_IA64_REG_AR_EFLAG); - t->thread.fsr = ia64_getreg(_IA64_REG_AR_FSR); - t->thread.fcr = ia64_getreg(_IA64_REG_AR_FCR); - t->thread.fir = ia64_getreg(_IA64_REG_AR_FIR); - t->thread.fdr = ia64_getreg(_IA64_REG_AR_FDR); - ia64_set_kr(IA64_KR_IO_BASE, t->thread.old_iob); - ia64_set_kr(IA64_KR_TSSD, t->thread.old_k1); -} - -void -ia32_load_state (struct task_struct *t) -{ - unsigned long eflag, fsr, fcr, fir, fdr, tssd; - struct pt_regs *regs = task_pt_regs(t); - - eflag = t->thread.eflag; - fsr = t->thread.fsr; - fcr = t->thread.fcr; - fir = t->thread.fir; - fdr = t->thread.fdr; - tssd = load_desc(_TSS); /* TSSD */ - - ia64_setreg(_IA64_REG_AR_EFLAG, eflag); - ia64_setreg(_IA64_REG_AR_FSR, fsr); - ia64_setreg(_IA64_REG_AR_FCR, fcr); - ia64_setreg(_IA64_REG_AR_FIR, fir); - ia64_setreg(_IA64_REG_AR_FDR, fdr); - current->thread.old_iob = ia64_get_kr(IA64_KR_IO_BASE); - current->thread.old_k1 = ia64_get_kr(IA64_KR_TSSD); - ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE); - ia64_set_kr(IA64_KR_TSSD, tssd); - - regs->r17 = (_TSS << 48) | (_LDT << 32) | (__u32) regs->r17; - regs->r30 = load_desc(_LDT); /* LDTD */ - load_TLS(&t->thread, smp_processor_id()); -} - -/* - * Setup IA32 GDT and TSS - */ -void -ia32_gdt_init (void) -{ - int cpu = smp_processor_id(); - - ia32_shared_page[cpu] = alloc_page(GFP_KERNEL); - if (!ia32_shared_page[cpu]) - panic("failed to allocate ia32_shared_page[%d]\n", cpu); - - cpu_gdt_table[cpu] = page_address(ia32_shared_page[cpu]); - - /* Copy from the boot cpu's GDT */ - memcpy(cpu_gdt_table[cpu], ia32_boot_gdt, PAGE_SIZE); -} - - -/* - * Setup IA32 GDT and TSS - */ -static void -ia32_boot_gdt_init (void) -{ - unsigned long ldt_size; - - ia32_shared_page[0] = alloc_page(GFP_KERNEL); - if (!ia32_shared_page[0]) - panic("failed to allocate ia32_shared_page[0]\n"); - - ia32_boot_gdt = page_address(ia32_shared_page[0]); - cpu_gdt_table[0] = ia32_boot_gdt; - - /* CS descriptor in IA-32 (scrambled) format */ - ia32_boot_gdt[__USER_CS >> 3] - = IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT, - 0xb, 1, 3, 1, 1, 1, 1); - - /* DS descriptor in IA-32 (scrambled) format */ - ia32_boot_gdt[__USER_DS >> 3] - = IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT, - 0x3, 1, 3, 1, 1, 1, 1); - - ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE); - ia32_boot_gdt[TSS_ENTRY] = IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235, - 0xb, 0, 3, 1, 1, 1, 0); - ia32_boot_gdt[LDT_ENTRY] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1, - 0x2, 0, 3, 1, 1, 1, 0); -} - -static void -ia32_gate_page_init(void) -{ - unsigned long *sr; - - ia32_gate_page = alloc_page(GFP_KERNEL); - sr = page_address(ia32_gate_page); - /* This is popl %eax ; movl $,%eax ; int $0x80 */ - *sr++ = 0xb858 | (__IA32_NR_sigreturn << 16) | (0x80cdUL << 48); - - /* This is movl $,%eax ; int $0x80 */ - *sr = 0xb8 | (__IA32_NR_rt_sigreturn << 8) | (0x80cdUL << 40); -} - -void -ia32_mem_init(void) -{ - ia32_boot_gdt_init(); - ia32_gate_page_init(); -} - -/* - * Handle bad IA32 interrupt via syscall - */ -void -ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs) -{ - siginfo_t siginfo; - - if (die_if_kernel("Bad IA-32 interrupt", regs, int_num)) - return; - - siginfo.si_signo = SIGTRAP; - siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */ - siginfo.si_flags = 0; - siginfo.si_isr = 0; - siginfo.si_addr = NULL; - siginfo.si_imm = 0; - siginfo.si_code = TRAP_BRKPT; - force_sig_info(SIGTRAP, &siginfo, current); -} - -void -ia32_cpu_init (void) -{ - /* initialize global ia32 state - CR0 and CR4 */ - ia64_setreg(_IA64_REG_AR_CFLAG, (((ulong) IA32_CR4 << 32) | IA32_CR0)); -} - -static int __init -ia32_init (void) -{ -#if PAGE_SHIFT > IA32_PAGE_SHIFT - { - extern struct kmem_cache *ia64_partial_page_cachep; - - ia64_partial_page_cachep = kmem_cache_create("ia64_partial_page_cache", - sizeof(struct ia64_partial_page), - 0, SLAB_PANIC, NULL); - } -#endif - return 0; -} - -__initcall(ia32_init); diff --git a/arch/ia64/ia32/ia32_traps.c b/arch/ia64/ia32/ia32_traps.c deleted file mode 100644 index e486042672f1..000000000000 --- a/arch/ia64/ia32/ia32_traps.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * IA-32 exception handlers - * - * Copyright (C) 2000 Asit K. Mallick - * Copyright (C) 2001-2002 Hewlett-Packard Co - * David Mosberger-Tang - * - * 06/16/00 A. Mallick added siginfo for most cases (close to IA32) - * 09/29/00 D. Mosberger added ia32_intercept() - */ - -#include -#include - -#include "ia32priv.h" - -#include -#include - -int -ia32_intercept (struct pt_regs *regs, unsigned long isr) -{ - switch ((isr >> 16) & 0xff) { - case 0: /* Instruction intercept fault */ - case 4: /* Locked Data reference fault */ - case 1: /* Gate intercept trap */ - return -1; - - case 2: /* System flag trap */ - if (((isr >> 14) & 0x3) >= 2) { - /* MOV SS, POP SS instructions */ - ia64_psr(regs)->id = 1; - return 0; - } else - return -1; - } - return -1; -} - -int -ia32_exception (struct pt_regs *regs, unsigned long isr) -{ - struct siginfo siginfo; - - /* initialize these fields to avoid leaking kernel bits to user space: */ - siginfo.si_errno = 0; - siginfo.si_flags = 0; - siginfo.si_isr = 0; - siginfo.si_imm = 0; - switch ((isr >> 16) & 0xff) { - case 1: - case 2: - siginfo.si_signo = SIGTRAP; - if (isr == 0) - siginfo.si_code = TRAP_TRACE; - else if (isr & 0x4) - siginfo.si_code = TRAP_BRANCH; - else - siginfo.si_code = TRAP_BRKPT; - break; - - case 3: - siginfo.si_signo = SIGTRAP; - siginfo.si_code = TRAP_BRKPT; - break; - - case 0: /* Divide fault */ - siginfo.si_signo = SIGFPE; - siginfo.si_code = FPE_INTDIV; - break; - - case 4: /* Overflow */ - case 5: /* Bounds fault */ - siginfo.si_signo = SIGFPE; - siginfo.si_code = 0; - break; - - case 6: /* Invalid Op-code */ - siginfo.si_signo = SIGILL; - siginfo.si_code = ILL_ILLOPN; - break; - - case 7: /* FP DNA */ - case 8: /* Double Fault */ - case 9: /* Invalid TSS */ - case 11: /* Segment not present */ - case 12: /* Stack fault */ - case 13: /* General Protection Fault */ - siginfo.si_signo = SIGSEGV; - siginfo.si_code = 0; - break; - - case 16: /* Pending FP error */ - { - unsigned long fsr, fcr; - - fsr = ia64_getreg(_IA64_REG_AR_FSR); - fcr = ia64_getreg(_IA64_REG_AR_FCR); - - siginfo.si_signo = SIGFPE; - /* - * (~cwd & swd) will mask out exceptions that are not set to unmasked - * status. 0x3f is the exception bits in these regs, 0x200 is the - * C1 reg you need in case of a stack fault, 0x040 is the stack - * fault bit. We should only be taking one exception at a time, - * so if this combination doesn't produce any single exception, - * then we have a bad program that isn't synchronizing its FPU usage - * and it will suffer the consequences since we won't be able to - * fully reproduce the context of the exception - */ - siginfo.si_isr = isr; - siginfo.si_flags = __ISR_VALID; - switch(((~fcr) & (fsr & 0x3f)) | (fsr & 0x240)) { - case 0x000: - default: - siginfo.si_code = 0; - break; - case 0x001: /* Invalid Op */ - case 0x040: /* Stack Fault */ - case 0x240: /* Stack Fault | Direction */ - siginfo.si_code = FPE_FLTINV; - break; - case 0x002: /* Denormalize */ - case 0x010: /* Underflow */ - siginfo.si_code = FPE_FLTUND; - break; - case 0x004: /* Zero Divide */ - siginfo.si_code = FPE_FLTDIV; - break; - case 0x008: /* Overflow */ - siginfo.si_code = FPE_FLTOVF; - break; - case 0x020: /* Precision */ - siginfo.si_code = FPE_FLTRES; - break; - } - - break; - } - - case 17: /* Alignment check */ - siginfo.si_signo = SIGSEGV; - siginfo.si_code = BUS_ADRALN; - break; - - case 19: /* SSE Numeric error */ - siginfo.si_signo = SIGFPE; - siginfo.si_code = 0; - break; - - default: - return -1; - } - force_sig_info(siginfo.si_signo, &siginfo, current); - return 0; -} diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h deleted file mode 100644 index 0f15349c3c6b..000000000000 --- a/arch/ia64/ia32/ia32priv.h +++ /dev/null @@ -1,532 +0,0 @@ -#ifndef _ASM_IA64_IA32_PRIV_H -#define _ASM_IA64_IA32_PRIV_H - - -#include - -#ifdef CONFIG_IA32_SUPPORT - -#include -#include -#include - -#include - -/* - * 32 bit structures for IA32 support. - */ - -#define IA32_PAGE_SIZE (1UL << IA32_PAGE_SHIFT) -#define IA32_PAGE_MASK (~(IA32_PAGE_SIZE - 1)) -#define IA32_PAGE_ALIGN(addr) (((addr) + IA32_PAGE_SIZE - 1) & IA32_PAGE_MASK) -#define IA32_CLOCKS_PER_SEC 100 /* Cast in stone for IA32 Linux */ - -/* - * partially mapped pages provide precise accounting of which 4k sub pages - * are mapped and which ones are not, thereby improving IA-32 compatibility. - */ -struct ia64_partial_page { - struct ia64_partial_page *next; /* linked list, sorted by address */ - struct rb_node pp_rb; - /* 64K is the largest "normal" page supported by ia64 ABI. So 4K*64 - * should suffice.*/ - unsigned long bitmap; - unsigned int base; -}; - -struct ia64_partial_page_list { - struct ia64_partial_page *pp_head; /* list head, points to the lowest - * addressed partial page */ - struct rb_root ppl_rb; - struct ia64_partial_page *pp_hint; /* pp_hint->next is the last - * accessed partial page */ - atomic_t pp_count; /* reference count */ -}; - -#if PAGE_SHIFT > IA32_PAGE_SHIFT -struct ia64_partial_page_list* ia32_init_pp_list (void); -#else -# define ia32_init_pp_list() 0 -#endif - -/* sigcontext.h */ -/* - * As documented in the iBCS2 standard.. - * - * The first part of "struct _fpstate" is just the - * normal i387 hardware setup, the extra "status" - * word is used to save the coprocessor status word - * before entering the handler. - */ -struct _fpreg_ia32 { - unsigned short significand[4]; - unsigned short exponent; -}; - -struct _fpxreg_ia32 { - unsigned short significand[4]; - unsigned short exponent; - unsigned short padding[3]; -}; - -struct _xmmreg_ia32 { - unsigned int element[4]; -}; - - -struct _fpstate_ia32 { - unsigned int cw, - sw, - tag, - ipoff, - cssel, - dataoff, - datasel; - struct _fpreg_ia32 _st[8]; - unsigned short status; - unsigned short magic; /* 0xffff = regular FPU data only */ - - /* FXSR FPU environment */ - unsigned int _fxsr_env[6]; /* FXSR FPU env is ignored */ - unsigned int mxcsr; - unsigned int reserved; - struct _fpxreg_ia32 _fxsr_st[8]; /* FXSR FPU reg data is ignored */ - struct _xmmreg_ia32 _xmm[8]; - unsigned int padding[56]; -}; - -struct sigcontext_ia32 { - unsigned short gs, __gsh; - unsigned short fs, __fsh; - unsigned short es, __esh; - unsigned short ds, __dsh; - unsigned int edi; - unsigned int esi; - unsigned int ebp; - unsigned int esp; - unsigned int ebx; - unsigned int edx; - unsigned int ecx; - unsigned int eax; - unsigned int trapno; - unsigned int err; - unsigned int eip; - unsigned short cs, __csh; - unsigned int eflags; - unsigned int esp_at_signal; - unsigned short ss, __ssh; - unsigned int fpstate; /* really (struct _fpstate_ia32 *) */ - unsigned int oldmask; - unsigned int cr2; -}; - -/* user.h */ -/* - * IA32 (Pentium III/4) FXSR, SSE support - * - * Provide support for the GDB 5.0+ PTRACE_{GET|SET}FPXREGS requests for - * interacting with the FXSR-format floating point environment. Floating - * point data can be accessed in the regular format in the usual manner, - * and both the standard and SIMD floating point data can be accessed via - * the new ptrace requests. In either case, changes to the FPU environment - * will be reflected in the task's state as expected. - */ -struct ia32_user_i387_struct { - int cwd; - int swd; - int twd; - int fip; - int fcs; - int foo; - int fos; - /* 8*10 bytes for each FP-reg = 80 bytes */ - struct _fpreg_ia32 st_space[8]; -}; - -struct ia32_user_fxsr_struct { - unsigned short cwd; - unsigned short swd; - unsigned short twd; - unsigned short fop; - int fip; - int fcs; - int foo; - int fos; - int mxcsr; - int reserved; - int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ - int xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ - int padding[56]; -}; - -/* signal.h */ -#define IA32_SET_SA_HANDLER(ka,handler,restorer) \ - ((ka)->sa.sa_handler = (__sighandler_t) \ - (((unsigned long)(restorer) << 32) \ - | ((handler) & 0xffffffff))) -#define IA32_SA_HANDLER(ka) ((unsigned long) (ka)->sa.sa_handler & 0xffffffff) -#define IA32_SA_RESTORER(ka) ((unsigned long) (ka)->sa.sa_handler >> 32) - -#define __IA32_NR_sigreturn 119 -#define __IA32_NR_rt_sigreturn 173 - -struct sigaction32 { - unsigned int sa_handler; /* Really a pointer, but need to deal with 32 bits */ - unsigned int sa_flags; - unsigned int sa_restorer; /* Another 32 bit pointer */ - compat_sigset_t sa_mask; /* A 32 bit mask */ -}; - -struct old_sigaction32 { - unsigned int sa_handler; /* Really a pointer, but need to deal - with 32 bits */ - compat_old_sigset_t sa_mask; /* A 32 bit mask */ - unsigned int sa_flags; - unsigned int sa_restorer; /* Another 32 bit pointer */ -}; - -typedef struct sigaltstack_ia32 { - unsigned int ss_sp; - int ss_flags; - unsigned int ss_size; -} stack_ia32_t; - -struct ucontext_ia32 { - unsigned int uc_flags; - unsigned int uc_link; - stack_ia32_t uc_stack; - struct sigcontext_ia32 uc_mcontext; - sigset_t uc_sigmask; /* mask last for extensibility */ -}; - -struct stat64 { - unsigned long long st_dev; - unsigned char __pad0[4]; - unsigned int __st_ino; - unsigned int st_mode; - unsigned int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - unsigned long long st_rdev; - unsigned char __pad3[4]; - unsigned int st_size_lo; - unsigned int st_size_hi; - unsigned int st_blksize; - unsigned int st_blocks; /* Number 512-byte blocks allocated. */ - unsigned int __pad4; /* future possible st_blocks high bits */ - unsigned int st_atime; - unsigned int st_atime_nsec; - unsigned int st_mtime; - unsigned int st_mtime_nsec; - unsigned int st_ctime; - unsigned int st_ctime_nsec; - unsigned int st_ino_lo; - unsigned int st_ino_hi; -}; - -typedef struct compat_siginfo { - int si_signo; - int si_errno; - int si_code; - - union { - int _pad[((128/sizeof(int)) - 3)]; - - /* kill() */ - struct { - unsigned int _pid; /* sender's pid */ - unsigned int _uid; /* sender's uid */ - } _kill; - - /* POSIX.1b timers */ - struct { - compat_timer_t _tid; /* timer id */ - int _overrun; /* overrun count */ - char _pad[sizeof(unsigned int) - sizeof(int)]; - compat_sigval_t _sigval; /* same as below */ - int _sys_private; /* not to be passed to user */ - } _timer; - - /* POSIX.1b signals */ - struct { - unsigned int _pid; /* sender's pid */ - unsigned int _uid; /* sender's uid */ - compat_sigval_t _sigval; - } _rt; - - /* SIGCHLD */ - struct { - unsigned int _pid; /* which child */ - unsigned int _uid; /* sender's uid */ - int _status; /* exit code */ - compat_clock_t _utime; - compat_clock_t _stime; - } _sigchld; - - /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ - struct { - unsigned int _addr; /* faulting insn/memory ref. */ - } _sigfault; - - /* SIGPOLL */ - struct { - int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ - int _fd; - } _sigpoll; - } _sifields; -} compat_siginfo_t; - -/* - * IA-32 ELF specific definitions for IA-64. - */ - -#define _ASM_IA64_ELF_H /* Don't include elf.h */ - -#include - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) ((x)->e_machine == EM_386) - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS32 -#define ELF_DATA ELFDATA2LSB -#define ELF_ARCH EM_386 - -#define IA32_STACK_TOP IA32_PAGE_OFFSET -#define IA32_GATE_OFFSET IA32_PAGE_OFFSET -#define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE - -/* - * The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the IA-32 engine can - * access them. - */ -#define IA32_GDT_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE) -#define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE) -#define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 3*PAGE_SIZE) - -#define ELF_EXEC_PAGESIZE IA32_PAGE_SIZE - -/* - * This is the location that an ET_DYN program is loaded if exec'ed. - * Typical use of this is to invoke "./ld.so someprog" to test out a - * new version of the loader. We need to make sure that it is out of - * the way of the program that it will "exec", and that there is - * sufficient room for the brk. - */ -#define ELF_ET_DYN_BASE (IA32_PAGE_OFFSET/3 + 0x1000000) - -void ia64_elf32_init(struct pt_regs *regs); -#define ELF_PLAT_INIT(_r, load_addr) ia64_elf32_init(_r) - -/* This macro yields a bitmask that programs can use to figure out - what instruction set this CPU supports. */ -#define ELF_HWCAP 0 - -/* This macro yields a string that ld.so will use to load - implementation specific libraries for optimization. Not terribly - relevant until we have real hardware to play with... */ -#define ELF_PLATFORM NULL - -#ifdef __KERNEL__ -# define SET_PERSONALITY(EX) \ - (current->personality = PER_LINUX) -#endif - -#define IA32_EFLAG 0x200 - -/* - * IA-32 ELF specific definitions for IA-64. - */ - -#define __USER_CS 0x23 -#define __USER_DS 0x2B - -/* - * The per-cpu GDT has 32 entries: see - */ -#define GDT_ENTRIES 32 - -#define GDT_SIZE (GDT_ENTRIES * 8) - -#define TSS_ENTRY 14 -#define LDT_ENTRY (TSS_ENTRY + 1) - -#define IA32_SEGSEL_RPL (0x3 << 0) -#define IA32_SEGSEL_TI (0x1 << 2) -#define IA32_SEGSEL_INDEX_SHIFT 3 - -#define _TSS ((unsigned long) TSS_ENTRY << IA32_SEGSEL_INDEX_SHIFT) -#define _LDT ((unsigned long) LDT_ENTRY << IA32_SEGSEL_INDEX_SHIFT) - -#define IA32_SEG_BASE 16 -#define IA32_SEG_TYPE 40 -#define IA32_SEG_SYS 44 -#define IA32_SEG_DPL 45 -#define IA32_SEG_P 47 -#define IA32_SEG_HIGH_LIMIT 48 -#define IA32_SEG_AVL 52 -#define IA32_SEG_DB 54 -#define IA32_SEG_G 55 -#define IA32_SEG_HIGH_BASE 56 - -#define IA32_SEG_DESCRIPTOR(base, limit, segtype, nonsysseg, dpl, segpresent, avl, segdb, gran) \ - (((limit) & 0xffff) \ - | (((unsigned long) (base) & 0xffffff) << IA32_SEG_BASE) \ - | ((unsigned long) (segtype) << IA32_SEG_TYPE) \ - | ((unsigned long) (nonsysseg) << IA32_SEG_SYS) \ - | ((unsigned long) (dpl) << IA32_SEG_DPL) \ - | ((unsigned long) (segpresent) << IA32_SEG_P) \ - | ((((unsigned long) (limit) >> 16) & 0xf) << IA32_SEG_HIGH_LIMIT) \ - | ((unsigned long) (avl) << IA32_SEG_AVL) \ - | ((unsigned long) (segdb) << IA32_SEG_DB) \ - | ((unsigned long) (gran) << IA32_SEG_G) \ - | ((((unsigned long) (base) >> 24) & 0xff) << IA32_SEG_HIGH_BASE)) - -#define SEG_LIM 32 -#define SEG_TYPE 52 -#define SEG_SYS 56 -#define SEG_DPL 57 -#define SEG_P 59 -#define SEG_AVL 60 -#define SEG_DB 62 -#define SEG_G 63 - -/* Unscramble an IA-32 segment descriptor into the IA-64 format. */ -#define IA32_SEG_UNSCRAMBLE(sd) \ - ( (((sd) >> IA32_SEG_BASE) & 0xffffff) | ((((sd) >> IA32_SEG_HIGH_BASE) & 0xff) << 24) \ - | ((((sd) & 0xffff) | ((((sd) >> IA32_SEG_HIGH_LIMIT) & 0xf) << 16)) << SEG_LIM) \ - | ((((sd) >> IA32_SEG_TYPE) & 0xf) << SEG_TYPE) \ - | ((((sd) >> IA32_SEG_SYS) & 0x1) << SEG_SYS) \ - | ((((sd) >> IA32_SEG_DPL) & 0x3) << SEG_DPL) \ - | ((((sd) >> IA32_SEG_P) & 0x1) << SEG_P) \ - | ((((sd) >> IA32_SEG_AVL) & 0x1) << SEG_AVL) \ - | ((((sd) >> IA32_SEG_DB) & 0x1) << SEG_DB) \ - | ((((sd) >> IA32_SEG_G) & 0x1) << SEG_G)) - -#define IA32_IOBASE 0x2000000000000000UL /* Virtual address for I/O space */ - -#define IA32_CR0 0x80000001 /* Enable PG and PE bits */ -#define IA32_CR4 0x600 /* MMXEX and FXSR on */ - -/* - * IA32 floating point control registers starting values - */ - -#define IA32_FSR_DEFAULT 0x55550000 /* set all tag bits */ -#define IA32_FCR_DEFAULT 0x17800000037fUL /* extended precision, all masks */ - -#define IA32_PTRACE_GETREGS 12 -#define IA32_PTRACE_SETREGS 13 -#define IA32_PTRACE_GETFPREGS 14 -#define IA32_PTRACE_SETFPREGS 15 -#define IA32_PTRACE_GETFPXREGS 18 -#define IA32_PTRACE_SETFPXREGS 19 - -#define ia32_start_thread(regs,new_ip,new_sp) do { \ - set_fs(USER_DS); \ - ia64_psr(regs)->cpl = 3; /* set user mode */ \ - ia64_psr(regs)->ri = 0; /* clear return slot number */ \ - ia64_psr(regs)->is = 1; /* IA-32 instruction set */ \ - regs->cr_iip = new_ip; \ - regs->ar_rsc = 0xc; /* enforced lazy mode, priv. level 3 */ \ - regs->ar_rnat = 0; \ - regs->loadrs = 0; \ - regs->r12 = new_sp; \ -} while (0) - -/* - * Local Descriptor Table (LDT) related declarations. - */ - -#define IA32_LDT_ENTRIES 8192 /* Maximum number of LDT entries supported. */ -#define IA32_LDT_ENTRY_SIZE 8 /* The size of each LDT entry. */ - -#define LDT_entry_a(info) \ - ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) - -#define LDT_entry_b(info) \ - (((info)->base_addr & 0xff000000) | \ - (((info)->base_addr & 0x00ff0000) >> 16) | \ - ((info)->limit & 0xf0000) | \ - (((info)->read_exec_only ^ 1) << 9) | \ - ((info)->contents << 10) | \ - (((info)->seg_not_present ^ 1) << 15) | \ - ((info)->seg_32bit << 22) | \ - ((info)->limit_in_pages << 23) | \ - ((info)->useable << 20) | \ - 0x7100) - -#define LDT_empty(info) ( \ - (info)->base_addr == 0 && \ - (info)->limit == 0 && \ - (info)->contents == 0 && \ - (info)->read_exec_only == 1 && \ - (info)->seg_32bit == 0 && \ - (info)->limit_in_pages == 0 && \ - (info)->seg_not_present == 1 && \ - (info)->useable == 0 ) - -static inline void -load_TLS (struct thread_struct *t, unsigned int cpu) -{ - extern unsigned long *cpu_gdt_table[NR_CPUS]; - - memcpy(cpu_gdt_table[cpu] + GDT_ENTRY_TLS_MIN + 0, &t->tls_array[0], sizeof(long)); - memcpy(cpu_gdt_table[cpu] + GDT_ENTRY_TLS_MIN + 1, &t->tls_array[1], sizeof(long)); - memcpy(cpu_gdt_table[cpu] + GDT_ENTRY_TLS_MIN + 2, &t->tls_array[2], sizeof(long)); -} - -struct ia32_user_desc { - unsigned int entry_number; - unsigned int base_addr; - unsigned int limit; - unsigned int seg_32bit:1; - unsigned int contents:2; - unsigned int read_exec_only:1; - unsigned int limit_in_pages:1; - unsigned int seg_not_present:1; - unsigned int useable:1; -}; - -struct linux_binprm; - -extern void ia32_init_addr_space (struct pt_regs *regs); -extern int ia32_setup_arg_pages (struct linux_binprm *bprm, int exec_stack); -extern unsigned long ia32_do_mmap (struct file *, unsigned long, unsigned long, int, int, loff_t); -extern void ia32_load_segment_descriptors (struct task_struct *task); - -#define ia32f2ia64f(dst,src) \ -do { \ - ia64_ldfe(6,src); \ - ia64_stop(); \ - ia64_stf_spill(dst, 6); \ -} while(0) - -#define ia64f2ia32f(dst,src) \ -do { \ - ia64_ldf_fill(6, src); \ - ia64_stop(); \ - ia64_stfe(dst, 6); \ -} while(0) - -struct user_regs_struct32 { - __u32 ebx, ecx, edx, esi, edi, ebp, eax; - unsigned short ds, __ds, es, __es; - unsigned short fs, __fs, gs, __gs; - __u32 orig_eax, eip; - unsigned short cs, __cs; - __u32 eflags, esp; - unsigned short ss, __ss; -}; - -/* Prototypes for use in elfcore32.h */ -extern int save_ia32_fpstate (struct task_struct *, struct ia32_user_i387_struct __user *); -extern int save_ia32_fpxstate (struct task_struct *, struct ia32_user_fxsr_struct __user *); - -#endif /* !CONFIG_IA32_SUPPORT */ - -#endif /* _ASM_IA64_IA32_PRIV_H */ diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c deleted file mode 100644 index 045b746b9808..000000000000 --- a/arch/ia64/ia32/sys_ia32.c +++ /dev/null @@ -1,2765 +0,0 @@ -/* - * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Derived from sys_sparc32.c. - * - * Copyright (C) 2000 VA Linux Co - * Copyright (C) 2000 Don Dugger - * Copyright (C) 1999 Arun Sharma - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 2000-2003, 2005 Hewlett-Packard Co - * David Mosberger-Tang - * Copyright (C) 2004 Gordon Jin - * - * These routines maintain argument size conversion between 32bit and 64bit - * environment. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "ia32priv.h" - -#include -#include - -#define DEBUG 0 - -#if DEBUG -# define DBG(fmt...) printk(KERN_DEBUG fmt) -#else -# define DBG(fmt...) -#endif - -#define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1))) - -#define OFFSET4K(a) ((a) & 0xfff) -#define PAGE_START(addr) ((addr) & PAGE_MASK) -#define MINSIGSTKSZ_IA32 2048 - -#define high2lowuid(uid) ((uid) > 65535 ? 65534 : (uid)) -#define high2lowgid(gid) ((gid) > 65535 ? 65534 : (gid)) - -/* - * Anything that modifies or inspects ia32 user virtual memory must hold this semaphore - * while doing so. - */ -/* XXX make per-mm: */ -static DEFINE_MUTEX(ia32_mmap_mutex); - -asmlinkage long -sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, - struct pt_regs *regs) -{ - long error; - char *filename; - unsigned long old_map_base, old_task_size, tssd; - - filename = getname(name); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - return error; - - old_map_base = current->thread.map_base; - old_task_size = current->thread.task_size; - tssd = ia64_get_kr(IA64_KR_TSSD); - - /* we may be exec'ing a 64-bit process: reset map base, task-size, and io-base: */ - current->thread.map_base = DEFAULT_MAP_BASE; - current->thread.task_size = DEFAULT_TASK_SIZE; - ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob); - ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1); - - error = compat_do_execve(filename, argv, envp, regs); - putname(filename); - - if (error < 0) { - /* oops, execve failed, switch back to old values... */ - ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE); - ia64_set_kr(IA64_KR_TSSD, tssd); - current->thread.map_base = old_map_base; - current->thread.task_size = old_task_size; - } - - return error; -} - - -#if PAGE_SHIFT > IA32_PAGE_SHIFT - - -static int -get_page_prot (struct vm_area_struct *vma, unsigned long addr) -{ - int prot = 0; - - if (!vma || vma->vm_start > addr) - return 0; - - if (vma->vm_flags & VM_READ) - prot |= PROT_READ; - if (vma->vm_flags & VM_WRITE) - prot |= PROT_WRITE; - if (vma->vm_flags & VM_EXEC) - prot |= PROT_EXEC; - return prot; -} - -/* - * Map a subpage by creating an anonymous page that contains the union of the old page and - * the subpage. - */ -static unsigned long -mmap_subpage (struct file *file, unsigned long start, unsigned long end, int prot, int flags, - loff_t off) -{ - void *page = NULL; - struct inode *inode; - unsigned long ret = 0; - struct vm_area_struct *vma = find_vma(current->mm, start); - int old_prot = get_page_prot(vma, start); - - DBG("mmap_subpage(file=%p,start=0x%lx,end=0x%lx,prot=%x,flags=%x,off=0x%llx)\n", - file, start, end, prot, flags, off); - - - /* Optimize the case where the old mmap and the new mmap are both anonymous */ - if ((old_prot & PROT_WRITE) && (flags & MAP_ANONYMOUS) && !vma->vm_file) { - if (clear_user((void __user *) start, end - start)) { - ret = -EFAULT; - goto out; - } - goto skip_mmap; - } - - page = (void *) get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - if (old_prot) - copy_from_user(page, (void __user *) PAGE_START(start), PAGE_SIZE); - - down_write(¤t->mm->mmap_sem); - { - ret = do_mmap(NULL, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE, - flags | MAP_FIXED | MAP_ANONYMOUS, 0); - } - up_write(¤t->mm->mmap_sem); - - if (IS_ERR((void *) ret)) - goto out; - - if (old_prot) { - /* copy back the old page contents. */ - if (offset_in_page(start)) - copy_to_user((void __user *) PAGE_START(start), page, - offset_in_page(start)); - if (offset_in_page(end)) - copy_to_user((void __user *) end, page + offset_in_page(end), - PAGE_SIZE - offset_in_page(end)); - } - - if (!(flags & MAP_ANONYMOUS)) { - /* read the file contents */ - inode = file->f_path.dentry->d_inode; - if (!inode->i_fop || !file->f_op->read - || ((*file->f_op->read)(file, (char __user *) start, end - start, &off) < 0)) - { - ret = -EINVAL; - goto out; - } - } - - skip_mmap: - if (!(prot & PROT_WRITE)) - ret = sys_mprotect(PAGE_START(start), PAGE_SIZE, prot | old_prot); - out: - if (page) - free_page((unsigned long) page); - return ret; -} - -/* SLAB cache for ia64_partial_page structures */ -struct kmem_cache *ia64_partial_page_cachep; - -/* - * init ia64_partial_page_list. - * return 0 means kmalloc fail. - */ -struct ia64_partial_page_list* -ia32_init_pp_list(void) -{ - struct ia64_partial_page_list *p; - - if ((p = kmalloc(sizeof(*p), GFP_KERNEL)) == NULL) - return p; - p->pp_head = NULL; - p->ppl_rb = RB_ROOT; - p->pp_hint = NULL; - atomic_set(&p->pp_count, 1); - return p; -} - -/* - * Search for the partial page with @start in partial page list @ppl. - * If finds the partial page, return the found partial page. - * Else, return 0 and provide @pprev, @rb_link, @rb_parent to - * be used by later __ia32_insert_pp(). - */ -static struct ia64_partial_page * -__ia32_find_pp(struct ia64_partial_page_list *ppl, unsigned int start, - struct ia64_partial_page **pprev, struct rb_node ***rb_link, - struct rb_node **rb_parent) -{ - struct ia64_partial_page *pp; - struct rb_node **__rb_link, *__rb_parent, *rb_prev; - - pp = ppl->pp_hint; - if (pp && pp->base == start) - return pp; - - __rb_link = &ppl->ppl_rb.rb_node; - rb_prev = __rb_parent = NULL; - - while (*__rb_link) { - __rb_parent = *__rb_link; - pp = rb_entry(__rb_parent, struct ia64_partial_page, pp_rb); - - if (pp->base == start) { - ppl->pp_hint = pp; - return pp; - } else if (pp->base < start) { - rb_prev = __rb_parent; - __rb_link = &__rb_parent->rb_right; - } else { - __rb_link = &__rb_parent->rb_left; - } - } - - *rb_link = __rb_link; - *rb_parent = __rb_parent; - *pprev = NULL; - if (rb_prev) - *pprev = rb_entry(rb_prev, struct ia64_partial_page, pp_rb); - return NULL; -} - -/* - * insert @pp into @ppl. - */ -static void -__ia32_insert_pp(struct ia64_partial_page_list *ppl, - struct ia64_partial_page *pp, struct ia64_partial_page *prev, - struct rb_node **rb_link, struct rb_node *rb_parent) -{ - /* link list */ - if (prev) { - pp->next = prev->next; - prev->next = pp; - } else { - ppl->pp_head = pp; - if (rb_parent) - pp->next = rb_entry(rb_parent, - struct ia64_partial_page, pp_rb); - else - pp->next = NULL; - } - - /* link rb */ - rb_link_node(&pp->pp_rb, rb_parent, rb_link); - rb_insert_color(&pp->pp_rb, &ppl->ppl_rb); - - ppl->pp_hint = pp; -} - -/* - * delete @pp from partial page list @ppl. - */ -static void -__ia32_delete_pp(struct ia64_partial_page_list *ppl, - struct ia64_partial_page *pp, struct ia64_partial_page *prev) -{ - if (prev) { - prev->next = pp->next; - if (ppl->pp_hint == pp) - ppl->pp_hint = prev; - } else { - ppl->pp_head = pp->next; - if (ppl->pp_hint == pp) - ppl->pp_hint = pp->next; - } - rb_erase(&pp->pp_rb, &ppl->ppl_rb); - kmem_cache_free(ia64_partial_page_cachep, pp); -} - -static struct ia64_partial_page * -__pp_prev(struct ia64_partial_page *pp) -{ - struct rb_node *prev = rb_prev(&pp->pp_rb); - if (prev) - return rb_entry(prev, struct ia64_partial_page, pp_rb); - else - return NULL; -} - -/* - * Delete partial pages with address between @start and @end. - * @start and @end are page aligned. - */ -static void -__ia32_delete_pp_range(unsigned int start, unsigned int end) -{ - struct ia64_partial_page *pp, *prev; - struct rb_node **rb_link, *rb_parent; - - if (start >= end) - return; - - pp = __ia32_find_pp(current->thread.ppl, start, &prev, - &rb_link, &rb_parent); - if (pp) - prev = __pp_prev(pp); - else { - if (prev) - pp = prev->next; - else - pp = current->thread.ppl->pp_head; - } - - while (pp && pp->base < end) { - struct ia64_partial_page *tmp = pp->next; - __ia32_delete_pp(current->thread.ppl, pp, prev); - pp = tmp; - } -} - -/* - * Set the range between @start and @end in bitmap. - * @start and @end should be IA32 page aligned and in the same IA64 page. - */ -static int -__ia32_set_pp(unsigned int start, unsigned int end, int flags) -{ - struct ia64_partial_page *pp, *prev; - struct rb_node ** rb_link, *rb_parent; - unsigned int pstart, start_bit, end_bit, i; - - pstart = PAGE_START(start); - start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE; - end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE; - if (end_bit == 0) - end_bit = PAGE_SIZE / IA32_PAGE_SIZE; - pp = __ia32_find_pp(current->thread.ppl, pstart, &prev, - &rb_link, &rb_parent); - if (pp) { - for (i = start_bit; i < end_bit; i++) - set_bit(i, &pp->bitmap); - /* - * Check: if this partial page has been set to a full page, - * then delete it. - */ - if (find_first_zero_bit(&pp->bitmap, sizeof(pp->bitmap)*8) >= - PAGE_SIZE/IA32_PAGE_SIZE) { - __ia32_delete_pp(current->thread.ppl, pp, __pp_prev(pp)); - } - return 0; - } - - /* - * MAP_FIXED may lead to overlapping mmap. - * In this case, the requested mmap area may already mmaped as a full - * page. So check vma before adding a new partial page. - */ - if (flags & MAP_FIXED) { - struct vm_area_struct *vma = find_vma(current->mm, pstart); - if (vma && vma->vm_start <= pstart) - return 0; - } - - /* new a ia64_partial_page */ - pp = kmem_cache_alloc(ia64_partial_page_cachep, GFP_KERNEL); - if (!pp) - return -ENOMEM; - pp->base = pstart; - pp->bitmap = 0; - for (i=start_bit; ibitmap)); - pp->next = NULL; - __ia32_insert_pp(current->thread.ppl, pp, prev, rb_link, rb_parent); - return 0; -} - -/* - * @start and @end should be IA32 page aligned, but don't need to be in the - * same IA64 page. Split @start and @end to make sure they're in the same IA64 - * page, then call __ia32_set_pp(). - */ -static void -ia32_set_pp(unsigned int start, unsigned int end, int flags) -{ - down_write(¤t->mm->mmap_sem); - if (flags & MAP_FIXED) { - /* - * MAP_FIXED may lead to overlapping mmap. When this happens, - * a series of complete IA64 pages results in deletion of - * old partial pages in that range. - */ - __ia32_delete_pp_range(PAGE_ALIGN(start), PAGE_START(end)); - } - - if (end < PAGE_ALIGN(start)) { - __ia32_set_pp(start, end, flags); - } else { - if (offset_in_page(start)) - __ia32_set_pp(start, PAGE_ALIGN(start), flags); - if (offset_in_page(end)) - __ia32_set_pp(PAGE_START(end), end, flags); - } - up_write(¤t->mm->mmap_sem); -} - -/* - * Unset the range between @start and @end in bitmap. - * @start and @end should be IA32 page aligned and in the same IA64 page. - * After doing that, if the bitmap is 0, then free the page and return 1, - * else return 0; - * If not find the partial page in the list, then - * If the vma exists, then the full page is set to a partial page; - * Else return -ENOMEM. - */ -static int -__ia32_unset_pp(unsigned int start, unsigned int end) -{ - struct ia64_partial_page *pp, *prev; - struct rb_node ** rb_link, *rb_parent; - unsigned int pstart, start_bit, end_bit, i; - struct vm_area_struct *vma; - - pstart = PAGE_START(start); - start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE; - end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE; - if (end_bit == 0) - end_bit = PAGE_SIZE / IA32_PAGE_SIZE; - - pp = __ia32_find_pp(current->thread.ppl, pstart, &prev, - &rb_link, &rb_parent); - if (pp) { - for (i = start_bit; i < end_bit; i++) - clear_bit(i, &pp->bitmap); - if (pp->bitmap == 0) { - __ia32_delete_pp(current->thread.ppl, pp, __pp_prev(pp)); - return 1; - } - return 0; - } - - vma = find_vma(current->mm, pstart); - if (!vma || vma->vm_start > pstart) { - return -ENOMEM; - } - - /* new a ia64_partial_page */ - pp = kmem_cache_alloc(ia64_partial_page_cachep, GFP_KERNEL); - if (!pp) - return -ENOMEM; - pp->base = pstart; - pp->bitmap = 0; - for (i = 0; i < start_bit; i++) - set_bit(i, &(pp->bitmap)); - for (i = end_bit; i < PAGE_SIZE / IA32_PAGE_SIZE; i++) - set_bit(i, &(pp->bitmap)); - pp->next = NULL; - __ia32_insert_pp(current->thread.ppl, pp, prev, rb_link, rb_parent); - return 0; -} - -/* - * Delete pp between PAGE_ALIGN(start) and PAGE_START(end) by calling - * __ia32_delete_pp_range(). Unset possible partial pages by calling - * __ia32_unset_pp(). - * The returned value see __ia32_unset_pp(). - */ -static int -ia32_unset_pp(unsigned int *startp, unsigned int *endp) -{ - unsigned int start = *startp, end = *endp; - int ret = 0; - - down_write(¤t->mm->mmap_sem); - - __ia32_delete_pp_range(PAGE_ALIGN(start), PAGE_START(end)); - - if (end < PAGE_ALIGN(start)) { - ret = __ia32_unset_pp(start, end); - if (ret == 1) { - *startp = PAGE_START(start); - *endp = PAGE_ALIGN(end); - } - if (ret == 0) { - /* to shortcut sys_munmap() in sys32_munmap() */ - *startp = PAGE_START(start); - *endp = PAGE_START(end); - } - } else { - if (offset_in_page(start)) { - ret = __ia32_unset_pp(start, PAGE_ALIGN(start)); - if (ret == 1) - *startp = PAGE_START(start); - if (ret == 0) - *startp = PAGE_ALIGN(start); - if (ret < 0) - goto out; - } - if (offset_in_page(end)) { - ret = __ia32_unset_pp(PAGE_START(end), end); - if (ret == 1) - *endp = PAGE_ALIGN(end); - if (ret == 0) - *endp = PAGE_START(end); - } - } - - out: - up_write(¤t->mm->mmap_sem); - return ret; -} - -/* - * Compare the range between @start and @end with bitmap in partial page. - * @start and @end should be IA32 page aligned and in the same IA64 page. - */ -static int -__ia32_compare_pp(unsigned int start, unsigned int end) -{ - struct ia64_partial_page *pp, *prev; - struct rb_node ** rb_link, *rb_parent; - unsigned int pstart, start_bit, end_bit, size; - unsigned int first_bit, next_zero_bit; /* the first range in bitmap */ - - pstart = PAGE_START(start); - - pp = __ia32_find_pp(current->thread.ppl, pstart, &prev, - &rb_link, &rb_parent); - if (!pp) - return 1; - - start_bit = (start % PAGE_SIZE) / IA32_PAGE_SIZE; - end_bit = (end % PAGE_SIZE) / IA32_PAGE_SIZE; - size = sizeof(pp->bitmap) * 8; - first_bit = find_first_bit(&pp->bitmap, size); - next_zero_bit = find_next_zero_bit(&pp->bitmap, size, first_bit); - if ((start_bit < first_bit) || (end_bit > next_zero_bit)) { - /* exceeds the first range in bitmap */ - return -ENOMEM; - } else if ((start_bit == first_bit) && (end_bit == next_zero_bit)) { - first_bit = find_next_bit(&pp->bitmap, size, next_zero_bit); - if ((next_zero_bit < first_bit) && (first_bit < size)) - return 1; /* has next range */ - else - return 0; /* no next range */ - } else - return 1; -} - -/* - * @start and @end should be IA32 page aligned, but don't need to be in the - * same IA64 page. Split @start and @end to make sure they're in the same IA64 - * page, then call __ia32_compare_pp(). - * - * Take this as example: the range is the 1st and 2nd 4K page. - * Return 0 if they fit bitmap exactly, i.e. bitmap = 00000011; - * Return 1 if the range doesn't cover whole bitmap, e.g. bitmap = 00001111; - * Return -ENOMEM if the range exceeds the bitmap, e.g. bitmap = 00000001 or - * bitmap = 00000101. - */ -static int -ia32_compare_pp(unsigned int *startp, unsigned int *endp) -{ - unsigned int start = *startp, end = *endp; - int retval = 0; - - down_write(¤t->mm->mmap_sem); - - if (end < PAGE_ALIGN(start)) { - retval = __ia32_compare_pp(start, end); - if (retval == 0) { - *startp = PAGE_START(start); - *endp = PAGE_ALIGN(end); - } - } else { - if (offset_in_page(start)) { - retval = __ia32_compare_pp(start, - PAGE_ALIGN(start)); - if (retval == 0) - *startp = PAGE_START(start); - if (retval < 0) - goto out; - } - if (offset_in_page(end)) { - retval = __ia32_compare_pp(PAGE_START(end), end); - if (retval == 0) - *endp = PAGE_ALIGN(end); - } - } - - out: - up_write(¤t->mm->mmap_sem); - return retval; -} - -static void -__ia32_drop_pp_list(struct ia64_partial_page_list *ppl) -{ - struct ia64_partial_page *pp = ppl->pp_head; - - while (pp) { - struct ia64_partial_page *next = pp->next; - kmem_cache_free(ia64_partial_page_cachep, pp); - pp = next; - } - - kfree(ppl); -} - -void -ia32_drop_ia64_partial_page_list(struct task_struct *task) -{ - struct ia64_partial_page_list* ppl = task->thread.ppl; - - if (ppl && atomic_dec_and_test(&ppl->pp_count)) - __ia32_drop_pp_list(ppl); -} - -/* - * Copy current->thread.ppl to ppl (already initialized). - */ -static int -__ia32_copy_pp_list(struct ia64_partial_page_list *ppl) -{ - struct ia64_partial_page *pp, *tmp, *prev; - struct rb_node **rb_link, *rb_parent; - - ppl->pp_head = NULL; - ppl->pp_hint = NULL; - ppl->ppl_rb = RB_ROOT; - rb_link = &ppl->ppl_rb.rb_node; - rb_parent = NULL; - prev = NULL; - - for (pp = current->thread.ppl->pp_head; pp; pp = pp->next) { - tmp = kmem_cache_alloc(ia64_partial_page_cachep, GFP_KERNEL); - if (!tmp) - return -ENOMEM; - *tmp = *pp; - __ia32_insert_pp(ppl, tmp, prev, rb_link, rb_parent); - prev = tmp; - rb_link = &tmp->pp_rb.rb_right; - rb_parent = &tmp->pp_rb; - } - return 0; -} - -int -ia32_copy_ia64_partial_page_list(struct task_struct *p, - unsigned long clone_flags) -{ - int retval = 0; - - if (clone_flags & CLONE_VM) { - atomic_inc(¤t->thread.ppl->pp_count); - p->thread.ppl = current->thread.ppl; - } else { - p->thread.ppl = ia32_init_pp_list(); - if (!p->thread.ppl) - return -ENOMEM; - down_write(¤t->mm->mmap_sem); - { - retval = __ia32_copy_pp_list(p->thread.ppl); - } - up_write(¤t->mm->mmap_sem); - } - - return retval; -} - -static unsigned long -emulate_mmap (struct file *file, unsigned long start, unsigned long len, int prot, int flags, - loff_t off) -{ - unsigned long tmp, end, pend, pstart, ret, is_congruent, fudge = 0; - struct inode *inode; - loff_t poff; - - end = start + len; - pstart = PAGE_START(start); - pend = PAGE_ALIGN(end); - - if (flags & MAP_FIXED) { - ia32_set_pp((unsigned int)start, (unsigned int)end, flags); - if (start > pstart) { - if (flags & MAP_SHARED) - printk(KERN_INFO - "%s(%d): emulate_mmap() can't share head (addr=0x%lx)\n", - current->comm, task_pid_nr(current), start); - ret = mmap_subpage(file, start, min(PAGE_ALIGN(start), end), prot, flags, - off); - if (IS_ERR((void *) ret)) - return ret; - pstart += PAGE_SIZE; - if (pstart >= pend) - goto out; /* done */ - } - if (end < pend) { - if (flags & MAP_SHARED) - printk(KERN_INFO - "%s(%d): emulate_mmap() can't share tail (end=0x%lx)\n", - current->comm, task_pid_nr(current), end); - ret = mmap_subpage(file, max(start, PAGE_START(end)), end, prot, flags, - (off + len) - offset_in_page(end)); - if (IS_ERR((void *) ret)) - return ret; - pend -= PAGE_SIZE; - if (pstart >= pend) - goto out; /* done */ - } - } else { - /* - * If a start address was specified, use it if the entire rounded out area - * is available. - */ - if (start && !pstart) - fudge = 1; /* handle case of mapping to range (0,PAGE_SIZE) */ - tmp = arch_get_unmapped_area(file, pstart - fudge, pend - pstart, 0, flags); - if (tmp != pstart) { - pstart = tmp; - start = pstart + offset_in_page(off); /* make start congruent with off */ - end = start + len; - pend = PAGE_ALIGN(end); - } - } - - poff = off + (pstart - start); /* note: (pstart - start) may be negative */ - is_congruent = (flags & MAP_ANONYMOUS) || (offset_in_page(poff) == 0); - - if ((flags & MAP_SHARED) && !is_congruent) - printk(KERN_INFO "%s(%d): emulate_mmap() can't share contents of incongruent mmap " - "(addr=0x%lx,off=0x%llx)\n", current->comm, task_pid_nr(current), start, off); - - DBG("mmap_body: mapping [0x%lx-0x%lx) %s with poff 0x%llx\n", pstart, pend, - is_congruent ? "congruent" : "not congruent", poff); - - down_write(¤t->mm->mmap_sem); - { - if (!(flags & MAP_ANONYMOUS) && is_congruent) - ret = do_mmap(file, pstart, pend - pstart, prot, flags | MAP_FIXED, poff); - else - ret = do_mmap(NULL, pstart, pend - pstart, - prot | ((flags & MAP_ANONYMOUS) ? 0 : PROT_WRITE), - flags | MAP_FIXED | MAP_ANONYMOUS, 0); - } - up_write(¤t->mm->mmap_sem); - - if (IS_ERR((void *) ret)) - return ret; - - if (!is_congruent) { - /* read the file contents */ - inode = file->f_path.dentry->d_inode; - if (!inode->i_fop || !file->f_op->read - || ((*file->f_op->read)(file, (char __user *) pstart, pend - pstart, &poff) - < 0)) - { - sys_munmap(pstart, pend - pstart); - return -EINVAL; - } - if (!(prot & PROT_WRITE) && sys_mprotect(pstart, pend - pstart, prot) < 0) - return -EINVAL; - } - - if (!(flags & MAP_FIXED)) - ia32_set_pp((unsigned int)start, (unsigned int)end, flags); -out: - return start; -} - -#endif /* PAGE_SHIFT > IA32_PAGE_SHIFT */ - -static inline unsigned int -get_prot32 (unsigned int prot) -{ - if (prot & PROT_WRITE) - /* on x86, PROT_WRITE implies PROT_READ which implies PROT_EEC */ - prot |= PROT_READ | PROT_WRITE | PROT_EXEC; - else if (prot & (PROT_READ | PROT_EXEC)) - /* on x86, there is no distinction between PROT_READ and PROT_EXEC */ - prot |= (PROT_READ | PROT_EXEC); - - return prot; -} - -unsigned long -ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot, int flags, - loff_t offset) -{ - DBG("ia32_do_mmap(file=%p,addr=0x%lx,len=0x%lx,prot=%x,flags=%x,offset=0x%llx)\n", - file, addr, len, prot, flags, offset); - - if (file && (!file->f_op || !file->f_op->mmap)) - return -ENODEV; - - len = IA32_PAGE_ALIGN(len); - if (len == 0) - return addr; - - if (len > IA32_PAGE_OFFSET || addr > IA32_PAGE_OFFSET - len) - { - if (flags & MAP_FIXED) - return -ENOMEM; - else - return -EINVAL; - } - - if (OFFSET4K(offset)) - return -EINVAL; - - prot = get_prot32(prot); - - if (flags & MAP_HUGETLB) - return -ENOMEM; - -#if PAGE_SHIFT > IA32_PAGE_SHIFT - mutex_lock(&ia32_mmap_mutex); - { - addr = emulate_mmap(file, addr, len, prot, flags, offset); - } - mutex_unlock(&ia32_mmap_mutex); -#else - down_write(¤t->mm->mmap_sem); - { - addr = do_mmap(file, addr, len, prot, flags, offset); - } - up_write(¤t->mm->mmap_sem); -#endif - DBG("ia32_do_mmap: returning 0x%lx\n", addr); - return addr; -} - -/* - * Linux/i386 didn't use to be able to handle more than 4 system call parameters, so these - * system calls used a memory block for parameter passing.. - */ - -struct mmap_arg_struct { - unsigned int addr; - unsigned int len; - unsigned int prot; - unsigned int flags; - unsigned int fd; - unsigned int offset; -}; - -asmlinkage long -sys32_mmap (struct mmap_arg_struct __user *arg) -{ - struct mmap_arg_struct a; - struct file *file = NULL; - unsigned long addr; - int flags; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - - if (OFFSET4K(a.offset)) - return -EINVAL; - - flags = a.flags; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(a.fd); - if (!file) - return -EBADF; - } - - addr = ia32_do_mmap(file, a.addr, a.len, a.prot, flags, a.offset); - - if (file) - fput(file); - return addr; -} - -asmlinkage long -sys32_mmap2 (unsigned int addr, unsigned int len, unsigned int prot, unsigned int flags, - unsigned int fd, unsigned int pgoff) -{ - struct file *file = NULL; - unsigned long retval; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - return -EBADF; - } - - retval = ia32_do_mmap(file, addr, len, prot, flags, - (unsigned long) pgoff << IA32_PAGE_SHIFT); - - if (file) - fput(file); - return retval; -} - -asmlinkage long -sys32_munmap (unsigned int start, unsigned int len) -{ - unsigned int end = start + len; - long ret; - -#if PAGE_SHIFT <= IA32_PAGE_SHIFT - ret = sys_munmap(start, end - start); -#else - if (OFFSET4K(start)) - return -EINVAL; - - end = IA32_PAGE_ALIGN(end); - if (start >= end) - return -EINVAL; - - ret = ia32_unset_pp(&start, &end); - if (ret < 0) - return ret; - - if (start >= end) - return 0; - - mutex_lock(&ia32_mmap_mutex); - ret = sys_munmap(start, end - start); - mutex_unlock(&ia32_mmap_mutex); -#endif - return ret; -} - -#if PAGE_SHIFT > IA32_PAGE_SHIFT - -/* - * When mprotect()ing a partial page, we set the permission to the union of the old - * settings and the new settings. In other words, it's only possible to make access to a - * partial page less restrictive. - */ -static long -mprotect_subpage (unsigned long address, int new_prot) -{ - int old_prot; - struct vm_area_struct *vma; - - if (new_prot == PROT_NONE) - return 0; /* optimize case where nothing changes... */ - vma = find_vma(current->mm, address); - old_prot = get_page_prot(vma, address); - return sys_mprotect(address, PAGE_SIZE, new_prot | old_prot); -} - -#endif /* PAGE_SHIFT > IA32_PAGE_SHIFT */ - -asmlinkage long -sys32_mprotect (unsigned int start, unsigned int len, int prot) -{ - unsigned int end = start + len; -#if PAGE_SHIFT > IA32_PAGE_SHIFT - long retval = 0; -#endif - - prot = get_prot32(prot); - -#if PAGE_SHIFT <= IA32_PAGE_SHIFT - return sys_mprotect(start, end - start, prot); -#else - if (OFFSET4K(start)) - return -EINVAL; - - end = IA32_PAGE_ALIGN(end); - if (end < start) - return -EINVAL; - - retval = ia32_compare_pp(&start, &end); - - if (retval < 0) - return retval; - - mutex_lock(&ia32_mmap_mutex); - { - if (offset_in_page(start)) { - /* start address is 4KB aligned but not page aligned. */ - retval = mprotect_subpage(PAGE_START(start), prot); - if (retval < 0) - goto out; - - start = PAGE_ALIGN(start); - if (start >= end) - goto out; /* retval is already zero... */ - } - - if (offset_in_page(end)) { - /* end address is 4KB aligned but not page aligned. */ - retval = mprotect_subpage(PAGE_START(end), prot); - if (retval < 0) - goto out; - - end = PAGE_START(end); - } - retval = sys_mprotect(start, end - start, prot); - } - out: - mutex_unlock(&ia32_mmap_mutex); - return retval; -#endif -} - -asmlinkage long -sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len, - unsigned int flags, unsigned int new_addr) -{ - long ret; - -#if PAGE_SHIFT <= IA32_PAGE_SHIFT - ret = sys_mremap(addr, old_len, new_len, flags, new_addr); -#else - unsigned int old_end, new_end; - - if (OFFSET4K(addr)) - return -EINVAL; - - old_len = IA32_PAGE_ALIGN(old_len); - new_len = IA32_PAGE_ALIGN(new_len); - old_end = addr + old_len; - new_end = addr + new_len; - - if (!new_len) - return -EINVAL; - - if ((flags & MREMAP_FIXED) && (OFFSET4K(new_addr))) - return -EINVAL; - - if (old_len >= new_len) { - ret = sys32_munmap(addr + new_len, old_len - new_len); - if (ret && old_len != new_len) - return ret; - ret = addr; - if (!(flags & MREMAP_FIXED) || (new_addr == addr)) - return ret; - old_len = new_len; - } - - addr = PAGE_START(addr); - old_len = PAGE_ALIGN(old_end) - addr; - new_len = PAGE_ALIGN(new_end) - addr; - - mutex_lock(&ia32_mmap_mutex); - ret = sys_mremap(addr, old_len, new_len, flags, new_addr); - mutex_unlock(&ia32_mmap_mutex); - - if ((ret >= 0) && (old_len < new_len)) { - /* mremap expanded successfully */ - ia32_set_pp(old_end, new_end, flags); - } -#endif - return ret; -} - -asmlinkage unsigned long -sys32_alarm (unsigned int seconds) -{ - return alarm_setitimer(seconds); -} - -struct sel_arg_struct { - unsigned int n; - unsigned int inp; - unsigned int outp; - unsigned int exp; - unsigned int tvp; -}; - -asmlinkage long -sys32_old_select (struct sel_arg_struct __user *arg) -{ - struct sel_arg_struct a; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp), - compat_ptr(a.exp), compat_ptr(a.tvp)); -} - -#define SEMOP 1 -#define SEMGET 2 -#define SEMCTL 3 -#define SEMTIMEDOP 4 -#define MSGSND 11 -#define MSGRCV 12 -#define MSGGET 13 -#define MSGCTL 14 -#define SHMAT 21 -#define SHMDT 22 -#define SHMGET 23 -#define SHMCTL 24 - -asmlinkage long -sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth) -{ - int version; - - version = call >> 16; /* hack for backward compatibility */ - call &= 0xffff; - - switch (call) { - case SEMTIMEDOP: - if (fifth) - return compat_sys_semtimedop(first, compat_ptr(ptr), - second, compat_ptr(fifth)); - /* else fall through for normal semop() */ - case SEMOP: - /* struct sembuf is the same on 32 and 64bit :)) */ - return sys_semtimedop(first, compat_ptr(ptr), second, - NULL); - case SEMGET: - return sys_semget(first, second, third); - case SEMCTL: - return compat_sys_semctl(first, second, third, compat_ptr(ptr)); - - case MSGSND: - return compat_sys_msgsnd(first, second, third, compat_ptr(ptr)); - case MSGRCV: - return compat_sys_msgrcv(first, second, fifth, third, version, compat_ptr(ptr)); - case MSGGET: - return sys_msgget((key_t) first, second); - case MSGCTL: - return compat_sys_msgctl(first, second, compat_ptr(ptr)); - - case SHMAT: - return compat_sys_shmat(first, second, third, version, compat_ptr(ptr)); - break; - case SHMDT: - return sys_shmdt(compat_ptr(ptr)); - case SHMGET: - return sys_shmget(first, (unsigned)second, third); - case SHMCTL: - return compat_sys_shmctl(first, second, compat_ptr(ptr)); - - default: - return -ENOSYS; - } - return -EINVAL; -} - -asmlinkage long -compat_sys_wait4 (compat_pid_t pid, compat_uint_t * stat_addr, int options, - struct compat_rusage *ru); - -asmlinkage long -sys32_waitpid (int pid, unsigned int *stat_addr, int options) -{ - return compat_sys_wait4(pid, stat_addr, options, NULL); -} - -/* - * The order in which registers are stored in the ptrace regs structure - */ -#define PT_EBX 0 -#define PT_ECX 1 -#define PT_EDX 2 -#define PT_ESI 3 -#define PT_EDI 4 -#define PT_EBP 5 -#define PT_EAX 6 -#define PT_DS 7 -#define PT_ES 8 -#define PT_FS 9 -#define PT_GS 10 -#define PT_ORIG_EAX 11 -#define PT_EIP 12 -#define PT_CS 13 -#define PT_EFL 14 -#define PT_UESP 15 -#define PT_SS 16 - -static unsigned int -getreg (struct task_struct *child, int regno) -{ - struct pt_regs *child_regs; - - child_regs = task_pt_regs(child); - switch (regno / sizeof(int)) { - case PT_EBX: return child_regs->r11; - case PT_ECX: return child_regs->r9; - case PT_EDX: return child_regs->r10; - case PT_ESI: return child_regs->r14; - case PT_EDI: return child_regs->r15; - case PT_EBP: return child_regs->r13; - case PT_EAX: return child_regs->r8; - case PT_ORIG_EAX: return child_regs->r1; /* see dispatch_to_ia32_handler() */ - case PT_EIP: return child_regs->cr_iip; - case PT_UESP: return child_regs->r12; - case PT_EFL: return child->thread.eflag; - case PT_DS: case PT_ES: case PT_FS: case PT_GS: case PT_SS: - return __USER_DS; - case PT_CS: return __USER_CS; - default: - printk(KERN_ERR "ia32.getreg(): unknown register %d\n", regno); - break; - } - return 0; -} - -static void -putreg (struct task_struct *child, int regno, unsigned int value) -{ - struct pt_regs *child_regs; - - child_regs = task_pt_regs(child); - switch (regno / sizeof(int)) { - case PT_EBX: child_regs->r11 = value; break; - case PT_ECX: child_regs->r9 = value; break; - case PT_EDX: child_regs->r10 = value; break; - case PT_ESI: child_regs->r14 = value; break; - case PT_EDI: child_regs->r15 = value; break; - case PT_EBP: child_regs->r13 = value; break; - case PT_EAX: child_regs->r8 = value; break; - case PT_ORIG_EAX: child_regs->r1 = value; break; - case PT_EIP: child_regs->cr_iip = value; break; - case PT_UESP: child_regs->r12 = value; break; - case PT_EFL: child->thread.eflag = value; break; - case PT_DS: case PT_ES: case PT_FS: case PT_GS: case PT_SS: - if (value != __USER_DS) - printk(KERN_ERR - "ia32.putreg: attempt to set invalid segment register %d = %x\n", - regno, value); - break; - case PT_CS: - if (value != __USER_CS) - printk(KERN_ERR - "ia32.putreg: attempt to set invalid segment register %d = %x\n", - regno, value); - break; - default: - printk(KERN_ERR "ia32.putreg: unknown register %d\n", regno); - break; - } -} - -static void -put_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp, - struct switch_stack *swp, int tos) -{ - struct _fpreg_ia32 *f; - char buf[32]; - - f = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); - if ((regno += tos) >= 8) - regno -= 8; - switch (regno) { - case 0: - ia64f2ia32f(f, &ptp->f8); - break; - case 1: - ia64f2ia32f(f, &ptp->f9); - break; - case 2: - ia64f2ia32f(f, &ptp->f10); - break; - case 3: - ia64f2ia32f(f, &ptp->f11); - break; - case 4: - case 5: - case 6: - case 7: - ia64f2ia32f(f, &swp->f12 + (regno - 4)); - break; - } - copy_to_user(reg, f, sizeof(*reg)); -} - -static void -get_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp, - struct switch_stack *swp, int tos) -{ - - if ((regno += tos) >= 8) - regno -= 8; - switch (regno) { - case 0: - copy_from_user(&ptp->f8, reg, sizeof(*reg)); - break; - case 1: - copy_from_user(&ptp->f9, reg, sizeof(*reg)); - break; - case 2: - copy_from_user(&ptp->f10, reg, sizeof(*reg)); - break; - case 3: - copy_from_user(&ptp->f11, reg, sizeof(*reg)); - break; - case 4: - case 5: - case 6: - case 7: - copy_from_user(&swp->f12 + (regno - 4), reg, sizeof(*reg)); - break; - } - return; -} - -int -save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save) -{ - struct switch_stack *swp; - struct pt_regs *ptp; - int i, tos; - - if (!access_ok(VERIFY_WRITE, save, sizeof(*save))) - return -EFAULT; - - __put_user(tsk->thread.fcr & 0xffff, &save->cwd); - __put_user(tsk->thread.fsr & 0xffff, &save->swd); - __put_user((tsk->thread.fsr>>16) & 0xffff, &save->twd); - __put_user(tsk->thread.fir, &save->fip); - __put_user((tsk->thread.fir>>32) & 0xffff, &save->fcs); - __put_user(tsk->thread.fdr, &save->foo); - __put_user((tsk->thread.fdr>>32) & 0xffff, &save->fos); - - /* - * Stack frames start with 16-bytes of temp space - */ - swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = task_pt_regs(tsk); - tos = (tsk->thread.fsr >> 11) & 7; - for (i = 0; i < 8; i++) - put_fpreg(i, &save->st_space[i], ptp, swp, tos); - return 0; -} - -static int -restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save) -{ - struct switch_stack *swp; - struct pt_regs *ptp; - int i, tos; - unsigned int fsrlo, fsrhi, num32; - - if (!access_ok(VERIFY_READ, save, sizeof(*save))) - return(-EFAULT); - - __get_user(num32, (unsigned int __user *)&save->cwd); - tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f); - __get_user(fsrlo, (unsigned int __user *)&save->swd); - __get_user(fsrhi, (unsigned int __user *)&save->twd); - num32 = (fsrhi << 16) | fsrlo; - tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32; - __get_user(num32, (unsigned int __user *)&save->fip); - tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32; - __get_user(num32, (unsigned int __user *)&save->foo); - tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32; - - /* - * Stack frames start with 16-bytes of temp space - */ - swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = task_pt_regs(tsk); - tos = (tsk->thread.fsr >> 11) & 7; - for (i = 0; i < 8; i++) - get_fpreg(i, &save->st_space[i], ptp, swp, tos); - return 0; -} - -int -save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save) -{ - struct switch_stack *swp; - struct pt_regs *ptp; - int i, tos; - unsigned long mxcsr=0; - unsigned long num128[2]; - - if (!access_ok(VERIFY_WRITE, save, sizeof(*save))) - return -EFAULT; - - __put_user(tsk->thread.fcr & 0xffff, &save->cwd); - __put_user(tsk->thread.fsr & 0xffff, &save->swd); - __put_user((tsk->thread.fsr>>16) & 0xffff, &save->twd); - __put_user(tsk->thread.fir, &save->fip); - __put_user((tsk->thread.fir>>32) & 0xffff, &save->fcs); - __put_user(tsk->thread.fdr, &save->foo); - __put_user((tsk->thread.fdr>>32) & 0xffff, &save->fos); - - /* - * Stack frames start with 16-bytes of temp space - */ - swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = task_pt_regs(tsk); - tos = (tsk->thread.fsr >> 11) & 7; - for (i = 0; i < 8; i++) - put_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos); - - mxcsr = ((tsk->thread.fcr>>32) & 0xff80) | ((tsk->thread.fsr>>32) & 0x3f); - __put_user(mxcsr & 0xffff, &save->mxcsr); - for (i = 0; i < 8; i++) { - memcpy(&(num128[0]), &(swp->f16) + i*2, sizeof(unsigned long)); - memcpy(&(num128[1]), &(swp->f17) + i*2, sizeof(unsigned long)); - copy_to_user(&save->xmm_space[0] + 4*i, num128, sizeof(struct _xmmreg_ia32)); - } - return 0; -} - -static int -restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save) -{ - struct switch_stack *swp; - struct pt_regs *ptp; - int i, tos; - unsigned int fsrlo, fsrhi, num32; - int mxcsr; - unsigned long num64; - unsigned long num128[2]; - - if (!access_ok(VERIFY_READ, save, sizeof(*save))) - return(-EFAULT); - - __get_user(num32, (unsigned int __user *)&save->cwd); - tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f); - __get_user(fsrlo, (unsigned int __user *)&save->swd); - __get_user(fsrhi, (unsigned int __user *)&save->twd); - num32 = (fsrhi << 16) | fsrlo; - tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32; - __get_user(num32, (unsigned int __user *)&save->fip); - tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32; - __get_user(num32, (unsigned int __user *)&save->foo); - tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32; - - /* - * Stack frames start with 16-bytes of temp space - */ - swp = (struct switch_stack *)(tsk->thread.ksp + 16); - ptp = task_pt_regs(tsk); - tos = (tsk->thread.fsr >> 11) & 7; - for (i = 0; i < 8; i++) - get_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos); - - __get_user(mxcsr, (unsigned int __user *)&save->mxcsr); - num64 = mxcsr & 0xff10; - tsk->thread.fcr = (tsk->thread.fcr & (~0xff1000000000UL)) | (num64<<32); - num64 = mxcsr & 0x3f; - tsk->thread.fsr = (tsk->thread.fsr & (~0x3f00000000UL)) | (num64<<32); - - for (i = 0; i < 8; i++) { - copy_from_user(num128, &save->xmm_space[0] + 4*i, sizeof(struct _xmmreg_ia32)); - memcpy(&(swp->f16) + i*2, &(num128[0]), sizeof(unsigned long)); - memcpy(&(swp->f17) + i*2, &(num128[1]), sizeof(unsigned long)); - } - return 0; -} - -long compat_arch_ptrace(struct task_struct *child, compat_long_t request, - compat_ulong_t caddr, compat_ulong_t cdata) -{ - unsigned long addr = caddr; - unsigned long data = cdata; - unsigned int tmp; - long i, ret; - - switch (request) { - case PTRACE_PEEKUSR: /* read word at addr in USER area */ - ret = -EIO; - if ((addr & 3) || addr > 17*sizeof(int)) - break; - - tmp = getreg(child, addr); - if (!put_user(tmp, (unsigned int __user *) compat_ptr(data))) - ret = 0; - break; - - case PTRACE_POKEUSR: /* write word at addr in USER area */ - ret = -EIO; - if ((addr & 3) || addr > 17*sizeof(int)) - break; - - putreg(child, addr, data); - ret = 0; - break; - - case IA32_PTRACE_GETREGS: - if (!access_ok(VERIFY_WRITE, compat_ptr(data), 17*sizeof(int))) { - ret = -EIO; - break; - } - for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) { - put_user(getreg(child, i), (unsigned int __user *) compat_ptr(data)); - data += sizeof(int); - } - ret = 0; - break; - - case IA32_PTRACE_SETREGS: - if (!access_ok(VERIFY_READ, compat_ptr(data), 17*sizeof(int))) { - ret = -EIO; - break; - } - for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) { - get_user(tmp, (unsigned int __user *) compat_ptr(data)); - putreg(child, i, tmp); - data += sizeof(int); - } - ret = 0; - break; - - case IA32_PTRACE_GETFPREGS: - ret = save_ia32_fpstate(child, (struct ia32_user_i387_struct __user *) - compat_ptr(data)); - break; - - case IA32_PTRACE_GETFPXREGS: - ret = save_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *) - compat_ptr(data)); - break; - - case IA32_PTRACE_SETFPREGS: - ret = restore_ia32_fpstate(child, (struct ia32_user_i387_struct __user *) - compat_ptr(data)); - break; - - case IA32_PTRACE_SETFPXREGS: - ret = restore_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *) - compat_ptr(data)); - break; - - default: - return compat_ptrace_request(child, request, caddr, cdata); - } - return ret; -} - -typedef struct { - unsigned int ss_sp; - unsigned int ss_flags; - unsigned int ss_size; -} ia32_stack_t; - -asmlinkage long -sys32_sigaltstack (ia32_stack_t __user *uss32, ia32_stack_t __user *uoss32, - long arg2, long arg3, long arg4, long arg5, long arg6, - long arg7, struct pt_regs pt) -{ - stack_t uss, uoss; - ia32_stack_t buf32; - int ret; - mm_segment_t old_fs = get_fs(); - - if (uss32) { - if (copy_from_user(&buf32, uss32, sizeof(ia32_stack_t))) - return -EFAULT; - uss.ss_sp = (void __user *) (long) buf32.ss_sp; - uss.ss_flags = buf32.ss_flags; - /* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the - check and set it to the user requested value later */ - if ((buf32.ss_flags != SS_DISABLE) && (buf32.ss_size < MINSIGSTKSZ_IA32)) { - ret = -ENOMEM; - goto out; - } - uss.ss_size = MINSIGSTKSZ; - } - set_fs(KERNEL_DS); - ret = do_sigaltstack(uss32 ? (stack_t __user *) &uss : NULL, - (stack_t __user *) &uoss, pt.r12); - current->sas_ss_size = buf32.ss_size; - set_fs(old_fs); -out: - if (ret < 0) - return(ret); - if (uoss32) { - buf32.ss_sp = (long __user) uoss.ss_sp; - buf32.ss_flags = uoss.ss_flags; - buf32.ss_size = uoss.ss_size; - if (copy_to_user(uoss32, &buf32, sizeof(ia32_stack_t))) - return -EFAULT; - } - return ret; -} - -asmlinkage int -sys32_msync (unsigned int start, unsigned int len, int flags) -{ - unsigned int addr; - - if (OFFSET4K(start)) - return -EINVAL; - addr = PAGE_START(start); - return sys_msync(addr, len + (start - addr), flags); -} - -asmlinkage long -sys32_newuname (struct new_utsname __user *name) -{ - int ret = sys_newuname(name); - - if (!ret) - if (copy_to_user(name->machine, "i686\0\0\0", 8)) - ret = -EFAULT; - return ret; -} - -asmlinkage long -sys32_getresuid16 (u16 __user *ruid, u16 __user *euid, u16 __user *suid) -{ - uid_t a, b, c; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_getresuid((uid_t __user *) &a, (uid_t __user *) &b, (uid_t __user *) &c); - set_fs(old_fs); - - if (put_user(a, ruid) || put_user(b, euid) || put_user(c, suid)) - return -EFAULT; - return ret; -} - -asmlinkage long -sys32_getresgid16 (u16 __user *rgid, u16 __user *egid, u16 __user *sgid) -{ - gid_t a, b, c; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_getresgid((gid_t __user *) &a, (gid_t __user *) &b, (gid_t __user *) &c); - set_fs(old_fs); - - if (ret) - return ret; - - return put_user(a, rgid) | put_user(b, egid) | put_user(c, sgid); -} - -asmlinkage long -sys32_lseek (unsigned int fd, int offset, unsigned int whence) -{ - /* Sign-extension of "offset" is important here... */ - return sys_lseek(fd, offset, whence); -} - -static int -groups16_to_user(short __user *grouplist, struct group_info *group_info) -{ - int i; - short group; - - for (i = 0; i < group_info->ngroups; i++) { - group = (short)GROUP_AT(group_info, i); - if (put_user(group, grouplist+i)) - return -EFAULT; - } - - return 0; -} - -static int -groups16_from_user(struct group_info *group_info, short __user *grouplist) -{ - int i; - short group; - - for (i = 0; i < group_info->ngroups; i++) { - if (get_user(group, grouplist+i)) - return -EFAULT; - GROUP_AT(group_info, i) = (gid_t)group; - } - - return 0; -} - -asmlinkage long -sys32_getgroups16 (int gidsetsize, short __user *grouplist) -{ - const struct cred *cred = current_cred(); - int i; - - if (gidsetsize < 0) - return -EINVAL; - - i = cred->group_info->ngroups; - if (gidsetsize) { - if (i > gidsetsize) { - i = -EINVAL; - goto out; - } - if (groups16_to_user(grouplist, cred->group_info)) { - i = -EFAULT; - goto out; - } - } -out: - return i; -} - -asmlinkage long -sys32_setgroups16 (int gidsetsize, short __user *grouplist) -{ - struct group_info *group_info; - int retval; - - if (!capable(CAP_SETGID)) - return -EPERM; - if ((unsigned)gidsetsize > NGROUPS_MAX) - return -EINVAL; - - group_info = groups_alloc(gidsetsize); - if (!group_info) - return -ENOMEM; - retval = groups16_from_user(group_info, grouplist); - if (retval) { - put_group_info(group_info); - return retval; - } - - retval = set_current_groups(group_info); - put_group_info(group_info); - - return retval; -} - -asmlinkage long -sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi) -{ - return sys_truncate(compat_ptr(path), ((unsigned long) len_hi << 32) | len_lo); -} - -asmlinkage long -sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi) -{ - return sys_ftruncate(fd, ((unsigned long) len_hi << 32) | len_lo); -} - -static int -putstat64 (struct stat64 __user *ubuf, struct kstat *kbuf) -{ - int err; - u64 hdev; - - if (clear_user(ubuf, sizeof(*ubuf))) - return -EFAULT; - - hdev = huge_encode_dev(kbuf->dev); - err = __put_user(hdev, (u32 __user*)&ubuf->st_dev); - err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_dev) + 1); - err |= __put_user(kbuf->ino, &ubuf->__st_ino); - err |= __put_user(kbuf->ino, &ubuf->st_ino_lo); - err |= __put_user(kbuf->ino >> 32, &ubuf->st_ino_hi); - err |= __put_user(kbuf->mode, &ubuf->st_mode); - err |= __put_user(kbuf->nlink, &ubuf->st_nlink); - err |= __put_user(kbuf->uid, &ubuf->st_uid); - err |= __put_user(kbuf->gid, &ubuf->st_gid); - hdev = huge_encode_dev(kbuf->rdev); - err = __put_user(hdev, (u32 __user*)&ubuf->st_rdev); - err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_rdev) + 1); - err |= __put_user(kbuf->size, &ubuf->st_size_lo); - err |= __put_user((kbuf->size >> 32), &ubuf->st_size_hi); - err |= __put_user(kbuf->atime.tv_sec, &ubuf->st_atime); - err |= __put_user(kbuf->atime.tv_nsec, &ubuf->st_atime_nsec); - err |= __put_user(kbuf->mtime.tv_sec, &ubuf->st_mtime); - err |= __put_user(kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec); - err |= __put_user(kbuf->ctime.tv_sec, &ubuf->st_ctime); - err |= __put_user(kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec); - err |= __put_user(kbuf->blksize, &ubuf->st_blksize); - err |= __put_user(kbuf->blocks, &ubuf->st_blocks); - return err; -} - -asmlinkage long -sys32_stat64 (char __user *filename, struct stat64 __user *statbuf) -{ - struct kstat s; - long ret = vfs_stat(filename, &s); - if (!ret) - ret = putstat64(statbuf, &s); - return ret; -} - -asmlinkage long -sys32_lstat64 (char __user *filename, struct stat64 __user *statbuf) -{ - struct kstat s; - long ret = vfs_lstat(filename, &s); - if (!ret) - ret = putstat64(statbuf, &s); - return ret; -} - -asmlinkage long -sys32_fstat64 (unsigned int fd, struct stat64 __user *statbuf) -{ - struct kstat s; - long ret = vfs_fstat(fd, &s); - if (!ret) - ret = putstat64(statbuf, &s); - return ret; -} - -asmlinkage long -sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec __user *interval) -{ - mm_segment_t old_fs = get_fs(); - struct timespec t; - long ret; - - set_fs(KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t); - set_fs(old_fs); - if (put_compat_timespec(&t, interval)) - return -EFAULT; - return ret; -} - -asmlinkage long -sys32_pread (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi) -{ - return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); -} - -asmlinkage long -sys32_pwrite (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi) -{ - return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); -} - -asmlinkage long -sys32_sendfile (int out_fd, int in_fd, int __user *offset, unsigned int count) -{ - mm_segment_t old_fs = get_fs(); - long ret; - off_t of; - - if (offset && get_user(of, offset)) - return -EFAULT; - - set_fs(KERNEL_DS); - ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *) &of : NULL, count); - set_fs(old_fs); - - if (offset && put_user(of, offset)) - return -EFAULT; - - return ret; -} - -asmlinkage long -sys32_personality (unsigned int personality) -{ - long ret; - - if (current->personality == PER_LINUX32 && personality == PER_LINUX) - personality = PER_LINUX32; - ret = sys_personality(personality); - if (ret == PER_LINUX32) - ret = PER_LINUX; - return ret; -} - -asmlinkage unsigned long -sys32_brk (unsigned int brk) -{ - unsigned long ret, obrk; - struct mm_struct *mm = current->mm; - - obrk = mm->brk; - ret = sys_brk(brk); - if (ret < obrk) - clear_user(compat_ptr(ret), PAGE_ALIGN(ret) - ret); - return ret; -} - -/* Structure for ia32 emulation on ia64 */ -struct epoll_event32 -{ - u32 events; - u32 data[2]; -}; - -asmlinkage long -sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 __user *event) -{ - mm_segment_t old_fs = get_fs(); - struct epoll_event event64; - int error; - u32 data_halfword; - - if (!access_ok(VERIFY_READ, event, sizeof(struct epoll_event32))) - return -EFAULT; - - __get_user(event64.events, &event->events); - __get_user(data_halfword, &event->data[0]); - event64.data = data_halfword; - __get_user(data_halfword, &event->data[1]); - event64.data |= (u64)data_halfword << 32; - - set_fs(KERNEL_DS); - error = sys_epoll_ctl(epfd, op, fd, (struct epoll_event __user *) &event64); - set_fs(old_fs); - - return error; -} - -asmlinkage long -sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents, - int timeout) -{ - struct epoll_event *events64 = NULL; - mm_segment_t old_fs = get_fs(); - int numevents, size; - int evt_idx; - int do_free_pages = 0; - - if (maxevents <= 0) { - return -EINVAL; - } - - /* Verify that the area passed by the user is writeable */ - if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event32))) - return -EFAULT; - - /* - * Allocate space for the intermediate copy. If the space needed - * is large enough to cause kmalloc to fail, then try again with - * __get_free_pages. - */ - size = maxevents * sizeof(struct epoll_event); - events64 = kmalloc(size, GFP_KERNEL); - if (events64 == NULL) { - events64 = (struct epoll_event *) - __get_free_pages(GFP_KERNEL, get_order(size)); - if (events64 == NULL) - return -ENOMEM; - do_free_pages = 1; - } - - /* Do the system call */ - set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/ - numevents = sys_epoll_wait(epfd, (struct epoll_event __user *) events64, - maxevents, timeout); - set_fs(old_fs); - - /* Don't modify userspace memory if we're returning an error */ - if (numevents > 0) { - /* Translate the 64-bit structures back into the 32-bit - structures */ - for (evt_idx = 0; evt_idx < numevents; evt_idx++) { - __put_user(events64[evt_idx].events, - &events[evt_idx].events); - __put_user((u32)events64[evt_idx].data, - &events[evt_idx].data[0]); - __put_user((u32)(events64[evt_idx].data >> 32), - &events[evt_idx].data[1]); - } - } - - if (do_free_pages) - free_pages((unsigned long) events64, get_order(size)); - else - kfree(events64); - return numevents; -} - -/* - * Get a yet unused TLS descriptor index. - */ -static int -get_free_idx (void) -{ - struct thread_struct *t = ¤t->thread; - int idx; - - for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) - if (desc_empty(t->tls_array + idx)) - return idx + GDT_ENTRY_TLS_MIN; - return -ESRCH; -} - -static void set_tls_desc(struct task_struct *p, int idx, - const struct ia32_user_desc *info, int n) -{ - struct thread_struct *t = &p->thread; - struct desc_struct *desc = &t->tls_array[idx - GDT_ENTRY_TLS_MIN]; - int cpu; - - /* - * We must not get preempted while modifying the TLS. - */ - cpu = get_cpu(); - - while (n-- > 0) { - if (LDT_empty(info)) { - desc->a = 0; - desc->b = 0; - } else { - desc->a = LDT_entry_a(info); - desc->b = LDT_entry_b(info); - } - - ++info; - ++desc; - } - - if (t == ¤t->thread) - load_TLS(t, cpu); - - put_cpu(); -} - -/* - * Set a given TLS descriptor: - */ -asmlinkage int -sys32_set_thread_area (struct ia32_user_desc __user *u_info) -{ - struct ia32_user_desc info; - int idx; - - if (copy_from_user(&info, u_info, sizeof(info))) - return -EFAULT; - idx = info.entry_number; - - /* - * index -1 means the kernel should try to find and allocate an empty descriptor: - */ - if (idx == -1) { - idx = get_free_idx(); - if (idx < 0) - return idx; - if (put_user(idx, &u_info->entry_number)) - return -EFAULT; - } - - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - set_tls_desc(current, idx, &info, 1); - return 0; -} - -/* - * Get the current Thread-Local Storage area: - */ - -#define GET_BASE(desc) ( \ - (((desc)->a >> 16) & 0x0000ffff) | \ - (((desc)->b << 16) & 0x00ff0000) | \ - ( (desc)->b & 0xff000000) ) - -#define GET_LIMIT(desc) ( \ - ((desc)->a & 0x0ffff) | \ - ((desc)->b & 0xf0000) ) - -#define GET_32BIT(desc) (((desc)->b >> 22) & 1) -#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) -#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) -#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) -#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) -#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) - -static void fill_user_desc(struct ia32_user_desc *info, int idx, - const struct desc_struct *desc) -{ - info->entry_number = idx; - info->base_addr = GET_BASE(desc); - info->limit = GET_LIMIT(desc); - info->seg_32bit = GET_32BIT(desc); - info->contents = GET_CONTENTS(desc); - info->read_exec_only = !GET_WRITABLE(desc); - info->limit_in_pages = GET_LIMIT_PAGES(desc); - info->seg_not_present = !GET_PRESENT(desc); - info->useable = GET_USEABLE(desc); -} - -asmlinkage int -sys32_get_thread_area (struct ia32_user_desc __user *u_info) -{ - struct ia32_user_desc info; - struct desc_struct *desc; - int idx; - - if (get_user(idx, &u_info->entry_number)) - return -EFAULT; - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; - fill_user_desc(&info, idx, desc); - - if (copy_to_user(u_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -struct regset_get { - void *kbuf; - void __user *ubuf; -}; - -struct regset_set { - const void *kbuf; - const void __user *ubuf; -}; - -struct regset_getset { - struct task_struct *target; - const struct user_regset *regset; - union { - struct regset_get get; - struct regset_set set; - } u; - unsigned int pos; - unsigned int count; - int ret; -}; - -static void getfpreg(struct task_struct *task, int regno, int *val) -{ - switch (regno / sizeof(int)) { - case 0: - *val = task->thread.fcr & 0xffff; - break; - case 1: - *val = task->thread.fsr & 0xffff; - break; - case 2: - *val = (task->thread.fsr>>16) & 0xffff; - break; - case 3: - *val = task->thread.fir; - break; - case 4: - *val = (task->thread.fir>>32) & 0xffff; - break; - case 5: - *val = task->thread.fdr; - break; - case 6: - *val = (task->thread.fdr >> 32) & 0xffff; - break; - } -} - -static void setfpreg(struct task_struct *task, int regno, int val) -{ - switch (regno / sizeof(int)) { - case 0: - task->thread.fcr = (task->thread.fcr & (~0x1f3f)) - | (val & 0x1f3f); - break; - case 1: - task->thread.fsr = (task->thread.fsr & (~0xffff)) | val; - break; - case 2: - task->thread.fsr = (task->thread.fsr & (~0xffff0000)) - | (val << 16); - break; - case 3: - task->thread.fir = (task->thread.fir & (~0xffffffff)) | val; - break; - case 5: - task->thread.fdr = (task->thread.fdr & (~0xffffffff)) | val; - break; - } -} - -static void access_fpreg_ia32(int regno, void *reg, - struct pt_regs *pt, struct switch_stack *sw, - int tos, int write) -{ - void *f; - - if ((regno += tos) >= 8) - regno -= 8; - if (regno < 4) - f = &pt->f8 + regno; - else if (regno <= 7) - f = &sw->f12 + (regno - 4); - else { - printk(KERN_ERR "regno must be less than 7 \n"); - return; - } - - if (write) - memcpy(f, reg, sizeof(struct _fpreg_ia32)); - else - memcpy(reg, f, sizeof(struct _fpreg_ia32)); -} - -static void do_fpregs_get(struct unw_frame_info *info, void *arg) -{ - struct regset_getset *dst = arg; - struct task_struct *task = dst->target; - struct pt_regs *pt; - int start, end, tos; - char buf[80]; - - if (dst->count == 0 || unw_unwind_to_user(info) < 0) - return; - if (dst->pos < 7 * sizeof(int)) { - end = min((dst->pos + dst->count), - (unsigned int)(7 * sizeof(int))); - for (start = dst->pos; start < end; start += sizeof(int)) - getfpreg(task, start, (int *)(buf + start)); - dst->ret = user_regset_copyout(&dst->pos, &dst->count, - &dst->u.get.kbuf, &dst->u.get.ubuf, buf, - 0, 7 * sizeof(int)); - if (dst->ret || dst->count == 0) - return; - } - if (dst->pos < sizeof(struct ia32_user_i387_struct)) { - pt = task_pt_regs(task); - tos = (task->thread.fsr >> 11) & 7; - end = min(dst->pos + dst->count, - (unsigned int)(sizeof(struct ia32_user_i387_struct))); - start = (dst->pos - 7 * sizeof(int)) / - sizeof(struct _fpreg_ia32); - end = (end - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32); - for (; start < end; start++) - access_fpreg_ia32(start, - (struct _fpreg_ia32 *)buf + start, - pt, info->sw, tos, 0); - dst->ret = user_regset_copyout(&dst->pos, &dst->count, - &dst->u.get.kbuf, &dst->u.get.ubuf, - buf, 7 * sizeof(int), - sizeof(struct ia32_user_i387_struct)); - if (dst->ret || dst->count == 0) - return; - } -} - -static void do_fpregs_set(struct unw_frame_info *info, void *arg) -{ - struct regset_getset *dst = arg; - struct task_struct *task = dst->target; - struct pt_regs *pt; - char buf[80]; - int end, start, tos; - - if (dst->count == 0 || unw_unwind_to_user(info) < 0) - return; - - if (dst->pos < 7 * sizeof(int)) { - start = dst->pos; - dst->ret = user_regset_copyin(&dst->pos, &dst->count, - &dst->u.set.kbuf, &dst->u.set.ubuf, buf, - 0, 7 * sizeof(int)); - if (dst->ret) - return; - for (; start < dst->pos; start += sizeof(int)) - setfpreg(task, start, *((int *)(buf + start))); - if (dst->count == 0) - return; - } - if (dst->pos < sizeof(struct ia32_user_i387_struct)) { - start = (dst->pos - 7 * sizeof(int)) / - sizeof(struct _fpreg_ia32); - dst->ret = user_regset_copyin(&dst->pos, &dst->count, - &dst->u.set.kbuf, &dst->u.set.ubuf, - buf, 7 * sizeof(int), - sizeof(struct ia32_user_i387_struct)); - if (dst->ret) - return; - pt = task_pt_regs(task); - tos = (task->thread.fsr >> 11) & 7; - end = (dst->pos - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32); - for (; start < end; start++) - access_fpreg_ia32(start, - (struct _fpreg_ia32 *)buf + start, - pt, info->sw, tos, 1); - if (dst->count == 0) - return; - } -} - -#define OFFSET(member) ((int)(offsetof(struct ia32_user_fxsr_struct, member))) -static void getfpxreg(struct task_struct *task, int start, int end, char *buf) -{ - int min_val; - - min_val = min(end, OFFSET(fop)); - while (start < min_val) { - if (start == OFFSET(cwd)) - *((short *)buf) = task->thread.fcr & 0xffff; - else if (start == OFFSET(swd)) - *((short *)buf) = task->thread.fsr & 0xffff; - else if (start == OFFSET(twd)) - *((short *)buf) = (task->thread.fsr>>16) & 0xffff; - buf += 2; - start += 2; - } - /* skip fop element */ - if (start == OFFSET(fop)) { - start += 2; - buf += 2; - } - while (start < end) { - if (start == OFFSET(fip)) - *((int *)buf) = task->thread.fir; - else if (start == OFFSET(fcs)) - *((int *)buf) = (task->thread.fir>>32) & 0xffff; - else if (start == OFFSET(foo)) - *((int *)buf) = task->thread.fdr; - else if (start == OFFSET(fos)) - *((int *)buf) = (task->thread.fdr>>32) & 0xffff; - else if (start == OFFSET(mxcsr)) - *((int *)buf) = ((task->thread.fcr>>32) & 0xff80) - | ((task->thread.fsr>>32) & 0x3f); - buf += 4; - start += 4; - } -} - -static void setfpxreg(struct task_struct *task, int start, int end, char *buf) -{ - int min_val, num32; - short num; - unsigned long num64; - - min_val = min(end, OFFSET(fop)); - while (start < min_val) { - num = *((short *)buf); - if (start == OFFSET(cwd)) { - task->thread.fcr = (task->thread.fcr & (~0x1f3f)) - | (num & 0x1f3f); - } else if (start == OFFSET(swd)) { - task->thread.fsr = (task->thread.fsr & (~0xffff)) | num; - } else if (start == OFFSET(twd)) { - task->thread.fsr = (task->thread.fsr & (~0xffff0000)) - | (((int)num) << 16); - } - buf += 2; - start += 2; - } - /* skip fop element */ - if (start == OFFSET(fop)) { - start += 2; - buf += 2; - } - while (start < end) { - num32 = *((int *)buf); - if (start == OFFSET(fip)) - task->thread.fir = (task->thread.fir & (~0xffffffff)) - | num32; - else if (start == OFFSET(foo)) - task->thread.fdr = (task->thread.fdr & (~0xffffffff)) - | num32; - else if (start == OFFSET(mxcsr)) { - num64 = num32 & 0xff10; - task->thread.fcr = (task->thread.fcr & - (~0xff1000000000UL)) | (num64<<32); - num64 = num32 & 0x3f; - task->thread.fsr = (task->thread.fsr & - (~0x3f00000000UL)) | (num64<<32); - } - buf += 4; - start += 4; - } -} - -static void do_fpxregs_get(struct unw_frame_info *info, void *arg) -{ - struct regset_getset *dst = arg; - struct task_struct *task = dst->target; - struct pt_regs *pt; - char buf[128]; - int start, end, tos; - - if (dst->count == 0 || unw_unwind_to_user(info) < 0) - return; - if (dst->pos < OFFSET(st_space[0])) { - end = min(dst->pos + dst->count, (unsigned int)32); - getfpxreg(task, dst->pos, end, buf); - dst->ret = user_regset_copyout(&dst->pos, &dst->count, - &dst->u.get.kbuf, &dst->u.get.ubuf, buf, - 0, OFFSET(st_space[0])); - if (dst->ret || dst->count == 0) - return; - } - if (dst->pos < OFFSET(xmm_space[0])) { - pt = task_pt_regs(task); - tos = (task->thread.fsr >> 11) & 7; - end = min(dst->pos + dst->count, - (unsigned int)OFFSET(xmm_space[0])); - start = (dst->pos - OFFSET(st_space[0])) / 16; - end = (end - OFFSET(st_space[0])) / 16; - for (; start < end; start++) - access_fpreg_ia32(start, buf + 16 * start, pt, - info->sw, tos, 0); - dst->ret = user_regset_copyout(&dst->pos, &dst->count, - &dst->u.get.kbuf, &dst->u.get.ubuf, - buf, OFFSET(st_space[0]), OFFSET(xmm_space[0])); - if (dst->ret || dst->count == 0) - return; - } - if (dst->pos < OFFSET(padding[0])) - dst->ret = user_regset_copyout(&dst->pos, &dst->count, - &dst->u.get.kbuf, &dst->u.get.ubuf, - &info->sw->f16, OFFSET(xmm_space[0]), - OFFSET(padding[0])); -} - -static void do_fpxregs_set(struct unw_frame_info *info, void *arg) -{ - struct regset_getset *dst = arg; - struct task_struct *task = dst->target; - char buf[128]; - int start, end; - - if (dst->count == 0 || unw_unwind_to_user(info) < 0) - return; - - if (dst->pos < OFFSET(st_space[0])) { - start = dst->pos; - dst->ret = user_regset_copyin(&dst->pos, &dst->count, - &dst->u.set.kbuf, &dst->u.set.ubuf, - buf, 0, OFFSET(st_space[0])); - if (dst->ret) - return; - setfpxreg(task, start, dst->pos, buf); - if (dst->count == 0) - return; - } - if (dst->pos < OFFSET(xmm_space[0])) { - struct pt_regs *pt; - int tos; - pt = task_pt_regs(task); - tos = (task->thread.fsr >> 11) & 7; - start = (dst->pos - OFFSET(st_space[0])) / 16; - dst->ret = user_regset_copyin(&dst->pos, &dst->count, - &dst->u.set.kbuf, &dst->u.set.ubuf, - buf, OFFSET(st_space[0]), OFFSET(xmm_space[0])); - if (dst->ret) - return; - end = (dst->pos - OFFSET(st_space[0])) / 16; - for (; start < end; start++) - access_fpreg_ia32(start, buf + 16 * start, pt, info->sw, - tos, 1); - if (dst->count == 0) - return; - } - if (dst->pos < OFFSET(padding[0])) - dst->ret = user_regset_copyin(&dst->pos, &dst->count, - &dst->u.set.kbuf, &dst->u.set.ubuf, - &info->sw->f16, OFFSET(xmm_space[0]), - OFFSET(padding[0])); -} -#undef OFFSET - -static int do_regset_call(void (*call)(struct unw_frame_info *, void *), - struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - struct regset_getset info = { .target = target, .regset = regset, - .pos = pos, .count = count, - .u.set = { .kbuf = kbuf, .ubuf = ubuf }, - .ret = 0 }; - - if (target == current) - unw_init_running(call, &info); - else { - struct unw_frame_info ufi; - memset(&ufi, 0, sizeof(ufi)); - unw_init_from_blocked_task(&ufi, target); - (*call)(&ufi, &info); - } - - return info.ret; -} - -static int ia32_fpregs_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - return do_regset_call(do_fpregs_get, target, regset, pos, count, - kbuf, ubuf); -} - -static int ia32_fpregs_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - return do_regset_call(do_fpregs_set, target, regset, pos, count, - kbuf, ubuf); -} - -static int ia32_fpxregs_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - return do_regset_call(do_fpxregs_get, target, regset, pos, count, - kbuf, ubuf); -} - -static int ia32_fpxregs_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - return do_regset_call(do_fpxregs_set, target, regset, pos, count, - kbuf, ubuf); -} - -static int ia32_genregs_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - if (kbuf) { - u32 *kp = kbuf; - while (count > 0) { - *kp++ = getreg(target, pos); - pos += 4; - count -= 4; - } - } else { - u32 __user *up = ubuf; - while (count > 0) { - if (__put_user(getreg(target, pos), up++)) - return -EFAULT; - pos += 4; - count -= 4; - } - } - return 0; -} - -static int ia32_genregs_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int ret = 0; - - if (kbuf) { - const u32 *kp = kbuf; - while (!ret && count > 0) { - putreg(target, pos, *kp++); - pos += 4; - count -= 4; - } - } else { - const u32 __user *up = ubuf; - u32 val; - while (!ret && count > 0) { - ret = __get_user(val, up++); - if (!ret) - putreg(target, pos, val); - pos += 4; - count -= 4; - } - } - return ret; -} - -static int ia32_tls_active(struct task_struct *target, - const struct user_regset *regset) -{ - struct thread_struct *t = &target->thread; - int n = GDT_ENTRY_TLS_ENTRIES; - while (n > 0 && desc_empty(&t->tls_array[n -1])) - --n; - return n; -} - -static int ia32_tls_get(struct task_struct *target, - const struct user_regset *regset, unsigned int pos, - unsigned int count, void *kbuf, void __user *ubuf) -{ - const struct desc_struct *tls; - - if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct ia32_user_desc) || - (pos % sizeof(struct ia32_user_desc)) != 0 || - (count % sizeof(struct ia32_user_desc)) != 0) - return -EINVAL; - - pos /= sizeof(struct ia32_user_desc); - count /= sizeof(struct ia32_user_desc); - - tls = &target->thread.tls_array[pos]; - - if (kbuf) { - struct ia32_user_desc *info = kbuf; - while (count-- > 0) - fill_user_desc(info++, GDT_ENTRY_TLS_MIN + pos++, - tls++); - } else { - struct ia32_user_desc __user *u_info = ubuf; - while (count-- > 0) { - struct ia32_user_desc info; - fill_user_desc(&info, GDT_ENTRY_TLS_MIN + pos++, tls++); - if (__copy_to_user(u_info++, &info, sizeof(info))) - return -EFAULT; - } - } - - return 0; -} - -static int ia32_tls_set(struct task_struct *target, - const struct user_regset *regset, unsigned int pos, - unsigned int count, const void *kbuf, const void __user *ubuf) -{ - struct ia32_user_desc infobuf[GDT_ENTRY_TLS_ENTRIES]; - const struct ia32_user_desc *info; - - if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct ia32_user_desc) || - (pos % sizeof(struct ia32_user_desc)) != 0 || - (count % sizeof(struct ia32_user_desc)) != 0) - return -EINVAL; - - if (kbuf) - info = kbuf; - else if (__copy_from_user(infobuf, ubuf, count)) - return -EFAULT; - else - info = infobuf; - - set_tls_desc(target, - GDT_ENTRY_TLS_MIN + (pos / sizeof(struct ia32_user_desc)), - info, count / sizeof(struct ia32_user_desc)); - - return 0; -} - -/* - * This should match arch/i386/kernel/ptrace.c:native_regsets. - * XXX ioperm? vm86? - */ -static const struct user_regset ia32_regsets[] = { - { - .core_note_type = NT_PRSTATUS, - .n = sizeof(struct user_regs_struct32)/4, - .size = 4, .align = 4, - .get = ia32_genregs_get, .set = ia32_genregs_set - }, - { - .core_note_type = NT_PRFPREG, - .n = sizeof(struct ia32_user_i387_struct) / 4, - .size = 4, .align = 4, - .get = ia32_fpregs_get, .set = ia32_fpregs_set - }, - { - .core_note_type = NT_PRXFPREG, - .n = sizeof(struct ia32_user_fxsr_struct) / 4, - .size = 4, .align = 4, - .get = ia32_fpxregs_get, .set = ia32_fpxregs_set - }, - { - .core_note_type = NT_386_TLS, - .n = GDT_ENTRY_TLS_ENTRIES, - .bias = GDT_ENTRY_TLS_MIN, - .size = sizeof(struct ia32_user_desc), - .align = sizeof(struct ia32_user_desc), - .active = ia32_tls_active, - .get = ia32_tls_get, .set = ia32_tls_set, - }, -}; - -const struct user_regset_view user_ia32_view = { - .name = "i386", .e_machine = EM_386, - .regsets = ia32_regsets, .n = ARRAY_SIZE(ia32_regsets) -}; - -long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, - __u32 len_low, __u32 len_high, int advice) -{ - return sys_fadvise64_64(fd, - (((u64)offset_high)<<32) | offset_low, - (((u64)len_high)<<32) | len_low, - advice); -} - -#ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */ - -asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid) -{ - uid_t sruid, seuid; - - sruid = (ruid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)ruid); - seuid = (euid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)euid); - return sys_setreuid(sruid, seuid); -} - -asmlinkage long -sys32_setresuid(compat_uid_t ruid, compat_uid_t euid, - compat_uid_t suid) -{ - uid_t sruid, seuid, ssuid; - - sruid = (ruid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)ruid); - seuid = (euid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)euid); - ssuid = (suid == (compat_uid_t)-1) ? ((uid_t)-1) : ((uid_t)suid); - return sys_setresuid(sruid, seuid, ssuid); -} - -asmlinkage long -sys32_setregid(compat_gid_t rgid, compat_gid_t egid) -{ - gid_t srgid, segid; - - srgid = (rgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)rgid); - segid = (egid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)egid); - return sys_setregid(srgid, segid); -} - -asmlinkage long -sys32_setresgid(compat_gid_t rgid, compat_gid_t egid, - compat_gid_t sgid) -{ - gid_t srgid, segid, ssgid; - - srgid = (rgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)rgid); - segid = (egid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)egid); - ssgid = (sgid == (compat_gid_t)-1) ? ((gid_t)-1) : ((gid_t)sgid); - return sys_setresgid(srgid, segid, ssgid); -} -#endif /* NOTYET */ diff --git a/arch/ia64/include/asm/ia32.h b/arch/ia64/include/asm/ia32.h deleted file mode 100644 index 2390ee145aa1..000000000000 --- a/arch/ia64/include/asm/ia32.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _ASM_IA64_IA32_H -#define _ASM_IA64_IA32_H - - -#include -#include - -#define IA32_NR_syscalls 285 /* length of syscall table */ -#define IA32_PAGE_SHIFT 12 /* 4KB pages */ - -#ifndef __ASSEMBLY__ - -# ifdef CONFIG_IA32_SUPPORT - -#define IA32_PAGE_OFFSET 0xc0000000 - -extern void ia32_cpu_init (void); -extern void ia32_mem_init (void); -extern void ia32_gdt_init (void); -extern int ia32_exception (struct pt_regs *regs, unsigned long isr); -extern int ia32_intercept (struct pt_regs *regs, unsigned long isr); -extern int ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs); - -# endif /* !CONFIG_IA32_SUPPORT */ - -/* Declare this unconditionally, so we don't get warnings for unreachable code. */ -extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs); -#if PAGE_SHIFT > IA32_PAGE_SHIFT -extern int ia32_copy_ia64_partial_page_list(struct task_struct *, - unsigned long); -extern void ia32_drop_ia64_partial_page_list(struct task_struct *); -#else -# define ia32_copy_ia64_partial_page_list(a1, a2) 0 -# define ia32_drop_ia64_partial_page_list(a1) do { ; } while (0) -#endif - -#endif /* !__ASSEMBLY__ */ - -#endif /* _ASM_IA64_IA32_H */ diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h index 7fa90f73f6be..348e44d08ce3 100644 --- a/arch/ia64/include/asm/processor.h +++ b/arch/ia64/include/asm/processor.h @@ -270,23 +270,6 @@ typedef struct { (int __user *) (addr)); \ }) -#ifdef CONFIG_IA32_SUPPORT -struct desc_struct { - unsigned int a, b; -}; - -#define desc_empty(desc) (!((desc)->a | (desc)->b)) -#define desc_equal(desc1, desc2) (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b)) - -#define GDT_ENTRY_TLS_ENTRIES 3 -#define GDT_ENTRY_TLS_MIN 6 -#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1) - -#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8) - -struct ia64_partial_page_list; -#endif - struct thread_struct { __u32 flags; /* various thread flags (see IA64_THREAD_*) */ /* writing on_ustack is performance-critical, so it's worth spending 8 bits on it... */ @@ -298,29 +281,6 @@ struct thread_struct { __u64 rbs_bot; /* the base address for the RBS */ int last_fph_cpu; /* CPU that may hold the contents of f32-f127 */ -#ifdef CONFIG_IA32_SUPPORT - __u64 eflag; /* IA32 EFLAGS reg */ - __u64 fsr; /* IA32 floating pt status reg */ - __u64 fcr; /* IA32 floating pt control reg */ - __u64 fir; /* IA32 fp except. instr. reg */ - __u64 fdr; /* IA32 fp except. data reg */ - __u64 old_k1; /* old value of ar.k1 */ - __u64 old_iob; /* old IOBase value */ - struct ia64_partial_page_list *ppl; /* partial page list for 4K page size issue */ - /* cached TLS descriptors. */ - struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; - -# define INIT_THREAD_IA32 .eflag = 0, \ - .fsr = 0, \ - .fcr = 0x17800000037fULL, \ - .fir = 0, \ - .fdr = 0, \ - .old_k1 = 0, \ - .old_iob = 0, \ - .ppl = NULL, -#else -# define INIT_THREAD_IA32 -#endif /* CONFIG_IA32_SUPPORT */ #ifdef CONFIG_PERFMON void *pfm_context; /* pointer to detailed PMU context */ unsigned long pfm_needs_checking; /* when >0, pending perfmon work on kernel exit */ @@ -342,7 +302,6 @@ struct thread_struct { .rbs_bot = STACK_TOP - DEFAULT_USER_STACK_SIZE, \ .task_size = DEFAULT_TASK_SIZE, \ .last_fph_cpu = -1, \ - INIT_THREAD_IA32 \ INIT_THREAD_PM \ .dbr = {0, }, \ .ibr = {0, }, \ @@ -485,11 +444,6 @@ extern void __ia64_load_fpu (struct ia64_fpreg *fph); extern void ia64_save_debug_regs (unsigned long *save_area); extern void ia64_load_debug_regs (unsigned long *save_area); -#ifdef CONFIG_IA32_SUPPORT -extern void ia32_save_state (struct task_struct *task); -extern void ia32_load_state (struct task_struct *task); -#endif - #define ia64_fph_enable() do { ia64_rsm(IA64_PSR_DFH); ia64_srlz_d(); } while (0) #define ia64_fph_disable() do { ia64_ssm(IA64_PSR_DFH); ia64_srlz_d(); } while (0) diff --git a/arch/ia64/include/asm/syscall.h b/arch/ia64/include/asm/syscall.h index 2f758a42f94b..a7ff1c6ab068 100644 --- a/arch/ia64/include/asm/syscall.h +++ b/arch/ia64/include/asm/syscall.h @@ -22,33 +22,18 @@ static inline long syscall_get_nr(struct task_struct *task, if ((long)regs->cr_ifs < 0) /* Not a syscall */ return -1; -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) - return regs->r1; -#endif - return regs->r15; } static inline void syscall_rollback(struct task_struct *task, struct pt_regs *regs) { -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) - regs->r8 = regs->r1; -#endif - /* do nothing */ } static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) - return regs->r8; -#endif - return regs->r10 == -1 ? regs->r8:0; } @@ -62,13 +47,6 @@ static inline void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, int error, long val) { -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) { - regs->r8 = (long) error ? error : val; - return; - } -#endif - if (error) { /* error < 0, but ia64 uses > 0 return value */ regs->r8 = -error; @@ -89,37 +67,6 @@ static inline void syscall_get_arguments(struct task_struct *task, { BUG_ON(i + n > 6); -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) { - switch (i + n) { - case 6: - if (!n--) break; - *args++ = regs->r13; - case 5: - if (!n--) break; - *args++ = regs->r15; - case 4: - if (!n--) break; - *args++ = regs->r14; - case 3: - if (!n--) break; - *args++ = regs->r10; - case 2: - if (!n--) break; - *args++ = regs->r9; - case 1: - if (!n--) break; - *args++ = regs->r11; - case 0: - if (!n--) break; - default: - BUG(); - break; - } - - return; - } -#endif ia64_syscall_get_set_arguments(task, regs, i, n, args, 0); } @@ -130,34 +77,6 @@ static inline void syscall_set_arguments(struct task_struct *task, { BUG_ON(i + n > 6); -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(regs)) { - switch (i + n) { - case 6: - if (!n--) break; - regs->r13 = *args++; - case 5: - if (!n--) break; - regs->r15 = *args++; - case 4: - if (!n--) break; - regs->r14 = *args++; - case 3: - if (!n--) break; - regs->r10 = *args++; - case 2: - if (!n--) break; - regs->r9 = *args++; - case 1: - if (!n--) break; - regs->r11 = *args++; - case 0: - if (!n--) break; - } - - return; - } -#endif ia64_syscall_get_set_arguments(task, regs, i, n, args, 1); } #endif /* _ASM_SYSCALL_H */ diff --git a/arch/ia64/include/asm/system.h b/arch/ia64/include/asm/system.h index 927a381c20ca..9f342a574ce8 100644 --- a/arch/ia64/include/asm/system.h +++ b/arch/ia64/include/asm/system.h @@ -191,15 +191,6 @@ do { \ #ifdef __KERNEL__ -#ifdef CONFIG_IA32_SUPPORT -# define IS_IA32_PROCESS(regs) (ia64_psr(regs)->is != 0) -#else -# define IS_IA32_PROCESS(regs) 0 -struct task_struct; -static inline void ia32_save_state(struct task_struct *t __attribute__((unused))){} -static inline void ia32_load_state(struct task_struct *t __attribute__((unused))){} -#endif - /* * Context switch from one thread to another. If the two threads have * different address spaces, schedule() has already taken care of @@ -233,7 +224,7 @@ extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct #define IA64_HAS_EXTRA_STATE(t) \ ((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID) \ - || IS_IA32_PROCESS(task_pt_regs(t)) || PERFMON_IS_SYSWIDE()) + || PERFMON_IS_SYSWIDE()) #define __switch_to(prev,next,last) do { \ IA64_ACCOUNT_ON_SWITCH(prev, next); \ diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index 10a8f21ca9e3..bb8b0fff32b3 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h @@ -335,20 +335,6 @@ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND -#ifdef CONFIG_IA32_SUPPORT -# define __ARCH_WANT_SYS_FADVISE64 -# define __ARCH_WANT_SYS_GETPGRP -# define __ARCH_WANT_SYS_LLSEEK -# define __ARCH_WANT_SYS_NICE -# define __ARCH_WANT_SYS_OLD_GETRLIMIT -# define __ARCH_WANT_SYS_OLDUMOUNT -# define __ARCH_WANT_SYS_PAUSE -# define __ARCH_WANT_SYS_SIGPENDING -# define __ARCH_WANT_SYS_SIGPROCMASK -# define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND -# define __ARCH_WANT_COMPAT_SYS_TIME -#endif - #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) #include diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c index f3802ae89b10..96a9d18ff4c4 100644 --- a/arch/ia64/kernel/audit.c +++ b/arch/ia64/kernel/audit.c @@ -30,20 +30,11 @@ static unsigned signal_class[] = { int audit_classify_arch(int arch) { -#ifdef CONFIG_IA32_SUPPORT - if (arch == AUDIT_ARCH_I386) - return 1; -#endif return 0; } int audit_classify_syscall(int abi, unsigned syscall) { -#ifdef CONFIG_IA32_SUPPORT - extern int ia32_classify_syscall(unsigned); - if (abi == AUDIT_ARCH_I386) - return ia32_classify_syscall(syscall); -#endif switch(syscall) { case __NR_open: return 2; @@ -58,18 +49,6 @@ int audit_classify_syscall(int abi, unsigned syscall) static int __init audit_classes_init(void) { -#ifdef CONFIG_IA32_SUPPORT - extern __u32 ia32_dir_class[]; - extern __u32 ia32_write_class[]; - extern __u32 ia32_read_class[]; - extern __u32 ia32_chattr_class[]; - extern __u32 ia32_signal_class[]; - audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class); - audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class); - audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); - audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); - audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class); -#endif audit_register_class(AUDIT_CLASS_WRITE, write_class); audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index d75b872ca4dc..9a260b317d8d 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -71,15 +71,6 @@ ENTRY(ia64_execve) add out3=16,sp // regs br.call.sptk.many rp=sys_execve .ret0: -#ifdef CONFIG_IA32_SUPPORT - /* - * Check if we're returning to ia32 mode. If so, we need to restore ia32 registers - * from pt_regs. - */ - adds r16=PT(CR_IPSR)+16,sp - ;; - ld8 r16=[r16] -#endif cmp4.ge p6,p7=r8,r0 mov ar.pfs=loc1 // restore ar.pfs sxt4 r8=r8 // return 64-bit result @@ -108,12 +99,6 @@ ENTRY(ia64_execve) ldf.fill f23=[sp]; ldf.fill f24=[sp]; mov f25=f0 ldf.fill f26=[sp]; ldf.fill f27=[sp]; mov f28=f0 ldf.fill f29=[sp]; ldf.fill f30=[sp]; mov f31=f0 -#ifdef CONFIG_IA32_SUPPORT - tbit.nz p6,p0=r16, IA64_PSR_IS_BIT - movl loc0=ia64_ret_from_ia32_execve - ;; -(p6) mov rp=loc0 -#endif br.ret.sptk.many rp END(ia64_execve) @@ -848,30 +833,6 @@ __paravirt_work_processed_syscall: br.cond.sptk.many rbs_switch // B END(__paravirt_leave_syscall) -#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE -#ifdef CONFIG_IA32_SUPPORT -GLOBAL_ENTRY(ia64_ret_from_ia32_execve) - PT_REGS_UNWIND_INFO(0) - adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 - adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10 - ;; - .mem.offset 0,0 - st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit - .mem.offset 8,0 - st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit -#ifdef CONFIG_PARAVIRT - ;; - // don't fall through, ia64_leave_kernel may be #define'd - br.cond.sptk.few ia64_leave_kernel - ;; -#endif /* CONFIG_PARAVIRT */ -END(ia64_ret_from_ia32_execve) -#ifndef CONFIG_PARAVIRT - // fall through -#endif -#endif /* CONFIG_IA32_SUPPORT */ -#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */ - GLOBAL_ENTRY(__paravirt_leave_kernel) PT_REGS_UNWIND_INFO(0) /* diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index ec9a5fdfa1b9..179fd122e837 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -49,7 +49,6 @@ #include #include -#include #include #include #include @@ -1386,28 +1385,6 @@ END(ia32_exception) // 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71) ENTRY(ia32_intercept) DBG_FAULT(46) -#ifdef CONFIG_IA32_SUPPORT - mov r31=pr - MOV_FROM_ISR(r16) - ;; - extr.u r17=r16,16,8 // get ISR.code - mov r18=ar.eflag - MOV_FROM_IIM(r19) // old eflag value - ;; - cmp.ne p6,p0=2,r17 -(p6) br.cond.spnt 1f // not a system flag fault - xor r16=r18,r19 - ;; - extr.u r17=r16,18,1 // get the eflags.ac bit - ;; - cmp.eq p6,p0=0,r17 -(p6) br.cond.spnt 1f // eflags.ac bit didn't change - ;; - mov pr=r31,-1 // restore predicate registers - RFI - -1: -#endif // CONFIG_IA32_SUPPORT FAULT(46) END(ia32_intercept) @@ -1416,12 +1393,7 @@ END(ia32_intercept) // 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74) ENTRY(ia32_interrupt) DBG_FAULT(47) -#ifdef CONFIG_IA32_SUPPORT - mov r31=pr - br.sptk.many dispatch_to_ia32_handler -#else FAULT(47) -#endif END(ia32_interrupt) .org ia64_ivt+0x6c00 @@ -1715,89 +1687,3 @@ ENTRY(dispatch_illegal_op_fault) (p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel br.sptk.many ia64_leave_kernel END(dispatch_illegal_op_fault) - -#ifdef CONFIG_IA32_SUPPORT - - /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... - */ - - // IA32 interrupt entry point - -ENTRY(dispatch_to_ia32_handler) - SAVE_MIN - ;; - MOV_FROM_ISR(r14) - SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24) - // guarantee that interruption collection is on - ;; - SSM_PSR_I(p15, p15, r3) - adds r3=8,r2 // Base pointer for SAVE_REST - ;; - SAVE_REST - ;; - mov r15=0x80 - shr r14=r14,16 // Get interrupt number - ;; - cmp.ne p6,p0=r14,r15 -(p6) br.call.dpnt.many b6=non_ia32_syscall - - adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions - adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp - ;; - cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 - ld8 r8=[r14] // get r8 - ;; - st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP) - ;; - alloc r15=ar.pfs,0,0,6,0 // must first in an insn group - ;; - ld4 r8=[r14],8 // r8 == eax (syscall number) - mov r15=IA32_NR_syscalls - ;; - cmp.ltu.unc p6,p7=r8,r15 - ld4 out1=[r14],8 // r9 == ecx - ;; - ld4 out2=[r14],8 // r10 == edx - ;; - ld4 out0=[r14] // r11 == ebx - adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp - ;; - ld4 out5=[r14],PT(R14)-PT(R13) // r13 == ebp - ;; - ld4 out3=[r14],PT(R15)-PT(R14) // r14 == esi - adds r2=TI_FLAGS+IA64_TASK_SIZE,r13 - ;; - ld4 out4=[r14] // r15 == edi - movl r16=ia32_syscall_table - ;; -(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number - ld4 r2=[r2] // r2 = current_thread_info()->flags - ;; - ld8 r16=[r16] - and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit - ;; - mov b6=r16 - movl r15=ia32_ret_from_syscall - cmp.eq p8,p0=r2,r0 - ;; - mov rp=r15 -(p8) br.call.sptk.many b6=b6 - br.cond.sptk ia32_trace_syscall - -non_ia32_syscall: - alloc r15=ar.pfs,0,0,2,0 - mov out0=r14 // interrupt # - add out1=16,sp // pointer to pt_regs - ;; // avoid WAW on CFM - br.call.sptk.many rp=ia32_bad_interrupt -.ret1: movl r15=ia64_leave_kernel - ;; - mov rp=r15 - br.ret.sptk.many rp -END(dispatch_to_ia32_handler) - -#endif /* CONFIG_IA32_SUPPORT */ diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 9bcec9945c12..883ecc9cfef5 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -358,11 +357,6 @@ ia64_save_extra (struct task_struct *task) if (info & PFM_CPUINFO_SYST_WIDE) pfm_syst_wide_update_task(task, info, 0); #endif - -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(task_pt_regs(task))) - ia32_save_state(task); -#endif } void @@ -383,11 +377,6 @@ ia64_load_extra (struct task_struct *task) if (info & PFM_CPUINFO_SYST_WIDE) pfm_syst_wide_update_task(task, info, 1); #endif - -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(task_pt_regs(task))) - ia32_load_state(task); -#endif } /* @@ -426,7 +415,7 @@ copy_thread(unsigned long clone_flags, unsigned long user_stack_base, unsigned long user_stack_size, struct task_struct *p, struct pt_regs *regs) { - extern char ia64_ret_from_clone, ia32_ret_from_clone; + extern char ia64_ret_from_clone; struct switch_stack *child_stack, *stack; unsigned long rbs, child_rbs, rbs_size; struct pt_regs *child_ptregs; @@ -457,7 +446,7 @@ copy_thread(unsigned long clone_flags, memcpy((void *) child_rbs, (void *) rbs, rbs_size); if (likely(user_mode(child_ptregs))) { - if ((clone_flags & CLONE_SETTLS) && !IS_IA32_PROCESS(regs)) + if (clone_flags & CLONE_SETTLS) child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ if (user_stack_base) { child_ptregs->r12 = user_stack_base + user_stack_size - 16; @@ -477,10 +466,7 @@ copy_thread(unsigned long clone_flags, child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */ } child_stack->ar_bspstore = child_rbs + rbs_size; - if (IS_IA32_PROCESS(regs)) - child_stack->b0 = (unsigned long) &ia32_ret_from_clone; - else - child_stack->b0 = (unsigned long) &ia64_ret_from_clone; + child_stack->b0 = (unsigned long) &ia64_ret_from_clone; /* copy parts of thread_struct: */ p->thread.ksp = (unsigned long) child_stack - 16; @@ -515,22 +501,6 @@ copy_thread(unsigned long clone_flags, p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | THREAD_FLAGS_TO_SET); ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ -#ifdef CONFIG_IA32_SUPPORT - /* - * If we're cloning an IA32 task then save the IA32 extra - * state from the current task to the new task - */ - if (IS_IA32_PROCESS(task_pt_regs(current))) { - ia32_save_state(p); - if (clone_flags & CLONE_SETTLS) - retval = ia32_clone_tls(p, child_ptregs); - - /* Copy partially mapped page list */ - if (!retval) - retval = ia32_copy_ia64_partial_page_list(p, - clone_flags); - } -#endif #ifdef CONFIG_PERFMON if (current->thread.pfm_context) @@ -704,15 +674,6 @@ EXPORT_SYMBOL(kernel_thread); int kernel_thread_helper (int (*fn)(void *), void *arg) { -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(task_pt_regs(current))) { - /* A kernel thread is always a 64-bit process. */ - current->thread.map_base = DEFAULT_MAP_BASE; - current->thread.task_size = DEFAULT_TASK_SIZE; - ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob); - ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1); - } -#endif return (*fn)(arg); } @@ -725,14 +686,6 @@ flush_thread (void) /* drop floating-point and debug-register state if it exists: */ current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID); ia64_drop_fpu(current); -#ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(task_pt_regs(current))) { - ia32_drop_ia64_partial_page_list(current); - current->thread.task_size = IA32_PAGE_OFFSET; - set_fs(USER_DS); - memset(current->thread.tls_array, 0, sizeof(current->thread.tls_array)); - } -#endif } /* @@ -753,8 +706,6 @@ exit_thread (void) if (current->thread.flags & IA64_THREAD_DBG_VALID) pfm_release_debug_registers(current); #endif - if (IS_IA32_PROCESS(task_pt_regs(current))) - ia32_drop_ia64_partial_page_list(current); } unsigned long diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 9daa87fdb018..b61afbbe076f 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -1250,13 +1250,8 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, long syscall; int arch; - if (IS_IA32_PROCESS(®s)) { - syscall = regs.r1; - arch = AUDIT_ARCH_I386; - } else { - syscall = regs.r15; - arch = AUDIT_ARCH_IA64; - } + syscall = regs.r15; + arch = AUDIT_ARCH_IA64; audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3); } @@ -2172,11 +2167,6 @@ static const struct user_regset_view user_ia64_view = { const struct user_regset_view *task_user_regset_view(struct task_struct *tsk) { -#ifdef CONFIG_IA32_SUPPORT - extern const struct user_regset_view user_ia32_view; - if (IS_IA32_PROCESS(task_pt_regs(tsk))) - return &user_ia32_view; -#endif return &user_ia64_view; } diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index a1ea87919777..41ae6a596b50 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include @@ -1016,10 +1015,6 @@ cpu_init (void) ia64_mmu_init(ia64_imva(cpu_data)); ia64_mca_cpu_init(ia64_imva(cpu_data)); -#ifdef CONFIG_IA32_SUPPORT - ia32_cpu_init(); -#endif - /* Clear ITC to eliminate sched_clock() overflows in human time. */ ia64_set_itc(0); diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index e1821ca4c7df..7bdafc8788bd 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -425,14 +424,8 @@ static long handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct sigscratch *scr) { - if (IS_IA32_PROCESS(&scr->pt)) { - /* send signal to IA-32 process */ - if (!ia32_setup_frame1(sig, ka, info, oldset, &scr->pt)) - return 0; - } else - /* send signal to IA-64 process */ - if (!setup_frame(sig, ka, info, oldset, scr)) - return 0; + if (!setup_frame(sig, ka, info, oldset, scr)) + return 0; spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); @@ -462,7 +455,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) siginfo_t info; long restart = in_syscall; long errno = scr->pt.r8; -# define ERR_CODE(c) (IS_IA32_PROCESS(&scr->pt) ? -(c) : (c)) /* * In the ia64_leave_kernel code path, we want the common case to go fast, which @@ -490,14 +482,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) * inferior call), thus it's important to check for restarting _after_ * get_signal_to_deliver(). */ - if (IS_IA32_PROCESS(&scr->pt)) { - if (in_syscall) { - if (errno >= 0) - restart = 0; - else - errno = -errno; - } - } else if ((long) scr->pt.r10 != -1) + if ((long) scr->pt.r10 != -1) /* * A system calls has to be restarted only if one of the error codes * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10 @@ -513,22 +498,18 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) switch (errno) { case ERESTART_RESTARTBLOCK: case ERESTARTNOHAND: - scr->pt.r8 = ERR_CODE(EINTR); + scr->pt.r8 = EINTR; /* note: scr->pt.r10 is already -1 */ break; case ERESTARTSYS: if ((ka.sa.sa_flags & SA_RESTART) == 0) { - scr->pt.r8 = ERR_CODE(EINTR); + scr->pt.r8 = EINTR; /* note: scr->pt.r10 is already -1 */ break; } case ERESTARTNOINTR: - if (IS_IA32_PROCESS(&scr->pt)) { - scr->pt.r8 = scr->pt.r1; - scr->pt.cr_iip -= 2; - } else - ia64_decrement_ip(&scr->pt); + ia64_decrement_ip(&scr->pt); restart = 0; /* don't restart twice if handle_signal() fails... */ } } @@ -555,21 +536,14 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) if (errno == ERESTARTNOHAND || errno == ERESTARTSYS || errno == ERESTARTNOINTR || errno == ERESTART_RESTARTBLOCK) { - if (IS_IA32_PROCESS(&scr->pt)) { - scr->pt.r8 = scr->pt.r1; - scr->pt.cr_iip -= 2; - if (errno == ERESTART_RESTARTBLOCK) - scr->pt.r8 = 0; /* x86 version of __NR_restart_syscall */ - } else { - /* - * Note: the syscall number is in r15 which is saved in - * pt_regs so all we need to do here is adjust ip so that - * the "break" instruction gets re-executed. - */ - ia64_decrement_ip(&scr->pt); - if (errno == ERESTART_RESTARTBLOCK) - scr->pt.r15 = __NR_restart_syscall; - } + /* + * Note: the syscall number is in r15 which is saved in + * pt_regs so all we need to do here is adjust ip so that + * the "break" instruction gets re-executed. + */ + ia64_decrement_ip(&scr->pt); + if (errno == ERESTART_RESTARTBLOCK) + scr->pt.r15 = __NR_restart_syscall; } } diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index de100aa7ff03..e5230b2ff2c5 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -443,10 +442,6 @@ smp_callin (void) calibrate_delay(); local_cpu_data->loops_per_jiffy = loops_per_jiffy; -#ifdef CONFIG_IA32_SUPPORT - ia32_gdt_init(); -#endif - /* * Allow the master to continue. */ diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index f0cda765e681..fd80e70018a9 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -626,10 +625,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, break; case 45: -#ifdef CONFIG_IA32_SUPPORT - if (ia32_exception(®s, isr) == 0) - return; -#endif printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n"); printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", iip, ifa, isr); @@ -637,10 +632,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, break; case 46: -#ifdef CONFIG_IA32_SUPPORT - if (ia32_intercept(®s, isr) == 0) - return; -#endif printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n"); printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n", iip, ifa, isr, iim); diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 7c0d4814a68d..ca3335ea56cc 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -668,10 +667,6 @@ mem_init (void) fsyscall_table[i] = sys_call_table[i] | 1; } setup_gate(); - -#ifdef CONFIG_IA32_SUPPORT - ia32_mem_init(); -#endif } #ifdef CONFIG_MEMORY_HOTPLUG diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S index e32dae444dd6..08847aa12583 100644 --- a/arch/ia64/xen/hypercall.S +++ b/arch/ia64/xen/hypercall.S @@ -58,11 +58,6 @@ __HCALL2(xen_ptcga, HYPERPRIVOP_PTC_GA) __HCALL2(xen_set_rr, HYPERPRIVOP_SET_RR) __HCALL2(xen_set_kr, HYPERPRIVOP_SET_KR) -#ifdef CONFIG_IA32_SUPPORT -__HCALL0(xen_get_eflag, HYPERPRIVOP_GET_EFLAG) -__HCALL1(xen_set_eflag, HYPERPRIVOP_SET_EFLAG) // refer SDM vol1 3.1.8 -#endif /* CONFIG_IA32_SUPPORT */ - GLOBAL_ENTRY(xen_set_rr0_to_rr4) mov r8=r32 mov r9=r33 diff --git a/arch/ia64/xen/xen_pv_ops.c b/arch/ia64/xen/xen_pv_ops.c index 5e2270a999fa..8adc6a14272a 100644 --- a/arch/ia64/xen/xen_pv_ops.c +++ b/arch/ia64/xen/xen_pv_ops.c @@ -301,11 +301,6 @@ static void xen_setreg(int regnum, unsigned long val) case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: xen_set_kr(regnum - _IA64_REG_AR_KR0, val); break; -#ifdef CONFIG_IA32_SUPPORT - case _IA64_REG_AR_EFLAG: - xen_set_eflag(val); - break; -#endif case _IA64_REG_AR_ITC: xen_set_itc(val); break; @@ -332,11 +327,6 @@ static unsigned long xen_getreg(int regnum) case _IA64_REG_PSR: res = xen_get_psr(); break; -#ifdef CONFIG_IA32_SUPPORT - case _IA64_REG_AR_EFLAG: - res = xen_get_eflag(); - break; -#endif case _IA64_REG_AR_ITC: res = xen_get_itc(); break; @@ -710,9 +700,6 @@ extern unsigned long xen_getreg(int regnum); __DEFINE_FUNC(getreg, __DEFINE_GET_REG(PSR, PSR) -#ifdef CONFIG_IA32_SUPPORT - __DEFINE_GET_REG(AR_EFLAG, EFLAG) -#endif /* get_itc */ "mov r2 = " __stringify(_IA64_REG_AR_ITC) "\n" @@ -789,9 +776,6 @@ __DEFINE_FUNC(setreg, ";;\n" "(p6) br.cond.spnt xen_set_itc\n" -#ifdef CONFIG_IA32_SUPPORT - __DEFINE_SET_REG(AR_EFLAG, SET_EFLAG) -#endif __DEFINE_SET_REG(CR_TPR, SET_TPR) __DEFINE_SET_REG(CR_EOI, EOI) diff --git a/drivers/input/input-compat.h b/drivers/input/input-compat.h index 47cd9eaee66a..4d8ea32e8a00 100644 --- a/drivers/input/input-compat.h +++ b/drivers/input/input-compat.h @@ -21,8 +21,6 @@ you why the ifdefs are needed? Think about it again. -AK */ #ifdef CONFIG_X86_64 # define INPUT_COMPAT_TEST is_compat_task() -#elif defined(CONFIG_IA64) -# define INPUT_COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current)) #elif defined(CONFIG_S390) # define INPUT_COMPAT_TEST test_thread_flag(TIF_31BIT) #elif defined(CONFIG_MIPS) -- cgit v1.2.3 From 74e7e725e4766a2045708d274d4d07cd4fae8adc Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Sun, 7 Feb 2010 23:10:05 -0800 Subject: Input: mark {corgi,spitz,tosa}kbd drivers deprecated Provided that now keyboards on these devices are fully supported by generic GPIO based matrix keypad driver, mark these hardcoded and difficult to maintain drivers as deprecated. Signed-off-by: Eric Miao Acked-by: Pavel Machek Signed-off-by: Dmitry Torokhov --- Documentation/feature-removal-schedule.txt | 11 +++++++++++ drivers/input/keyboard/Kconfig | 18 ++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 0a46833c1b76..f8dc4d92e114 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -542,3 +542,14 @@ Why: Duplicate functionality with the gspca_zc3xx driver, zc0301 only sensors) wich are also supported by the gspca_zc3xx driver (which supports 53 USB-ID's in total) Who: Hans de Goede + +---------------------------- + +What: corgikbd, spitzkbd, tosakbd driver +When: 2.6.35 +Files: drivers/input/keyboard/{corgi,spitz,tosa}kbd.c +Why: We now have a generic GPIO based matrix keyboard driver that + are fully capable of handling all the keys on these devices. + The original drivers manipulate the GPIO registers directly + and so are difficult to maintain. +Who: Eric Miao diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 616a3916d187..1ad9435d30aa 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -144,13 +144,15 @@ config KEYBOARD_BFIN module will be called bf54x-keys. config KEYBOARD_CORGI - tristate "Corgi keyboard" + tristate "Corgi keyboard (deprecated)" depends on PXA_SHARPSL - default y help Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx series of PDAs. + This driver is now deprecated, use generic GPIO based matrix + keyboard driver instead. + To compile this driver as a module, choose M here: the module will be called corgikbd. @@ -338,13 +340,15 @@ config KEYBOARD_PXA930_ROTARY module will be called pxa930_rotary. config KEYBOARD_SPITZ - tristate "Spitz keyboard" + tristate "Spitz keyboard (deprecated)" depends on PXA_SHARPSL - default y help Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, SL-C3000 and Sl-C3100 series of PDAs. + This driver is now deprecated, use generic GPIO based matrix + keyboard driver instead. + To compile this driver as a module, choose M here: the module will be called spitzkbd. @@ -411,12 +415,14 @@ config KEYBOARD_TWL4030 module will be called twl4030_keypad. config KEYBOARD_TOSA - tristate "Tosa keyboard" + tristate "Tosa keyboard (deprecated)" depends on MACH_TOSA - default y help Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) + This driver is now deprecated, use generic GPIO based matrix + keyboard driver instead. + To compile this driver as a module, choose M here: the module will be called tosakbd. -- cgit v1.2.3 From b63de38591605916fff5d483e0bedc65dfe3d395 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Sun, 7 Feb 2010 23:10:05 -0800 Subject: Input: schedule corgi_ssp and corgi_ts to be removed Signed-off-by: Eric Miao Acked-by: Richard Purdie Acked-by: Pavel Machek Signed-off-by: Dmitry Torokhov --- Documentation/feature-removal-schedule.txt | 12 ++++++++++++ drivers/input/touchscreen/Kconfig | 1 - 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index f8dc4d92e114..54d2d7795544 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -553,3 +553,15 @@ Why: We now have a generic GPIO based matrix keyboard driver that The original drivers manipulate the GPIO registers directly and so are difficult to maintain. Who: Eric Miao + +---------------------------- + +What: corgi_ssp and corgi_ts driver +When: 2.6.35 +Files: arch/arm/mach-pxa/corgi_ssp.c, drivers/input/touchscreen/corgi_ts.c +Why: The corgi touchscreen is now deprecated in favour of the generic + ads7846.c driver. The noise reduction technique used in corgi_ts.c, + that's to wait till vsync before ADC sampling, is also integrated into + ads7846 driver now. Provided that the original driver is not generic + and is difficult to maintain, it will be removed later. +Who: Eric Miao diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index a1e2d845f680..6457e060ae49 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -90,7 +90,6 @@ config TOUCHSCREEN_CORGI tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" depends on PXA_SHARPSL select CORGI_SSP_DEPRECATED - default y help Say Y here to enable the driver for the touchscreen on the Sharp SL-C7xx and SL-Cxx00 series of PDAs. -- cgit v1.2.3 From 2b14a808fbbb042d0de323260d939bdf95e9efdf Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 10 Feb 2010 22:13:21 -0800 Subject: Input: sh_keysc - factor out hw access functions Update the sh_keysc driver to factor out the register access functions sh_keysc_read(), sh_keysc_write() together with sh_keysc_level_mode(). This makes the code a bit easier to follow. Signed-off-by: Magnus Damm Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/sh_keysc.c | 69 ++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 26 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index efcc3a3b9b53..6218b2f02495 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -22,14 +22,6 @@ #include #include -#define KYCR1_OFFS 0x00 -#define KYCR2_OFFS 0x04 -#define KYINDR_OFFS 0x08 -#define KYOUTDR_OFFS 0x0c - -#define KYCR2_IRQ_LEVEL 0x10 -#define KYCR2_IRQ_DISABLED 0x00 - static const struct { unsigned char kymd, keyout, keyin; } sh_keysc_mode[] = { @@ -48,6 +40,37 @@ struct sh_keysc_priv { struct sh_keysc_info pdata; }; +#define KYCR1 0 +#define KYCR2 1 +#define KYINDR 2 +#define KYOUTDR 3 + +#define KYCR2_IRQ_LEVEL 0x10 +#define KYCR2_IRQ_DISABLED 0x00 + +static unsigned long sh_keysc_read(struct sh_keysc_priv *p, int reg_nr) +{ + return ioread16(p->iomem_base + (reg_nr << 2)); +} + +static void sh_keysc_write(struct sh_keysc_priv *p, int reg_nr, + unsigned long value) +{ + iowrite16(value, p->iomem_base + (reg_nr << 2)); +} + +static void sh_keysc_level_mode(struct sh_keysc_priv *p, + unsigned long keys_set) +{ + struct sh_keysc_info *pdata = &p->pdata; + + sh_keysc_write(p, KYOUTDR, 0); + sh_keysc_write(p, KYCR2, KYCR2_IRQ_LEVEL | (keys_set << 8)); + + if (pdata->kycr2_delay) + udelay(pdata->kycr2_delay); +} + static irqreturn_t sh_keysc_isr(int irq, void *dev_id) { struct platform_device *pdev = dev_id; @@ -66,24 +89,19 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id) keys = 0; keyin_set = 0; - iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); + sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED); for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) { - iowrite16(0xfff ^ (3 << (i * 2)), - priv->iomem_base + KYOUTDR_OFFS); + sh_keysc_write(priv, KYOUTDR, 0xfff ^ (3 << (i * 2))); udelay(pdata->delay); - tmp = ioread16(priv->iomem_base + KYINDR_OFFS); + tmp = sh_keysc_read(priv, KYINDR); + keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i); tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1; keyin_set |= tmp; } - iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); - iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8), - priv->iomem_base + KYCR2_OFFS); - - if (pdata->kycr2_delay) - udelay(pdata->kycr2_delay); + sh_keysc_level_mode(priv, keyin_set); keys ^= ~0; keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * @@ -93,7 +111,7 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id) dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys); - } while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01); + } while (sh_keysc_read(priv, KYCR2) & 0x01); dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n", priv->last_keys, keys0, keys1); @@ -220,10 +238,9 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) clk_enable(priv->clk); - iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) | - pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); - iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); - iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); + sh_keysc_write(priv, KYCR1, (sh_keysc_mode[pdata->mode].kymd << 8) | + pdata->scan_timing); + sh_keysc_level_mode(priv, 0); device_init_wakeup(&pdev->dev, 1); @@ -248,7 +265,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) { struct sh_keysc_priv *priv = platform_get_drvdata(pdev); - iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); + sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED); input_unregister_device(priv->input); free_irq(platform_get_irq(pdev, 0), pdev); @@ -270,7 +287,7 @@ static int sh_keysc_suspend(struct device *dev) int irq = platform_get_irq(pdev, 0); unsigned short value; - value = ioread16(priv->iomem_base + KYCR1_OFFS); + value = sh_keysc_read(priv, KYCR1); if (device_may_wakeup(dev)) { value |= 0x80; @@ -279,7 +296,7 @@ static int sh_keysc_suspend(struct device *dev) value &= ~0x80; } - iowrite16(value, priv->iomem_base + KYCR1_OFFS); + sh_keysc_write(priv, KYCR1, value); return 0; } -- cgit v1.2.3 From 324e5ade1569111a40c349726d8a2694b28d7943 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 10 Feb 2010 22:13:21 -0800 Subject: Input: sh_keysc - switch to using bitmaps Use bitmaps instead of using 32-bit integers to keep track of the key states. With this change in place the driver supports key pads with more than 32 keys. Signed-off-by: Magnus Damm Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/sh_keysc.c | 69 +++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 25 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 6218b2f02495..c2fc97732f0c 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,7 @@ static const struct { struct sh_keysc_priv { void __iomem *iomem_base; struct clk *clk; - unsigned long last_keys; + DECLARE_BITMAP(last_keys, SH_KEYSC_MAXKEYS); struct input_dev *input; struct sh_keysc_info pdata; }; @@ -71,69 +72,87 @@ static void sh_keysc_level_mode(struct sh_keysc_priv *p, udelay(pdata->kycr2_delay); } +static void sh_keysc_map_dbg(struct device *dev, unsigned long *map, + const char *str) +{ + int k; + + for (k = 0; k < BITS_TO_LONGS(SH_KEYSC_MAXKEYS); k++) + dev_dbg(dev, "%s[%d] 0x%lx\n", str, k, map[k]); +} + static irqreturn_t sh_keysc_isr(int irq, void *dev_id) { struct platform_device *pdev = dev_id; struct sh_keysc_priv *priv = platform_get_drvdata(pdev); struct sh_keysc_info *pdata = &priv->pdata; - unsigned long keys, keys1, keys0, mask; + int keyout_nr = sh_keysc_mode[pdata->mode].keyout; + int keyin_nr = sh_keysc_mode[pdata->mode].keyin; + DECLARE_BITMAP(keys, SH_KEYSC_MAXKEYS); + DECLARE_BITMAP(keys0, SH_KEYSC_MAXKEYS); + DECLARE_BITMAP(keys1, SH_KEYSC_MAXKEYS); unsigned char keyin_set, tmp; - int i, k; + int i, k, n; dev_dbg(&pdev->dev, "isr!\n"); - keys1 = ~0; - keys0 = 0; + bitmap_fill(keys1, SH_KEYSC_MAXKEYS); + bitmap_zero(keys0, SH_KEYSC_MAXKEYS); do { - keys = 0; + bitmap_zero(keys, SH_KEYSC_MAXKEYS); keyin_set = 0; sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED); - for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) { + for (i = 0; i < keyout_nr; i++) { + n = keyin_nr * i; + + /* drive one KEYOUT pin low, read KEYIN pins */ sh_keysc_write(priv, KYOUTDR, 0xfff ^ (3 << (i * 2))); udelay(pdata->delay); tmp = sh_keysc_read(priv, KYINDR); - keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i); - tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1; - keyin_set |= tmp; + /* set bit if key press has been detected */ + for (k = 0; k < keyin_nr; k++) { + if (tmp & (1 << k)) + __set_bit(n + k, keys); + } + + /* keep track of which KEYIN bits that have been set */ + keyin_set |= tmp ^ ((1 << keyin_nr) - 1); } sh_keysc_level_mode(priv, keyin_set); - keys ^= ~0; - keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * - sh_keysc_mode[pdata->mode].keyout)) - 1; - keys1 &= keys; - keys0 |= keys; + bitmap_complement(keys, keys, SH_KEYSC_MAXKEYS); + bitmap_and(keys1, keys1, keys, SH_KEYSC_MAXKEYS); + bitmap_or(keys0, keys0, keys, SH_KEYSC_MAXKEYS); - dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys); + sh_keysc_map_dbg(&pdev->dev, keys, "keys"); } while (sh_keysc_read(priv, KYCR2) & 0x01); - dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n", - priv->last_keys, keys0, keys1); + sh_keysc_map_dbg(&pdev->dev, priv->last_keys, "last_keys"); + sh_keysc_map_dbg(&pdev->dev, keys0, "keys0"); + sh_keysc_map_dbg(&pdev->dev, keys1, "keys1"); for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { k = pdata->keycodes[i]; if (!k) continue; - mask = 1 << i; - - if (!((priv->last_keys ^ keys0) & mask)) + if (test_bit(i, keys0) == test_bit(i, priv->last_keys)) continue; - if ((keys1 | keys0) & mask) { + if (test_bit(i, keys1) || test_bit(i, keys0)) { input_event(priv->input, EV_KEY, k, 1); - priv->last_keys |= mask; + __set_bit(i, priv->last_keys); } - if (!(keys1 & mask)) { + if (!test_bit(i, keys1)) { input_event(priv->input, EV_KEY, k, 0); - priv->last_keys &= ~mask; + __clear_bit(i, priv->last_keys); } } -- cgit v1.2.3 From 8f8be2439cd368cc6ba94888919ee90b5a26f0cb Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 10 Feb 2010 23:03:22 -0800 Subject: Input: sh_keysc - update the driver with mode 6 Add mode 6 support to the sh_keysc driver. Also update the KYOUTDR mask value to include all 16 register bits. Signed-off-by: Magnus Damm Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/sh_keysc.c | 3 ++- include/linux/input/sh_keysc.h | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index c2fc97732f0c..854e2035cd6e 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -31,6 +31,7 @@ static const struct { [SH_KEYSC_MODE_3] = { 2, 4, 7 }, [SH_KEYSC_MODE_4] = { 3, 6, 6 }, [SH_KEYSC_MODE_5] = { 4, 6, 7 }, + [SH_KEYSC_MODE_6] = { 5, 7, 7 }, }; struct sh_keysc_priv { @@ -109,7 +110,7 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id) n = keyin_nr * i; /* drive one KEYOUT pin low, read KEYIN pins */ - sh_keysc_write(priv, KYOUTDR, 0xfff ^ (3 << (i * 2))); + sh_keysc_write(priv, KYOUTDR, 0xffff ^ (3 << (i * 2))); udelay(pdata->delay); tmp = sh_keysc_read(priv, KYINDR); diff --git a/include/linux/input/sh_keysc.h b/include/linux/input/sh_keysc.h index 2aff38bcf2ba..649dc7f12925 100644 --- a/include/linux/input/sh_keysc.h +++ b/include/linux/input/sh_keysc.h @@ -1,15 +1,15 @@ #ifndef __SH_KEYSC_H__ #define __SH_KEYSC_H__ -#define SH_KEYSC_MAXKEYS 42 +#define SH_KEYSC_MAXKEYS 49 struct sh_keysc_info { enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3, - SH_KEYSC_MODE_4, SH_KEYSC_MODE_5 } mode; + SH_KEYSC_MODE_4, SH_KEYSC_MODE_5, SH_KEYSC_MODE_6 } mode; int scan_timing; /* 0 -> 7, see KYCR1, SCN[2:0] */ int delay; int kycr2_delay; - int keycodes[SH_KEYSC_MAXKEYS]; + int keycodes[SH_KEYSC_MAXKEYS]; /* KEYIN * KEYOUT */ }; #endif /* __SH_KEYSC_H__ */ -- cgit v1.2.3 From 5deeac99fe1146532eb7c64f9adb17d17628d751 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Wed, 10 Feb 2010 23:18:05 -0800 Subject: Input: rotary-encoder - set gpio direction for each requested gpio Even with the correct pin mux settings, you still need to explicitly set the gpio direction. Call gpio_direction_input() after each requested gpio. Signed-off-by: Andrew Clayton Signed-off-by: Mark Somerville Tested-by: H Hartley Sweeten Acked-by: Daniel Mack Signed-off-by: Dmitry Torokhov --- drivers/input/misc/rotary_encoder.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 3b9f588fc747..4ae07935985e 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -152,6 +152,13 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) goto exit_unregister_input; } + err = gpio_direction_input(pdata->gpio_a); + if (err) { + dev_err(&pdev->dev, "unable to set GPIO %d for input\n", + pdata->gpio_a); + goto exit_unregister_input; + } + err = gpio_request(pdata->gpio_b, DRV_NAME); if (err) { dev_err(&pdev->dev, "unable to request GPIO %d\n", @@ -159,6 +166,13 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) goto exit_free_gpio_a; } + err = gpio_direction_input(pdata->gpio_b); + if (err) { + dev_err(&pdev->dev, "unable to set GPIO %d for input\n", + pdata->gpio_b); + goto exit_free_gpio_a; + } + /* request the IRQs */ err = request_irq(encoder->irq_a, &rotary_encoder_irq, IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, -- cgit v1.2.3 From b036f6fb3aa23a52d90da5fc57e0803f08292e82 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Wed, 10 Feb 2010 23:06:23 -0800 Subject: Input: wacom - get features from driver info Get the features information from the driver info of the usb device id structure provided by the caller. The device ids and feature structs are strong coupled using indices. Signed-off-by: Bastian Blank Tested-by: Jason Childs Acked-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom.h | 5 +- drivers/input/tablet/wacom_sys.c | 10 +- drivers/input/tablet/wacom_wac.c | 342 ++++++++++++++++++++++----------------- 3 files changed, 205 insertions(+), 152 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 16310f368dab..8fef1b689c69 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -85,6 +85,7 @@ #include #include #include +#include #include #include #include @@ -120,6 +121,8 @@ struct wacom_combo { struct urb *urb; }; +extern const struct usb_device_id wacom_ids[]; + extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); @@ -142,7 +145,5 @@ extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wa extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern __u16 wacom_le16_to_cpu(unsigned char *data); extern __u16 wacom_be16_to_cpu(unsigned char *data); -extern struct wacom_features *get_wacom_feature(const struct usb_device_id *id); -extern const struct usb_device_id *get_device_table(void); #endif diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 072f33b3b2b0..be4b76f264a7 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -530,10 +530,13 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i struct usb_endpoint_descriptor *endpoint; struct wacom *wacom; struct wacom_wac *wacom_wac; - struct wacom_features *features; + struct wacom_features *features = (void *)id->driver_info; struct input_dev *input_dev; int error = -ENOMEM; + if (!features) + return -EINVAL; + wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); input_dev = input_allocate_device(); @@ -555,7 +558,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); - wacom_wac->features = features = get_wacom_feature(id); + wacom_wac->features = features; BUG_ON(features->pktlen > WACOM_PKGLEN_MAX); input_dev->name = wacom_wac->features->name; @@ -663,6 +666,7 @@ static int wacom_reset_resume(struct usb_interface *intf) static struct usb_driver wacom_driver = { .name = "wacom", + .id_table = wacom_ids, .probe = wacom_probe, .disconnect = wacom_disconnect, .suspend = wacom_suspend, @@ -674,7 +678,7 @@ static struct usb_driver wacom_driver = { static int __init wacom_init(void) { int result; - wacom_driver.id_table = get_device_table(); + result = usb_register(&wacom_driver); if (result == 0) printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 1056f149fe31..56aaf0164a56 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -903,153 +903,201 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w return; } -static struct wacom_features wacom_features[] = { - { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER }, - { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }, - { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }, - { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, 63, GRAPHIRE }, - { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, GRAPHIRE }, - { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }, - { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_G4 }, - { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, WACOM_G4 }, - { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }, - { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, 63, WACOM_MO }, - { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }, - { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }, - { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, 63, GRAPHIRE }, - { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }, - { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, 63, GRAPHIRE }, - { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, 63, GRAPHIRE }, - { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }, - { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }, - { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }, - { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }, - { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }, - { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }, - { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }, - { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, 0, PL }, - { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, 0, PL }, - { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, 0, PL }, - { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, 0, PL }, - { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, 0, PL }, - { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, 0, PL }, - { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, 0, PL }, - { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }, - { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, 0, PL }, - { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }, - { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }, - { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }, - { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, 0, PTU }, - { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }, - { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }, - { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }, - { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }, - { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }, - { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, 63, INTUOS3S }, - { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, 63, INTUOS3 }, - { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, 63, INTUOS3 }, - { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, 63, INTUOS3L }, - { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, 63, INTUOS3L }, - { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, 63, INTUOS3 }, - { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, 63, INTUOS3S }, - { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOS4S }, - { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS4 }, - { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L }, - { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L }, - { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ }, - { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE }, - { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }, - { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }, - { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, - { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, - { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, - { "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC }, - { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }, - { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }, - { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }, +static struct wacom_features wacom_features_0x00 = + { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER }; +static struct wacom_features wacom_features_0x10 = + { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x11 = + { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x12 = + { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x13 = + { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x14 = + { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x15 = + { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_G4 }; +static struct wacom_features wacom_features_0x16 = + { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, WACOM_G4 }; +static struct wacom_features wacom_features_0x17 = + { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; +static struct wacom_features wacom_features_0x18 = + { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, 63, WACOM_MO }; +static struct wacom_features wacom_features_0x19 = + { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x60 = + { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x61 = + { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x62 = + { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x63 = + { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x64 = + { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x65 = + { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; +static struct wacom_features wacom_features_0x69 = + { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; +static struct wacom_features wacom_features_0x20 = + { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0x21 = + { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0x22 = + { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0x23 = + { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0x24 = + { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0x30 = + { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, 0, PL }; +static struct wacom_features wacom_features_0x31 = + { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, 0, PL }; +static struct wacom_features wacom_features_0x32 = + { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, 0, PL }; +static struct wacom_features wacom_features_0x33 = + { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, 0, PL }; +static struct wacom_features wacom_features_0x34 = + { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, 0, PL }; +static struct wacom_features wacom_features_0x35 = + { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, 0, PL }; +static struct wacom_features wacom_features_0x37 = + { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, 0, PL }; +static struct wacom_features wacom_features_0x38 = + { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; +static struct wacom_features wacom_features_0x39 = + { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, 0, PL }; +static struct wacom_features wacom_features_0xC4 = + { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; +static struct wacom_features wacom_features_0xC0 = + { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; +static struct wacom_features wacom_features_0xC2 = + { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; +static struct wacom_features wacom_features_0x03 = + { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, 0, PTU }; +static struct wacom_features wacom_features_0x41 = + { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0x42 = + { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0x43 = + { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0x44 = + { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0x45 = + { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; +static struct wacom_features wacom_features_0xB0 = + { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, 63, INTUOS3S }; +static struct wacom_features wacom_features_0xB1 = + { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, 63, INTUOS3 }; +static struct wacom_features wacom_features_0xB2 = + { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, 63, INTUOS3 }; +static struct wacom_features wacom_features_0xB3 = + { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, 63, INTUOS3L }; +static struct wacom_features wacom_features_0xB4 = + { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, 63, INTUOS3L }; +static struct wacom_features wacom_features_0xB5 = + { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, 63, INTUOS3 }; +static struct wacom_features wacom_features_0xB7 = + { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, 63, INTUOS3S }; +static struct wacom_features wacom_features_0xB8 = + { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOS4S }; +static struct wacom_features wacom_features_0xB9 = + { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS4 }; +static struct wacom_features wacom_features_0xBA = + { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L }; +static struct wacom_features wacom_features_0xBB = + { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L }; +static struct wacom_features wacom_features_0x3F = + { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ }; +static struct wacom_features wacom_features_0xC5 = + { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE }; +static struct wacom_features wacom_features_0xC6 = + { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }; +static struct wacom_features wacom_features_0xC7 = + { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }; +static struct wacom_features wacom_features_0x90 = + { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; +static struct wacom_features wacom_features_0x93 = + { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; +static struct wacom_features wacom_features_0x9A = + { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; +static struct wacom_features wacom_features_0x9F = + { "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC }; +static struct wacom_features wacom_features_0xE2 = + { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; +static struct wacom_features wacom_features_0xE3 = + { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; +static struct wacom_features wacom_features_0x47 = + { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; + +#define USB_DEVICE_WACOM(prod) \ + USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ + .driver_info = (kernel_ulong_t)&wacom_features_##prod + +const struct usb_device_id wacom_ids[] = { + { USB_DEVICE_WACOM(0x00) }, + { USB_DEVICE_WACOM(0x10) }, + { USB_DEVICE_WACOM(0x11) }, + { USB_DEVICE_WACOM(0x12) }, + { USB_DEVICE_WACOM(0x13) }, + { USB_DEVICE_WACOM(0x14) }, + { USB_DEVICE_WACOM(0x15) }, + { USB_DEVICE_WACOM(0x16) }, + { USB_DEVICE_WACOM(0x17) }, + { USB_DEVICE_WACOM(0x18) }, + { USB_DEVICE_WACOM(0x19) }, + { USB_DEVICE_WACOM(0x60) }, + { USB_DEVICE_WACOM(0x61) }, + { USB_DEVICE_WACOM(0x62) }, + { USB_DEVICE_WACOM(0x63) }, + { USB_DEVICE_WACOM(0x64) }, + { USB_DEVICE_WACOM(0x65) }, + { USB_DEVICE_WACOM(0x69) }, + { USB_DEVICE_WACOM(0x20) }, + { USB_DEVICE_WACOM(0x21) }, + { USB_DEVICE_WACOM(0x22) }, + { USB_DEVICE_WACOM(0x23) }, + { USB_DEVICE_WACOM(0x24) }, + { USB_DEVICE_WACOM(0x30) }, + { USB_DEVICE_WACOM(0x31) }, + { USB_DEVICE_WACOM(0x32) }, + { USB_DEVICE_WACOM(0x33) }, + { USB_DEVICE_WACOM(0x34) }, + { USB_DEVICE_WACOM(0x35) }, + { USB_DEVICE_WACOM(0x37) }, + { USB_DEVICE_WACOM(0x38) }, + { USB_DEVICE_WACOM(0x39) }, + { USB_DEVICE_WACOM(0xC4) }, + { USB_DEVICE_WACOM(0xC0) }, + { USB_DEVICE_WACOM(0xC2) }, + { USB_DEVICE_WACOM(0x03) }, + { USB_DEVICE_WACOM(0x41) }, + { USB_DEVICE_WACOM(0x42) }, + { USB_DEVICE_WACOM(0x43) }, + { USB_DEVICE_WACOM(0x44) }, + { USB_DEVICE_WACOM(0x45) }, + { USB_DEVICE_WACOM(0xB0) }, + { USB_DEVICE_WACOM(0xB1) }, + { USB_DEVICE_WACOM(0xB2) }, + { USB_DEVICE_WACOM(0xB3) }, + { USB_DEVICE_WACOM(0xB4) }, + { USB_DEVICE_WACOM(0xB5) }, + { USB_DEVICE_WACOM(0xB7) }, + { USB_DEVICE_WACOM(0xB8) }, + { USB_DEVICE_WACOM(0xB9) }, + { USB_DEVICE_WACOM(0xBA) }, + { USB_DEVICE_WACOM(0xBB) }, + { USB_DEVICE_WACOM(0x3F) }, + { USB_DEVICE_WACOM(0xC5) }, + { USB_DEVICE_WACOM(0xC6) }, + { USB_DEVICE_WACOM(0xC7) }, + { USB_DEVICE_WACOM(0x90) }, + { USB_DEVICE_WACOM(0x93) }, + { USB_DEVICE_WACOM(0x9A) }, + { USB_DEVICE_WACOM(0x9F) }, + { USB_DEVICE_WACOM(0xE2) }, + { USB_DEVICE_WACOM(0xE3) }, + { USB_DEVICE_WACOM(0x47) }, { } }; - -static struct usb_device_id wacom_ids[] = { - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x69) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB8) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB9) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBA) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBB) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9F) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE2) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE3) }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, - { } -}; - -const struct usb_device_id *get_device_table(void) -{ - const struct usb_device_id *id_table = wacom_ids; - - return id_table; -} - -struct wacom_features * get_wacom_feature(const struct usb_device_id *id) -{ - int index = id - wacom_ids; - struct wacom_features *wf = &wacom_features[index]; - - return wf; -} - MODULE_DEVICE_TABLE(usb, wacom_ids); -- cgit v1.2.3 From 4e45ad5e89128939c671e927f030cb3909fe1d69 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Feb 2010 21:50:58 -0800 Subject: Input: sh_keysc - enable building on SH-Mobile ARM Update the Kconfig entry for the sh_keysc driver to enable build on SH-Mobile ARM platforms. Signed-off-by: Magnus Damm Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 1ad9435d30aa..64c102355f53 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -376,7 +376,7 @@ config KEYBOARD_SUNKBD config KEYBOARD_SH_KEYSC tristate "SuperH KEYSC keypad support" - depends on SUPERH + depends on SUPERH || ARCH_SHMOBILE help Say Y here if you want to use a keypad attached to the KEYSC block on SuperH processors such as sh7722 and sh7343. -- cgit v1.2.3 From e33da8a5486aaadf5161118869e6cfb3d119beea Mon Sep 17 00:00:00 2001 From: Jason Childs Date: Wed, 17 Feb 2010 22:38:31 -0800 Subject: Input: wacom - use per-device instance of wacom_features Since we mangle data in wacom_features when dealing with certain devices let's use a private (per-device) instance of wacom_features in wacom_wac. This way same product ID can support more than one type of device, such as pen and touch, and not interfere with each other. Signed-off-by: Jason Childs Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 58 ++++++++++++++++++++++------------- drivers/input/tablet/wacom_wac.c | 66 ++++++++++++++++++++++------------------ drivers/input/tablet/wacom_wac.h | 10 +++--- 3 files changed, 78 insertions(+), 56 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index be4b76f264a7..f22b88d03c6c 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -211,7 +211,8 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); - input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); + input_set_abs_params(input_dev, ABS_DISTANCE, + 0, wacom_wac->features.distance_max, 0, 0); } void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -261,7 +262,8 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); - input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); + input_set_abs_params(input_dev, ABS_DISTANCE, + 0, wacom_wac->features.distance_max, 0, 0); input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); @@ -282,17 +284,19 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP || - wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) { - input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0); - input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); + struct wacom_features *features = &wacom_wac->features; + + if (features->device_type == BTN_TOOL_DOUBLETAP || + features->device_type == BTN_TOOL_TRIPLETAP) { + input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); } } void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - if (wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) { + if (wacom_wac->features.device_type == BTN_TOOL_TRIPLETAP) { input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); input_dev->evbit[0] |= BIT_MASK(EV_MSC); input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); @@ -530,26 +534,40 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i struct usb_endpoint_descriptor *endpoint; struct wacom *wacom; struct wacom_wac *wacom_wac; - struct wacom_features *features = (void *)id->driver_info; + struct wacom_features *features; struct input_dev *input_dev; - int error = -ENOMEM; + int error; - if (!features) + if (!id->driver_info) return -EINVAL; wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); input_dev = input_allocate_device(); - if (!wacom || !input_dev || !wacom_wac) + if (!wacom || !input_dev || !wacom_wac) { + error = -ENOMEM; + goto fail1; + } + + wacom_wac->features = *((struct wacom_features *)id->driver_info); + features = &wacom_wac->features; + if (features->pktlen > WACOM_PKGLEN_MAX) { + error = -EINVAL; goto fail1; + } - wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, GFP_KERNEL, &wacom->data_dma); - if (!wacom_wac->data) + wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, + GFP_KERNEL, &wacom->data_dma); + if (!wacom_wac->data) { + error = -ENOMEM; goto fail1; + } wacom->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!wacom->irq) + if (!wacom->irq) { + error = -ENOMEM; goto fail2; + } wacom->usbdev = dev; wacom->dev = input_dev; @@ -558,11 +576,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); - wacom_wac->features = features; - BUG_ON(features->pktlen > WACOM_PKGLEN_MAX); - - input_dev->name = wacom_wac->features->name; - wacom->wacom_wac = wacom_wac; usb_to_input_id(dev, &input_dev->id); input_dev->dev.parent = &intf->dev; @@ -579,6 +592,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i if (error) goto fail2; + input_dev->name = features->name; + wacom->wacom_wac = wacom_wac; + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); @@ -643,7 +659,7 @@ static int wacom_suspend(struct usb_interface *intf, pm_message_t message) static int wacom_resume(struct usb_interface *intf) { struct wacom *wacom = usb_get_intfdata(intf); - struct wacom_features *features = wacom->wacom_wac->features; + struct wacom_features *features = &wacom->wacom_wac->features; int rv; mutex_lock(&wacom->lock); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 56aaf0164a56..e4a1a7dcd9a4 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -55,6 +55,7 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; int prox, pressure; @@ -68,9 +69,9 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) if (prox) { wacom->id[0] = ERASER_DEVICE_ID; pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); - if (wacom->features->pressure_max > 255) + if (features->pressure_max > 255) pressure = (pressure << 1) | ((data[4] >> 6) & 1); - pressure += (wacom->features->pressure_max + 1) / 2; + pressure += (features->pressure_max + 1) / 2; /* * if going from out of proximity into proximity select between the eraser @@ -152,6 +153,7 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; int x, y, rw; static int penData = 0; @@ -179,8 +181,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) case 2: /* Mouse with wheel */ wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); - if (wacom->features->type == WACOM_G4 || - wacom->features->type == WACOM_MO) { + if (features->type == WACOM_G4 || features->type == WACOM_MO) { rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); wacom_report_rel(wcombo, REL_WHEEL, -rw); } else @@ -192,8 +193,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom->id[0] = CURSOR_DEVICE_ID; wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); - if (wacom->features->type == WACOM_G4 || - wacom->features->type == WACOM_MO) + if (features->type == WACOM_G4 || features->type == WACOM_MO) wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); else wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); @@ -230,7 +230,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) } /* send pad data */ - switch (wacom->features->type) { + switch (features->type) { case WACOM_G4: if (data[7] & 0xf8) { if (penData) { @@ -300,11 +300,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; int idx = 0; /* tool number */ - if (wacom->features->type == INTUOS) + if (features->type == INTUOS) idx = data[1] & 0x01; /* Enter report */ @@ -402,7 +403,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_STYLUS2, 0); wacom_report_key(wcombo, BTN_TOUCH, 0); wacom_report_abs(wcombo, ABS_WHEEL, 0); - if (wacom->features->type >= INTUOS3S) + if (features->type >= INTUOS3S) wacom_report_abs(wcombo, ABS_Z, 0); } wacom_report_key(wcombo, wacom->tool[idx], 0); @@ -416,13 +417,14 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; unsigned int t; /* general pen packet */ if ((data[1] & 0xb8) == 0xa0) { t = (data[6] << 2) | ((data[7] >> 6) & 3); - if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) + if (features->type >= INTUOS4S && features->type <= INTUOS4L) t = (t << 1) | (data[1] & 1); wacom_report_abs(wcombo, ABS_PRESSURE, t); wacom_report_abs(wcombo, ABS_TILT_X, @@ -446,6 +448,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; unsigned int t; int idx = 0, result; @@ -457,7 +460,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) } /* tool number */ - if (wacom->features->type == INTUOS) + if (features->type == INTUOS) idx = data[1] & 0x01; /* pad packets. Works as a second tool and is always in prox */ @@ -466,7 +469,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) if (wacom->tool[1] != BTN_TOOL_FINGER) wacom->tool[1] = BTN_TOOL_FINGER; - if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { + if (features->type >= INTUOS4S && features->type <= INTUOS4L) { wacom_report_key(wcombo, BTN_0, (data[2] & 0x01)); wacom_report_key(wcombo, BTN_1, (data[3] & 0x01)); wacom_report_key(wcombo, BTN_2, (data[3] & 0x02)); @@ -480,7 +483,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) /* Out of proximity, clear wheel value. */ wacom_report_abs(wcombo, ABS_WHEEL, 0); } - if (wacom->features->type != INTUOS4S) { + if (features->type != INTUOS4S) { wacom_report_key(wcombo, BTN_7, (data[3] & 0x40)); wacom_report_key(wcombo, BTN_8, (data[3] & 0x80)); } @@ -528,18 +531,20 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) return 0; /* Only large Intuos support Lense Cursor */ - if ((wacom->tool[idx] == BTN_TOOL_LENS) - && ((wacom->features->type == INTUOS3) - || (wacom->features->type == INTUOS3S) - || (wacom->features->type == INTUOS4) - || (wacom->features->type == INTUOS4S))) + if (wacom->tool[idx] == BTN_TOOL_LENS && + (features->type == INTUOS3 || + features->type == INTUOS3S || + features->type == INTUOS4 || + features->type == INTUOS4S)) { + return 0; + } /* Cintiq doesn't send data when RDY bit isn't set */ - if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) + if (features->type == CINTIQ && !(data[1] & 0x40)) return 0; - if (wacom->features->type >= INTUOS3S) { + if (features->type >= INTUOS3S) { wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); @@ -557,7 +562,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) if (data[1] & 0x02) { /* Rotation packet */ - if (wacom->features->type >= INTUOS3S) { + if (features->type >= INTUOS3S) { /* I3 marker pen rotation */ t = (data[6] << 3) | ((data[7] >> 5) & 7); t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : @@ -570,7 +575,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) ((t - 1) / 2) : -t / 2); } - } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) { + } else if (!(data[1] & 0x10) && features->type < INTUOS3S) { /* 4D mouse packet */ wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); @@ -583,7 +588,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* I4 mouse */ - if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { + if (features->type >= INTUOS4S && features->type <= INTUOS4L) { wacom_report_key(wcombo, BTN_LEFT, data[6] & 0x01); wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02); wacom_report_key(wcombo, BTN_RIGHT, data[6] & 0x04); @@ -604,13 +609,13 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) - ((data[8] & 0x02) >> 1)); /* I3 2D mouse side buttons */ - if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) { + if (features->type >= INTUOS3S && features->type <= INTUOS3L) { wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); } } - } else if ((wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L || - wacom->features->type == INTUOS4L) && + } else if ((features->type < INTUOS3S || features->type == INTUOS3L || + features->type == INTUOS4L) && wacom->tool[idx] == BTN_TOOL_LENS) { /* Lens cursor packets */ wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); @@ -718,6 +723,7 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; char *data = wacom->data; int prox = 0, pressure, idx = -1; static int stylusInProx, touchInProx = 1, touchOut; @@ -791,7 +797,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); pressure = ((data[7] & 0x01) << 8) | data[6]; if (pressure < 0) - pressure = wacom->features->pressure_max + pressure + 1; + pressure = features->pressure_max + pressure + 1; wacom_report_abs(wcombo, ABS_PRESSURE, pressure); wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); } else { @@ -815,7 +821,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) { - switch (wacom_wac->features->type) { + switch (wacom_wac->features.type) { case PENPARTNER: return wacom_penpartner_irq(wacom_wac, wcombo); @@ -853,7 +859,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - switch (wacom_wac->features->type) { + switch (wacom_wac->features.type) { case WACOM_MO: input_dev_mo(input_dev, wacom_wac); case WACOM_G4: @@ -888,7 +894,7 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w /* fall through */ case TABLETPC: input_dev_tpc(input_dev, wacom_wac); - if (wacom_wac->features->device_type != BTN_TOOL_PEN) + if (wacom_wac->features.device_type != BTN_TOOL_PEN) break; /* no need to process stylus stuff */ /* fall through */ diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index ee01e1902785..3f4b89d51fe2 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -15,11 +15,11 @@ /* packet length for individual models */ #define WACOM_PKGLEN_PENPRTN 7 #define WACOM_PKGLEN_GRAPHIRE 8 -#define WACOM_PKGLEN_BBFUN 9 -#define WACOM_PKGLEN_INTUOS 10 +#define WACOM_PKGLEN_BBFUN 9 +#define WACOM_PKGLEN_INTUOS 10 #define WACOM_PKGLEN_PENABLED 8 #define WACOM_PKGLEN_TPC1FG 5 -#define WACOM_PKGLEN_TPC2FG 14 +#define WACOM_PKGLEN_TPC2FG 14 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -58,7 +58,7 @@ enum { }; struct wacom_features { - char *name; + const char *name; int pktlen; int x_max; int y_max; @@ -77,7 +77,7 @@ struct wacom_wac { int tool[2]; int id[2]; __u32 serial[2]; - struct wacom_features *features; + struct wacom_features features; }; #endif -- cgit v1.2.3 From e87a344d0eef52cadcd5e1ef33a8771afc879896 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 18 Feb 2010 01:51:47 -0800 Subject: Input: wacom - constify product features data Features are not supposed to be modified; devices use their own private copies, so let's mark them const. Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 126 +++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 63 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index e4a1a7dcd9a4..3d81443e683a 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -909,131 +909,131 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w return; } -static struct wacom_features wacom_features_0x00 = +static const struct wacom_features wacom_features_0x00 = { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER }; -static struct wacom_features wacom_features_0x10 = +static const struct wacom_features wacom_features_0x10 = { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x11 = +static const struct wacom_features wacom_features_0x11 = { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x12 = +static const struct wacom_features wacom_features_0x12 = { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x13 = +static const struct wacom_features wacom_features_0x13 = { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x14 = +static const struct wacom_features wacom_features_0x14 = { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x15 = +static const struct wacom_features wacom_features_0x15 = { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_G4 }; -static struct wacom_features wacom_features_0x16 = +static const struct wacom_features wacom_features_0x16 = { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, WACOM_G4 }; -static struct wacom_features wacom_features_0x17 = +static const struct wacom_features wacom_features_0x17 = { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; -static struct wacom_features wacom_features_0x18 = +static const struct wacom_features wacom_features_0x18 = { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, 63, WACOM_MO }; -static struct wacom_features wacom_features_0x19 = +static const struct wacom_features wacom_features_0x19 = { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x60 = +static const struct wacom_features wacom_features_0x60 = { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x61 = +static const struct wacom_features wacom_features_0x61 = { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x62 = +static const struct wacom_features wacom_features_0x62 = { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x63 = +static const struct wacom_features wacom_features_0x63 = { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x64 = +static const struct wacom_features wacom_features_0x64 = { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x65 = +static const struct wacom_features wacom_features_0x65 = { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; -static struct wacom_features wacom_features_0x69 = +static const struct wacom_features wacom_features_0x69 = { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; -static struct wacom_features wacom_features_0x20 = +static const struct wacom_features wacom_features_0x20 = { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0x21 = +static const struct wacom_features wacom_features_0x21 = { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0x22 = +static const struct wacom_features wacom_features_0x22 = { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0x23 = +static const struct wacom_features wacom_features_0x23 = { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0x24 = +static const struct wacom_features wacom_features_0x24 = { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0x30 = +static const struct wacom_features wacom_features_0x30 = { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, 0, PL }; -static struct wacom_features wacom_features_0x31 = +static const struct wacom_features wacom_features_0x31 = { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, 0, PL }; -static struct wacom_features wacom_features_0x32 = +static const struct wacom_features wacom_features_0x32 = { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, 0, PL }; -static struct wacom_features wacom_features_0x33 = +static const struct wacom_features wacom_features_0x33 = { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, 0, PL }; -static struct wacom_features wacom_features_0x34 = +static const struct wacom_features wacom_features_0x34 = { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, 0, PL }; -static struct wacom_features wacom_features_0x35 = +static const struct wacom_features wacom_features_0x35 = { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, 0, PL }; -static struct wacom_features wacom_features_0x37 = +static const struct wacom_features wacom_features_0x37 = { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, 0, PL }; -static struct wacom_features wacom_features_0x38 = +static const struct wacom_features wacom_features_0x38 = { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; -static struct wacom_features wacom_features_0x39 = +static const struct wacom_features wacom_features_0x39 = { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, 0, PL }; -static struct wacom_features wacom_features_0xC4 = +static const struct wacom_features wacom_features_0xC4 = { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; -static struct wacom_features wacom_features_0xC0 = +static const struct wacom_features wacom_features_0xC0 = { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; -static struct wacom_features wacom_features_0xC2 = +static const struct wacom_features wacom_features_0xC2 = { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; -static struct wacom_features wacom_features_0x03 = +static const struct wacom_features wacom_features_0x03 = { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, 0, PTU }; -static struct wacom_features wacom_features_0x41 = +static const struct wacom_features wacom_features_0x41 = { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0x42 = +static const struct wacom_features wacom_features_0x42 = { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0x43 = +static const struct wacom_features wacom_features_0x43 = { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0x44 = +static const struct wacom_features wacom_features_0x44 = { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0x45 = +static const struct wacom_features wacom_features_0x45 = { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0xB0 = +static const struct wacom_features wacom_features_0xB0 = { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, 63, INTUOS3S }; -static struct wacom_features wacom_features_0xB1 = +static const struct wacom_features wacom_features_0xB1 = { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, 63, INTUOS3 }; -static struct wacom_features wacom_features_0xB2 = +static const struct wacom_features wacom_features_0xB2 = { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, 63, INTUOS3 }; -static struct wacom_features wacom_features_0xB3 = +static const struct wacom_features wacom_features_0xB3 = { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, 63, INTUOS3L }; -static struct wacom_features wacom_features_0xB4 = +static const struct wacom_features wacom_features_0xB4 = { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, 63, INTUOS3L }; -static struct wacom_features wacom_features_0xB5 = +static const struct wacom_features wacom_features_0xB5 = { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, 63, INTUOS3 }; -static struct wacom_features wacom_features_0xB7 = +static const struct wacom_features wacom_features_0xB7 = { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, 63, INTUOS3S }; -static struct wacom_features wacom_features_0xB8 = +static const struct wacom_features wacom_features_0xB8 = { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOS4S }; -static struct wacom_features wacom_features_0xB9 = +static const struct wacom_features wacom_features_0xB9 = { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS4 }; -static struct wacom_features wacom_features_0xBA = +static const struct wacom_features wacom_features_0xBA = { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L }; -static struct wacom_features wacom_features_0xBB = +static const struct wacom_features wacom_features_0xBB = { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L }; -static struct wacom_features wacom_features_0x3F = +static const struct wacom_features wacom_features_0x3F = { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ }; -static struct wacom_features wacom_features_0xC5 = +static const struct wacom_features wacom_features_0xC5 = { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE }; -static struct wacom_features wacom_features_0xC6 = +static const struct wacom_features wacom_features_0xC6 = { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }; -static struct wacom_features wacom_features_0xC7 = +static const struct wacom_features wacom_features_0xC7 = { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }; -static struct wacom_features wacom_features_0x90 = +static const struct wacom_features wacom_features_0x90 = { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; -static struct wacom_features wacom_features_0x93 = +static const struct wacom_features wacom_features_0x93 = { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; -static struct wacom_features wacom_features_0x9A = +static const struct wacom_features wacom_features_0x9A = { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; -static struct wacom_features wacom_features_0x9F = +static const struct wacom_features wacom_features_0x9F = { "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC }; -static struct wacom_features wacom_features_0xE2 = +static const struct wacom_features wacom_features_0xE2 = { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; -static struct wacom_features wacom_features_0xE3 = +static const struct wacom_features wacom_features_0xE3 = { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; -static struct wacom_features wacom_features_0x47 = +static const struct wacom_features wacom_features_0x47 = { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; #define USB_DEVICE_WACOM(prod) \ -- cgit v1.2.3 From 2f09586557ed9b6d50bc8bb5104e70006513bdc2 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Fri, 19 Feb 2010 01:18:11 -0800 Subject: Input: s3c24xx_ts - re-enable IRQ on resume IRQ should be re-enabled on resume, otherwise driver stops reporting events. Signed-off-by: Vasily Khoruzhick Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/s3c2410_ts.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 6386b441ef85..ffc355e696dc 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -401,6 +401,7 @@ static int s3c2410ts_resume(struct device *dev) struct s3c2410_ts_mach_info *info = pdev->dev.platform_data; clk_enable(ts.clock); + enable_irq(ts.irq_tc); /* Initialise registers */ if ((info->delay & 0xffff) > 0) -- cgit v1.2.3 From 23c239be223d7427da51656d6f196bde965d9796 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Sat, 20 Feb 2010 01:06:20 -0800 Subject: Input: s3c24xx_ts - report touch only when stylus is down Currently driver reports touches when it gets (1 << ts.shift) samples, even if stylus is up, which is incorrect. We should only report coordinates and touch condition when stylus is down. Signed-off-by: Vasily Khoruzhick Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/s3c2410_ts.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index ffc355e696dc..3755a47d053c 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -128,27 +128,29 @@ static void touch_timer_fire(unsigned long data) down = get_down(data0, data1); - if (ts.count == (1 << ts.shift)) { - ts.xp >>= ts.shift; - ts.yp >>= ts.shift; + if (down) { + if (ts.count == (1 << ts.shift)) { + ts.xp >>= ts.shift; + ts.yp >>= ts.shift; - dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n", - __func__, ts.xp, ts.yp, ts.count); + dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n", + __func__, ts.xp, ts.yp, ts.count); - input_report_abs(ts.input, ABS_X, ts.xp); - input_report_abs(ts.input, ABS_Y, ts.yp); + input_report_abs(ts.input, ABS_X, ts.xp); + input_report_abs(ts.input, ABS_Y, ts.yp); - input_report_key(ts.input, BTN_TOUCH, 1); - input_sync(ts.input); + input_report_key(ts.input, BTN_TOUCH, 1); + input_sync(ts.input); - ts.xp = 0; - ts.yp = 0; - ts.count = 0; - } + ts.xp = 0; + ts.yp = 0; + ts.count = 0; + } - if (down) { s3c_adc_start(ts.client, 0, 1 << ts.shift); } else { + ts.xp = 0; + ts.yp = 0; ts.count = 0; input_report_key(ts.input, BTN_TOUCH, 0); -- cgit v1.2.3 From 49b764aebde6ceea393f56cd3449bfa5720f8383 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Sat, 20 Feb 2010 00:53:49 -0800 Subject: Input: wacom - add device type to device name string Devices supporting both pen and touch features share the same product ID, but presented as 2 separate input devices. By adding device type to device name string we can help userspace applications and users differentiate between them. 'Finger' is used for the touch since touch has been used as a suffix by userland hotplugging services. Signed-off-by: Jason Childs Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 12 +++++++++++- drivers/input/tablet/wacom_wac.h | 7 ++++--- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index f22b88d03c6c..a1770e6feeec 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -592,7 +592,17 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i if (error) goto fail2; - input_dev->name = features->name; + strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); + + if (features->type == TABLETPC || features->type == TABLETPC2FG) { + /* Append the device type to the name */ + strlcat(wacom_wac->name, + features->device_type == BTN_TOOL_PEN ? + " Pen" : " Finger", + sizeof(wacom_wac->name)); + } + + input_dev->name = wacom_wac->name; wacom->wacom_wac = wacom_wac; input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 3f4b89d51fe2..8590b1e8ec37 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -73,10 +73,11 @@ struct wacom_features { }; struct wacom_wac { + char name[64]; unsigned char *data; - int tool[2]; - int id[2]; - __u32 serial[2]; + int tool[2]; + int id[2]; + __u32 serial[2]; struct wacom_features features; }; -- cgit v1.2.3 From 7aa9e0e8263259f4517ba1788f4fbaa88e878400 Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Sun, 21 Feb 2010 20:53:55 -0800 Subject: Input: gamecon - add rumble support for N64 pads Add force-feedback support for N64 pads with rumble pak accessory installed. Actually we do not check for the presence of rumble pad but simply assume it is installed and expect the device to ignore FF commands if rumble pak is missing. Signed-off-by: Scott Moreau Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/Kconfig | 1 + drivers/input/joystick/gamecon.c | 125 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 120 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index b11419590cfe..5b596165b571 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -221,6 +221,7 @@ config JOYSTICK_DB9 config JOYSTICK_GAMECON tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads" depends on PARPORT + select INPUT_FF_MEMLESS ---help--- Say Y here if you have a Nintendo Entertainment System gamepad, Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad, diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 07a32aff5a31..bbde4e524da3 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -85,6 +85,10 @@ struct gc { char phys[GC_MAX_DEVICES][32]; }; +struct gc_subdev { + unsigned int idx; +}; + static struct gc *gc_base[3]; static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; @@ -100,9 +104,16 @@ static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 }; static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START }; #define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */ -#define GC_N64_REQUEST_LENGTH 37 /* transmit request sequence is 9 bits long */ +#define GC_N64_STOP_LENGTH 5 /* Length of encoded stop bit */ +#define GC_N64_CMD_00 0x11111111UL +#define GC_N64_CMD_01 0xd1111111UL +#define GC_N64_CMD_03 0xdd111111UL +#define GC_N64_CMD_1b 0xdd1dd111UL +#define GC_N64_CMD_c0 0x111111ddUL +#define GC_N64_CMD_80 0x1111111dUL +#define GC_N64_STOP_BIT 0x1d /* Encoded stop bit */ +#define GC_N64_REQUEST_DATA GC_N64_CMD_01 /* the request data command */ #define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */ -#define GC_N64_REQUEST 0x1dd1111111ULL /* the request data command (encoded for 000000011) */ #define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */ /* GC_N64_DWS > 24 is known to fail */ #define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */ @@ -113,6 +124,37 @@ static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, /* than 123 us */ #define GC_N64_CLOCK 0x02 /* clock bits for read */ +/* + * Used for rumble code. + */ + +/* Send encoded command */ +static void gc_n64_send_command(struct gc *gc, unsigned long cmd, + unsigned char target) +{ + struct parport *port = gc->pd->port; + int i; + + for (i = 0; i < GC_N64_LENGTH; i++) { + unsigned char data = (cmd >> i) & 1 ? target : 0; + parport_write_data(port, GC_N64_POWER_W | data); + udelay(GC_N64_DWS); + } +} + +/* Send stop bit */ +static void gc_n64_send_stop_bit(struct gc *gc, unsigned char target) +{ + struct parport *port = gc->pd->port; + int i; + + for (i = 0; i < GC_N64_STOP_LENGTH; i++) { + unsigned char data = (GC_N64_STOP_BIT >> i) & 1 ? target : 0; + parport_write_data(port, GC_N64_POWER_W | data); + udelay(GC_N64_DWS); + } +} + /* * gc_n64_read_packet() reads an N64 packet. * Each pad uses one bit per byte. So all pads connected to this port are read in parallel. @@ -128,10 +170,8 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) */ local_irq_save(flags); - for (i = 0; i < GC_N64_REQUEST_LENGTH; i++) { - parport_write_data(gc->pd->port, GC_N64_POWER_W | ((GC_N64_REQUEST >> i) & 1 ? GC_N64_OUT : 0)); - udelay(GC_N64_DWS); - } + gc_n64_send_command(gc, GC_N64_REQUEST_DATA, GC_N64_OUT); + gc_n64_send_stop_bit(gc, GC_N64_OUT); local_irq_restore(flags); /* @@ -146,6 +186,7 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) for (i = 0; i < GC_N64_LENGTH; i++) { parport_write_data(gc->pd->port, GC_N64_POWER_R); + udelay(2); data[i] = parport_read_status(gc->pd->port); parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK); } @@ -199,6 +240,70 @@ static void gc_n64_process_packet(struct gc *gc) } } +static int gc_n64_play_effect(struct input_dev *dev, void *data, + struct ff_effect *effect) +{ + int i; + unsigned long flags; + struct gc *gc = input_get_drvdata(dev); + struct gc_subdev *sdev = data; + unsigned char target = 1 << sdev->idx; /* select desired pin */ + + if (effect->type == FF_RUMBLE) { + struct ff_rumble_effect *rumble = &effect->u.rumble; + unsigned int cmd = + rumble->strong_magnitude || rumble->weak_magnitude ? + GC_N64_CMD_01 : GC_N64_CMD_00; + + local_irq_save(flags); + + /* Init Rumble - 0x03, 0x80, 0x01, (34)0x80 */ + gc_n64_send_command(gc, GC_N64_CMD_03, target); + gc_n64_send_command(gc, GC_N64_CMD_80, target); + gc_n64_send_command(gc, GC_N64_CMD_01, target); + for (i = 0; i < 32; i++) + gc_n64_send_command(gc, GC_N64_CMD_80, target); + gc_n64_send_stop_bit(gc, target); + + udelay(GC_N64_DELAY); + + /* Now start or stop it - 0x03, 0xc0, 0zx1b, (32)0x01/0x00 */ + gc_n64_send_command(gc, GC_N64_CMD_03, target); + gc_n64_send_command(gc, GC_N64_CMD_c0, target); + gc_n64_send_command(gc, GC_N64_CMD_1b, target); + for (i = 0; i < 32; i++) + gc_n64_send_command(gc, cmd, target); + gc_n64_send_stop_bit(gc, target); + + local_irq_restore(flags); + + } + + return 0; +} + +static int __init gc_n64_init_ff(struct input_dev *dev, int i) +{ + struct gc_subdev *sdev; + int err; + + sdev = kmalloc(sizeof(*sdev), GFP_KERNEL); + if (!sdev) + return -ENOMEM; + + sdev->idx = i; + + input_set_capability(dev, EV_FF, FF_RUMBLE); + + err = input_ff_create_memless(dev, sdev, gc_n64_play_effect); + if (err) { + kfree(sdev); + return err; + } + + return 0; +} + /* * NES/SNES support. */ @@ -624,6 +729,7 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) { struct input_dev *input_dev; int i; + int err; if (!pad_type) return 0; @@ -673,6 +779,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); } + err = gc_n64_init_ff(input_dev, idx); + if (err) { + printk(KERN_WARNING "gamecon.c: Failed to initiate rumble for N64 device %d\n", idx); + input_free_device(input_dev); + return err; + } + break; case GC_SNESMOUSE: -- cgit v1.2.3 From d38fcb9690532e6e2e064d711262b14d638113b9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 21 Feb 2010 20:54:28 -0800 Subject: Input: gamecon - fix some formatting issues Fix formatting of 'switch' statements and change the code to stay closer to 80 column limit where it does not hurt code readability. Tested-by: Scott Moreau Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/gamecon.c | 347 ++++++++++++++++++++++----------------- 1 file changed, 194 insertions(+), 153 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index bbde4e524da3..ec01bea8dc81 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -93,15 +93,21 @@ static struct gc *gc_base[3]; static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; -static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", - "Multisystem 2-button joystick", "N64 controller", "PSX controller", - "PSX DDR controller", "SNES mouse" }; +static char *gc_names[] = { + NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", + "Multisystem 2-button joystick", "N64 controller", "PSX controller", + "PSX DDR controller", "SNES mouse" +}; + /* * N64 support. */ static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 }; -static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START }; +static short gc_n64_btn[] = { + BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, + BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START +}; #define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */ #define GC_N64_STOP_LENGTH 5 /* Length of encoded stop bit */ @@ -157,7 +163,8 @@ static void gc_n64_send_stop_bit(struct gc *gc, unsigned char target) /* * gc_n64_read_packet() reads an N64 packet. - * Each pad uses one bit per byte. So all pads connected to this port are read in parallel. + * Each pad uses one bit per byte. So all pads connected to this port + * are read in parallel. */ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) @@ -175,7 +182,8 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) local_irq_restore(flags); /* - * Wait for the pad response to be loaded into the 33-bit register of the adapter + * Wait for the pad response to be loaded into the 33-bit register + * of the adapter. */ udelay(GC_N64_DELAY); @@ -192,8 +200,9 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) } /* - * We must wait 200 ms here for the controller to reinitialize before the next read request. - * No worries as long as gc_read is polled less frequently than this. + * We must wait 200 ms here for the controller to reinitialize before + * the next read request. No worries as long as gc_read is polled less + * frequently than this. */ } @@ -201,9 +210,9 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) static void gc_n64_process_packet(struct gc *gc) { unsigned char data[GC_N64_LENGTH]; - signed char axes[2]; struct input_dev *dev; int i, j, s; + signed char x, y; gc_n64_read_packet(gc, data); @@ -217,23 +226,26 @@ static void gc_n64_process_packet(struct gc *gc) if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) { - axes[0] = axes[1] = 0; + x = y = 0; for (j = 0; j < 8; j++) { if (data[23 - j] & s) - axes[0] |= 1 << j; + x |= 1 << j; if (data[31 - j] & s) - axes[1] |= 1 << j; + y |= 1 << j; } - input_report_abs(dev, ABS_X, axes[0]); - input_report_abs(dev, ABS_Y, -axes[1]); + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, -y); - input_report_abs(dev, ABS_HAT0X, !(s & data[6]) - !(s & data[7])); - input_report_abs(dev, ABS_HAT0Y, !(s & data[4]) - !(s & data[5])); + input_report_abs(dev, ABS_HAT0X, + !(s & data[6]) - !(s & data[7])); + input_report_abs(dev, ABS_HAT0Y, + !(s & data[4]) - !(s & data[5])); for (j = 0; j < 10; j++) - input_report_key(dev, gc_n64_btn[j], s & data[gc_n64_bytes[j]]); + input_report_key(dev, gc_n64_btn[j], + s & data[gc_n64_bytes[j]]); input_sync(dev); } @@ -321,7 +333,9 @@ static int __init gc_n64_init_ff(struct input_dev *dev, int i) static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 }; static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 }; -static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR }; +static short gc_snes_btn[] = { + BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR +}; /* * gc_nes_read_packet() reads a NES/SNES packet. @@ -373,16 +387,19 @@ static void gc_nes_process_packet(struct gc *gc) if (s & gc->pads[GC_NES]) for (j = 0; j < 4; j++) - input_report_key(dev, gc_snes_btn[j], s & data[gc_nes_bytes[j]]); + input_report_key(dev, gc_snes_btn[j], + s & data[gc_nes_bytes[j]]); if (s & gc->pads[GC_SNES]) for (j = 0; j < 8; j++) - input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]); + input_report_key(dev, gc_snes_btn[j], + s & data[gc_snes_bytes[j]]); if (s & gc->pads[GC_SNESMOUSE]) { /* - * The 4 unused bits from SNES controllers appear to be ID bits - * so use them to make sure iwe are dealing with a mouse. + * The 4 unused bits from SNES controllers appear + * to be ID bits so use them to make sure we are + * dealing with a mouse. * gamepad is connected. This is important since * my SNES gamepad sends 1's for bits 16-31, which * cause the mouse pointer to quickly move to the @@ -445,10 +462,11 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data) static void gc_multi_process_packet(struct gc *gc) { unsigned char data[GC_MULTI2_LENGTH]; + int data_len = gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH; struct input_dev *dev; int i, s; - gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data); + gc_multi_read_packet(gc, data_len, data); for (i = 0; i < GC_MAX_DEVICES; i++) { @@ -459,8 +477,10 @@ static void gc_multi_process_packet(struct gc *gc) s = gc_status_bit[i]; if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) { - input_report_abs(dev, ABS_X, !(s & data[2]) - !(s & data[3])); - input_report_abs(dev, ABS_Y, !(s & data[0]) - !(s & data[1])); + input_report_abs(dev, ABS_X, + !(s & data[2]) - !(s & data[3])); + input_report_abs(dev, ABS_Y, + !(s & data[0]) - !(s & data[1])); input_report_key(dev, BTN_TRIGGER, s & data[4]); } @@ -503,9 +523,13 @@ static int gc_psx_delay = GC_PSX_DELAY; module_param_named(psx_delay, gc_psx_delay, uint, 0); MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)"); -static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y }; -static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y, - BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR }; +static short gc_psx_abs[] = { + ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y +}; +static short gc_psx_btn[] = { + BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y, + BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR +}; static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; /* @@ -513,18 +537,18 @@ static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; * the psx pad. */ -static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_MAX_DEVICES]) +static void gc_psx_command(struct gc *gc, int b, unsigned char *data) { + struct parport *port = gc->pd->port; int i, j, cmd, read; - for (i = 0; i < GC_MAX_DEVICES; i++) - data[i] = 0; + memset(data, 0, GC_MAX_DEVICES); for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) { cmd = (b & 1) ? GC_PSX_COMMAND : 0; - parport_write_data(gc->pd->port, cmd | GC_PSX_POWER); + parport_write_data(port, cmd | GC_PSX_POWER); udelay(gc_psx_delay); - read = parport_read_status(gc->pd->port) ^ 0x80; + read = parport_read_status(port) ^ 0x80; for (j = 0; j < GC_MAX_DEVICES; j++) data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0; parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); @@ -544,24 +568,29 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES] unsigned long flags; unsigned char data2[GC_MAX_DEVICES]; - parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */ + /* Select pad */ + parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); udelay(gc_psx_delay); - parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); /* Deselect, begin command */ + /* Deselect, begin command */ + parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); udelay(gc_psx_delay); local_irq_save(flags); - gc_psx_command(gc, 0x01, data2); /* Access pad */ - gc_psx_command(gc, 0x42, id); /* Get device ids */ - gc_psx_command(gc, 0, data2); /* Dump status */ + gc_psx_command(gc, 0x01, data2); /* Access pad */ + gc_psx_command(gc, 0x42, id); /* Get device ids */ + gc_psx_command(gc, 0, data2); /* Dump status */ - for (i =0; i < GC_MAX_DEVICES; i++) /* Find the longest pad */ - if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) - && (GC_PSX_LEN(id[i]) > max_len) - && (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES)) + /* Find the longest pad */ + for (i = 0; i < GC_MAX_DEVICES; i++) + if ((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) && + GC_PSX_LEN(id[i]) > max_len && + GC_PSX_LEN(id[i]) <= GC_PSX_BYTES) { max_len = GC_PSX_LEN(id[i]); + } - for (i = 0; i < max_len; i++) { /* Read in all the data */ + /* Read in all the data */ + for (i = 0; i < max_len; i++) { gc_psx_command(gc, 0, data2); for (j = 0; j < GC_MAX_DEVICES; j++) data[j][i] = data2[j]; @@ -571,86 +600,99 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES] parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); - for(i = 0; i < GC_MAX_DEVICES; i++) /* Set id's to the real value */ + /* Set id's to the real value */ + for (i = 0; i < GC_MAX_DEVICES; i++) id[i] = GC_PSX_ID(id[i]); } -static void gc_psx_process_packet(struct gc *gc) +static void gc_psx_report_one(struct gc *gc, struct input_dev *dev, + unsigned char pad_type, unsigned char status_bit, + unsigned char *data) { - unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES]; - unsigned char id[GC_MAX_DEVICES]; - struct input_dev *dev; - int i, j; + int i; - gc_psx_read_packet(gc, data, id); + switch (pad_type) { - for (i = 0; i < GC_MAX_DEVICES; i++) { + case GC_PSX_RUMBLE: - dev = gc->dev[i]; - if (!dev) - continue; + input_report_key(dev, BTN_THUMBL, ~data[0] & 0x04); + input_report_key(dev, BTN_THUMBR, ~data[0] & 0x02); - switch (id[i]) { + case GC_PSX_NEGCON: + case GC_PSX_ANALOG: - case GC_PSX_RUMBLE: + if (gc->pads[GC_DDR] & status_bit) { + for (i = 0; i < 4; i++) + input_report_key(dev, gc_psx_ddr_btn[i], + ~data[0] & (0x10 << i)); + } else { + for (i = 0; i < 4; i++) + input_report_abs(dev, gc_psx_abs[i + 2], + data[i + 2]); - input_report_key(dev, BTN_THUMBL, ~data[i][0] & 0x04); - input_report_key(dev, BTN_THUMBR, ~data[i][0] & 0x02); + input_report_abs(dev, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128); + input_report_abs(dev, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128); + } - case GC_PSX_NEGCON: - case GC_PSX_ANALOG: + for (i = 0; i < 8; i++) + input_report_key(dev, gc_psx_btn[i], ~data[1] & (1 << i)); - if (gc->pads[GC_DDR] & gc_status_bit[i]) { - for(j = 0; j < 4; j++) - input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j)); - } else { - for (j = 0; j < 4; j++) - input_report_abs(dev, gc_psx_abs[j + 2], data[i][j + 2]); + input_report_key(dev, BTN_START, ~data[0] & 0x08); + input_report_key(dev, BTN_SELECT, ~data[0] & 0x01); - input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128); - input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128); - } + input_sync(dev); - for (j = 0; j < 8; j++) - input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j)); + break; - input_report_key(dev, BTN_START, ~data[i][0] & 0x08); - input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01); + case GC_PSX_NORMAL: + if (gc->pads[GC_DDR] & status_bit) { + for (i = 0; i < 4; i++) + input_report_key(dev, gc_psx_ddr_btn[i], + ~data[0] & (0x10 << i)); + } else { + input_report_abs(dev, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128); + input_report_abs(dev, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128); - input_sync(dev); + /* + * For some reason if the extra axes are left unset + * they drift. + * for (i = 0; i < 4; i++) + input_report_abs(dev, gc_psx_abs[i + 2], 128); + * This needs to be debugged properly, + * maybe fuzz processing needs to be done + * in input_sync() + * --vojtech + */ + } - break; + for (i = 0; i < 8; i++) + input_report_key(dev, gc_psx_btn[i], ~data[1] & (1 << i)); - case GC_PSX_NORMAL: - if (gc->pads[GC_DDR] & gc_status_bit[i]) { - for(j = 0; j < 4; j++) - input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j)); - } else { - input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128); - input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128); + input_report_key(dev, BTN_START, ~data[0] & 0x08); + input_report_key(dev, BTN_SELECT, ~data[0] & 0x01); - /* for some reason if the extra axes are left unset they drift */ - /* for (j = 0; j < 4; j++) - input_report_abs(dev, gc_psx_abs[j + 2], 128); - * This needs to be debugged properly, - * maybe fuzz processing needs to be done in input_sync() - * --vojtech - */ - } + input_sync(dev); + + break; - for (j = 0; j < 8; j++) - input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j)); + case 0: /* not a pad, ignore */ + break; + } +} - input_report_key(dev, BTN_START, ~data[i][0] & 0x08); - input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01); +static void gc_psx_process_packet(struct gc *gc) +{ + unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES]; + unsigned char id[GC_MAX_DEVICES]; + int i; - input_sync(dev); + gc_psx_read_packet(gc, data, id); - break; + for (i = 0; i < GC_MAX_DEVICES; i++) { - case 0: /* not a pad, ignore */ - break; - } + if (gc->dev[i]) + gc_psx_report_one(gc, gc->dev[i], + id[i], gc_status_bit[i], data[i]); } } @@ -770,60 +812,61 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) switch (pad_type) { - case GC_N64: - for (i = 0; i < 10; i++) - set_bit(gc_n64_btn[i], input_dev->keybit); - - for (i = 0; i < 2; i++) { - input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2); - input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); - } - - err = gc_n64_init_ff(input_dev, idx); - if (err) { - printk(KERN_WARNING "gamecon.c: Failed to initiate rumble for N64 device %d\n", idx); - input_free_device(input_dev); - return err; - } - - break; - - case GC_SNESMOUSE: - set_bit(BTN_LEFT, input_dev->keybit); - set_bit(BTN_RIGHT, input_dev->keybit); - set_bit(REL_X, input_dev->relbit); - set_bit(REL_Y, input_dev->relbit); - break; - - case GC_SNES: - for (i = 4; i < 8; i++) - set_bit(gc_snes_btn[i], input_dev->keybit); - case GC_NES: - for (i = 0; i < 4; i++) - set_bit(gc_snes_btn[i], input_dev->keybit); - break; + case GC_N64: + for (i = 0; i < 10; i++) + __set_bit(gc_n64_btn[i], input_dev->keybit); - case GC_MULTI2: - set_bit(BTN_THUMB, input_dev->keybit); - case GC_MULTI: - set_bit(BTN_TRIGGER, input_dev->keybit); - break; - - case GC_PSX: - for (i = 0; i < 6; i++) - input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2); - for (i = 0; i < 12; i++) - set_bit(gc_psx_btn[i], input_dev->keybit); - - break; + for (i = 0; i < 2; i++) { + input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2); + input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); + } - case GC_DDR: - for (i = 0; i < 4; i++) - set_bit(gc_psx_ddr_btn[i], input_dev->keybit); - for (i = 0; i < 12; i++) - set_bit(gc_psx_btn[i], input_dev->keybit); + err = gc_n64_init_ff(input_dev, idx); + if (err) { + printk(KERN_WARNING "gamecon.c: Failed to initiate rumble for N64 device %d\n", idx); + input_free_device(input_dev); + return err; + } - break; + break; + + case GC_SNESMOUSE: + __set_bit(BTN_LEFT, input_dev->keybit); + __set_bit(BTN_RIGHT, input_dev->keybit); + __set_bit(REL_X, input_dev->relbit); + __set_bit(REL_Y, input_dev->relbit); + break; + + case GC_SNES: + for (i = 4; i < 8; i++) + __set_bit(gc_snes_btn[i], input_dev->keybit); + case GC_NES: + for (i = 0; i < 4; i++) + __set_bit(gc_snes_btn[i], input_dev->keybit); + break; + + case GC_MULTI2: + __set_bit(BTN_THUMB, input_dev->keybit); + case GC_MULTI: + __set_bit(BTN_TRIGGER, input_dev->keybit); + break; + + case GC_PSX: + for (i = 0; i < 6; i++) + input_set_abs_params(input_dev, + gc_psx_abs[i], 4, 252, 0, 2); + for (i = 0; i < 12; i++) + __set_bit(gc_psx_btn[i], input_dev->keybit); + + break; + + case GC_DDR: + for (i = 0; i < 4; i++) + __set_bit(gc_psx_ddr_btn[i], input_dev->keybit); + for (i = 0; i < 12; i++) + __set_bit(gc_psx_btn[i], input_dev->keybit); + + break; } return 0; @@ -860,9 +903,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) mutex_init(&gc->mutex); gc->pd = pd; - init_timer(&gc->timer); - gc->timer.data = (long) gc; - gc->timer.function = gc_timer; + setup_timer(&gc->timer, gc_timer, (long) gc); for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) { if (!pads[i]) -- cgit v1.2.3 From 315543fd112ae3b573bc44e7dbfef99c11714610 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 21 Feb 2010 20:54:31 -0800 Subject: Input: gamecon - simplify coordinate calculation for PSX Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/gamecon.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index ec01bea8dc81..d57edd4a5992 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -630,8 +630,10 @@ static void gc_psx_report_one(struct gc *gc, struct input_dev *dev, input_report_abs(dev, gc_psx_abs[i + 2], data[i + 2]); - input_report_abs(dev, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128); - input_report_abs(dev, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128); + input_report_abs(dev, ABS_X, + !!(data[0] & 0x80) * 128 + !(data[0] & 0x20) * 127); + input_report_abs(dev, ABS_Y, + !!(data[0] & 0x10) * 128 + !(data[0] & 0x40) * 127); } for (i = 0; i < 8; i++) @@ -650,8 +652,10 @@ static void gc_psx_report_one(struct gc *gc, struct input_dev *dev, input_report_key(dev, gc_psx_ddr_btn[i], ~data[0] & (0x10 << i)); } else { - input_report_abs(dev, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128); - input_report_abs(dev, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128); + input_report_abs(dev, ABS_X, + !!(data[0] & 0x80) * 128 + !(data[0] & 0x20) * 127); + input_report_abs(dev, ABS_Y, + !!(data[0] & 0x10) * 128 + !(data[0] & 0x40) * 127); /* * For some reason if the extra axes are left unset -- cgit v1.2.3 From 0995174dda3e97d70fd9c335c55041b6b5aa11dd Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 21 Feb 2010 20:54:54 -0800 Subject: Input: gamecon - simplify pad type handling Instead of having array bitmasks by type for all gamepads have explicit type field in every pad structure. Tested-by: Scott Moreau Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/gamecon.c | 202 ++++++++++++++++++++++++--------------- 1 file changed, 123 insertions(+), 79 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index d57edd4a5992..e9c6647e1f74 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -61,28 +61,36 @@ MODULE_PARM_DESC(map3, "Describes third set of devices"); /* see also gs_psx_delay parameter in PSX support section */ -#define GC_SNES 1 -#define GC_NES 2 -#define GC_NES4 3 -#define GC_MULTI 4 -#define GC_MULTI2 5 -#define GC_N64 6 -#define GC_PSX 7 -#define GC_DDR 8 -#define GC_SNESMOUSE 9 - -#define GC_MAX 9 +enum gc_type { + GC_NONE = 0, + GC_SNES, + GC_NES, + GC_NES4, + GC_MULTI, + GC_MULTI2, + GC_N64, + GC_PSX, + GC_DDR, + GC_SNESMOUSE, + GC_MAX +}; #define GC_REFRESH_TIME HZ/100 +struct gc_pad { + struct input_dev *dev; + enum gc_type type; + char phys[32]; +}; + struct gc { struct pardevice *pd; + struct gc_pad pads[GC_MAX_DEVICES]; struct input_dev *dev[GC_MAX_DEVICES]; struct timer_list timer; - unsigned char pads[GC_MAX + 1]; + int pad_count[GC_MAX]; int used; struct mutex mutex; - char phys[GC_MAX_DEVICES][32]; }; struct gc_subdev { @@ -218,13 +226,13 @@ static void gc_n64_process_packet(struct gc *gc) for (i = 0; i < GC_MAX_DEVICES; i++) { - dev = gc->dev[i]; - if (!dev) + if (gc->pads[i].type != GC_N64) continue; + dev = gc->pads[i].dev; s = gc_status_bit[i]; - if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) { + if (s & ~(data[8] | data[9])) { x = y = 0; @@ -363,39 +371,47 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data) static void gc_nes_process_packet(struct gc *gc) { unsigned char data[GC_SNESMOUSE_LENGTH]; + struct gc_pad *pad; struct input_dev *dev; int i, j, s, len; char x_rel, y_rel; - len = gc->pads[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH : - (gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH); + len = gc->pad_count[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH : + (gc->pad_count[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH); gc_nes_read_packet(gc, len, data); for (i = 0; i < GC_MAX_DEVICES; i++) { + pad = &gc->pads[i]; dev = gc->dev[i]; - if (!dev) - continue; - s = gc_status_bit[i]; - if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) { + switch (pad->type) { + + case GC_NES: + input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); - } - if (s & gc->pads[GC_NES]) for (j = 0; j < 4; j++) input_report_key(dev, gc_snes_btn[j], s & data[gc_nes_bytes[j]]); + input_sync(dev); + break; + + case GC_SNES: + + input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); + input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); - if (s & gc->pads[GC_SNES]) for (j = 0; j < 8; j++) input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]); + input_sync(dev); + break; - if (s & gc->pads[GC_SNESMOUSE]) { + case GC_SNESMOUSE: /* * The 4 unused bits from SNES controllers appear * to be ID bits so use them to make sure we are @@ -432,9 +448,14 @@ static void gc_nes_process_packet(struct gc *gc) y_rel = -y_rel; input_report_rel(dev, REL_Y, y_rel); } + + input_sync(dev); } + break; + + default: + break; } - input_sync(dev); } } @@ -462,32 +483,35 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data) static void gc_multi_process_packet(struct gc *gc) { unsigned char data[GC_MULTI2_LENGTH]; - int data_len = gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH; + int data_len = gc->pad_count[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH; + struct gc_pad *pad; struct input_dev *dev; int i, s; gc_multi_read_packet(gc, data_len, data); for (i = 0; i < GC_MAX_DEVICES; i++) { - - dev = gc->dev[i]; - if (!dev) - continue; - + pad = &gc->pads[i]; + dev = pad->dev; s = gc_status_bit[i]; - if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) { + switch (pad->type) { + case GC_MULTI2: + input_report_key(dev, BTN_THUMB, s & data[5]); + /* fall through */ + + case GC_MULTI: input_report_abs(dev, ABS_X, !(s & data[2]) - !(s & data[3])); input_report_abs(dev, ABS_Y, !(s & data[0]) - !(s & data[1])); input_report_key(dev, BTN_TRIGGER, s & data[4]); - } - - if (s & gc->pads[GC_MULTI2]) - input_report_key(dev, BTN_THUMB, s & data[5]); + input_sync(dev); + break; - input_sync(dev); + default: + break; + } } } @@ -548,9 +572,16 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char *data) cmd = (b & 1) ? GC_PSX_COMMAND : 0; parport_write_data(port, cmd | GC_PSX_POWER); udelay(gc_psx_delay); + read = parport_read_status(port) ^ 0x80; - for (j = 0; j < GC_MAX_DEVICES; j++) - data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0; + + for (j = 0; j < GC_MAX_DEVICES; j++) { + struct gc_pad *pad = &gc->pads[i]; + + if (pad->type == GC_PSX || pad->type == GC_DDR) + data[j] |= (read & gc_status_bit[j]) ? (1 << i) : 0; + } + parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); udelay(gc_psx_delay); } @@ -561,7 +592,8 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char *data) * device identifier code. */ -static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES], +static void gc_psx_read_packet(struct gc *gc, + unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES], unsigned char id[GC_MAX_DEVICES]) { int i, j, max_len = 0; @@ -582,12 +614,15 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES] gc_psx_command(gc, 0, data2); /* Dump status */ /* Find the longest pad */ - for (i = 0; i < GC_MAX_DEVICES; i++) - if ((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) && + for (i = 0; i < GC_MAX_DEVICES; i++) { + struct gc_pad *pad = &gc->pads[i]; + + if ((pad->type == GC_PSX || pad->type == GC_DDR) && GC_PSX_LEN(id[i]) > max_len && GC_PSX_LEN(id[i]) <= GC_PSX_BYTES) { max_len = GC_PSX_LEN(id[i]); } + } /* Read in all the data */ for (i = 0; i < max_len; i++) { @@ -605,13 +640,13 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES] id[i] = GC_PSX_ID(id[i]); } -static void gc_psx_report_one(struct gc *gc, struct input_dev *dev, - unsigned char pad_type, unsigned char status_bit, +static void gc_psx_report_one(struct gc_pad *pad, unsigned char psx_type, unsigned char *data) { + struct input_dev *dev = pad->dev; int i; - switch (pad_type) { + switch (psx_type) { case GC_PSX_RUMBLE: @@ -621,7 +656,7 @@ static void gc_psx_report_one(struct gc *gc, struct input_dev *dev, case GC_PSX_NEGCON: case GC_PSX_ANALOG: - if (gc->pads[GC_DDR] & status_bit) { + if (pad->type == GC_DDR) { for (i = 0; i < 4; i++) input_report_key(dev, gc_psx_ddr_btn[i], ~data[0] & (0x10 << i)); @@ -647,7 +682,8 @@ static void gc_psx_report_one(struct gc *gc, struct input_dev *dev, break; case GC_PSX_NORMAL: - if (gc->pads[GC_DDR] & status_bit) { + + if (pad->type == GC_DDR) { for (i = 0; i < 4; i++) input_report_key(dev, gc_psx_ddr_btn[i], ~data[0] & (0x10 << i)); @@ -679,7 +715,7 @@ static void gc_psx_report_one(struct gc *gc, struct input_dev *dev, break; - case 0: /* not a pad, ignore */ + default: /* not a pad, ignore */ break; } } @@ -688,15 +724,15 @@ static void gc_psx_process_packet(struct gc *gc) { unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES]; unsigned char id[GC_MAX_DEVICES]; + struct gc_pad *pad; int i; gc_psx_read_packet(gc, data, id); for (i = 0; i < GC_MAX_DEVICES; i++) { - - if (gc->dev[i]) - gc_psx_report_one(gc, gc->dev[i], - id[i], gc_status_bit[i], data[i]); + pad = &gc->pads[i]; + if (pad->type == GC_PSX || pad->type == GC_DDR) + gc_psx_report_one(pad, id[i], data[i]); } } @@ -712,28 +748,31 @@ static void gc_timer(unsigned long private) * N64 pads - must be read first, any read confuses them for 200 us */ - if (gc->pads[GC_N64]) + if (gc->pad_count[GC_N64]) gc_n64_process_packet(gc); /* * NES and SNES pads or mouse */ - if (gc->pads[GC_NES] || gc->pads[GC_SNES] || gc->pads[GC_SNESMOUSE]) + if (gc->pad_count[GC_NES] || + gc->pad_count[GC_SNES] || + gc->pad_count[GC_SNESMOUSE]) { gc_nes_process_packet(gc); + } /* * Multi and Multi2 joysticks */ - if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) + if (gc->pad_count[GC_MULTI] || gc->pad_count[GC_MULTI2]) gc_multi_process_packet(gc); /* * PSX controllers */ - if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) + if (gc->pad_count[GC_PSX] || gc->pad_count[GC_DDR]) gc_psx_process_packet(gc); mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); @@ -773,26 +812,29 @@ static void gc_close(struct input_dev *dev) static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) { + struct gc_pad *pad = &gc->pads[idx]; struct input_dev *input_dev; int i; int err; - if (!pad_type) - return 0; - if (pad_type < 1 || pad_type > GC_MAX) { printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type); return -EINVAL; } - gc->dev[idx] = input_dev = input_allocate_device(); + pad->dev = input_dev = input_allocate_device(); if (!input_dev) { printk(KERN_ERR "gamecon.c: Not enough memory for input device\n"); return -ENOMEM; } + pad->type = pad_type; + + snprintf(pad->phys, sizeof(pad->phys), + "%s/input%d", gc->pd->port->name, idx); + input_dev->name = gc_names[pad_type]; - input_dev->phys = gc->phys[idx]; + input_dev->phys = pad->phys; input_dev->id.bustype = BUS_PARPORT; input_dev->id.vendor = 0x0001; input_dev->id.product = pad_type; @@ -811,8 +853,7 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) } else input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - gc->pads[0] |= gc_status_bit[idx]; - gc->pads[pad_type] |= gc_status_bit[idx]; + gc->pad_count[pad_type]++; switch (pad_type) { @@ -828,8 +869,7 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) err = gc_n64_init_ff(input_dev, idx); if (err) { printk(KERN_WARNING "gamecon.c: Failed to initiate rumble for N64 device %d\n", idx); - input_free_device(input_dev); - return err; + goto err_free_dev; } break; @@ -873,7 +913,16 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) break; } + err = input_register_device(pad->dev); + if (err) + goto err_free_dev; + return 0; + +err_free_dev: + input_free_device(pad->dev); + pad->dev = NULL; + return err; } static struct gc __init *gc_probe(int parport, int *pads, int n_pads) @@ -882,6 +931,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) struct parport *pp; struct pardevice *pd; int i; + int count = 0; int err; pp = parport_find_number(parport); @@ -913,18 +963,14 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) if (!pads[i]) continue; - snprintf(gc->phys[i], sizeof(gc->phys[i]), - "%s/input%d", gc->pd->port->name, i); err = gc_setup_pad(gc, i, pads[i]); if (err) goto err_unreg_devs; - err = input_register_device(gc->dev[i]); - if (err) - goto err_free_dev; + count++; } - if (!gc->pads[0]) { + if (count == 0) { printk(KERN_ERR "gamecon.c: No valid devices specified\n"); err = -EINVAL; goto err_free_gc; @@ -933,12 +979,10 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) parport_put_port(pp); return gc; - err_free_dev: - input_free_device(gc->dev[i]); err_unreg_devs: while (--i >= 0) - if (gc->dev[i]) - input_unregister_device(gc->dev[i]); + if (gc->pads[i].dev) + input_unregister_device(gc->pads[i].dev); err_free_gc: kfree(gc); err_unreg_pardev: @@ -954,8 +998,8 @@ static void gc_remove(struct gc *gc) int i; for (i = 0; i < GC_MAX_DEVICES; i++) - if (gc->dev[i]) - input_unregister_device(gc->dev[i]); + if (gc->pads[i].dev) + input_unregister_device(gc->pads[i].dev); parport_unregister_device(gc->pd); kfree(gc); } -- cgit v1.2.3 From af930d646251a6d3f4fd80c5fe158177487f43b7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 21 Feb 2010 20:55:09 -0800 Subject: Input: gamecon - constify some of the setup structures Tested-by: Scott Moreau Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/gamecon.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index e9c6647e1f74..9ba65eae5f68 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -99,9 +99,9 @@ struct gc_subdev { static struct gc *gc_base[3]; -static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; +static const int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; -static char *gc_names[] = { +static const char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", "Multisystem 2-button joystick", "N64 controller", "PSX controller", "PSX DDR controller", "SNES mouse" @@ -111,8 +111,8 @@ static char *gc_names[] = { * N64 support. */ -static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 }; -static short gc_n64_btn[] = { +static const unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 }; +static const short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START }; @@ -339,9 +339,9 @@ static int __init gc_n64_init_ff(struct input_dev *dev, int i) #define GC_NES_CLOCK 0x01 #define GC_NES_LATCH 0x02 -static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 }; -static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 }; -static short gc_snes_btn[] = { +static const unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 }; +static const unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 }; +static const short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR }; @@ -547,14 +547,14 @@ static int gc_psx_delay = GC_PSX_DELAY; module_param_named(psx_delay, gc_psx_delay, uint, 0); MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)"); -static short gc_psx_abs[] = { +static const short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y }; -static short gc_psx_btn[] = { +static const short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y, BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR }; -static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; +static const short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; /* * gc_psx_command() writes 8bit command and reads 8bit data from -- cgit v1.2.3 From a1e1274747b2741188b554e35dc5d4056ef7beac Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 21 Feb 2010 20:55:31 -0800 Subject: Input: gamecon - use pr_err() and friends Tested-by: Scott Moreau Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/gamecon.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 9ba65eae5f68..ae998d99a5ae 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -30,6 +30,8 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -818,13 +820,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) int err; if (pad_type < 1 || pad_type > GC_MAX) { - printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type); + pr_err("Pad type %d unknown\n", pad_type); return -EINVAL; } pad->dev = input_dev = input_allocate_device(); if (!input_dev) { - printk(KERN_ERR "gamecon.c: Not enough memory for input device\n"); + pr_err("Not enough memory for input device\n"); return -ENOMEM; } @@ -868,7 +870,7 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) err = gc_n64_init_ff(input_dev, idx); if (err) { - printk(KERN_WARNING "gamecon.c: Failed to initiate rumble for N64 device %d\n", idx); + pr_warning("Failed to initiate rumble for N64 device %d\n", idx); goto err_free_dev; } @@ -936,21 +938,21 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) pp = parport_find_number(parport); if (!pp) { - printk(KERN_ERR "gamecon.c: no such parport\n"); + pr_err("no such parport %d\n", parport); err = -EINVAL; goto err_out; } pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); if (!pd) { - printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n"); + pr_err("parport busy already - lp.o loaded?\n"); err = -EBUSY; goto err_put_pp; } gc = kzalloc(sizeof(struct gc), GFP_KERNEL); if (!gc) { - printk(KERN_ERR "gamecon.c: Not enough memory\n"); + pr_err("Not enough memory\n"); err = -ENOMEM; goto err_unreg_pardev; } @@ -971,7 +973,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) } if (count == 0) { - printk(KERN_ERR "gamecon.c: No valid devices specified\n"); + pr_err("No valid devices specified\n"); err = -EINVAL; goto err_free_gc; } @@ -1015,7 +1017,7 @@ static int __init gc_init(void) continue; if (gc_cfg[i].nargs < 2) { - printk(KERN_ERR "gamecon.c: at least one device must be specified\n"); + pr_err("at least one device must be specified\n"); err = -EINVAL; break; } -- cgit v1.2.3 From 197d4db752e67160d79fed09968c2140376a80a3 Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Wed, 24 Feb 2010 02:08:29 -0800 Subject: Input: winbond-cir - fix suspend/resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes suspend/resume problem with the driver caused by the fact that ACPI _DIS method would completely power off the SP3 module leaving the output lines (including IRQ lines) in an undefined state. This could cause spurious interrupts and requires reinitializing hardware from scratch during resume. This fixes: http://bugzilla.kernel.org/show_bug.cgi?id=15257 Signed-off-by: David Härdeman Signed-off-by: Dmitry Torokhov --- drivers/input/misc/winbond-cir.c | 213 +++++++++++++++++++-------------------- 1 file changed, 104 insertions(+), 109 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c index c8f5a9a3fa14..cbec3dfdd42b 100644 --- a/drivers/input/misc/winbond-cir.c +++ b/drivers/input/misc/winbond-cir.c @@ -538,6 +538,7 @@ wbcir_reset_irdata(struct wbcir_data *data) data->irdata_count = 0; data->irdata_off = 0; data->irdata_error = 0; + data->idle_count = 0; } /* Adds one bit of irdata */ @@ -1006,7 +1007,6 @@ wbcir_irq_handler(int irqno, void *cookie) } wbcir_reset_irdata(data); - data->idle_count = 0; } out: @@ -1018,7 +1018,7 @@ out: /***************************************************************************** * - * SUSPEND/RESUME FUNCTIONS + * SETUP/INIT/SUSPEND/RESUME FUNCTIONS * *****************************************************************************/ @@ -1197,7 +1197,16 @@ finish: } /* Disable interrupts */ + wbcir_select_bank(data, WBCIR_BANK_0); outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); + + /* + * ACPI will set the HW disable bit for SP3 which means that the + * output signals are left in an undefined state which may cause + * spurious interrupts which we need to ignore until the hardware + * is reinitialized. + */ + disable_irq(data->irq); } static int @@ -1207,37 +1216,15 @@ wbcir_suspend(struct pnp_dev *device, pm_message_t state) return 0; } -static int -wbcir_resume(struct pnp_dev *device) -{ - struct wbcir_data *data = pnp_get_drvdata(device); - - /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); - - /* Clear CEIR_EN */ - wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); - - /* Enable interrupts */ - wbcir_reset_irdata(data); - outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); - - return 0; -} - - - -/***************************************************************************** - * - * SETUP/INIT FUNCTIONS - * - *****************************************************************************/ - static void -wbcir_cfg_ceir(struct wbcir_data *data) +wbcir_init_hw(struct wbcir_data *data) { u8 tmp; + /* Disable interrupts */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); + /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ tmp = protocol << 4; if (invert) @@ -1264,6 +1251,93 @@ wbcir_cfg_ceir(struct wbcir_data *data) * set SP3_IRRX_SW to binary 01, helpfully not documented */ outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); + + /* Enable extended mode */ + wbcir_select_bank(data, WBCIR_BANK_2); + outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); + + /* + * Configure baud generator, IR data will be sampled at + * a bitrate of: (24Mhz * prescaler) / (divisor * 16). + * + * The ECIR registers include a flag to change the + * 24Mhz clock freq to 48Mhz. + * + * It's not documented in the specs, but fifo levels + * other than 16 seems to be unsupported. + */ + + /* prescaler 1.0, tx/rx fifo lvl 16 */ + outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); + + /* Set baud divisor to generate one byte per bit/cell */ + switch (protocol) { + case IR_PROTOCOL_RC5: + outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); + break; + case IR_PROTOCOL_RC6: + outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); + break; + case IR_PROTOCOL_NEC: + outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); + break; + } + outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); + + /* Set CEIR mode */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); + inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ + inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ + + /* Disable RX demod, run-length encoding/decoding, set freq span */ + wbcir_select_bank(data, WBCIR_BANK_7); + outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); + + /* Disable timer */ + wbcir_select_bank(data, WBCIR_BANK_4); + outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); + + /* Enable MSR interrupt, Clear AUX_IRX */ + wbcir_select_bank(data, WBCIR_BANK_5); + outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); + + /* Disable CRC */ + wbcir_select_bank(data, WBCIR_BANK_6); + outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); + + /* Set RX/TX (de)modulation freq, not really used */ + wbcir_select_bank(data, WBCIR_BANK_7); + outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); + outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); + + /* Set invert and pin direction */ + if (invert) + outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); + else + outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); + + /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ + wbcir_select_bank(data, WBCIR_BANK_0); + outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); + + /* Clear AUX status bits */ + outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); + + /* Enable interrupts */ + wbcir_reset_irdata(data); + outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); +} + +static int +wbcir_resume(struct pnp_dev *device) +{ + struct wbcir_data *data = pnp_get_drvdata(device); + + wbcir_init_hw(data); + enable_irq(data->irq); + + return 0; } static int __devinit @@ -1393,86 +1467,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) device_init_wakeup(&device->dev, 1); - wbcir_cfg_ceir(data); - - /* Disable interrupts */ - wbcir_select_bank(data, WBCIR_BANK_0); - outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); - - /* Enable extended mode */ - wbcir_select_bank(data, WBCIR_BANK_2); - outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); - - /* - * Configure baud generator, IR data will be sampled at - * a bitrate of: (24Mhz * prescaler) / (divisor * 16). - * - * The ECIR registers include a flag to change the - * 24Mhz clock freq to 48Mhz. - * - * It's not documented in the specs, but fifo levels - * other than 16 seems to be unsupported. - */ - - /* prescaler 1.0, tx/rx fifo lvl 16 */ - outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); - - /* Set baud divisor to generate one byte per bit/cell */ - switch (protocol) { - case IR_PROTOCOL_RC5: - outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); - break; - case IR_PROTOCOL_RC6: - outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); - break; - case IR_PROTOCOL_NEC: - outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); - break; - } - outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); - - /* Set CEIR mode */ - wbcir_select_bank(data, WBCIR_BANK_0); - outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); - inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ - inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ - - /* Disable RX demod, run-length encoding/decoding, set freq span */ - wbcir_select_bank(data, WBCIR_BANK_7); - outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); - - /* Disable timer */ - wbcir_select_bank(data, WBCIR_BANK_4); - outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); - - /* Enable MSR interrupt, Clear AUX_IRX */ - wbcir_select_bank(data, WBCIR_BANK_5); - outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); - - /* Disable CRC */ - wbcir_select_bank(data, WBCIR_BANK_6); - outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); - - /* Set RX/TX (de)modulation freq, not really used */ - wbcir_select_bank(data, WBCIR_BANK_7); - outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); - outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); - - /* Set invert and pin direction */ - if (invert) - outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); - else - outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); - - /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ - wbcir_select_bank(data, WBCIR_BANK_0); - outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); - - /* Clear AUX status bits */ - outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); - - /* Enable interrupts */ - outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); + wbcir_init_hw(data); return 0; -- cgit v1.2.3 From 91143379b01b2020d8878d627ebe9dfb9d6eb4c8 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Thu, 25 Feb 2010 02:04:56 -0800 Subject: Input: ads7846 - add regulator support The ADS7846/TSC2046 touchscreen controllers can (and usually are) connected to various regulators for power, so add regulator support. Valid regulator will now be required, so boards without complete regulator setup should either disable regulator framework or enable CONFIG_REGULATOR_DUMMY. Signed-off-by: Grazvydas Ignotas Acked-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 52d2ca147d8f..8b05d8e97543 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -27,6 +27,7 @@ #include #include #include +#include #include /* @@ -85,6 +86,7 @@ struct ads7846 { char name[32]; struct spi_device *spi; + struct regulator *reg; #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) struct attribute_group *attr_group; @@ -788,6 +790,8 @@ static void ads7846_disable(struct ads7846 *ts) } } + regulator_disable(ts->reg); + /* we know the chip's in lowpower mode since we always * leave it that way after every request */ @@ -799,6 +803,8 @@ static void ads7846_enable(struct ads7846 *ts) if (!ts->disabled) return; + regulator_enable(ts->reg); + ts->disabled = 0; ts->irq_disabled = 0; enable_irq(ts->spi->irq); @@ -1139,6 +1145,19 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->last_msg = m; + ts->reg = regulator_get(&spi->dev, "vcc"); + if (IS_ERR(ts->reg)) { + dev_err(&spi->dev, "unable to get regulator: %ld\n", + PTR_ERR(ts->reg)); + goto err_free_gpio; + } + + err = regulator_enable(ts->reg); + if (err) { + dev_err(&spi->dev, "unable to enable regulator: %d\n", err); + goto err_put_regulator; + } + if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, spi->dev.driver->name, ts)) { dev_info(&spi->dev, @@ -1148,7 +1167,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) spi->dev.driver->name, ts); if (err) { dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); - goto err_free_gpio; + goto err_disable_regulator; } } @@ -1180,6 +1199,10 @@ static int __devinit ads7846_probe(struct spi_device *spi) ads784x_hwmon_unregister(spi, ts); err_free_irq: free_irq(spi->irq, ts); + err_disable_regulator: + regulator_disable(ts->reg); + err_put_regulator: + regulator_put(ts->reg); err_free_gpio: if (ts->gpio_pendown != -1) gpio_free(ts->gpio_pendown); @@ -1208,6 +1231,9 @@ static int __devexit ads7846_remove(struct spi_device *spi) /* suspend left the IRQ disabled */ enable_irq(ts->spi->irq); + regulator_disable(ts->reg); + regulator_put(ts->reg); + if (ts->gpio_pendown != -1) gpio_free(ts->gpio_pendown); -- cgit v1.2.3 From 4b70858ba8d4537daf782defebe5f2ff80ccef2b Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 26 Feb 2010 00:22:04 -0800 Subject: Input: atkbd - release previously reserved keycodes 248 - 254 Keycodes in 248 - 254 range were reserved for special needs (scrolling) of atkbd driver. Now that the driver has been switched to use unsigned short keycodes instead of unsigned char we can release this range back into pull. We keep code 255 (ATKBD_KEY_NULL) reserved since users may have been using it to silence keys they do not care about since atkbd silently drops scancodes mapped to this keycode. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 26 +++++++++++++++----------- include/linux/input.h | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 326875be192e..d358ef8623f4 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -153,16 +153,16 @@ static const unsigned short atkbd_unxlate_table[128] = { #define ATKBD_RET_HANGEUL 0xf2 #define ATKBD_RET_ERR 0xff -#define ATKBD_KEY_UNKNOWN 0 +#define ATKBD_KEY_UNKNOWN 0 #define ATKBD_KEY_NULL 255 -#define ATKBD_SCR_1 254 -#define ATKBD_SCR_2 253 -#define ATKBD_SCR_4 252 -#define ATKBD_SCR_8 251 -#define ATKBD_SCR_CLICK 250 -#define ATKBD_SCR_LEFT 249 -#define ATKBD_SCR_RIGHT 248 +#define ATKBD_SCR_1 0xfffe +#define ATKBD_SCR_2 0xfffd +#define ATKBD_SCR_4 0xfffc +#define ATKBD_SCR_8 0xfffb +#define ATKBD_SCR_CLICK 0xfffa +#define ATKBD_SCR_LEFT 0xfff9 +#define ATKBD_SCR_RIGHT 0xfff8 #define ATKBD_SPECIAL ATKBD_SCR_RIGHT @@ -177,7 +177,7 @@ static const unsigned short atkbd_unxlate_table[128] = { #define ATKBD_XL_HANJA 0x20 static const struct { - unsigned char keycode; + unsigned short keycode; unsigned char set2; } atkbd_scroll_keys[] = { { ATKBD_SCR_1, 0xc5 }, @@ -1074,9 +1074,13 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) input_dev->keycodesize = sizeof(unsigned short); input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); - for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) - if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) + for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) { + if (atkbd->keycode[i] != KEY_RESERVED && + atkbd->keycode[i] != ATKBD_KEY_NULL && + atkbd->keycode[i] < ATKBD_SPECIAL) { __set_bit(atkbd->keycode[i], input_dev->keybit); + } + } } /* diff --git a/include/linux/input.h b/include/linux/input.h index 828c3feb7213..b1a74fb2e436 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -377,7 +377,7 @@ struct input_absinfo { #define KEY_WIMAX 246 -/* Range 248 - 255 is reserved for special needs of AT keyboard driver */ +/* Code 255 is reserved for special needs of AT keyboard driver */ #define BTN_MISC 0x100 #define BTN_0 0x100 -- cgit v1.2.3