diff options
| author | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-07-26 01:39:38 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-07-26 01:39:38 -0700 |
| commit | a8a4e4a9b2fa28ebf48ef9c34f461de95256a020 (patch) | |
| tree | 10fec7baa36bd0ae83e599ef2897be7e325be593 /drivers | |
| parent | 025f143cddaaf9827fca546eba574fea6e0f514a (diff) | |
| parent | d243f1a8e0dcb20c1728919dce5f6e8b3e4136dc (diff) | |
Merge bk://lsm.bkbits.net/linus-2.5
into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
Diffstat (limited to 'drivers')
156 files changed, 7428 insertions, 6007 deletions
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index c98eefa44766..c9faecf0e450 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -1,5 +1,5 @@ /* - * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 26 $) + * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 27 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -47,13 +47,13 @@ int acpi_ac_add (struct acpi_device *device); int acpi_ac_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_ac_driver = { - name: ACPI_AC_DRIVER_NAME, - class: ACPI_AC_CLASS, - ids: ACPI_AC_HID, - ops: { - add: acpi_ac_add, - remove: acpi_ac_remove, - }, + .name = ACPI_AC_DRIVER_NAME, + .class = ACPI_AC_CLASS, + .ids = ACPI_AC_HID, + .ops = { + .add = acpi_ac_add, + .remove = acpi_ac_remove, + }, }; struct acpi_ac { diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 6684da84decd..6a096d8c1463 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1,5 +1,5 @@ /* - * acpi_battery.c - ACPI Battery Driver ($Revision: 36 $) + * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -52,13 +52,13 @@ static int acpi_battery_add (struct acpi_device *device); static int acpi_battery_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_battery_driver = { - name: ACPI_BATTERY_DRIVER_NAME, - class: ACPI_BATTERY_CLASS, - ids: ACPI_BATTERY_HID, - ops: { - add: acpi_battery_add, - remove: acpi_battery_remove, - }, + .name = ACPI_BATTERY_DRIVER_NAME, + .class = ACPI_BATTERY_CLASS, + .ids = ACPI_BATTERY_HID, + .ops = { + .add = acpi_battery_add, + .remove = acpi_battery_remove, + }, }; struct acpi_battery_status { diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 900cbe0de6b2..881d02a7c5c7 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1,5 +1,5 @@ /* - * acpi_bus.c - ACPI Bus Driver ($Revision: 79 $) + * acpi_bus.c - ACPI Bus Driver ($Revision: 80 $) * * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * @@ -97,10 +97,10 @@ static int acpi_device_suspend(struct device *dev, u32 state, u32 stage); static int acpi_device_resume(struct device *dev, u32 stage); static struct device_driver acpi_bus_driver = { - probe: acpi_device_probe, - remove: acpi_device_remove, - suspend: acpi_device_suspend, - resume: acpi_device_resume, + .probe = acpi_device_probe, + .remove = acpi_device_remove, + .suspend = acpi_device_suspend, + .resume = acpi_device_resume, }; diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 5beed76b3dd3..cdd6c926ea5c 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -1,5 +1,5 @@ /* - * acpi_button.c - ACPI Button Driver ($Revision: 29 $) + * acpi_button.c - ACPI Button Driver ($Revision: 30 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -47,13 +47,13 @@ int acpi_button_add (struct acpi_device *device); int acpi_button_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_button_driver = { - name: ACPI_BUTTON_DRIVER_NAME, - class: ACPI_BUTTON_CLASS, - ids: "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E", - ops: { - add: acpi_button_add, - remove: acpi_button_remove, - }, + .name = ACPI_BUTTON_DRIVER_NAME, + .class = ACPI_BUTTON_CLASS, + .ids = "ACPI_FPB,ACPI_FSB,PNP0C0D,PNP0C0C,PNP0C0E", + .ops = { + .add = acpi_button_add, + .remove = acpi_button_remove, + }, }; struct acpi_button { diff --git a/drivers/acpi/debugger/dbcmds.c b/drivers/acpi/debugger/dbcmds.c index 0a3a4282cbb3..6cb00097d1d5 100644 --- a/drivers/acpi/debugger/dbcmds.c +++ b/drivers/acpi/debugger/dbcmds.c @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbcmds - debug commands and output routines - * $Revision: 84 $ + * $Revision: 85 $ * ******************************************************************************/ @@ -31,6 +31,7 @@ #include "acevents.h" #include "acdebug.h" #include "acresrc.h" +#include "acdisasm.h" #ifdef ENABLE_DEBUGGER @@ -342,7 +343,7 @@ acpi_db_disassemble_aml ( num_statements = ACPI_STRTOUL (statements, NULL, 0); } - acpi_db_display_op (NULL, op, num_statements); + acpi_dm_disassemble (NULL, op, num_statements); } diff --git a/drivers/acpi/debugger/dbfileio.c b/drivers/acpi/debugger/dbfileio.c index d9c7406c7f0c..a814fc858135 100644 --- a/drivers/acpi/debugger/dbfileio.c +++ b/drivers/acpi/debugger/dbfileio.c @@ -2,7 +2,7 @@ * * Module Name: dbfileio - Debugger file I/O commands. These can't usually * be used when running the debugger in Ring 0 (Kernel mode) - * $Revision: 64 $ + * $Revision: 67 $ * ******************************************************************************/ @@ -30,7 +30,7 @@ #include "acnamesp.h" #include "actables.h" -#ifdef ENABLE_DEBUGGER +#if (defined ENABLE_DEBUGGER || defined ACPI_DISASSEMBLER) #define _COMPONENT ACPI_DEBUGGER ACPI_MODULE_NAME ("dbfileio") @@ -86,6 +86,7 @@ acpi_db_match_argument ( } +#ifdef ENABLE_DEBUGGER /******************************************************************************* * * FUNCTION: Acpi_db_close_debug_file @@ -148,6 +149,7 @@ acpi_db_open_debug_file ( #endif } +#endif #ifdef ACPI_APPLICATION @@ -190,7 +192,7 @@ acpi_db_load_table( status = acpi_tb_validate_table_header (&table_header); if ((ACPI_FAILURE (status)) || - (table_header.length > 524288)) /* 1/2 Mbyte should be enough */ { + (table_header.length > 0x800000)) /* 8 Mbyte should be enough */ { acpi_os_printf ("Table header is invalid!\n"); return (AE_ERROR); } @@ -296,7 +298,7 @@ ae_local_load_table ( } -#ifndef PARSER_ONLY +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node); if (ACPI_FAILURE (status)) { /* Uninstall table and free the buffer */ @@ -330,7 +332,7 @@ acpi_db_get_acpi_table ( /* Get the entire file */ - acpi_os_printf ("Loading Acpi table from file %s\n", filename); + fprintf (stderr, "Loading Acpi table from file %s\n", filename); status = acpi_db_load_table (fp, &acpi_gbl_db_table_ptr, &table_length); fclose(fp); @@ -383,8 +385,8 @@ acpi_db_load_acpi_table ( return (status); } - acpi_os_printf ("%4.4s at %p successfully installed and loaded\n", - acpi_gbl_db_table_ptr->signature, acpi_gbl_db_table_ptr); + fprintf (stderr, "Acpi table [%4.4s] successfully installed and loaded\n", + acpi_gbl_db_table_ptr->signature); acpi_gbl_acpi_hardware_present = FALSE; diff --git a/drivers/acpi/debugger/dbxface.c b/drivers/acpi/debugger/dbxface.c index d0cad6347c5d..50d28c7ac8e4 100644 --- a/drivers/acpi/debugger/dbxface.c +++ b/drivers/acpi/debugger/dbxface.c @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dbxface - AML Debugger external interfaces - * $Revision: 59 $ + * $Revision: 61 $ * ******************************************************************************/ @@ -27,6 +27,7 @@ #include "acpi.h" #include "amlcode.h" #include "acdebug.h" +#include "acdisasm.h" #ifdef ENABLE_DEBUGGER @@ -164,7 +165,7 @@ acpi_db_single_step ( /* Now we can display it */ - acpi_db_display_op (walk_state, display_op, ACPI_UINT32_MAX); + acpi_dm_disassemble (walk_state, display_op, ACPI_UINT32_MAX); if ((op->common.aml_opcode == AML_IF_OP) || (op->common.aml_opcode == AML_WHILE_OP)) { @@ -351,7 +352,6 @@ acpi_db_initialize (void) } if (!acpi_gbl_db_opt_verbose) { - acpi_gbl_db_disasm_indent = " "; acpi_gbl_db_opt_disasm = TRUE; acpi_gbl_db_opt_stats = FALSE; } diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index a78f428efe25..9923b6650cc4 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dsobject - Dispatcher object management routines - * $Revision: 104 $ + * $Revision: 105 $ * *****************************************************************************/ @@ -35,6 +35,7 @@ ACPI_MODULE_NAME ("dsobject") +#ifndef ACPI_NO_METHOD_EXECUTION /******************************************************************************* * * FUNCTION: Acpi_ds_init_one_object @@ -218,199 +219,6 @@ acpi_ds_initialize_objects ( /***************************************************************************** * - * FUNCTION: Acpi_ds_init_object_from_op - * - * PARAMETERS: Walk_state - Current walk state - * Op - Parser op used to init the internal object - * Opcode - AML opcode associated with the object - * Ret_obj_desc - Namespace object to be initialized - * - * RETURN: Status - * - * DESCRIPTION: Initialize a namespace object from a parser Op and its - * associated arguments. The namespace object is a more compact - * representation of the Op and its arguments. - * - ****************************************************************************/ - -acpi_status -acpi_ds_init_object_from_op ( - acpi_walk_state *walk_state, - acpi_parse_object *op, - u16 opcode, - acpi_operand_object **ret_obj_desc) -{ - const acpi_opcode_info *op_info; - acpi_operand_object *obj_desc; - acpi_status status = AE_OK; - - - ACPI_FUNCTION_TRACE ("Ds_init_object_from_op"); - - - obj_desc = *ret_obj_desc; - op_info = acpi_ps_get_opcode_info (opcode); - if (op_info->class == AML_CLASS_UNKNOWN) { - /* Unknown opcode */ - - return_ACPI_STATUS (AE_TYPE); - } - - /* Perform per-object initialization */ - - switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { - case ACPI_TYPE_BUFFER: - - /* - * Defer evaluation of Buffer Term_arg operand - */ - obj_desc->buffer.node = (acpi_namespace_node *) walk_state->operands[0]; - obj_desc->buffer.aml_start = op->named.data; - obj_desc->buffer.aml_length = op->named.length; - break; - - - case ACPI_TYPE_PACKAGE: - - /* - * Defer evaluation of Package Term_arg operand - */ - obj_desc->package.node = (acpi_namespace_node *) walk_state->operands[0]; - obj_desc->package.aml_start = op->named.data; - obj_desc->package.aml_length = op->named.length; - break; - - - case ACPI_TYPE_INTEGER: - - switch (op_info->type) { - case AML_TYPE_CONSTANT: - /* - * Resolve AML Constants here - AND ONLY HERE! - * All constants are integers. - * We mark the integer with a flag that indicates that it started life - * as a constant -- so that stores to constants will perform as expected (noop). - * (Zero_op is used as a placeholder for optional target operands.) - */ - obj_desc->common.flags = AOPOBJ_AML_CONSTANT; - - switch (opcode) { - case AML_ZERO_OP: - - obj_desc->integer.value = 0; - break; - - case AML_ONE_OP: - - obj_desc->integer.value = 1; - break; - - case AML_ONES_OP: - - obj_desc->integer.value = ACPI_INTEGER_MAX; - - /* Truncate value if we are executing from a 32-bit ACPI table */ - - acpi_ex_truncate_for32bit_table (obj_desc); - break; - - case AML_REVISION_OP: - - obj_desc->integer.value = ACPI_CA_SUPPORT_LEVEL; - break; - - default: - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown constant opcode %X\n", opcode)); - status = AE_AML_OPERAND_TYPE; - break; - } - break; - - - case AML_TYPE_LITERAL: - - obj_desc->integer.value = op->common.value.integer; - break; - - - default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n", op_info->type)); - status = AE_AML_OPERAND_TYPE; - break; - } - break; - - - case ACPI_TYPE_STRING: - - obj_desc->string.pointer = op->common.value.string; - obj_desc->string.length = ACPI_STRLEN (op->common.value.string); - - /* - * The string is contained in the ACPI table, don't ever try - * to delete it - */ - obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; - break; - - - case ACPI_TYPE_METHOD: - break; - - - case INTERNAL_TYPE_REFERENCE: - - switch (op_info->type) { - case AML_TYPE_LOCAL_VARIABLE: - - /* Split the opcode into a base opcode + offset */ - - obj_desc->reference.opcode = AML_LOCAL_OP; - obj_desc->reference.offset = opcode - AML_LOCAL_OP; - acpi_ds_method_data_get_node (AML_LOCAL_OP, obj_desc->reference.offset, - walk_state, (acpi_namespace_node **) &obj_desc->reference.object); - break; - - - case AML_TYPE_METHOD_ARGUMENT: - - /* Split the opcode into a base opcode + offset */ - - obj_desc->reference.opcode = AML_ARG_OP; - obj_desc->reference.offset = opcode - AML_ARG_OP; - break; - - - default: /* Other literals, etc.. */ - - if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { - /* Node was saved in Op */ - - obj_desc->reference.node = op->common.node; - } - - obj_desc->reference.opcode = opcode; - break; - } - break; - - - default: - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n", - ACPI_GET_OBJECT_TYPE (obj_desc))); - - status = AE_AML_OPERAND_TYPE; - break; - } - - return_ACPI_STATUS (status); -} - - -/***************************************************************************** - * * FUNCTION: Acpi_ds_build_internal_object * * PARAMETERS: Walk_state - Current walk state @@ -781,4 +589,202 @@ acpi_ds_create_node ( return_ACPI_STATUS (status); } +#endif /* ACPI_NO_METHOD_EXECUTION */ + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_init_object_from_op + * + * PARAMETERS: Walk_state - Current walk state + * Op - Parser op used to init the internal object + * Opcode - AML opcode associated with the object + * Ret_obj_desc - Namespace object to be initialized + * + * RETURN: Status + * + * DESCRIPTION: Initialize a namespace object from a parser Op and its + * associated arguments. The namespace object is a more compact + * representation of the Op and its arguments. + * + ****************************************************************************/ + +acpi_status +acpi_ds_init_object_from_op ( + acpi_walk_state *walk_state, + acpi_parse_object *op, + u16 opcode, + acpi_operand_object **ret_obj_desc) +{ + const acpi_opcode_info *op_info; + acpi_operand_object *obj_desc; + acpi_status status = AE_OK; + + + ACPI_FUNCTION_TRACE ("Ds_init_object_from_op"); + + + obj_desc = *ret_obj_desc; + op_info = acpi_ps_get_opcode_info (opcode); + if (op_info->class == AML_CLASS_UNKNOWN) { + /* Unknown opcode */ + + return_ACPI_STATUS (AE_TYPE); + } + + /* Perform per-object initialization */ + + switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + case ACPI_TYPE_BUFFER: + + /* + * Defer evaluation of Buffer Term_arg operand + */ + obj_desc->buffer.node = (acpi_namespace_node *) walk_state->operands[0]; + obj_desc->buffer.aml_start = op->named.data; + obj_desc->buffer.aml_length = op->named.length; + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * Defer evaluation of Package Term_arg operand + */ + obj_desc->package.node = (acpi_namespace_node *) walk_state->operands[0]; + obj_desc->package.aml_start = op->named.data; + obj_desc->package.aml_length = op->named.length; + break; + + + case ACPI_TYPE_INTEGER: + + switch (op_info->type) { + case AML_TYPE_CONSTANT: + /* + * Resolve AML Constants here - AND ONLY HERE! + * All constants are integers. + * We mark the integer with a flag that indicates that it started life + * as a constant -- so that stores to constants will perform as expected (noop). + * (Zero_op is used as a placeholder for optional target operands.) + */ + obj_desc->common.flags = AOPOBJ_AML_CONSTANT; + + switch (opcode) { + case AML_ZERO_OP: + + obj_desc->integer.value = 0; + break; + + case AML_ONE_OP: + + obj_desc->integer.value = 1; + break; + + case AML_ONES_OP: + + obj_desc->integer.value = ACPI_INTEGER_MAX; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + +#ifndef ACPI_NO_METHOD_EXECUTION + acpi_ex_truncate_for32bit_table (obj_desc); +#endif + break; + + case AML_REVISION_OP: + + obj_desc->integer.value = ACPI_CA_SUPPORT_LEVEL; + break; + + default: + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown constant opcode %X\n", opcode)); + status = AE_AML_OPERAND_TYPE; + break; + } + break; + + + case AML_TYPE_LITERAL: + + obj_desc->integer.value = op->common.value.integer; + break; + + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n", op_info->type)); + status = AE_AML_OPERAND_TYPE; + break; + } + break; + + + case ACPI_TYPE_STRING: + + obj_desc->string.pointer = op->common.value.string; + obj_desc->string.length = ACPI_STRLEN (op->common.value.string); + + /* + * The string is contained in the ACPI table, don't ever try + * to delete it + */ + obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; + break; + + + case ACPI_TYPE_METHOD: + break; + + + case INTERNAL_TYPE_REFERENCE: + + switch (op_info->type) { + case AML_TYPE_LOCAL_VARIABLE: + + /* Split the opcode into a base opcode + offset */ + + obj_desc->reference.opcode = AML_LOCAL_OP; + obj_desc->reference.offset = opcode - AML_LOCAL_OP; +#ifndef ACPI_NO_METHOD_EXECUTION + acpi_ds_method_data_get_node (AML_LOCAL_OP, obj_desc->reference.offset, + walk_state, (acpi_namespace_node **) &obj_desc->reference.object); +#endif + break; + + + case AML_TYPE_METHOD_ARGUMENT: + + /* Split the opcode into a base opcode + offset */ + + obj_desc->reference.opcode = AML_ARG_OP; + obj_desc->reference.offset = opcode - AML_ARG_OP; + break; + + default: /* Other literals, etc.. */ + + if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { + /* Node was saved in Op */ + + obj_desc->reference.node = op->common.node; + } + + obj_desc->reference.opcode = opcode; + break; + } + break; + + + default: + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n", + ACPI_GET_OBJECT_TYPE (obj_desc))); + + status = AE_AML_OPERAND_TYPE; + break; + } + + return_ACPI_STATUS (status); +} + diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 77b50406d3a2..66b6d64bfe6d 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: dsutils - Dispatcher utilities - * $Revision: 93 $ + * $Revision: 94 $ * ******************************************************************************/ @@ -35,6 +35,7 @@ #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME ("dsutils") +#ifndef ACPI_NO_METHOD_EXECUTION /******************************************************************************* * @@ -237,6 +238,47 @@ acpi_ds_delete_result_if_not_used ( /******************************************************************************* * + * FUNCTION: Acpi_ds_resolve_operands + * + * PARAMETERS: Walk_state - Current walk state with operands on stack + * + * RETURN: Status + * + * DESCRIPTION: Resolve all operands to their values. Used to prepare + * arguments to a control method invocation (a call from one + * method to another.) + * + ******************************************************************************/ + +acpi_status +acpi_ds_resolve_operands ( + acpi_walk_state *walk_state) +{ + u32 i; + acpi_status status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR ("Ds_resolve_operands", walk_state); + + + /* + * Attempt to resolve each of the valid operands + * Method arguments are passed by value, not by reference + */ + for (i = 0; i < walk_state->num_operands; i++) { + status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state); + if (ACPI_FAILURE (status)) { + break; + } + } + + return_ACPI_STATUS (status); +} +#endif + + +/******************************************************************************* + * * FUNCTION: Acpi_ds_create_operand * * PARAMETERS: Walk_state @@ -515,42 +557,3 @@ cleanup: } -/******************************************************************************* - * - * FUNCTION: Acpi_ds_resolve_operands - * - * PARAMETERS: Walk_state - Current walk state with operands on stack - * - * RETURN: Status - * - * DESCRIPTION: Resolve all operands to their values. Used to prepare - * arguments to a control method invocation (a call from one - * method to another.) - * - ******************************************************************************/ - -acpi_status -acpi_ds_resolve_operands ( - acpi_walk_state *walk_state) -{ - u32 i; - acpi_status status = AE_OK; - - - ACPI_FUNCTION_TRACE_PTR ("Ds_resolve_operands", walk_state); - - - /* - * Attempt to resolve each of the valid operands - * Method arguments are passed by value, not by reference - */ - for (i = 0; i < walk_state->num_operands; i++) { - status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state); - if (ACPI_FAILURE (status)) { - break; - } - } - - return_ACPI_STATUS (status); -} - diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index c73bbcaf6213..3da768ff5856 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dswload - Dispatcher namespace load callbacks - * $Revision: 67 $ + * $Revision: 69 $ * *****************************************************************************/ @@ -70,9 +70,11 @@ acpi_ds_init_callbacks ( break; case 3: +#ifndef ACPI_NO_METHOD_EXECUTION walk_state->parse_flags |= ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE; walk_state->descending_callback = acpi_ds_exec_begin_op; walk_state->ascending_callback = acpi_ds_exec_end_op; +#endif break; default: @@ -169,6 +171,11 @@ acpi_ds_load1_begin_op ( op->named.name = node->name.integer; +#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) + op->named.path = (u8 *) path; +#endif + + /* * Put the Node in the "op" object that the parser uses, so we * can get it again quickly when this scope is closed @@ -221,6 +228,7 @@ acpi_ds_load1_end_op ( object_type = walk_state->op_info->object_type; +#ifndef ACPI_NO_METHOD_EXECUTION if (walk_state->op_info->flags & AML_FIELD) { if (walk_state->opcode == AML_FIELD_OP || walk_state->opcode == AML_BANK_FIELD_OP || @@ -238,6 +246,7 @@ acpi_ds_load1_end_op ( return (status); } } +#endif if (op->common.aml_opcode == AML_NAME_OP) { /* For Name opcode, get the object type from the argument */ @@ -430,7 +439,9 @@ acpi_ds_load2_end_op ( acpi_namespace_node *node; acpi_parse_object *arg; acpi_namespace_node *new_node; +#ifndef ACPI_NO_METHOD_EXECUTION u32 i; +#endif ACPI_FUNCTION_NAME ("Ds_load2_end_op"); @@ -478,6 +489,7 @@ acpi_ds_load2_end_op ( } } + /* * Named operations are as follows: * @@ -515,6 +527,8 @@ acpi_ds_load2_end_op ( arg = op->common.value.arg; switch (walk_state->op_info->type) { +#ifndef ACPI_NO_METHOD_EXECUTION + case AML_TYPE_CREATE_FIELD: /* @@ -604,7 +618,7 @@ acpi_ds_load2_end_op ( } break; - +#endif /* ACPI_NO_METHOD_EXECUTION */ case AML_TYPE_NAMED_COMPLEX: @@ -629,6 +643,7 @@ acpi_ds_load2_end_op ( break; +#ifndef ACPI_NO_METHOD_EXECUTION case AML_REGION_OP: /* * The Op_region is not fully parsed at this time. Only valid argument is the Space_id. @@ -656,6 +671,7 @@ acpi_ds_load2_end_op ( status = acpi_ds_create_node (walk_state, node, op); break; +#endif /* ACPI_NO_METHOD_EXECUTION */ default: diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 37bb06d5fd9b..c5f83e5704d0 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dswstate - Dispatcher parse tree walk management routines - * $Revision: 65 $ + * $Revision: 67 $ * *****************************************************************************/ @@ -837,7 +837,7 @@ acpi_ds_create_walk_state ( /* Init the method args/local */ -#ifndef _ACPI_ASL_COMPILER +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) acpi_ds_method_data_init (walk_state); #endif @@ -858,7 +858,6 @@ acpi_ds_create_walk_state ( } -#ifndef _ACPI_ASL_COMPILER /******************************************************************************* * * FUNCTION: Acpi_ds_init_aml_walk @@ -943,7 +942,6 @@ acpi_ds_init_aml_walk ( status = acpi_ds_init_callbacks (walk_state, pass_number); return_ACPI_STATUS (status); } -#endif /******************************************************************************* diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3dba2994bd6a..a0fc74029b09 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1,5 +1,5 @@ /* - * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 35 $) + * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -62,15 +62,15 @@ static int acpi_ec_start (struct acpi_device *device); static int acpi_ec_stop (struct acpi_device *device, int type); static struct acpi_driver acpi_ec_driver = { - name: ACPI_EC_DRIVER_NAME, - class: ACPI_EC_CLASS, - ids: ACPI_EC_HID, - ops: { - add: acpi_ec_add, - remove: acpi_ec_remove, - start: acpi_ec_start, - stop: acpi_ec_stop, - }, + .name = ACPI_EC_DRIVER_NAME, + .class = ACPI_EC_CLASS, + .ids = ACPI_EC_HID, + .ops = { + .add = acpi_ec_add, + .remove = acpi_ec_remove, + .start = acpi_ec_start, + .stop = acpi_ec_stop, + }, }; struct acpi_ec { @@ -134,7 +134,7 @@ static int acpi_ec_read ( struct acpi_ec *ec, u8 address, - u8 *data) + u32 *data) { acpi_status status = AE_OK; int result = 0; @@ -167,7 +167,7 @@ acpi_ec_read ( goto end; - acpi_hw_low_level_read(8, (u32*) data, &ec->data_addr, 0); + acpi_hw_low_level_read(8, data, &ec->data_addr, 0); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", *data, address)); @@ -237,7 +237,7 @@ end: static int acpi_ec_query ( struct acpi_ec *ec, - u8 *data) + u32 *data) { int result = 0; acpi_status status = AE_OK; @@ -269,7 +269,7 @@ acpi_ec_query ( if (result) goto end; - acpi_hw_low_level_read(8, (u32*) data, &ec->data_addr, 0); + acpi_hw_low_level_read(8, data, &ec->data_addr, 0); if (!*data) result = -ENODATA; @@ -328,7 +328,7 @@ acpi_ec_gpe_handler ( { acpi_status status = AE_OK; struct acpi_ec *ec = (struct acpi_ec *) data; - u8 value = 0; + u32 value = 0; unsigned long flags = 0; struct acpi_ec_query_data *query_data = NULL; @@ -336,7 +336,7 @@ acpi_ec_gpe_handler ( return; spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_read(8, (u32*) &value, &ec->command_addr, 0); + acpi_hw_low_level_read(8, &value, &ec->command_addr, 0); spin_unlock_irqrestore(&ec->lock, flags); /* TBD: Implement asynch events! @@ -398,6 +398,7 @@ acpi_ec_space_handler ( { int result = 0; struct acpi_ec *ec = NULL; + u32 temp = 0; ACPI_FUNCTION_TRACE("acpi_ec_space_handler"); @@ -408,7 +409,8 @@ acpi_ec_space_handler ( switch (function) { case ACPI_READ: - result = acpi_ec_read(ec, (u8) address, (u8*) value); + result = acpi_ec_read(ec, (u8) address, &temp); + *value = (acpi_integer) temp; break; case ACPI_WRITE: result = acpi_ec_write(ec, (u8) address, (u8) *value); diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 7ea92f53a22b..2f9c06242e88 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: excreate - Named object creation - * $Revision: 92 $ + * $Revision: 93 $ * *****************************************************************************/ @@ -36,6 +36,7 @@ ACPI_MODULE_NAME ("excreate") +#ifndef ACPI_NO_METHOD_EXECUTION /***************************************************************************** * * FUNCTION: Acpi_ex_create_alias @@ -490,6 +491,7 @@ acpi_ex_create_power_resource ( return_ACPI_STATUS (status); } +#endif /***************************************************************************** * diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 49c68d410a68..634d2a4385d7 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exdump - Interpreter debug output routines - * $Revision: 156 $ + * $Revision: 157 $ * *****************************************************************************/ @@ -575,14 +575,14 @@ acpi_ex_dump_object_descriptor ( { if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { - return; + return_VOID; } } if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { acpi_os_printf ("Ex_dump_object_descriptor: %p is not a valid ACPI object\n", obj_desc); - return; + return_VOID; } /* Common Fields */ diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 688e2b80c892..803b00ea38c3 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exoparg1 - AML execution - opcodes with 1 argument - * $Revision: 140 $ + * $Revision: 141 $ * *****************************************************************************/ @@ -804,16 +804,7 @@ acpi_ex_opcode_1A_0T_1R ( switch (operand[0]->reference.target_type) { case ACPI_TYPE_BUFFER_FIELD: - /* Ensure that the Buffer arguments are evaluated */ - temp_desc = operand[0]->reference.object; -#if 0 - - status = acpi_ds_get_buffer_arguments (temp_desc); - if (ACPI_FAILURE (status)) { - goto cleanup; - } -#endif /* * Create a new object that contains one element of the @@ -841,14 +832,6 @@ acpi_ex_opcode_1A_0T_1R ( case ACPI_TYPE_PACKAGE: -#if 0 - /* Ensure that the Package arguments are evaluated */ - - status = acpi_ds_get_package_arguments (operand[0]->reference.object); - if (ACPI_FAILURE (status)) { - goto cleanup; - } -#endif /* * Return the referenced element of the package. We must add * another reference to the referenced object, however. @@ -884,6 +867,11 @@ acpi_ex_opcode_1A_0T_1R ( return_desc = operand[0]->reference.object; + if (ACPI_GET_DESCRIPTOR_TYPE (return_desc) == ACPI_DESC_TYPE_NAMED) { + + return_desc = acpi_ns_get_attached_object ((acpi_namespace_node *) return_desc); + } + /* Add another reference to the object! */ acpi_ut_add_reference (return_desc); diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 11005af6a7a2..6e5b06166f92 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exutils - interpreter/scanner utilities - * $Revision: 100 $ + * $Revision: 102 $ * *****************************************************************************/ @@ -52,6 +52,34 @@ /******************************************************************************* * + * FUNCTION: Acpi_ex_validate_object_type + * + * PARAMETERS: Type Object type to validate + * + * DESCRIPTION: Determine if a type is a valid ACPI object type + * + ******************************************************************************/ + +u8 +acpi_ex_validate_object_type ( + acpi_object_type type) +{ + + ACPI_FUNCTION_ENTRY (); + + + if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) || + (type > INTERNAL_TYPE_MAX)) { + return (FALSE); + } + + return (TRUE); +} + +#ifndef ACPI_NO_METHOD_EXECUTION + +/******************************************************************************* + * * FUNCTION: Acpi_ex_enter_interpreter * * PARAMETERS: None @@ -118,33 +146,6 @@ acpi_ex_exit_interpreter (void) /******************************************************************************* * - * FUNCTION: Acpi_ex_validate_object_type - * - * PARAMETERS: Type Object type to validate - * - * DESCRIPTION: Determine if a type is a valid ACPI object type - * - ******************************************************************************/ - -u8 -acpi_ex_validate_object_type ( - acpi_object_type type) -{ - - ACPI_FUNCTION_ENTRY (); - - - if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) || - (type > INTERNAL_TYPE_MAX)) { - return (FALSE); - } - - return (TRUE); -} - - -/******************************************************************************* - * * FUNCTION: Acpi_ex_truncate_for32bit_table * * PARAMETERS: Obj_desc - Object to be truncated @@ -263,6 +264,8 @@ acpi_ex_release_global_lock ( ACPI_REPORT_ERROR (("Could not release ACPI Global Lock\n")); } } + + return_VOID; } @@ -378,4 +381,4 @@ acpi_ex_unsigned_integer_to_string ( } } - +#endif diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 3429bbf111be..3b3c728d3eac 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -1,5 +1,5 @@ /* - * acpi_fan.c - ACPI Fan Driver ($Revision: 28 $) + * acpi_fan.c - ACPI Fan Driver ($Revision: 29 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -47,13 +47,13 @@ int acpi_fan_add (struct acpi_device *device); int acpi_fan_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_fan_driver = { - name: ACPI_FAN_DRIVER_NAME, - class: ACPI_FAN_CLASS, - ids: ACPI_FAN_HID, - ops: { - add: acpi_fan_add, - remove: acpi_fan_remove, - }, + .name = ACPI_FAN_DRIVER_NAME, + .class = ACPI_FAN_CLASS, + .ids = ACPI_FAN_HID, + .ops = { + .add = acpi_fan_add, + .remove = acpi_fan_remove, + }, }; struct acpi_fan { diff --git a/drivers/acpi/include/acconfig.h b/drivers/acpi/include/acconfig.h index 3987706d5ecf..bc88390e874c 100644 --- a/drivers/acpi/include/acconfig.h +++ b/drivers/acpi/include/acconfig.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acconfig.h - Global configuration constants - * $Revision: 105 $ + * $Revision: 107 $ * *****************************************************************************/ @@ -54,7 +54,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20020702 +#define ACPI_CA_VERSION 0x20020725 /* Version of ACPI supported */ @@ -152,6 +152,15 @@ #define ACPI_MAX_ADDRESS_SPACE 255 +/* Array sizes. Used for range checking also */ + +#define NUM_ACCESS_TYPES 6 +#define NUM_UPDATE_RULES 3 +#define NUM_LOCK_RULES 2 +#define NUM_MATCH_OPS 6 +#define NUM_OPCODES 256 +#define NUM_FIELD_NAMES 2 + /* RSDP checksums */ #define ACPI_RSDP_CHECKSUM_LENGTH 20 diff --git a/drivers/acpi/include/acdebug.h b/drivers/acpi/include/acdebug.h index e76ad4b956fc..f32ebd8fe1bc 100644 --- a/drivers/acpi/include/acdebug.h +++ b/drivers/acpi/include/acdebug.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acdebug.h - ACPI/AML debugger - * $Revision: 62 $ + * $Revision: 63 $ * *****************************************************************************/ @@ -29,7 +29,6 @@ #define ACPI_DEBUG_BUFFER_SIZE 4196 - typedef struct command_info { NATIVE_CHAR *name; /* Command Name */ @@ -186,47 +185,6 @@ acpi_db_walk_for_specific_objects ( /* - * dbdisasm - AML disassembler - */ - -void -acpi_db_display_op ( - acpi_walk_state *walk_state, - acpi_parse_object *origin, - u32 num_opcodes); - -void -acpi_db_display_namestring ( - NATIVE_CHAR *name); - -void -acpi_db_display_path ( - acpi_parse_object *op); - -void -acpi_db_display_opcode ( - acpi_walk_state *walk_state, - acpi_parse_object *op); - -void -acpi_db_decode_internal_object ( - acpi_operand_object *obj_desc); - -void -acpi_db_decode_node ( - acpi_namespace_node *node); - -u32 -acpi_db_block_type ( - acpi_parse_object *op); - -acpi_status -acpi_ps_display_object_pathname ( - acpi_walk_state *walk_state, - acpi_parse_object *op); - - -/* * dbdisply - debug display commands */ @@ -282,6 +240,10 @@ void * acpi_db_get_pointer ( void *target); +void +acpi_db_decode_internal_object ( + acpi_operand_object *obj_desc); + /* * dbexec - debugger control method execution diff --git a/drivers/acpi/include/acdisasm.h b/drivers/acpi/include/acdisasm.h new file mode 100644 index 000000000000..6c126d07f728 --- /dev/null +++ b/drivers/acpi/include/acdisasm.h @@ -0,0 +1,362 @@ +/****************************************************************************** + * + * Name: acdisasm.h - AML disassembler + * $Revision: 2 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2002, R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACDISASM_H__ +#define __ACDISASM_H__ + +#include "amlresrc.h" + + +#define BLOCK_NONE 0 +#define BLOCK_PAREN 1 +#define BLOCK_BRACE 2 +#define BLOCK_COMMA_LIST 4 + +extern const char *acpi_gbl_io_decode[2]; +extern const char *acpi_gbl_word_decode[4]; +extern const char *acpi_gbl_consume_decode[2]; +extern const char *acpi_gbl_min_decode[2]; +extern const char *acpi_gbl_max_decode[2]; +extern const char *acpi_gbl_DECdecode[2]; +extern const char *acpi_gbl_RNGdecode[4]; +extern const char *acpi_gbl_MEMdecode[4]; +extern const char *acpi_gbl_RWdecode[2]; +extern const char *acpi_gbl_irq_decode[2]; +extern const char *acpi_gbl_HEdecode[2]; +extern const char *acpi_gbl_LLdecode[2]; +extern const char *acpi_gbl_SHRdecode[2]; +extern const char *acpi_gbl_TYPdecode[4]; +extern const char *acpi_gbl_BMdecode[2]; +extern const char *acpi_gbl_SIZdecode[4]; +extern const NATIVE_CHAR *acpi_gbl_lock_rule[NUM_LOCK_RULES]; +extern const NATIVE_CHAR *acpi_gbl_access_types[NUM_ACCESS_TYPES]; +extern const NATIVE_CHAR *acpi_gbl_update_rules[NUM_UPDATE_RULES]; +extern const NATIVE_CHAR *acpi_gbl_match_ops[NUM_MATCH_OPS]; + + +typedef struct acpi_op_walk_info +{ + u32 level; + u32 bit_offset; + +} ACPI_OP_WALK_INFO; + +typedef +acpi_status (*ASL_WALK_CALLBACK) ( + acpi_parse_object *op, + u32 level, + void *context); + + +/* + * dmwalk + */ + +void +acpi_dm_walk_parse_tree ( + acpi_parse_object *op, + ASL_WALK_CALLBACK descending_callback, + ASL_WALK_CALLBACK ascending_callback, + void *context); + +acpi_status +acpi_dm_descending_op ( + acpi_parse_object *op, + u32 level, + void *context); + +acpi_status +acpi_dm_ascending_op ( + acpi_parse_object *op, + u32 level, + void *context); + + +/* + * dmopcode + */ + +void +acpi_dm_validate_name ( + char *name, + acpi_parse_object *op); + +u32 +acpi_dm_dump_name ( + char *name); + +void +acpi_dm_string ( + char *string); + +void +acpi_dm_unicode ( + acpi_parse_object *op); + +void +acpi_dm_disassemble ( + acpi_walk_state *walk_state, + acpi_parse_object *origin, + u32 num_opcodes); + +void +acpi_dm_namestring ( + NATIVE_CHAR *name); + +void +acpi_dm_display_path ( + acpi_parse_object *op); + +void +acpi_dm_disassemble_one_op ( + acpi_walk_state *walk_state, + ACPI_OP_WALK_INFO *info, + acpi_parse_object *op); + +void +acpi_dm_decode_internal_object ( + acpi_operand_object *obj_desc); + +void +acpi_dm_decode_node ( + acpi_namespace_node *node); + +u32 +acpi_dm_block_type ( + acpi_parse_object *op); + +u32 +acpi_dm_list_type ( + acpi_parse_object *op); + +acpi_status +acpi_ps_display_object_pathname ( + acpi_walk_state *walk_state, + acpi_parse_object *op); + +void +acpi_dm_method_flags ( + acpi_parse_object *op); + +void +acpi_dm_field_flags ( + acpi_parse_object *op); + +void +acpi_dm_address_space ( + u8 space_id); + +void +acpi_dm_region_flags ( + acpi_parse_object *op); + +void +acpi_dm_match_op ( + acpi_parse_object *op); + +void +acpi_dm_match_keyword ( + acpi_parse_object *op); + +u8 +acpi_dm_comma_if_list_member ( + acpi_parse_object *op); + +void +acpi_dm_comma_if_field_member ( + acpi_parse_object *op); + + +/* + * dmbuffer + */ + +void +acpi_is_eisa_id ( + acpi_parse_object *op); + +void +acpi_dm_eisa_id ( + u32 encoded_id); + +u8 +acpi_dm_is_unicode_buffer ( + acpi_parse_object *op); + +u8 +acpi_dm_is_string_buffer ( + acpi_parse_object *op); + + +/* + * dmresrc + */ + +void +acpi_dm_disasm_byte_list ( + u32 level, + u8 *byte_data, + u32 byte_count); + +void +acpi_dm_byte_list ( + ACPI_OP_WALK_INFO *info, + acpi_parse_object *op); + +void +acpi_dm_resource_descriptor ( + ACPI_OP_WALK_INFO *info, + u8 *byte_data, + u32 byte_count); + +u8 +acpi_dm_is_resource_descriptor ( + acpi_parse_object *op); + +void +acpi_dm_indent ( + u32 level); + +void +acpi_dm_bit_list ( + u16 mask); + + +/* + * dmresrcl + */ + +void +acpi_dm_io_flags ( + u8 flags); + +void +acpi_dm_memory_flags ( + u8 flags, + u8 specific_flags); + +void +acpi_dm_word_descriptor ( + ASL_WORD_ADDRESS_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_dword_descriptor ( + ASL_DWORD_ADDRESS_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_qword_descriptor ( + ASL_QWORD_ADDRESS_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_memory24_descriptor ( + ASL_MEMORY_24_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_memory32_descriptor ( + ASL_MEMORY_32_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_fixed_mem32_descriptor ( + ASL_FIXED_MEMORY_32_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_generic_register_descriptor ( + ASL_GENERAL_REGISTER_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_interrupt_descriptor ( + ASL_EXTENDED_XRUPT_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_vendor_large_descriptor ( + ASL_LARGE_VENDOR_DESC *resource, + u32 length, + u32 level); + + +/* + * dmresrcs + */ + +void +acpi_dm_irq_descriptor ( + ASL_IRQ_FORMAT_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_dma_descriptor ( + ASL_DMA_FORMAT_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_io_descriptor ( + ASL_IO_PORT_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_fixed_io_descriptor ( + ASL_FIXED_IO_PORT_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_start_dependent_descriptor ( + ASL_START_DEPENDENT_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_end_dependent_descriptor ( + ASL_START_DEPENDENT_DESC *resource, + u32 length, + u32 level); + +void +acpi_dm_vendor_small_descriptor ( + ASL_SMALL_VENDOR_DESC *resource, + u32 length, + u32 level); + + +#endif /* __ACDISASM_H__ */ diff --git a/drivers/acpi/include/acglobal.h b/drivers/acpi/include/acglobal.h index 1d10c1b4203a..28e9d46ae359 100644 --- a/drivers/acpi/include/acglobal.h +++ b/drivers/acpi/include/acglobal.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acglobal.h - Declarations for global variables - * $Revision: 126 $ + * $Revision: 128 $ * *****************************************************************************/ @@ -140,8 +140,9 @@ ACPI_EXTERN u8 acpi_gbl_global_lock_present; extern u8 acpi_gbl_shutdown; extern u32 acpi_gbl_startup_flags; extern const u8 acpi_gbl_decode_to8bit[8]; -extern const NATIVE_CHAR *acpi_gbl_db_sleep_states[ACPI_NUM_SLEEP_STATES]; +extern const NATIVE_CHAR *acpi_gbl_db_sleep_states[ACPI_NUM_SLEEP_STATES]; extern const acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; +extern const NATIVE_CHAR *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; /***************************************************************************** @@ -237,6 +238,12 @@ ACPI_EXTERN ACPI_GPE_INDEX_INFO *acpi_gbl_gpe_number_to_index; ACPI_EXTERN u8 acpi_gbl_db_output_flags; +#ifdef ACPI_DISASSEMBLER + +ACPI_EXTERN u8 acpi_gbl_db_opt_disasm; +ACPI_EXTERN u8 acpi_gbl_db_opt_verbose; +#endif + #ifdef ENABLE_DEBUGGER @@ -247,9 +254,7 @@ ACPI_EXTERN int optind; ACPI_EXTERN NATIVE_CHAR *optarg; ACPI_EXTERN u8 acpi_gbl_db_opt_tables; -ACPI_EXTERN u8 acpi_gbl_db_opt_disasm; ACPI_EXTERN u8 acpi_gbl_db_opt_stats; -ACPI_EXTERN u8 acpi_gbl_db_opt_verbose; ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods; @@ -261,7 +266,6 @@ ACPI_EXTERN NATIVE_CHAR acpi_gbl_db_debug_filename[40]; ACPI_EXTERN u8 acpi_gbl_db_output_to_file; ACPI_EXTERN NATIVE_CHAR *acpi_gbl_db_buffer; ACPI_EXTERN NATIVE_CHAR *acpi_gbl_db_filename; -ACPI_EXTERN NATIVE_CHAR *acpi_gbl_db_disasm_indent; ACPI_EXTERN u32 acpi_gbl_db_debug_level; ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; ACPI_EXTERN acpi_table_header *acpi_gbl_db_table_ptr; diff --git a/drivers/acpi/include/aclocal.h b/drivers/acpi/include/aclocal.h index 54eb05fc66c8..f9d6e2f1f031 100644 --- a/drivers/acpi/include/aclocal.h +++ b/drivers/acpi/include/aclocal.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: aclocal.h - Internal data types used across the ACPI subsystem - * $Revision: 168 $ + * $Revision: 173 $ * *****************************************************************************/ @@ -567,8 +567,8 @@ acpi_status (*ACPI_EXECUTE_OP) ( */ typedef struct acpi_opcode_info { -#ifdef _OPCODE_NAMES - NATIVE_CHAR *name; /* Opcode name (debug only) */ +#if defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUG) + NATIVE_CHAR *name; /* Opcode name (disassembler/debug only) */ #endif u32 parse_args; /* Grammar/Parse time arguments */ u32 runtime_args; /* Interpret time arguments */ @@ -603,15 +603,23 @@ typedef union acpi_parse_val u32 aml_offset; /* offset of declaration in AML */\ union acpi_parse_obj *parent; /* parent op */\ union acpi_parse_obj *next; /* next op */\ - ACPI_DEBUG_ONLY_MEMBERS (\ + ACPI_DISASM_ONLY_MEMBERS (\ + u8 disasm_flags; /* Used during AML disassembly */\ + u8 disasm_opcode; /* Subtype used for disassembly */\ NATIVE_CHAR aml_op_name[16]) /* op name (debug only) */\ /* NON-DEBUG members below: */\ acpi_namespace_node *node; /* for use by interpreter */\ acpi_parse_value value; /* Value or args associated with the opcode */\ +#define ACPI_DASM_BUFFER 0x00 +#define ACPI_DASM_RESOURCE 0x01 +#define ACPI_DASM_STRING 0x02 +#define ACPI_DASM_UNICODE 0x03 +#define ACPI_DASM_EISAID 0x04 +#define ACPI_DASM_MATCHOP 0x05 /* - * generic operation (eg. If, While, Store) + * generic operation (for example: If, While, Store) */ typedef struct acpi_parseobj_common { @@ -626,6 +634,7 @@ typedef struct acpi_parseobj_common typedef struct acpi_parseobj_named { ACPI_PARSE_COMMON + u8 *path; u8 *data; /* AML body or bytelist data */ u32 length; /* AML length */ u32 name; /* 4-byte name or zero if no name */ @@ -653,15 +662,15 @@ typedef struct acpi_parseobj_asl u32 logical_byte_offset; u32 end_line; u32 end_logical_line; - u16 parse_opcode; u32 acpi_btype; u32 aml_length; u32 aml_subtree_length; u32 final_aml_length; u32 final_aml_offset; + u16 parse_opcode; + u16 compile_flags; u8 aml_opcode_length; u8 aml_pkg_len_bytes; - u16 compile_flags; u8 extra; char parse_op_name[12]; @@ -705,6 +714,13 @@ typedef struct acpi_parse_state #define ACPI_PARSEOP_BYTELIST 0x08 #define ACPI_PARSEOP_IN_CACHE 0x80 +/* Parse object Disasm_flags */ + +#define ACPI_PARSEOP_IGNORE 0x01 +#define ACPI_PARSEOP_PARAMLIST 0x02 +#define ACPI_PARSEOP_EMPTY_TERMLIST 0x04 +#define ACPI_PARSEOP_SPECIAL 0x10 + /***************************************************************************** * diff --git a/drivers/acpi/include/acmacros.h b/drivers/acpi/include/acmacros.h index f48ac95210bf..57452f9b6cbf 100644 --- a/drivers/acpi/include/acmacros.h +++ b/drivers/acpi/include/acmacros.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acmacros.h - C macros for the entire subsystem. - * $Revision: 124 $ + * $Revision: 126 $ * *****************************************************************************/ @@ -287,12 +287,18 @@ /* * Macros for the master AML opcode table */ -#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER) +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG) #define ACPI_OP(name,Pargs,Iargs,obj_type,class,type,flags) {name,Pargs,Iargs,flags,obj_type,class,type} #else #define ACPI_OP(name,Pargs,Iargs,obj_type,class,type,flags) {Pargs,Iargs,flags,obj_type,class,type} #endif +#ifdef ACPI_DISASSEMBLER +#define ACPI_DISASM_ONLY_MEMBERS(a) a; +#else +#define ACPI_DISASM_ONLY_MEMBERS(a) +#endif + #define ARG_TYPE_WIDTH 5 #define ARG_1(x) ((u32)(x)) #define ARG_2(x) ((u32)(x) << (1 * ARG_TYPE_WIDTH)) @@ -435,7 +441,6 @@ #define ACPI_DEBUG_DEFINE(a) a; #define ACPI_DEBUG_ONLY_MEMBERS(a) a; -#define _OPCODE_NAMES #define _VERBOSE_STRUCTURES @@ -515,10 +520,6 @@ #define return_VALUE(s) return(s) #define return_PTR(s) return(s) -#ifdef ENABLE_DEBUGGER -#define _OPCODE_NAMES -#endif - #endif /* diff --git a/drivers/acpi/include/acnamesp.h b/drivers/acpi/include/acnamesp.h index c5a90435c3f7..49c5223e1f27 100644 --- a/drivers/acpi/include/acnamesp.h +++ b/drivers/acpi/include/acnamesp.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acnamesp.h - Namespace subcomponent prototypes and defines - * $Revision: 125 $ + * $Revision: 126 $ * *****************************************************************************/ @@ -43,7 +43,7 @@ /* Definitions of the predefined namespace names */ #define ACPI_UNKNOWN_NAME (u32) 0x3F3F3F3F /* Unknown name is "????" */ -#define ACPI_ROOT_NAME (u32) 0x2F202020 /* Root name is "/ " */ +#define ACPI_ROOT_NAME (u32) 0x5F5F5F5C /* Root name is "\___" */ #define ACPI_SYS_BUS_NAME (u32) 0x5F53425F /* Sys bus name is "_SB_" */ #define ACPI_NS_ROOT_PATH "\\" diff --git a/drivers/acpi/include/acpiosxf.h b/drivers/acpi/include/acpiosxf.h index 56d4037f8b46..b6cac89b91b9 100644 --- a/drivers/acpi/include/acpiosxf.h +++ b/drivers/acpi/include/acpiosxf.h @@ -204,7 +204,6 @@ acpi_os_read_port ( void *value, u32 width); - acpi_status acpi_os_write_port ( ACPI_IO_ADDRESS address, @@ -222,7 +221,6 @@ acpi_os_read_memory ( void *value, u32 width); - acpi_status acpi_os_write_memory ( ACPI_PHYSICAL_ADDRESS address, @@ -241,7 +239,6 @@ acpi_os_read_pci_configuration ( void *value, u32 width); - acpi_status acpi_os_write_pci_configuration ( acpi_pci_id *pci_id, @@ -259,7 +256,6 @@ acpi_os_readable ( void *pointer, u32 length); - u8 acpi_os_writable ( void *pointer, @@ -288,6 +284,10 @@ acpi_os_vprintf ( const NATIVE_CHAR *format, va_list args); +void +acpi_os_redirect_output ( + void *destination); + /* * Debug input diff --git a/drivers/acpi/include/acutils.h b/drivers/acpi/include/acutils.h index 46ea89bafd70..3af0afac24b5 100644 --- a/drivers/acpi/include/acutils.h +++ b/drivers/acpi/include/acutils.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acutils.h -- prototypes for the common (subsystem-wide) procedures - * $Revision: 140 $ + * $Revision: 142 $ * *****************************************************************************/ @@ -224,6 +224,9 @@ extern const u8 _acpi_ctype[]; #define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) #define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) #define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) +#define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU)) +#define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) +#define ACPI_IS_ASCII(c) ((c) < 0x80) #endif /* ACPI_USE_SYSTEM_CLIBRARY */ diff --git a/drivers/acpi/include/amlcode.h b/drivers/acpi/include/amlcode.h index ddcffdf80897..b5802baca761 100644 --- a/drivers/acpi/include/amlcode.h +++ b/drivers/acpi/include/amlcode.h @@ -3,7 +3,7 @@ * Name: amlcode.h - Definitions for AML, as included in "definition blocks" * Declarations and definitions contained herein are derived * directly from the ACPI specification. - * $Revision: 68 $ + * $Revision: 69 $ * *****************************************************************************/ @@ -474,13 +474,4 @@ typedef enum #define METHOD_FLAGS_SYNCH_LEVEL 0xF0 -/* Array sizes. Used for range checking also */ - -#define NUM_ACCESS_TYPES 6 -#define NUM_UPDATE_RULES 3 -#define NUM_MATCH_OPS 7 -#define NUM_OPCODES 256 -#define NUM_FIELD_NAMES 2 - - #endif /* __AMLCODE_H__ */ diff --git a/drivers/acpi/include/amlresrc.h b/drivers/acpi/include/amlresrc.h index d8aa2befb2c1..a97dbf2f59e4 100644 --- a/drivers/acpi/include/amlresrc.h +++ b/drivers/acpi/include/amlresrc.h @@ -1,8 +1,8 @@ /****************************************************************************** * - * Module Name: aslresource.h - ASL resource descriptors - * $Revision: 19 $ + * Module Name: amlresrc.h - AML resource descriptors + * $Revision: 20 $ * *****************************************************************************/ @@ -25,8 +25,8 @@ */ -#ifndef __ASLRESOURCE_H -#define __ASLRESOURCE_H +#ifndef __AMLRESRC_H +#define __AMLRESRC_H #define ASL_RESNAME_ADDRESS "_ADR" @@ -80,11 +80,13 @@ typedef struct asl_resource_node /* - * Resource descriptors defined in the ACPI specification + * Resource descriptors defined in the ACPI specification. + * + * Alignment must be BYTE because these descriptors + * are used to overlay the AML byte stream. */ - - #pragma pack(1) + typedef struct asl_irq_format_desc { u8 descriptor_type; @@ -94,7 +96,6 @@ typedef struct asl_irq_format_desc } ASL_IRQ_FORMAT_DESC; -#pragma pack(1) typedef struct asl_irq_noflags_desc { u8 descriptor_type; @@ -103,7 +104,6 @@ typedef struct asl_irq_noflags_desc } ASL_IRQ_NOFLAGS_DESC; -#pragma pack(1) typedef struct asl_dma_format_desc { u8 descriptor_type; @@ -113,7 +113,6 @@ typedef struct asl_dma_format_desc } ASL_DMA_FORMAT_DESC; -#pragma pack(1) typedef struct asl_start_dependent_desc { u8 descriptor_type; @@ -122,7 +121,6 @@ typedef struct asl_start_dependent_desc } ASL_START_DEPENDENT_DESC; -#pragma pack(1) typedef struct asl_start_dependent_noprio_desc { u8 descriptor_type; @@ -130,7 +128,6 @@ typedef struct asl_start_dependent_noprio_desc } ASL_START_DEPENDENT_NOPRIO_DESC; -#pragma pack(1) typedef struct asl_end_dependent_desc { u8 descriptor_type; @@ -138,7 +135,6 @@ typedef struct asl_end_dependent_desc } ASL_END_DEPENDENT_DESC; -#pragma pack(1) typedef struct asl_io_port_desc { u8 descriptor_type; @@ -151,7 +147,6 @@ typedef struct asl_io_port_desc } ASL_IO_PORT_DESC; -#pragma pack(1) typedef struct asl_fixed_io_port_desc { u8 descriptor_type; @@ -161,7 +156,6 @@ typedef struct asl_fixed_io_port_desc } ASL_FIXED_IO_PORT_DESC; -#pragma pack(1) typedef struct asl_small_vendor_desc { u8 descriptor_type; @@ -170,7 +164,6 @@ typedef struct asl_small_vendor_desc } ASL_SMALL_VENDOR_DESC; -#pragma pack(1) typedef struct asl_end_tag_desc { u8 descriptor_type; @@ -181,7 +174,6 @@ typedef struct asl_end_tag_desc /* LARGE descriptors */ -#pragma pack(1) typedef struct asl_memory_24_desc { u8 descriptor_type; @@ -195,7 +187,6 @@ typedef struct asl_memory_24_desc } ASL_MEMORY_24_DESC; -#pragma pack(1) typedef struct asl_large_vendor_desc { u8 descriptor_type; @@ -205,7 +196,6 @@ typedef struct asl_large_vendor_desc } ASL_LARGE_VENDOR_DESC; -#pragma pack(1) typedef struct asl_memory_32_desc { u8 descriptor_type; @@ -219,7 +209,6 @@ typedef struct asl_memory_32_desc } ASL_MEMORY_32_DESC; -#pragma pack(1) typedef struct asl_fixed_memory_32_desc { u8 descriptor_type; @@ -231,7 +220,6 @@ typedef struct asl_fixed_memory_32_desc } ASL_FIXED_MEMORY_32_DESC; -#pragma pack(1) typedef struct asl_qword_address_desc { u8 descriptor_type; @@ -249,7 +237,6 @@ typedef struct asl_qword_address_desc } ASL_QWORD_ADDRESS_DESC; -#pragma pack(1) typedef struct asl_dword_address_desc { u8 descriptor_type; @@ -267,7 +254,6 @@ typedef struct asl_dword_address_desc } ASL_DWORD_ADDRESS_DESC; -#pragma pack(1) typedef struct asl_word_address_desc { u8 descriptor_type; @@ -285,7 +271,6 @@ typedef struct asl_word_address_desc } ASL_WORD_ADDRESS_DESC; -#pragma pack(1) typedef struct asl_extended_xrupt_desc { u8 descriptor_type; @@ -298,7 +283,6 @@ typedef struct asl_extended_xrupt_desc } ASL_EXTENDED_XRUPT_DESC; -#pragma pack(1) typedef struct asl_general_register_desc { u8 descriptor_type; @@ -311,6 +295,9 @@ typedef struct asl_general_register_desc } ASL_GENERAL_REGISTER_DESC; +/* restore default alignment */ + +#pragma pack() /* Union of all resource descriptors, sow we can allocate the worst case */ diff --git a/drivers/acpi/include/platform/acenv.h b/drivers/acpi/include/platform/acenv.h index 1cb3f2939509..47f8f1cb2d3e 100644 --- a/drivers/acpi/include/platform/acenv.h +++ b/drivers/acpi/include/platform/acenv.h @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acenv.h - Generation environment specific items - * $Revision: 95 $ + * $Revision: 99 $ * *****************************************************************************/ @@ -32,11 +32,13 @@ */ #ifdef _ACPI_DUMP_APP +#ifndef MSDOS #define ACPI_DEBUG +#endif #define ACPI_APPLICATION -#define ENABLE_DEBUGGER +#define ACPI_DISASSEMBLER +#define ACPI_NO_METHOD_EXECUTION #define ACPI_USE_SYSTEM_CLIBRARY -#define PARSER_ONLY #endif #ifdef _ACPI_EXEC_APP @@ -45,13 +47,15 @@ #define ACPI_DEBUG #define ACPI_APPLICATION #define ENABLE_DEBUGGER +#define ACPI_DISASSEMBLER #define ACPI_USE_SYSTEM_CLIBRARY #endif #ifdef _ACPI_ASL_COMPILER #define ACPI_DEBUG #define ACPI_APPLICATION -/* #define ENABLE_DEBUGGER */ +#define ACPI_DISASSEMBLER +#define ACPI_CONSTANT_EVAL_ONLY #define ACPI_USE_SYSTEM_CLIBRARY #endif @@ -183,7 +187,6 @@ /* * Use the standard C library headers. * We want to keep these to a minimum. - * */ #ifdef ACPI_USE_STANDARD_HEADERS @@ -213,12 +216,16 @@ #define ACPI_STRTOUL(d,s,n) strtoul((d), (s), (ACPI_SIZE)(n)) #define ACPI_MEMCPY(d,s,n) (void) memcpy((d), (s), (ACPI_SIZE)(n)) #define ACPI_MEMSET(d,s,n) (void) memset((d), (s), (ACPI_SIZE)(n)) + #define ACPI_TOUPPER toupper #define ACPI_TOLOWER tolower #define ACPI_IS_XDIGIT isxdigit #define ACPI_IS_DIGIT isdigit #define ACPI_IS_SPACE isspace #define ACPI_IS_UPPER isupper +#define ACPI_IS_PRINT isprint +#define ACPI_IS_ALPHA isalpha +#define ACPI_IS_ASCII isascii /****************************************************************************** * diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index da59d90b095f..5a6c8c520af4 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsdump - table dumping routines for debug - * $Revision: 136 $ + * $Revision: 137 $ * *****************************************************************************/ @@ -619,93 +619,6 @@ acpi_ns_dump_objects ( } -#ifndef _ACPI_ASL_COMPILER -/******************************************************************************* - * - * FUNCTION: Acpi_ns_dump_one_device - * - * PARAMETERS: Handle - Node to be dumped - * Level - Nesting level of the handle - * Context - Passed into Walk_namespace - * - * DESCRIPTION: Dump a single Node that represents a device - * This procedure is a User_function called by Acpi_ns_walk_namespace. - * - ******************************************************************************/ - -acpi_status -acpi_ns_dump_one_device ( - acpi_handle obj_handle, - u32 level, - void *context, - void **return_value) -{ - acpi_device_info info; - acpi_status status; - u32 i; - - - ACPI_FUNCTION_NAME ("Ns_dump_one_device"); - - - status = acpi_ns_dump_one_object (obj_handle, level, context, return_value); - - status = acpi_get_object_info (obj_handle, &info); - if (ACPI_SUCCESS (status)) { - for (i = 0; i < level; i++) { - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " ")); - } - - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info.hardware_id, - ACPI_HIDWORD (info.address), ACPI_LODWORD (info.address), - info.current_status)); - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ns_dump_root_devices - * - * PARAMETERS: None - * - * DESCRIPTION: Dump all objects of type "device" - * - ******************************************************************************/ - -void -acpi_ns_dump_root_devices (void) -{ - acpi_handle sys_bus_handle; - acpi_status status; - - - ACPI_FUNCTION_NAME ("Ns_dump_root_devices"); - - - /* Only dump the table if tracing is enabled */ - - if (!(ACPI_LV_TABLES & acpi_dbg_level)) { - return; - } - - status = acpi_get_handle (0, ACPI_NS_SYSTEM_BUS, &sys_bus_handle); - if (ACPI_FAILURE (status)) { - return; - } - - ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Display of all devices in the namespace:\n")); - - status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle, - ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, - acpi_ns_dump_one_device, NULL, NULL); -} - -#endif - /******************************************************************************* * * FUNCTION: Acpi_ns_dump_tables diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c new file mode 100644 index 000000000000..0c82ecb93b7d --- /dev/null +++ b/drivers/acpi/namespace/nsdumpdv.c @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * Module Name: nsdump - table dumping routines for debug + * $Revision: 1 $ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2002, R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acnamesp.h" +#include "acparser.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsdumpdv") + + +#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER) + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_dump_one_device + * + * PARAMETERS: Handle - Node to be dumped + * Level - Nesting level of the handle + * Context - Passed into Walk_namespace + * + * DESCRIPTION: Dump a single Node that represents a device + * This procedure is a User_function called by Acpi_ns_walk_namespace. + * + ******************************************************************************/ + +acpi_status +acpi_ns_dump_one_device ( + acpi_handle obj_handle, + u32 level, + void *context, + void **return_value) +{ + acpi_device_info info; + acpi_status status; + u32 i; + + + ACPI_FUNCTION_NAME ("Ns_dump_one_device"); + + + status = acpi_ns_dump_one_object (obj_handle, level, context, return_value); + + status = acpi_get_object_info (obj_handle, &info); + if (ACPI_SUCCESS (status)) { + for (i = 0; i < level; i++) { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " ")); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", + info.hardware_id, + ACPI_HIDWORD (info.address), ACPI_LODWORD (info.address), + info.current_status)); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_dump_root_devices + * + * PARAMETERS: None + * + * DESCRIPTION: Dump all objects of type "device" + * + ******************************************************************************/ + +void +acpi_ns_dump_root_devices (void) +{ + acpi_handle sys_bus_handle; + acpi_status status; + + + ACPI_FUNCTION_NAME ("Ns_dump_root_devices"); + + + /* Only dump the table if tracing is enabled */ + + if (!(ACPI_LV_TABLES & acpi_dbg_level)) { + return; + } + + status = acpi_get_handle (0, ACPI_NS_SYSTEM_BUS, &sys_bus_handle); + if (ACPI_FAILURE (status)) { + return; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "Display of all devices in the namespace:\n")); + + status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle, + ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, + acpi_ns_dump_one_device, NULL, NULL); +} + +#endif + + diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index cfbb32ba5779..967ed83b6937 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsload - namespace loading/expanding/contracting procedures - * $Revision: 56 $ + * $Revision: 57 $ * *****************************************************************************/ @@ -37,59 +37,7 @@ /******************************************************************************* * - * FUNCTION: Acpi_load_namespace - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. - * (DSDT points to either the BIOS or a buffer.) - * - ******************************************************************************/ - -acpi_status -acpi_ns_load_namespace ( - void) -{ - acpi_status status; - - - ACPI_FUNCTION_TRACE ("Acpi_load_name_space"); - - - /* There must be at least a DSDT installed */ - - if (acpi_gbl_DSDT == NULL) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n")); - return_ACPI_STATUS (AE_NO_ACPI_TABLES); - } - - /* - * Load the namespace. The DSDT is required, - * but the SSDT and PSDT tables are optional. - */ - status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - - /* Ignore exceptions from these */ - - (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT); - (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT); - - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, - "ACPI Namespace successfully loaded at root %p\n", - acpi_gbl_root_node)); - - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ns_one_parse_pass + * FUNCTION: Ns_one_complete_parse * * PARAMETERS: Pass_number - 1 or 2 * Table_desc - The table to be parsed. @@ -203,6 +151,7 @@ acpi_ns_parse_table ( return_ACPI_STATUS (status); } +#ifndef ACPI_NO_METHOD_EXECUTION /******************************************************************************* * @@ -421,6 +370,58 @@ unlock_and_exit: /******************************************************************************* * + * FUNCTION: Acpi_load_namespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. + * (DSDT points to either the BIOS or a buffer.) + * + ******************************************************************************/ + +acpi_status +acpi_ns_load_namespace ( + void) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("Acpi_load_name_space"); + + + /* There must be at least a DSDT installed */ + + if (acpi_gbl_DSDT == NULL) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n")); + return_ACPI_STATUS (AE_NO_ACPI_TABLES); + } + + /* + * Load the namespace. The DSDT is required, + * but the SSDT and PSDT tables are optional. + */ + status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Ignore exceptions from these */ + + (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT); + (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT); + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, + "ACPI Namespace successfully loaded at root %p\n", + acpi_gbl_root_node)); + + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * * FUNCTION: Acpi_ns_delete_subtree * * PARAMETERS: Start_handle - Handle in namespace where search begins @@ -550,4 +551,5 @@ acpi_ns_unload_namespace ( return_ACPI_STATUS (status); } +#endif diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c new file mode 100644 index 000000000000..0eded64d3647 --- /dev/null +++ b/drivers/acpi/namespace/nsxfeval.c @@ -0,0 +1,719 @@ +/******************************************************************************* + * + * Module Name: nsxfeval - Public interfaces to the ACPI subsystem + * ACPI Object evaluation interfaces + * $Revision: 1 $ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2002, R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsxfeval") + + +/******************************************************************************* + * + * FUNCTION: Acpi_evaluate_object_typed + * + * PARAMETERS: Handle - Object handle (optional) + * *Pathname - Object pathname (optional) + * **External_params - List of parameters to pass to method, + * terminated by NULL. May be NULL + * if no parameters are being passed. + * *Return_buffer - Where to put method's return value (if + * any). If NULL, no value is returned. + * Return_type - Expected type of return object + * + * RETURN: Status + * + * DESCRIPTION: Find and evaluate the given object, passing the given + * parameters if necessary. One of "Handle" or "Pathname" must + * be valid (non-null) + * + ******************************************************************************/ + +acpi_status +acpi_evaluate_object_typed ( + acpi_handle handle, + acpi_string pathname, + acpi_object_list *external_params, + acpi_buffer *return_buffer, + acpi_object_type return_type) +{ + acpi_status status; + u8 must_free = FALSE; + + + ACPI_FUNCTION_TRACE ("Acpi_evaluate_object_typed"); + + + /* Return buffer must be valid */ + + if (!return_buffer) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { + must_free = TRUE; + } + + /* Evaluate the object */ + + status = acpi_evaluate_object (handle, pathname, external_params, return_buffer); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* Type ANY means "don't care" */ + + if (return_type == ACPI_TYPE_ANY) { + return_ACPI_STATUS (AE_OK); + } + + if (return_buffer->length == 0) { + /* Error because caller specifically asked for a return value */ + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "No return value\n")); + + return_ACPI_STATUS (AE_NULL_OBJECT); + } + + /* Examine the object type returned from Evaluate_object */ + + if (((acpi_object *) return_buffer->pointer)->type == return_type) { + return_ACPI_STATUS (AE_OK); + } + + /* Return object type does not match requested type */ + + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Incorrect return type [%s] requested [%s]\n", + acpi_ut_get_type_name (((acpi_object *) return_buffer->pointer)->type), + acpi_ut_get_type_name (return_type))); + + if (must_free) { + /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ + + acpi_os_free (return_buffer->pointer); + return_buffer->pointer = NULL; + } + + return_buffer->length = 0; + return_ACPI_STATUS (AE_TYPE); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_evaluate_object + * + * PARAMETERS: Handle - Object handle (optional) + * *Pathname - Object pathname (optional) + * **External_params - List of parameters to pass to method, + * terminated by NULL. May be NULL + * if no parameters are being passed. + * *Return_buffer - Where to put method's return value (if + * any). If NULL, no value is returned. + * + * RETURN: Status + * + * DESCRIPTION: Find and evaluate the given object, passing the given + * parameters if necessary. One of "Handle" or "Pathname" must + * be valid (non-null) + * + ******************************************************************************/ + +acpi_status +acpi_evaluate_object ( + acpi_handle handle, + acpi_string pathname, + acpi_object_list *external_params, + acpi_buffer *return_buffer) +{ + acpi_status status; + acpi_operand_object **internal_params = NULL; + acpi_operand_object *internal_return_obj = NULL; + ACPI_SIZE buffer_space_needed; + u32 i; + + + ACPI_FUNCTION_TRACE ("Acpi_evaluate_object"); + + + /* + * If there are parameters to be passed to the object + * (which must be a control method), the external objects + * must be converted to internal objects + */ + if (external_params && external_params->count) { + /* + * Allocate a new parameter block for the internal objects + * Add 1 to count to allow for null terminated internal list + */ + internal_params = ACPI_MEM_CALLOCATE (((ACPI_SIZE) external_params->count + 1) * + sizeof (void *)); + if (!internal_params) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* + * Convert each external object in the list to an + * internal object + */ + for (i = 0; i < external_params->count; i++) { + status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i], + &internal_params[i]); + if (ACPI_FAILURE (status)) { + acpi_ut_delete_internal_object_list (internal_params); + return_ACPI_STATUS (status); + } + } + internal_params[external_params->count] = NULL; + } + + /* + * Three major cases: + * 1) Fully qualified pathname + * 2) No handle, not fully qualified pathname (error) + * 3) Valid handle + */ + if ((pathname) && + (acpi_ns_valid_root_prefix (pathname[0]))) { + /* + * The path is fully qualified, just evaluate by name + */ + status = acpi_ns_evaluate_by_name (pathname, internal_params, + &internal_return_obj); + } + else if (!handle) { + /* + * A handle is optional iff a fully qualified pathname + * is specified. Since we've already handled fully + * qualified names above, this is an error + */ + if (!pathname) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Both Handle and Pathname are NULL\n")); + } + else { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Handle is NULL and Pathname is relative\n")); + } + + status = AE_BAD_PARAMETER; + } + else { + /* + * We get here if we have a handle -- and if we have a + * pathname it is relative. The handle will be validated + * in the lower procedures + */ + if (!pathname) { + /* + * The null pathname case means the handle is for + * the actual object to be evaluated + */ + status = acpi_ns_evaluate_by_handle (handle, internal_params, + &internal_return_obj); + } + else { + /* + * Both a Handle and a relative Pathname + */ + status = acpi_ns_evaluate_relative (handle, pathname, internal_params, + &internal_return_obj); + } + } + + + /* + * If we are expecting a return value, and all went well above, + * copy the return value to an external object. + */ + if (return_buffer) { + if (!internal_return_obj) { + return_buffer->length = 0; + } + else { + if (ACPI_GET_DESCRIPTOR_TYPE (internal_return_obj) == ACPI_DESC_TYPE_NAMED) { + /* + * If we received a NS Node as a return object, this means that + * the object we are evaluating has nothing interesting to + * return (such as a mutex, etc.) We return an error because + * these types are essentially unsupported by this interface. + * We don't check up front because this makes it easier to add + * support for various types at a later date if necessary. + */ + status = AE_TYPE; + internal_return_obj = NULL; /* No need to delete a NS Node */ + return_buffer->length = 0; + } + + if (ACPI_SUCCESS (status)) { + /* + * Find out how large a buffer is needed + * to contain the returned object + */ + status = acpi_ut_get_object_size (internal_return_obj, + &buffer_space_needed); + if (ACPI_SUCCESS (status)) { + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed); + if (ACPI_FAILURE (status)) { + /* + * Caller's buffer is too small or a new one can't be allocated + */ + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Needed buffer size %X, %s\n", + (u32) buffer_space_needed, acpi_format_exception (status))); + } + else { + /* + * We have enough space for the object, build it + */ + status = acpi_ut_copy_iobject_to_eobject (internal_return_obj, + return_buffer); + } + } + } + } + } + + /* Delete the return and parameter objects */ + + if (internal_return_obj) { + /* + * Delete the internal return object. (Or at least + * decrement the reference count by one) + */ + acpi_ut_remove_reference (internal_return_obj); + } + + /* + * Free the input parameter list (if we created one), + */ + if (internal_params) { + /* Free the allocated parameter block */ + + acpi_ut_delete_internal_object_list (internal_params); + } + + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_walk_namespace + * + * PARAMETERS: Type - acpi_object_type to search for + * Start_object - Handle in namespace where search begins + * Max_depth - Depth to which search is to reach + * User_function - Called when an object of "Type" is found + * Context - Passed to user function + * Return_value - Location where return value of + * User_function is put if terminated early + * + * RETURNS Return value from the User_function if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by Start_handle. + * The User_function is called whenever an object that matches + * the type parameter is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * The point of this procedure is to provide a generic namespace + * walk routine that can be called from multiple places to + * provide multiple services; the User Function can be tailored + * to each task, whether it is a print function, a compare + * function, etc. + * + ******************************************************************************/ + +acpi_status +acpi_walk_namespace ( + acpi_object_type type, + acpi_handle start_object, + u32 max_depth, + acpi_walk_callback user_function, + void *context, + void **return_value) +{ + acpi_status status; + + + ACPI_FUNCTION_TRACE ("Acpi_walk_namespace"); + + + /* Parameter validation */ + + if ((type > ACPI_TYPE_MAX) || + (!max_depth) || + (!user_function)) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Lock the namespace around the walk. + * The namespace will be unlocked/locked around each call + * to the user function - since this function + * must be allowed to make Acpi calls itself. + */ + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_ns_walk_namespace (type, start_object, max_depth, ACPI_NS_WALK_UNLOCK, + user_function, context, return_value); + + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_get_device_callback + * + * PARAMETERS: Callback from Acpi_get_device + * + * RETURN: Status + * + * DESCRIPTION: Takes callbacks from Walk_namespace and filters out all non- + * present devices, or if they specified a HID, it filters based + * on that. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_get_device_callback ( + acpi_handle obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + acpi_status status; + acpi_namespace_node *node; + u32 flags; + acpi_device_id hid; + acpi_device_id cid; + acpi_get_devices_info *info; + + + info = context; + + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return (status); + } + + node = acpi_ns_map_handle_to_node (obj_handle); + status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return (status); + } + + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* + * Run _STA to determine if device is present + */ + status = acpi_ut_execute_STA (node, &flags); + if (ACPI_FAILURE (status)) { + return (AE_CTRL_DEPTH); + } + + if (!(flags & 0x01)) { + /* Don't return at the device or children of the device if not there */ + return (AE_CTRL_DEPTH); + } + + /* + * Filter based on device HID & CID + */ + if (info->hid != NULL) { + status = acpi_ut_execute_HID (node, &hid); + if (status == AE_NOT_FOUND) { + return (AE_OK); + } + else if (ACPI_FAILURE (status)) { + return (AE_CTRL_DEPTH); + } + + if (ACPI_STRNCMP (hid.buffer, info->hid, sizeof (hid.buffer)) != 0) { + status = acpi_ut_execute_CID (node, &cid); + if (status == AE_NOT_FOUND) { + return (AE_OK); + } + else if (ACPI_FAILURE (status)) { + return (AE_CTRL_DEPTH); + } + + /* TBD: Handle CID packages */ + + if (ACPI_STRNCMP (cid.buffer, info->hid, sizeof (cid.buffer)) != 0) { + return (AE_OK); + } + } + } + + status = info->user_function (obj_handle, nesting_level, info->context, return_value); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_devices + * + * PARAMETERS: HID - HID to search for. Can be NULL. + * User_function - Called when a matching object is found + * Context - Passed to user function + * Return_value - Location where return value of + * User_function is put if terminated early + * + * RETURNS Return value from the User_function if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by Start_handle. + * The User_function is called whenever an object that matches + * the type parameter is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * This is a wrapper for Walk_namespace, but the callback performs + * additional filtering. Please see Acpi_get_device_callback. + * + ******************************************************************************/ + +acpi_status +acpi_get_devices ( + NATIVE_CHAR *HID, + acpi_walk_callback user_function, + void *context, + void **return_value) +{ + acpi_status status; + acpi_get_devices_info info; + + + ACPI_FUNCTION_TRACE ("Acpi_get_devices"); + + + /* Parameter validation */ + + if (!user_function) { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * We're going to call their callback from OUR callback, so we need + * to know what it is, and their context parameter. + */ + info.context = context; + info.user_function = user_function; + info.hid = HID; + + /* + * Lock the namespace around the walk. + * The namespace will be unlocked/locked around each call + * to the user function - since this function + * must be allowed to make Acpi calls itself. + */ + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, + ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, + acpi_ns_get_device_callback, &info, + return_value); + + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_attach_data + * + * PARAMETERS: + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +acpi_status +acpi_attach_data ( + acpi_handle obj_handle, + ACPI_OBJECT_HANDLER handler, + void *data) +{ + acpi_namespace_node *node; + acpi_status status; + + + /* Parameter validation */ + + if (!obj_handle || + !handler || + !data) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Convert and validate the handle */ + + node = acpi_ns_map_handle_to_node (obj_handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + status = acpi_ns_attach_data (node, handler, data); + +unlock_and_exit: + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_detach_data + * + * PARAMETERS: + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +acpi_status +acpi_detach_data ( + acpi_handle obj_handle, + ACPI_OBJECT_HANDLER handler) +{ + acpi_namespace_node *node; + acpi_status status; + + + /* Parameter validation */ + + if (!obj_handle || + !handler) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Convert and validate the handle */ + + node = acpi_ns_map_handle_to_node (obj_handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + status = acpi_ns_detach_data (node, handler); + +unlock_and_exit: + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_data + * + * PARAMETERS: + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +acpi_status +acpi_get_data ( + acpi_handle obj_handle, + ACPI_OBJECT_HANDLER handler, + void **data) +{ + acpi_namespace_node *node; + acpi_status status; + + + /* Parameter validation */ + + if (!obj_handle || + !handler || + !data) { + return (AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Convert and validate the handle */ + + node = acpi_ns_map_handle_to_node (obj_handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + status = acpi_ns_get_attached_data (node, handler, data); + +unlock_and_exit: + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c index def0a7318950..703308421005 100644 --- a/drivers/acpi/namespace/nsxfobj.c +++ b/drivers/acpi/namespace/nsxfobj.c @@ -2,7 +2,7 @@ * * Module Name: nsxfobj - Public interfaces to the ACPI subsystem * ACPI Object oriented interfaces - * $Revision: 112 $ + * $Revision: 113 $ * ******************************************************************************/ @@ -32,384 +32,6 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME ("nsxfobj") - -/******************************************************************************* - * - * FUNCTION: Acpi_evaluate_object_typed - * - * PARAMETERS: Handle - Object handle (optional) - * *Pathname - Object pathname (optional) - * **External_params - List of parameters to pass to method, - * terminated by NULL. May be NULL - * if no parameters are being passed. - * *Return_buffer - Where to put method's return value (if - * any). If NULL, no value is returned. - * Return_type - Expected type of return object - * - * RETURN: Status - * - * DESCRIPTION: Find and evaluate the given object, passing the given - * parameters if necessary. One of "Handle" or "Pathname" must - * be valid (non-null) - * - ******************************************************************************/ - -acpi_status -acpi_evaluate_object_typed ( - acpi_handle handle, - acpi_string pathname, - acpi_object_list *external_params, - acpi_buffer *return_buffer, - acpi_object_type return_type) -{ - acpi_status status; - u8 must_free = FALSE; - - - ACPI_FUNCTION_TRACE ("Acpi_evaluate_object_typed"); - - - /* Return buffer must be valid */ - - if (!return_buffer) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { - must_free = TRUE; - } - - /* Evaluate the object */ - - status = acpi_evaluate_object (handle, pathname, external_params, return_buffer); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - - /* Type ANY means "don't care" */ - - if (return_type == ACPI_TYPE_ANY) { - return_ACPI_STATUS (AE_OK); - } - - if (return_buffer->length == 0) { - /* Error because caller specifically asked for a return value */ - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "No return value\n")); - - return_ACPI_STATUS (AE_NULL_OBJECT); - } - - /* Examine the object type returned from Evaluate_object */ - - if (((acpi_object *) return_buffer->pointer)->type == return_type) { - return_ACPI_STATUS (AE_OK); - } - - /* Return object type does not match requested type */ - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Incorrect return type [%s] requested [%s]\n", - acpi_ut_get_type_name (((acpi_object *) return_buffer->pointer)->type), - acpi_ut_get_type_name (return_type))); - - if (must_free) { - /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ - - acpi_os_free (return_buffer->pointer); - return_buffer->pointer = NULL; - } - - return_buffer->length = 0; - return_ACPI_STATUS (AE_TYPE); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_evaluate_object - * - * PARAMETERS: Handle - Object handle (optional) - * *Pathname - Object pathname (optional) - * **External_params - List of parameters to pass to method, - * terminated by NULL. May be NULL - * if no parameters are being passed. - * *Return_buffer - Where to put method's return value (if - * any). If NULL, no value is returned. - * - * RETURN: Status - * - * DESCRIPTION: Find and evaluate the given object, passing the given - * parameters if necessary. One of "Handle" or "Pathname" must - * be valid (non-null) - * - ******************************************************************************/ - -acpi_status -acpi_evaluate_object ( - acpi_handle handle, - acpi_string pathname, - acpi_object_list *external_params, - acpi_buffer *return_buffer) -{ - acpi_status status; - acpi_operand_object **internal_params = NULL; - acpi_operand_object *internal_return_obj = NULL; - ACPI_SIZE buffer_space_needed; - u32 i; - - - ACPI_FUNCTION_TRACE ("Acpi_evaluate_object"); - - - /* - * If there are parameters to be passed to the object - * (which must be a control method), the external objects - * must be converted to internal objects - */ - if (external_params && external_params->count) { - /* - * Allocate a new parameter block for the internal objects - * Add 1 to count to allow for null terminated internal list - */ - internal_params = ACPI_MEM_CALLOCATE (((ACPI_SIZE) external_params->count + 1) * - sizeof (void *)); - if (!internal_params) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* - * Convert each external object in the list to an - * internal object - */ - for (i = 0; i < external_params->count; i++) { - status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i], - &internal_params[i]); - if (ACPI_FAILURE (status)) { - acpi_ut_delete_internal_object_list (internal_params); - return_ACPI_STATUS (status); - } - } - internal_params[external_params->count] = NULL; - } - - /* - * Three major cases: - * 1) Fully qualified pathname - * 2) No handle, not fully qualified pathname (error) - * 3) Valid handle - */ - if ((pathname) && - (acpi_ns_valid_root_prefix (pathname[0]))) { - /* - * The path is fully qualified, just evaluate by name - */ - status = acpi_ns_evaluate_by_name (pathname, internal_params, - &internal_return_obj); - } - else if (!handle) { - /* - * A handle is optional iff a fully qualified pathname - * is specified. Since we've already handled fully - * qualified names above, this is an error - */ - if (!pathname) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Both Handle and Pathname are NULL\n")); - } - else { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Handle is NULL and Pathname is relative\n")); - } - - status = AE_BAD_PARAMETER; - } - else { - /* - * We get here if we have a handle -- and if we have a - * pathname it is relative. The handle will be validated - * in the lower procedures - */ - if (!pathname) { - /* - * The null pathname case means the handle is for - * the actual object to be evaluated - */ - status = acpi_ns_evaluate_by_handle (handle, internal_params, - &internal_return_obj); - } - else { - /* - * Both a Handle and a relative Pathname - */ - status = acpi_ns_evaluate_relative (handle, pathname, internal_params, - &internal_return_obj); - } - } - - - /* - * If we are expecting a return value, and all went well above, - * copy the return value to an external object. - */ - if (return_buffer) { - if (!internal_return_obj) { - return_buffer->length = 0; - } - else { - if (ACPI_GET_DESCRIPTOR_TYPE (internal_return_obj) == ACPI_DESC_TYPE_NAMED) { - /* - * If we received a NS Node as a return object, this means that - * the object we are evaluating has nothing interesting to - * return (such as a mutex, etc.) We return an error because - * these types are essentially unsupported by this interface. - * We don't check up front because this makes it easier to add - * support for various types at a later date if necessary. - */ - status = AE_TYPE; - internal_return_obj = NULL; /* No need to delete a NS Node */ - return_buffer->length = 0; - } - - if (ACPI_SUCCESS (status)) { - /* - * Find out how large a buffer is needed - * to contain the returned object - */ - status = acpi_ut_get_object_size (internal_return_obj, - &buffer_space_needed); - if (ACPI_SUCCESS (status)) { - /* Validate/Allocate/Clear caller buffer */ - - status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed); - if (ACPI_FAILURE (status)) { - /* - * Caller's buffer is too small or a new one can't be allocated - */ - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, - "Needed buffer size %X, %s\n", - (u32) buffer_space_needed, acpi_format_exception (status))); - } - else { - /* - * We have enough space for the object, build it - */ - status = acpi_ut_copy_iobject_to_eobject (internal_return_obj, - return_buffer); - } - } - } - } - } - - /* Delete the return and parameter objects */ - - if (internal_return_obj) { - /* - * Delete the internal return object. (Or at least - * decrement the reference count by one) - */ - acpi_ut_remove_reference (internal_return_obj); - } - - /* - * Free the input parameter list (if we created one), - */ - if (internal_params) { - /* Free the allocated parameter block */ - - acpi_ut_delete_internal_object_list (internal_params); - } - - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_get_next_object - * - * PARAMETERS: Type - Type of object to be searched for - * Parent - Parent object whose children we are getting - * Last_child - Previous child that was found. - * The NEXT child will be returned - * Ret_handle - Where handle to the next object is placed - * - * RETURN: Status - * - * DESCRIPTION: Return the next peer object within the namespace. If Handle is - * valid, Scope is ignored. Otherwise, the first object within - * Scope is returned. - * - ******************************************************************************/ - -acpi_status -acpi_get_next_object ( - acpi_object_type type, - acpi_handle parent, - acpi_handle child, - acpi_handle *ret_handle) -{ - acpi_status status; - acpi_namespace_node *node; - acpi_namespace_node *parent_node = NULL; - acpi_namespace_node *child_node = NULL; - - - /* Parameter validation */ - - if (type > ACPI_TYPE_MAX) { - return (AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* If null handle, use the parent */ - - if (!child) { - /* Start search at the beginning of the specified scope */ - - parent_node = acpi_ns_map_handle_to_node (parent); - if (!parent_node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - } - else { - /* Non-null handle, ignore the parent */ - /* Convert and validate the handle */ - - child_node = acpi_ns_map_handle_to_node (child); - if (!child_node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - } - - /* Internal function does the real work */ - - node = acpi_ns_get_next_node (type, parent_node, child_node); - if (!node) { - status = AE_NOT_FOUND; - goto unlock_and_exit; - } - - if (ret_handle) { - *ret_handle = acpi_ns_convert_entry_to_handle (node); - } - - -unlock_and_exit: - - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - return (status); -} - - /******************************************************************************* * * FUNCTION: Acpi_get_type @@ -535,271 +157,38 @@ unlock_and_exit: /******************************************************************************* * - * FUNCTION: Acpi_walk_namespace - * - * PARAMETERS: Type - acpi_object_type to search for - * Start_object - Handle in namespace where search begins - * Max_depth - Depth to which search is to reach - * User_function - Called when an object of "Type" is found - * Context - Passed to user function - * Return_value - Location where return value of - * User_function is put if terminated early - * - * RETURNS Return value from the User_function if terminated early. - * Otherwise, returns NULL. - * - * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, - * starting (and ending) at the object specified by Start_handle. - * The User_function is called whenever an object that matches - * the type parameter is found. If the user function returns - * a non-zero value, the search is terminated immediately and this - * value is returned to the caller. - * - * The point of this procedure is to provide a generic namespace - * walk routine that can be called from multiple places to - * provide multiple services; the User Function can be tailored - * to each task, whether it is a print function, a compare - * function, etc. - * - ******************************************************************************/ - -acpi_status -acpi_walk_namespace ( - acpi_object_type type, - acpi_handle start_object, - u32 max_depth, - acpi_walk_callback user_function, - void *context, - void **return_value) -{ - acpi_status status; - - - ACPI_FUNCTION_TRACE ("Acpi_walk_namespace"); - - - /* Parameter validation */ - - if ((type > ACPI_TYPE_MAX) || - (!max_depth) || - (!user_function)) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - /* - * Lock the namespace around the walk. - * The namespace will be unlocked/locked around each call - * to the user function - since this function - * must be allowed to make Acpi calls itself. - */ - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - - status = acpi_ns_walk_namespace (type, start_object, max_depth, ACPI_NS_WALK_UNLOCK, - user_function, context, return_value); - - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_ns_get_device_callback + * FUNCTION: Acpi_get_next_object * - * PARAMETERS: Callback from Acpi_get_device + * PARAMETERS: Type - Type of object to be searched for + * Parent - Parent object whose children we are getting + * Last_child - Previous child that was found. + * The NEXT child will be returned + * Ret_handle - Where handle to the next object is placed * * RETURN: Status * - * DESCRIPTION: Takes callbacks from Walk_namespace and filters out all non- - * present devices, or if they specified a HID, it filters based - * on that. - * - ******************************************************************************/ - -static acpi_status -acpi_ns_get_device_callback ( - acpi_handle obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - acpi_status status; - acpi_namespace_node *node; - u32 flags; - acpi_device_id hid; - acpi_device_id cid; - acpi_get_devices_info *info; - - - info = context; - - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return (status); - } - - node = acpi_ns_map_handle_to_node (obj_handle); - status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return (status); - } - - if (!node) { - return (AE_BAD_PARAMETER); - } - - /* - * Run _STA to determine if device is present - */ - status = acpi_ut_execute_STA (node, &flags); - if (ACPI_FAILURE (status)) { - return (AE_CTRL_DEPTH); - } - - if (!(flags & 0x01)) { - /* Don't return at the device or children of the device if not there */ - return (AE_CTRL_DEPTH); - } - - /* - * Filter based on device HID & CID - */ - if (info->hid != NULL) { - status = acpi_ut_execute_HID (node, &hid); - if (status == AE_NOT_FOUND) { - return (AE_OK); - } - else if (ACPI_FAILURE (status)) { - return (AE_CTRL_DEPTH); - } - - if (ACPI_STRNCMP (hid.buffer, info->hid, sizeof (hid.buffer)) != 0) { - status = acpi_ut_execute_CID (node, &cid); - if (status == AE_NOT_FOUND) { - return (AE_OK); - } - else if (ACPI_FAILURE (status)) { - return (AE_CTRL_DEPTH); - } - - /* TBD: Handle CID packages */ - - if (ACPI_STRNCMP (cid.buffer, info->hid, sizeof (cid.buffer)) != 0) { - return (AE_OK); - } - } - } - - status = info->user_function (obj_handle, nesting_level, info->context, return_value); - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_get_devices - * - * PARAMETERS: HID - HID to search for. Can be NULL. - * User_function - Called when a matching object is found - * Context - Passed to user function - * Return_value - Location where return value of - * User_function is put if terminated early - * - * RETURNS Return value from the User_function if terminated early. - * Otherwise, returns NULL. - * - * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, - * starting (and ending) at the object specified by Start_handle. - * The User_function is called whenever an object that matches - * the type parameter is found. If the user function returns - * a non-zero value, the search is terminated immediately and this - * value is returned to the caller. - * - * This is a wrapper for Walk_namespace, but the callback performs - * additional filtering. Please see Acpi_get_device_callback. + * DESCRIPTION: Return the next peer object within the namespace. If Handle is + * valid, Scope is ignored. Otherwise, the first object within + * Scope is returned. * ******************************************************************************/ acpi_status -acpi_get_devices ( - NATIVE_CHAR *HID, - acpi_walk_callback user_function, - void *context, - void **return_value) +acpi_get_next_object ( + acpi_object_type type, + acpi_handle parent, + acpi_handle child, + acpi_handle *ret_handle) { acpi_status status; - acpi_get_devices_info info; - - - ACPI_FUNCTION_TRACE ("Acpi_get_devices"); - - - /* Parameter validation */ - - if (!user_function) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - /* - * We're going to call their callback from OUR callback, so we need - * to know what it is, and their context parameter. - */ - info.context = context; - info.user_function = user_function; - info.hid = HID; - - /* - * Lock the namespace around the walk. - * The namespace will be unlocked/locked around each call - * to the user function - since this function - * must be allowed to make Acpi calls itself. - */ - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - - status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, - ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - ACPI_NS_WALK_UNLOCK, - acpi_ns_get_device_callback, &info, - return_value); - - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - return_ACPI_STATUS (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_attach_data - * - * PARAMETERS: - * - * RETURN: Status - * - * DESCRIPTION: - * - ******************************************************************************/ - -acpi_status -acpi_attach_data ( - acpi_handle obj_handle, - ACPI_OBJECT_HANDLER handler, - void *data) -{ acpi_namespace_node *node; - acpi_status status; + acpi_namespace_node *parent_node = NULL; + acpi_namespace_node *child_node = NULL; /* Parameter validation */ - if (!obj_handle || - !handler || - !data) { + if (type > ACPI_TYPE_MAX) { return (AE_BAD_PARAMETER); } @@ -808,117 +197,43 @@ acpi_attach_data ( return (status); } - /* Convert and validate the handle */ - - node = acpi_ns_map_handle_to_node (obj_handle); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; - } - - status = acpi_ns_attach_data (node, handler, data); - -unlock_and_exit: - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_detach_data - * - * PARAMETERS: - * - * RETURN: Status - * - * DESCRIPTION: - * - ******************************************************************************/ - -acpi_status -acpi_detach_data ( - acpi_handle obj_handle, - ACPI_OBJECT_HANDLER handler) -{ - acpi_namespace_node *node; - acpi_status status; - + /* If null handle, use the parent */ - /* Parameter validation */ + if (!child) { + /* Start search at the beginning of the specified scope */ - if (!obj_handle || - !handler) { - return (AE_BAD_PARAMETER); + parent_node = acpi_ns_map_handle_to_node (parent); + if (!parent_node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } } + else { + /* Non-null handle, ignore the parent */ + /* Convert and validate the handle */ - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return (status); + child_node = acpi_ns_map_handle_to_node (child); + if (!child_node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } } - /* Convert and validate the handle */ + /* Internal function does the real work */ - node = acpi_ns_map_handle_to_node (obj_handle); + node = acpi_ns_get_next_node (type, parent_node, child_node); if (!node) { - status = AE_BAD_PARAMETER; + status = AE_NOT_FOUND; goto unlock_and_exit; } - status = acpi_ns_detach_data (node, handler); - -unlock_and_exit: - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_get_data - * - * PARAMETERS: - * - * RETURN: Status - * - * DESCRIPTION: - * - ******************************************************************************/ - -acpi_status -acpi_get_data ( - acpi_handle obj_handle, - ACPI_OBJECT_HANDLER handler, - void **data) -{ - acpi_namespace_node *node; - acpi_status status; - - - /* Parameter validation */ - - if (!obj_handle || - !handler || - !data) { - return (AE_BAD_PARAMETER); - } - - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Convert and validate the handle */ - - node = acpi_ns_map_handle_to_node (obj_handle); - if (!node) { - status = AE_BAD_PARAMETER; - goto unlock_and_exit; + if (ret_handle) { + *ret_handle = acpi_ns_convert_entry_to_handle (node); } - status = acpi_ns_get_attached_data (node, handler, data); unlock_and_exit: + (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return (status); } diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index bd9dab948f38..4fa6579cd8c3 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psargs - Parse AML opcode arguments - * $Revision: 61 $ + * $Revision: 62 $ * *****************************************************************************/ @@ -332,7 +332,7 @@ acpi_ps_get_next_namepath ( NATIVE_CHAR *path; acpi_parse_object *name_op; acpi_status status; - acpi_namespace_node *method_node = NULL; + acpi_operand_object *method_desc; acpi_namespace_node *node; acpi_generic_state scope_info; @@ -369,30 +369,36 @@ acpi_ps_get_next_namepath ( &node); if (ACPI_SUCCESS (status)) { if (node->type == ACPI_TYPE_METHOD) { - method_node = node; - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "method - %p Path=%p\n", - method_node, path)); + method_desc = acpi_ns_get_attached_object (node); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Control Method - %p Desc %p Path=%p\n", + node, method_desc, path)); name_op = acpi_ps_alloc_op (AML_INT_NAMEPATH_OP); - if (name_op) { - /* Change arg into a METHOD CALL and attach name to it */ + if (!name_op) { + return_VOID; + } - acpi_ps_init_op (arg, AML_INT_METHODCALL_OP); + /* Change arg into a METHOD CALL and attach name to it */ - name_op->common.value.name = path; + acpi_ps_init_op (arg, AML_INT_METHODCALL_OP); - /* Point METHODCALL/NAME to the METHOD Node */ + name_op->common.value.name = path; - name_op->common.node = method_node; - acpi_ps_append_arg (arg, name_op); + /* Point METHODCALL/NAME to the METHOD Node */ - if (!acpi_ns_get_attached_object (method_node)) { - return_VOID; - } + name_op->common.node = node; + acpi_ps_append_arg (arg, name_op); - *arg_count = (acpi_ns_get_attached_object (method_node))->method.param_count; + if (!method_desc) { + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Control Method - %p has no attached object\n", + node)); + return_VOID; } + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Control Method - %p Args %X\n", + node, method_desc->method.param_count)); + + *arg_count = method_desc->method.param_count; return_VOID; } diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 42fad5f92a77..2f2c593f330e 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psopcode - Parser/Interpreter opcode information table - * $Revision: 70 $ + * $Revision: 71 $ * *****************************************************************************/ @@ -734,7 +734,7 @@ NATIVE_CHAR * acpi_ps_get_opcode_name ( u16 opcode) { -#ifdef ACPI_DEBUG +#ifdef ACPI_DISASSEMBLER const acpi_opcode_info *op; diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 0e24c31c6135..fd61b0863d25 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psparse - Parser top level AML parse routines - * $Revision: 128 $ + * $Revision: 129 $ * *****************************************************************************/ @@ -473,7 +473,7 @@ acpi_ps_parse_loop ( parser_state = &walk_state->parser_state; walk_state->arg_types = 0; -#ifndef PARSER_ONLY +#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { /* We are restarting a preempted control method */ diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index d8df196e3080..7c8950786d35 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: psutils - Parser miscellaneous utilities (Parser only) - * $Revision: 52 $ + * $Revision: 54 $ * *****************************************************************************/ @@ -88,7 +88,7 @@ acpi_ps_init_op ( op->common.data_type = ACPI_DESC_TYPE_PARSER; op->common.aml_opcode = opcode; - ACPI_DEBUG_ONLY_MEMBERS (ACPI_STRNCPY (op->common.aml_op_name, + ACPI_DISASM_ONLY_MEMBERS (ACPI_STRNCPY (op->common.aml_op_name, (acpi_ps_get_opcode_info (opcode))->name, sizeof (op->common.aml_op_name))); } @@ -186,7 +186,7 @@ acpi_ps_free_op ( ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n", op)); } - if (op->common.flags == ACPI_PARSEOP_GENERIC) { + if (op->common.flags & ACPI_PARSEOP_GENERIC) { acpi_ut_release_to_cache (ACPI_MEM_LIST_PSNODE, op); } else { diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index a2b1cd595057..5d5edb42f24c 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -1,5 +1,5 @@ /* - * pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 10 $) + * pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 11 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 2320a8e016bd..b94b85b1cea4 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -1,5 +1,5 @@ /* - * pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 33 $) + * pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -54,13 +54,13 @@ static int acpi_pci_link_add (struct acpi_device *device); static int acpi_pci_link_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_pci_link_driver = { - name: ACPI_PCI_LINK_DRIVER_NAME, - class: ACPI_PCI_LINK_CLASS, - ids: ACPI_PCI_LINK_HID, - ops: { - add: acpi_pci_link_add, - remove: acpi_pci_link_remove, - }, + .name = ACPI_PCI_LINK_DRIVER_NAME, + .class = ACPI_PCI_LINK_CLASS, + .ids = ACPI_PCI_LINK_HID, + .ops = { + .add = acpi_pci_link_add, + .remove = acpi_pci_link_remove, + }, }; struct acpi_pci_link_irq { diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7fef16be6d47..a56fedea61b4 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -1,5 +1,5 @@ /* - * pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 39 $) + * pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 40 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -47,13 +47,13 @@ static int acpi_pci_root_add (struct acpi_device *device); static int acpi_pci_root_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_pci_root_driver = { - name: ACPI_PCI_ROOT_DRIVER_NAME, - class: ACPI_PCI_ROOT_CLASS, - ids: ACPI_PCI_ROOT_HID, - ops: { - add: acpi_pci_root_add, - remove: acpi_pci_root_remove, - }, + .name = ACPI_PCI_ROOT_DRIVER_NAME, + .class = ACPI_PCI_ROOT_CLASS, + .ids = ACPI_PCI_ROOT_HID, + .ops = { + .add = acpi_pci_root_add, + .remove = acpi_pci_root_remove, + }, }; struct acpi_pci_root { diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 5e4f55dbfc90..986ebd729528 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -1,5 +1,5 @@ /* - * acpi_power.c - ACPI Bus Power Management ($Revision: 38 $) + * acpi_power.c - ACPI Bus Power Management ($Revision: 39 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -43,13 +43,13 @@ int acpi_power_add (struct acpi_device *device); int acpi_power_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_power_driver = { - name: ACPI_POWER_DRIVER_NAME, - class: ACPI_POWER_CLASS, - ids: ACPI_POWER_HID, - ops: { - add: acpi_power_add, - remove: acpi_power_remove, - }, + .name = ACPI_POWER_DRIVER_NAME, + .class = ACPI_POWER_CLASS, + .ids = ACPI_POWER_HID, + .ops = { + .add = acpi_power_add, + .remove = acpi_power_remove, + }, }; struct acpi_power_resource diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c index 028ee228dcb0..933251d46b19 100644 --- a/drivers/acpi/processor.c +++ b/drivers/acpi/processor.c @@ -1,5 +1,5 @@ /* - * acpi_processor.c - ACPI Processor Driver ($Revision: 69 $) + * acpi_processor.c - ACPI Processor Driver ($Revision: 71 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -78,13 +78,13 @@ static int acpi_processor_add (struct acpi_device *device); static int acpi_processor_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_processor_driver = { - name: ACPI_PROCESSOR_DRIVER_NAME, - class: ACPI_PROCESSOR_CLASS, - ids: ACPI_PROCESSOR_HID, - ops: { - add: acpi_processor_add, - remove: acpi_processor_remove, - }, + .name = ACPI_PROCESSOR_DRIVER_NAME, + .class = ACPI_PROCESSOR_CLASS, + .ids = ACPI_PROCESSOR_HID, + .ops = { + .add = acpi_processor_add, + .remove = acpi_processor_remove, + }, }; /* Power Management */ diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c index 11b2382e6ec2..3eda881b5ca0 100644 --- a/drivers/acpi/resources/rsio.c +++ b/drivers/acpi/resources/rsio.c @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsio - IO and DMA resource descriptors - * $Revision: 21 $ + * $Revision: 22 $ * ******************************************************************************/ @@ -399,7 +399,7 @@ acpi_rs_dma_resource ( buffer += 1; temp8 = *buffer; - /* Decode the IRQ bits */ + /* Decode the DMA channel bits */ for (i = 0, index = 0; index < 8; index++) { if ((temp8 >> index) & 0x01) { @@ -407,19 +407,16 @@ acpi_rs_dma_resource ( i++; } } - if (i == 0) { - /* Zero channels is invalid! */ - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found Zero DMA channels in resource list\n")); - return_ACPI_STATUS (AE_BAD_DATA); - } - output_struct->data.dma.number_of_channels = i; + /* Zero DMA channels is valid */ - /* - * Calculate the structure size based upon the number of interrupts - */ - struct_size += ((ACPI_SIZE) output_struct->data.dma.number_of_channels - 1) * 4; + output_struct->data.dma.number_of_channels = i; + if (i > 0) { + /* + * Calculate the structure size based upon the number of interrupts + */ + struct_size += ((ACPI_SIZE) i - 1) * 4; + } /* * Point to Byte 2 diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c index 5366f27dcad7..ab0d142895f9 100644 --- a/drivers/acpi/resources/rsirq.c +++ b/drivers/acpi/resources/rsirq.c @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: rsirq - IRQ resource descriptors - * $Revision: 29 $ + * $Revision: 30 $ * ******************************************************************************/ @@ -96,18 +96,15 @@ acpi_rs_irq_resource ( } } - if (i == 0) { - /* Zero interrupts is invalid! */ + /* Zero interrupts is valid */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found Zero interrupt levels in resource list\n")); - return_ACPI_STATUS (AE_BAD_DATA); - } output_struct->data.irq.number_of_interrupts = i; - - /* - * Calculate the structure size based upon the number of interrupts - */ - struct_size += ((ACPI_SIZE) output_struct->data.irq.number_of_interrupts - 1) * 4; + if (i > 0) { + /* + * Calculate the structure size based upon the number of interrupts + */ + struct_size += ((ACPI_SIZE) i - 1) * 4; + } /* * Point to Byte 3 if it is used diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1bd1555510b0..bfd02982e234 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -1,5 +1,5 @@ /* - * acpi_system.c - ACPI System Driver ($Revision: 60 $) + * acpi_system.c - ACPI System Driver ($Revision: 63 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -63,13 +63,13 @@ static int acpi_system_add (struct acpi_device *device); static int acpi_system_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_system_driver = { - name: ACPI_SYSTEM_DRIVER_NAME, - class: ACPI_SYSTEM_CLASS, - ids: ACPI_SYSTEM_HID, - ops: { - add: acpi_system_add, - remove: acpi_system_remove - }, + .name = ACPI_SYSTEM_DRIVER_NAME, + .class = ACPI_SYSTEM_CLASS, + .ids = ACPI_SYSTEM_HID, + .ops = { + .add = acpi_system_add, + .remove = acpi_system_remove + }, }; struct acpi_system @@ -383,10 +383,10 @@ static unsigned int acpi_system_poll_event(struct file *file, poll_table *wait); static struct file_operations acpi_system_event_ops = { - open: acpi_system_open_event, - read: acpi_system_read_event, - release: acpi_system_close_event, - poll: acpi_system_poll_event, + .open = acpi_system_open_event, + .read = acpi_system_read_event, + .release = acpi_system_close_event, + .poll = acpi_system_poll_event, }; static int @@ -479,7 +479,7 @@ acpi_system_poll_event( static ssize_t acpi_system_read_dsdt (struct file*, char*, size_t, loff_t*); static struct file_operations acpi_system_dsdt_ops = { - read: acpi_system_read_dsdt, + .read = acpi_system_read_dsdt, }; static ssize_t @@ -522,7 +522,7 @@ acpi_system_read_dsdt ( static ssize_t acpi_system_read_fadt (struct file*, char*, size_t, loff_t*); static struct file_operations acpi_system_fadt_ops = { - read: acpi_system_read_fadt, + .read = acpi_system_read_fadt, }; static ssize_t @@ -1165,15 +1165,15 @@ acpi_system_remove_fs ( /* Simple wrapper calling power down function. */ static void acpi_sysrq_power_off(int key, struct pt_regs *pt_regs, - struct tty_struct *tty) + struct tty_struct *tty) { acpi_power_off(); } struct sysrq_key_op sysrq_acpi_poweroff_op = { - handler: &acpi_sysrq_power_off, - help_msg: "Off", - action_msg: "Power Off\n" + .handler = &acpi_sysrq_power_off, + .help_msg = "Off", + .action_msg = "Power Off\n" }; #endif /* CONFIG_MAGIC_SYSRQ */ diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 8d5057758bfc..4a9f20ffa730 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -330,6 +330,11 @@ acpi_table_get_sdt ( return -ENODEV; } + if (acpi_table_compute_checksum(header, header->length)) { + printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n"); + return -ENODEV; + } + sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3; if (sdt.count > ACPI_MAX_TABLES) { printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n", @@ -370,6 +375,11 @@ acpi_table_get_sdt ( return -ENODEV; } + if (acpi_table_compute_checksum(header, header->length)) { + printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n"); + return -ENODEV; + } + sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 2; if (sdt.count > ACPI_MAX_TABLES) { printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n", diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c index 9aa4f425f2c2..3fe14948152b 100644 --- a/drivers/acpi/tables/tbrsdt.c +++ b/drivers/acpi/tables/tbrsdt.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbrsdt - ACPI RSDT table utilities - * $Revision: 1 $ + * $Revision: 2 $ * *****************************************************************************/ @@ -271,12 +271,6 @@ acpi_tb_get_table_rsdt ( return_ACPI_STATUS (status); } - /* - * Valid RSDT signature, verify the checksum. If it fails, just - * print a warning and ignore it. - */ - status = acpi_tb_verify_table_checksum (table_info.pointer); - /* Get the number of tables defined in the RSDT or XSDT */ acpi_gbl_rsdt_table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, table_info.pointer); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 0836b31843ca..bf5521e3403f 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1,5 +1,5 @@ /* - * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 40 $) + * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> @@ -65,13 +65,13 @@ static int acpi_thermal_add (struct acpi_device *device); static int acpi_thermal_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_thermal_driver = { - name: ACPI_THERMAL_DRIVER_NAME, - class: ACPI_THERMAL_CLASS, - ids: ACPI_THERMAL_HID, - ops: { - add: acpi_thermal_add, - remove: acpi_thermal_remove, - }, + .name = ACPI_THERMAL_DRIVER_NAME, + .class = ACPI_THERMAL_CLASS, + .ids = ACPI_THERMAL_HID, + .ops = { + .add = acpi_thermal_add, + .remove = acpi_thermal_remove, + }, }; struct acpi_thermal_state { diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 3641d106b886..97389a318f07 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: utglobal - Global variables for the ACPI subsystem - * $Revision: 164 $ + * $Revision: 165 $ * *****************************************************************************/ @@ -27,6 +27,7 @@ #include "acpi.h" #include "acnamesp.h" +#include "amlcode.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME ("utglobal") @@ -357,15 +358,15 @@ acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = /* Region type decoding */ -static const NATIVE_CHAR *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = +const NATIVE_CHAR *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { "System_memory", "System_iO", - "PCIConfig", + "PCI_Config", "Embedded_control", "SMBus", "CMOS", - "PCIBar_target", + "PCIBARTarget", "Data_table", }; @@ -555,55 +556,6 @@ acpi_ut_get_mutex_name ( } -/* Various strings for future use */ - -#if 0 -#include "amlcode.h" - -/* Data used in keeping track of fields */ - -static const NATIVE_CHAR *acpi_gbl_FEnames[NUM_FIELD_NAMES] = -{ - "skip", - "?access?" -}; /* FE = Field Element */ - - -static const NATIVE_CHAR *acpi_gbl_match_ops[NUM_MATCH_OPS] = -{ - "Error", - "MTR", - "MEQ", - "MLE", - "MLT", - "MGE", - "MGT" -}; - - -/* Access type decoding */ - -static const NATIVE_CHAR *acpi_gbl_access_types[NUM_ACCESS_TYPES] = -{ - "Any_acc", - "Byte_acc", - "Word_acc", - "DWord_acc", - "QWord_acc", - "Buffer_acc", -}; - - -/* Update rule decoding */ - -static const NATIVE_CHAR *acpi_gbl_update_rules[NUM_UPDATE_RULES] = -{ - "Preserve", - "Write_as_ones", - "Write_as_zeros" -}; -#endif /* Future use */ - #endif diff --git a/drivers/base/fs.c b/drivers/base/fs.c index 754d789f53e8..65225deedf7d 100644 --- a/drivers/base/fs.c +++ b/drivers/base/fs.c @@ -106,13 +106,17 @@ static void fill_devpath(struct device * dev, char * path, int length) static int create_symlink(struct driver_dir_entry * parent, char * name, char * path) { struct driver_file_entry * entry; + int error; entry = kmalloc(sizeof(struct driver_file_entry),GFP_KERNEL); if (!entry) return -ENOMEM; entry->name = name; entry->mode = S_IRUGO; - return driverfs_create_symlink(parent,entry,path); + error = driverfs_create_symlink(parent,entry,path); + if (error) + kfree(entry); + return error; } int device_bus_link(struct device * dev) diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index dc372aa4dbb1..59e4b53dfce5 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -2884,7 +2884,7 @@ static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, Command->BufferHeader = Request->bio; Command->RequestBuffer = Request->buffer; blkdev_dequeue_request(Request); - blkdev_release_request(Request); + blk_put_request(Request); DAC960_QueueReadWriteCommand(Command); return true; } diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index e73c1d823428..53f1706d2877 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -1233,9 +1233,47 @@ struct request *__blk_get_request(request_queue_t *q, int rw) return rq; } -void blk_put_request(struct request *rq) +/** + * blk_insert_request - insert a special request in to a request queue + * @q: request queue where request should be inserted + * @rq: request to be inserted + * @at_head: insert request at head or tail of queue + * @data: private data + * + * Description: + * Many block devices need to execute commands asynchronously, so they don't + * block the whole kernel from preemption during request execution. This is + * accomplished normally by inserting aritficial requests tagged as + * REQ_SPECIAL in to the corresponding request queue, and letting them be + * scheduled for actual execution by the request queue. + * + * We have the option of inserting the head or the tail of the queue. + * Typically we use the tail for new ioctls and so forth. We use the head + * of the queue for things like a QUEUE_FULL message from a device, or a + * host that is unable to accept a particular command. + */ +void blk_insert_request(request_queue_t *q, struct request *rq, + int at_head, void *data) { - blkdev_release_request(rq); + unsigned long flags; + + /* + * tell I/O scheduler that this isn't a regular read/write (ie it + * must not attempt merges on this) and that it acts as a soft + * barrier + */ + rq->flags &= REQ_QUEUED; + rq->flags |= REQ_SPECIAL | REQ_BARRIER; + + rq->special = data; + + spin_lock_irqsave(q->queue_lock, flags); + /* If command is tagged, release the tag */ + if(blk_rq_tagged(rq)) + blk_queue_end_tag(q, rq); + _elv_add_request(q, rq, !at_head, 0); + q->request_fn(q); + spin_unlock_irqrestore(q->queue_lock, flags); } /* RO fail safe mechanism */ @@ -1307,7 +1345,7 @@ static inline void add_request(request_queue_t * q, struct request * req, /* * Must be called with queue lock held and interrupts disabled */ -void blkdev_release_request(struct request *req) +void blk_put_request(struct request *req) { struct request_list *rl = req->rl; request_queue_t *q = req->q; @@ -1370,7 +1408,7 @@ static void attempt_merge(request_queue_t *q, struct request *req, req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors; - blkdev_release_request(next); + blk_put_request(next); } } @@ -1568,7 +1606,7 @@ get_rq: add_request(q, req, insert_here); out: if (freereq) - blkdev_release_request(freereq); + blk_put_request(freereq); spin_unlock_irq(q->queue_lock); return 0; @@ -2003,7 +2041,7 @@ void end_that_request_last(struct request *req) if (req->waiting) complete(req->waiting); - blkdev_release_request(req); + blk_put_request(req); } #define MB(kb) ((kb) << 10) @@ -2064,7 +2102,6 @@ EXPORT_SYMBOL(blk_cleanup_queue); EXPORT_SYMBOL(blk_queue_make_request); EXPORT_SYMBOL(blk_queue_bounce_limit); EXPORT_SYMBOL(generic_make_request); -EXPORT_SYMBOL(blkdev_release_request); EXPORT_SYMBOL(generic_unplug_device); EXPORT_SYMBOL(blk_plug_device); EXPORT_SYMBOL(blk_remove_plug); @@ -2088,6 +2125,7 @@ EXPORT_SYMBOL(blk_hw_contig_segment); EXPORT_SYMBOL(blk_get_request); EXPORT_SYMBOL(__blk_get_request); EXPORT_SYMBOL(blk_put_request); +EXPORT_SYMBOL(blk_insert_request); EXPORT_SYMBOL(blk_queue_prep_rq); diff --git a/drivers/char/serial_21285.c b/drivers/char/serial_21285.c deleted file mode 100644 index d775644e96ad..000000000000 --- a/drivers/char/serial_21285.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * linux/drivers/char/serial_21285.c - * - * Driver for the serial port on the 21285 StrongArm-110 core logic chip. - * - * Based on drivers/char/serial.c - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial.h> -#include <linux/major.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/console.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/dec21285.h> -#include <asm/hardware.h> - -#define BAUD_BASE (mem_fclk_21285/64) - -#define SERIAL_21285_NAME "ttyFB" -#define SERIAL_21285_MAJOR 204 -#define SERIAL_21285_MINOR 4 - -#define SERIAL_21285_AUXNAME "cuafb" -#define SERIAL_21285_AUXMAJOR 205 -#define SERIAL_21285_AUXMINOR 4 - -static struct tty_driver rs285_driver, callout_driver; -static int rs285_refcount; -static struct tty_struct *rs285_table[1]; - -static struct termios *rs285_termios[1]; -static struct termios *rs285_termios_locked[1]; - -static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char; -static struct tty_struct *rs285_tty; -static int rs285_use_count; - -static int rs285_write_room(struct tty_struct *tty) -{ - return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1); -} - -static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs) -{ - if (!rs285_tty) { - disable_irq(IRQ_CONRX); - return; - } - while (!(*CSR_UARTFLG & 0x10)) { - int ch, flag; - ch = *CSR_UARTDR; - flag = *CSR_RXSTAT; - if (flag & 4) - tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN); - if (flag & 2) - flag = TTY_PARITY; - else if (flag & 1) - flag = TTY_FRAME; - tty_insert_flip_char(rs285_tty, ch, flag); - } - tty_flip_buffer_push(rs285_tty); -} - -static void rs285_send_xchar(struct tty_struct *tty, char ch) -{ - x_char = ch; - enable_irq(IRQ_CONTX); -} - -static void rs285_throttle(struct tty_struct *tty) -{ - if (I_IXOFF(tty)) - rs285_send_xchar(tty, STOP_CHAR(tty)); -} - -static void rs285_unthrottle(struct tty_struct *tty) -{ - if (I_IXOFF(tty)) { - if (x_char) - x_char = 0; - else - rs285_send_xchar(tty, START_CHAR(tty)); - } -} - -static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs) -{ - while (!(*CSR_UARTFLG & 0x20)) { - if (x_char) { - *CSR_UARTDR = x_char; - x_char = 0; - continue; - } - if (putp == getp) { - disable_irq(IRQ_CONTX); - break; - } - *CSR_UARTDR = *getp; - if (++getp >= wbuf + sizeof(wbuf)) - getp = wbuf; - } - if (rs285_tty) - wake_up_interruptible(&rs285_tty->write_wait); -} - -static inline int rs285_xmit(int ch) -{ - if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf)) - return 0; - *putp = ch; - if (++putp >= wbuf + sizeof(wbuf)) - putp = wbuf; - enable_irq(IRQ_CONTX); - return 1; -} - -static int rs285_write(struct tty_struct *tty, int from_user, - const u_char * buf, int count) -{ - int i; - - if (from_user && verify_area(VERIFY_READ, buf, count)) - return -EINVAL; - - for (i = 0; i < count; i++) { - char ch; - if (from_user) - __get_user(ch, buf + i); - else - ch = buf[i]; - if (!rs285_xmit(ch)) - break; - } - return i; -} - -static void rs285_put_char(struct tty_struct *tty, u_char ch) -{ - rs285_xmit(ch); -} - -static int rs285_chars_in_buffer(struct tty_struct *tty) -{ - return sizeof(wbuf) - rs285_write_room(tty); -} - -static void rs285_flush_buffer(struct tty_struct *tty) -{ - disable_irq(IRQ_CONTX); - putp = getp = wbuf; - if (x_char) - enable_irq(IRQ_CONTX); -} - -static inline void rs285_set_cflag(int cflag) -{ - int h_lcr, baud, quot; - - switch (cflag & CSIZE) { - case CS5: - h_lcr = 0x10; - break; - case CS6: - h_lcr = 0x30; - break; - case CS7: - h_lcr = 0x50; - break; - default: /* CS8 */ - h_lcr = 0x70; - break; - - } - if (cflag & CSTOPB) - h_lcr |= 0x08; - if (cflag & PARENB) - h_lcr |= 0x02; - if (!(cflag & PARODD)) - h_lcr |= 0x04; - - switch (cflag & CBAUD) { - case B200: baud = 200; break; - case B300: baud = 300; break; - case B1200: baud = 1200; break; - case B1800: baud = 1800; break; - case B2400: baud = 2400; break; - case B4800: baud = 4800; break; - default: - case B9600: baud = 9600; break; - case B19200: baud = 19200; break; - case B38400: baud = 38400; break; - case B57600: baud = 57600; break; - case B115200: baud = 115200; break; - } - - /* - * The documented expression for selecting the divisor is: - * BAUD_BASE / baud - 1 - * However, typically BAUD_BASE is not divisible by baud, so - * we want to select the divisor that gives us the minimum - * error. Therefore, we want: - * int(BAUD_BASE / baud - 0.5) -> - * int(BAUD_BASE / baud - (baud >> 1) / baud) -> - * int((BAUD_BASE - (baud >> 1)) / baud) - */ - quot = (BAUD_BASE - (baud >> 1)) / baud; - - *CSR_UARTCON = 0; - *CSR_L_UBRLCR = quot & 0xff; - *CSR_M_UBRLCR = (quot >> 8) & 0x0f; - *CSR_H_UBRLCR = h_lcr; - *CSR_UARTCON = 1; -} - -static void rs285_set_termios(struct tty_struct *tty, struct termios *old) -{ - if (old && tty->termios->c_cflag == old->c_cflag) - return; - rs285_set_cflag(tty->termios->c_cflag); -} - - -static void rs285_stop(struct tty_struct *tty) -{ - disable_irq(IRQ_CONTX); -} - -static void rs285_start(struct tty_struct *tty) -{ - enable_irq(IRQ_CONTX); -} - -static void rs285_wait_until_sent(struct tty_struct *tty, int timeout) -{ - int orig_jiffies = jiffies; - while (*CSR_UARTFLG & 8) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - current->state = TASK_RUNNING; -} - -static int rs285_open(struct tty_struct *tty, struct file *filp) -{ - int line; - - MOD_INC_USE_COUNT; - line = minor(tty->device) - tty->driver.minor_start; - if (line) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - - tty->driver_data = NULL; - if (!rs285_tty) - rs285_tty = tty; - - enable_irq(IRQ_CONRX); - rs285_use_count++; - return 0; -} - -static void rs285_close(struct tty_struct *tty, struct file *filp) -{ - if (!--rs285_use_count) { - rs285_wait_until_sent(tty, 0); - disable_irq(IRQ_CONRX); - disable_irq(IRQ_CONTX); - rs285_tty = NULL; - } - MOD_DEC_USE_COUNT; -} - -static int __init rs285_init(void) -{ - int baud = B9600; - - if (machine_is_personal_server()) - baud = B57600; - - rs285_driver.magic = TTY_DRIVER_MAGIC; - rs285_driver.driver_name = "serial_21285"; - rs285_driver.name = SERIAL_21285_NAME; - rs285_driver.major = SERIAL_21285_MAJOR; - rs285_driver.minor_start = SERIAL_21285_MINOR; - rs285_driver.num = 1; - rs285_driver.type = TTY_DRIVER_TYPE_SERIAL; - rs285_driver.subtype = SERIAL_TYPE_NORMAL; - rs285_driver.init_termios = tty_std_termios; - rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL; - rs285_driver.flags = TTY_DRIVER_REAL_RAW; - rs285_driver.refcount = &rs285_refcount; - rs285_driver.table = rs285_table; - rs285_driver.termios = rs285_termios; - rs285_driver.termios_locked = rs285_termios_locked; - - rs285_driver.open = rs285_open; - rs285_driver.close = rs285_close; - rs285_driver.write = rs285_write; - rs285_driver.put_char = rs285_put_char; - rs285_driver.write_room = rs285_write_room; - rs285_driver.chars_in_buffer = rs285_chars_in_buffer; - rs285_driver.flush_buffer = rs285_flush_buffer; - rs285_driver.throttle = rs285_throttle; - rs285_driver.unthrottle = rs285_unthrottle; - rs285_driver.send_xchar = rs285_send_xchar; - rs285_driver.set_termios = rs285_set_termios; - rs285_driver.stop = rs285_stop; - rs285_driver.start = rs285_start; - rs285_driver.wait_until_sent = rs285_wait_until_sent; - - callout_driver = rs285_driver; - callout_driver.name = SERIAL_21285_AUXNAME; - callout_driver.major = SERIAL_21285_AUXMAJOR; - callout_driver.subtype = SERIAL_TYPE_CALLOUT; - - if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL)) - panic("Couldn't get rx irq for rs285"); - - if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL)) - panic("Couldn't get tx irq for rs285"); - - if (tty_register_driver(&rs285_driver)) - printk(KERN_ERR "Couldn't register 21285 serial driver\n"); - if (tty_register_driver(&callout_driver)) - printk(KERN_ERR "Couldn't register 21285 callout driver\n"); - - return 0; -} - -static void __exit rs285_fini(void) -{ - unsigned long flags; - int ret; - - save_flags(flags); - cli(); - ret = tty_unregister_driver(&callout_driver); - if (ret) - printk(KERN_ERR "Unable to unregister 21285 callout driver " - "(%d)\n", ret); - ret = tty_unregister_driver(&rs285_driver); - if (ret) - printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n", - ret); - free_irq(IRQ_CONTX, NULL); - free_irq(IRQ_CONRX, NULL); - restore_flags(flags); -} - -module_init(rs285_init); -module_exit(rs285_fini); - -#ifdef CONFIG_SERIAL_21285_CONSOLE -/************** console driver *****************/ - -static void rs285_console_write(struct console *co, const char *s, u_int count) -{ - int i; - - disable_irq(IRQ_CONTX); - for (i = 0; i < count; i++) { - while (*CSR_UARTFLG & 0x20); - *CSR_UARTDR = s[i]; - if (s[i] == '\n') { - while (*CSR_UARTFLG & 0x20); - *CSR_UARTDR = '\r'; - } - } - enable_irq(IRQ_CONTX); -} - -static kdev_t rs285_console_device(struct console *c) -{ - return mk_kdev(SERIAL_21285_MAJOR, SERIAL_21285_MINOR); -} - -static int __init rs285_console_setup(struct console *co, char *options) -{ - int baud = 9600; - int bits = 8; - int parity = 'n'; - int cflag = CREAD | HUPCL | CLOCAL; - - if (machine_is_personal_server()) - baud = 57600; - - if (options) { - char *s = options; - baud = simple_strtoul(options, NULL, 10); - while (*s >= '0' && *s <= '9') - s++; - if (*s) - parity = *s++; - if (*s) - bits = *s - '0'; - } - - /* - * Now construct a cflag setting. - */ - switch (baud) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 9600: - cflag |= B9600; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - default: - cflag |= B9600; - break; - } - switch (bits) { - case 7: - cflag |= CS7; - break; - default: - cflag |= CS8; - break; - } - switch (parity) { - case 'o': - case 'O': - cflag |= PARODD; - break; - case 'e': - case 'E': - cflag |= PARENB; - break; - } - co->cflag = cflag; - rs285_set_cflag(cflag); - rs285_console_write(NULL, "\e[2J\e[Hboot ", 12); - if (options) - rs285_console_write(NULL, options, strlen(options)); - else - rs285_console_write(NULL, "no options", 10); - rs285_console_write(NULL, "\n", 1); - - return 0; -} - -static struct console rs285_cons = -{ - name: SERIAL_21285_NAME, - write: rs285_console_write, - device: rs285_console_device, - setup: rs285_console_setup, - flags: CON_PRINTBUFFER, - index: -1, -}; - -void __init rs285_console_init(void) -{ - register_console(&rs285_cons); -} - -#endif /* CONFIG_SERIAL_21285_CONSOLE */ - -MODULE_LICENSE("GPL"); diff --git a/drivers/char/serial_amba.c b/drivers/char/serial_amba.c deleted file mode 100644 index 48d416e6277e..000000000000 --- a/drivers/char/serial_amba.c +++ /dev/null @@ -1,2014 +0,0 @@ -/* - * linux/drivers/char/serial_amba.c - * - * Driver for AMBA serial ports - * - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * - * Copyright 1999 ARM Limited - * Copyright (C) 2000 Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * This is a generic driver for ARM AMBA-type serial ports. They - * have a lot of 16550-like features, but are not register compatable. - * Note that although they do have CTS, DCD and DSR inputs, they do - * not have an RI input, nor do they have DTR or RTS outputs. If - * required, these have to be supplied via some other means (eg, GPIO) - * and hooked into this driver. - * - * This could very easily become a generic serial driver for dumb UARTs - * (eg, {82,16x}50, 21285, SA1100). - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/major.h> -#include <linux/string.h> -#include <linux/fcntl.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/circ_buf.h> -#include <linux/serial.h> -#include <linux/console.h> -#include <linux/sysrq.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#include <asm/bitops.h> - -#include <asm/hardware/serial_amba.h> - -#define SERIAL_AMBA_NAME "ttyAM" -#define SERIAL_AMBA_MAJOR 204 -#define SERIAL_AMBA_MINOR 16 -#define SERIAL_AMBA_NR 2 - -#define CALLOUT_AMBA_NAME "cuaam" -#define CALLOUT_AMBA_MAJOR 205 -#define CALLOUT_AMBA_MINOR 16 -#define CALLOUT_AMBA_NR SERIAL_AMBA_NR - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define DEBUG 0 -#define DEBUG_LEDS 0 - -#if DEBUG_LEDS -extern int get_leds(void); -extern int set_leds(int); -#endif - -/* - * Access routines for the AMBA UARTs - */ -#define UART_GET_INT_STATUS(p) IO_READ((p)->uart_base + AMBA_UARTIIR) -#define UART_GET_FR(p) IO_READ((p)->uart_base + AMBA_UARTFR) -#define UART_GET_CHAR(p) IO_READ((p)->uart_base + AMBA_UARTDR) -#define UART_PUT_CHAR(p, c) IO_WRITE((p)->uart_base + AMBA_UARTDR, (c)) -#define UART_GET_RSR(p) IO_READ((p)->uart_base + AMBA_UARTRSR) -#define UART_GET_CR(p) IO_READ((p)->uart_base + AMBA_UARTCR) -#define UART_PUT_CR(p,c) IO_WRITE((p)->uart_base + AMBA_UARTCR, (c)) -#define UART_GET_LCRL(p) IO_READ((p)->uart_base + AMBA_UARTLCR_L) -#define UART_PUT_LCRL(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_L, (c)) -#define UART_GET_LCRM(p) IO_READ((p)->uart_base + AMBA_UARTLCR_M) -#define UART_PUT_LCRM(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_M, (c)) -#define UART_GET_LCRH(p) IO_READ((p)->uart_base + AMBA_UARTLCR_H) -#define UART_PUT_LCRH(p,c) IO_WRITE((p)->uart_base + AMBA_UARTLCR_H, (c)) -#define UART_RX_DATA(s) (((s) & AMBA_UARTFR_RXFE) == 0) -#define UART_TX_READY(s) (((s) & AMBA_UARTFR_TXFF) == 0) -#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & AMBA_UARTFR_TMSK) == 0) - -#define AMBA_UARTRSR_ANY (AMBA_UARTRSR_OE|AMBA_UARTRSR_BE|AMBA_UARTRSR_PE|AMBA_UARTRSR_FE) -#define AMBA_UARTFR_MODEM_ANY (AMBA_UARTFR_DCD|AMBA_UARTFR_DSR|AMBA_UARTFR_CTS) - -/* - * Things needed by tty driver - */ -static struct tty_driver ambanormal_driver, ambacallout_driver; -static int ambauart_refcount; -static struct tty_struct *ambauart_table[SERIAL_AMBA_NR]; -static struct termios *ambauart_termios[SERIAL_AMBA_NR]; -static struct termios *ambauart_termios_locked[SERIAL_AMBA_NR]; - -#if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -/* - * Things needed internally to this driver - */ - -/* - * tmp_buf is used as a temporary buffer by serial_write. We need to - * lock it in case the copy_from_user blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static u_char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); - -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 -#define AMBA_ISR_PASS_LIMIT 256 - -#define EVT_WRITE_WAKEUP 0 - -struct amba_icount { - __u32 cts; - __u32 dsr; - __u32 rng; - __u32 dcd; - __u32 rx; - __u32 tx; - __u32 frame; - __u32 overrun; - __u32 parity; - __u32 brk; - __u32 buf_overrun; -}; - -/* - * Static information about the port - */ -struct amba_port { - unsigned int uart_base; - unsigned int irq; - unsigned int uartclk; - unsigned int fifosize; - unsigned int tiocm_support; - void (*set_mctrl)(struct amba_port *, u_int mctrl); -}; - -/* - * This is the state information which is persistent across opens - */ -struct amba_state { - struct amba_icount icount; - unsigned int line; - unsigned int close_delay; - unsigned int closing_wait; - unsigned int custom_divisor; - unsigned int flags; - struct termios normal_termios; - struct termios callout_termios; - - int count; - struct amba_info *info; -}; - -#define AMBA_XMIT_SIZE 1024 -/* - * This is the state information which is only valid when the port is open. - */ -struct amba_info { - struct amba_port *port; - struct amba_state *state; - struct tty_struct *tty; - unsigned char x_char; - unsigned char old_status; - unsigned char read_status_mask; - unsigned char ignore_status_mask; - struct circ_buf xmit; - unsigned int flags; -#ifdef SUPPORT_SYSRQ - unsigned long sysrq; -#endif - - unsigned int event; - unsigned int timeout; - unsigned int lcr_h; - unsigned int mctrl; - int blocked_open; - pid_t session; - pid_t pgrp; - - struct tasklet_struct tlet; - - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - wait_queue_head_t delta_msr_wait; -}; - -#ifdef CONFIG_SERIAL_AMBA_CONSOLE -static struct console ambauart_cons; -#endif -static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios); -static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout); - -#if 1 //def CONFIG_SERIAL_INTEGRATOR -static void amba_set_mctrl_null(struct amba_port *port, u_int mctrl) -{ -} - -static struct amba_port amba_ports[SERIAL_AMBA_NR] = { - { - uart_base: IO_ADDRESS(INTEGRATOR_UART0_BASE), - irq: IRQ_UARTINT0, - uartclk: 14745600, - fifosize: 8, - set_mctrl: amba_set_mctrl_null, - }, - { - uart_base: IO_ADDRESS(INTEGRATOR_UART1_BASE), - irq: IRQ_UARTINT1, - uartclk: 14745600, - fifosize: 8, - set_mctrl: amba_set_mctrl_null, - } -}; -#endif - -static struct amba_state amba_state[SERIAL_AMBA_NR]; - -static void ambauart_enable_rx_interrupt(struct amba_info *info) -{ - unsigned int cr; - - cr = UART_GET_CR(info->port); - cr |= AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE; - UART_PUT_CR(info->port, cr); -} - -static void ambauart_disable_rx_interrupt(struct amba_info *info) -{ - unsigned int cr; - - cr = UART_GET_CR(info->port); - cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE); - UART_PUT_CR(info->port, cr); -} - -static void ambauart_enable_tx_interrupt(struct amba_info *info) -{ - unsigned int cr; - - cr = UART_GET_CR(info->port); - cr |= AMBA_UARTCR_TIE; - UART_PUT_CR(info->port, cr); -} - -static void ambauart_disable_tx_interrupt(struct amba_info *info) -{ - unsigned int cr; - - cr = UART_GET_CR(info->port); - cr &= ~AMBA_UARTCR_TIE; - UART_PUT_CR(info->port, cr); -} - -static void ambauart_stop(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - save_flags(flags); cli(); - ambauart_disable_tx_interrupt(info); - restore_flags(flags); -} - -static void ambauart_start(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - save_flags(flags); cli(); - if (info->xmit.head != info->xmit.tail - && info->xmit.buf) - ambauart_enable_tx_interrupt(info); - restore_flags(flags); -} - - -/* - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - */ -static void ambauart_event(struct amba_info *info, int event) -{ - info->event |= 1 << event; - tasklet_schedule(&info->tlet); -} - -static void -#ifdef SUPPORT_SYSRQ -ambauart_rx_chars(struct amba_info *info, struct pt_regs *regs) -#else -ambauart_rx_chars(struct amba_info *info) -#endif -{ - struct tty_struct *tty = info->tty; - unsigned int status, ch, rsr, flg, ignored = 0; - struct amba_icount *icount = &info->state->icount; - struct amba_port *port = info->port; - - status = UART_GET_FR(port); - while (UART_RX_DATA(status)) { - ch = UART_GET_CHAR(port); - - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; - icount->rx++; - - flg = TTY_NORMAL; - - /* - * Note that the error handling code is - * out of the main execution path - */ - rsr = UART_GET_RSR(port); - if (rsr & AMBA_UARTRSR_ANY) - goto handle_error; -#ifdef SUPPORT_SYSRQ - if (info->sysrq) { - if (ch && time_before(jiffies, info->sysrq)) { - handle_sysrq(ch, regs, NULL, NULL); - info->sysrq = 0; - goto ignore_char; - } - info->sysrq = 0; - } -#endif - error_return: - *tty->flip.flag_buf_ptr++ = flg; - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; - ignore_char: - status = UART_GET_FR(port); - } -out: - tty_flip_buffer_push(tty); - return; - -handle_error: - if (rsr & AMBA_UARTRSR_BE) { - rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE); - icount->brk++; - -#ifdef SUPPORT_SYSRQ - if (info->state->line == ambauart_cons.index) { - if (!info->sysrq) { - info->sysrq = jiffies + HZ*5; - goto ignore_char; - } - } -#endif - } else if (rsr & AMBA_UARTRSR_PE) - icount->parity++; - else if (rsr & AMBA_UARTRSR_FE) - icount->frame++; - if (rsr & AMBA_UARTRSR_OE) - icount->overrun++; - - if (rsr & info->ignore_status_mask) { - if (++ignored > 100) - goto out; - goto ignore_char; - } - rsr &= info->read_status_mask; - - if (rsr & AMBA_UARTRSR_BE) - flg = TTY_BREAK; - else if (rsr & AMBA_UARTRSR_PE) - flg = TTY_PARITY; - else if (rsr & AMBA_UARTRSR_FE) - flg = TTY_FRAME; - - if (rsr & AMBA_UARTRSR_OE) { - /* - * CHECK: does overrun affect the current character? - * ASSUMPTION: it does not. - */ - *tty->flip.flag_buf_ptr++ = flg; - *tty->flip.char_buf_ptr++ = ch; - tty->flip.count++; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; - ch = 0; - flg = TTY_OVERRUN; - } -#ifdef SUPPORT_SYSRQ - info->sysrq = 0; -#endif - goto error_return; -} - -static void ambauart_tx_chars(struct amba_info *info) -{ - struct amba_port *port = info->port; - int count; - - if (info->x_char) { - UART_PUT_CHAR(port, info->x_char); - info->state->icount.tx++; - info->x_char = 0; - return; - } - if (info->xmit.head == info->xmit.tail - || info->tty->stopped - || info->tty->hw_stopped) { - ambauart_disable_tx_interrupt(info); - return; - } - - count = port->fifosize; - do { - UART_PUT_CHAR(port, info->xmit.buf[info->xmit.tail]); - info->xmit.tail = (info->xmit.tail + 1) & (AMBA_XMIT_SIZE - 1); - info->state->icount.tx++; - if (info->xmit.head == info->xmit.tail) - break; - } while (--count > 0); - - if (CIRC_CNT(info->xmit.head, - info->xmit.tail, - AMBA_XMIT_SIZE) < WAKEUP_CHARS) - ambauart_event(info, EVT_WRITE_WAKEUP); - - if (info->xmit.head == info->xmit.tail) { - ambauart_disable_tx_interrupt(info); - } -} - -static void ambauart_modem_status(struct amba_info *info) -{ - unsigned int status, delta; - struct amba_icount *icount = &info->state->icount; - - status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY; - - delta = status ^ info->old_status; - info->old_status = status; - - if (!delta) - return; - - if (delta & AMBA_UARTFR_DCD) { - icount->dcd++; -#ifdef CONFIG_HARD_PPS - if ((info->flags & ASYNC_HARDPPS_CD) && - (status & AMBA_UARTFR_DCD) - hardpps(); -#endif - if (info->flags & ASYNC_CHECK_CD) { - if (status & AMBA_UARTFR_DCD) - wake_up_interruptible(&info->open_wait); - else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_CALLOUT_NOHUP))) { - if (info->tty) - tty_hangup(info->tty); - } - } - } - - if (delta & AMBA_UARTFR_DSR) - icount->dsr++; - - if (delta & AMBA_UARTFR_CTS) { - icount->cts++; - - if (info->flags & ASYNC_CTS_FLOW) { - status &= AMBA_UARTFR_CTS; - - if (info->tty->hw_stopped) { - if (status) { - info->tty->hw_stopped = 0; - ambauart_enable_tx_interrupt(info); - ambauart_event(info, EVT_WRITE_WAKEUP); - } - } else { - if (!status) { - info->tty->hw_stopped = 1; - ambauart_disable_tx_interrupt(info); - } - } - } - } - wake_up_interruptible(&info->delta_msr_wait); - -} - -static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs) -{ - struct amba_info *info = dev_id; - unsigned int status, pass_counter = 0; - -#if DEBUG_LEDS - // tell the world - set_leds(get_leds() | RED_LED); -#endif - - status = UART_GET_INT_STATUS(info->port); - do { - /* - * FIXME: what about clearing the interrupts? - */ - - if (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS)) -#ifdef SUPPORT_SYSRQ - ambauart_rx_chars(info, regs); -#else - ambauart_rx_chars(info); -#endif - if (status & AMBA_UARTIIR_TIS) - ambauart_tx_chars(info); - if (status & AMBA_UARTIIR_MIS) - ambauart_modem_status(info); - if (pass_counter++ > AMBA_ISR_PASS_LIMIT) - break; - - status = UART_GET_INT_STATUS(info->port); - } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | AMBA_UARTIIR_TIS)); - -#if DEBUG_LEDS - // tell the world - set_leds(get_leds() & ~RED_LED); -#endif -} - -static void ambauart_tasklet_action(unsigned long data) -{ - struct amba_info *info = (struct amba_info *)data; - struct tty_struct *tty; - - tty = info->tty; - if (!tty || !test_and_clear_bit(EVT_WRITE_WAKEUP, &info->event)) - return; - - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); -} - -static int ambauart_startup(struct amba_info *info) -{ - unsigned long flags; - unsigned long page; - int retval = 0; - - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - save_flags(flags); cli(); - - if (info->flags & ASYNC_INITIALIZED) { - free_page(page); - goto errout; - } - - if (info->xmit.buf) - free_page(page); - else - info->xmit.buf = (unsigned char *) page; - - /* - * Allocate the IRQ - */ - retval = request_irq(info->port->irq, ambauart_int, 0, "amba", info); - if (retval) { - if (capable(CAP_SYS_ADMIN)) { - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - retval = 0; - } - goto errout; - } - - info->mctrl = 0; - if (info->tty->termios->c_cflag & CBAUD) - info->mctrl = TIOCM_RTS | TIOCM_DTR; - info->port->set_mctrl(info->port, info->mctrl); - - /* - * initialise the old status of the modem signals - */ - info->old_status = UART_GET_FR(info->port) & AMBA_UARTFR_MODEM_ANY; - - /* - * Finally, enable interrupts - */ - ambauart_enable_rx_interrupt(info); - - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - info->xmit.head = info->xmit.tail = 0; - - /* - * Set up the tty->alt_speed kludge - */ - if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } - - /* - * and set the speed of the serial port - */ - ambauart_change_speed(info, 0); - - info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); - return 0; - -errout: - restore_flags(flags); - return retval; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void ambauart_shutdown(struct amba_info *info) -{ - unsigned long flags; - - if (!(info->flags & ASYNC_INITIALIZED)) - return; - - save_flags(flags); cli(); /* Disable interrupts */ - - /* - * clear delta_msr_wait queue to avoid mem leaks: we may free the irq - * here so the queue might never be woken up - */ - wake_up_interruptible(&info->delta_msr_wait); - - /* - * Free the IRQ - */ - free_irq(info->port->irq, info); - - if (info->xmit.buf) { - unsigned long pg = (unsigned long) info->xmit.buf; - info->xmit.buf = NULL; - free_page(pg); - } - - /* - * disable all interrupts, disable the port - */ - UART_PUT_CR(info->port, 0); - - /* disable break condition and fifos */ - UART_PUT_LCRH(info->port, UART_GET_LCRH(info->port) & - ~(AMBA_UARTLCR_H_BRK | AMBA_UARTLCR_H_FEN)); - - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - info->mctrl &= ~(TIOCM_DTR|TIOCM_RTS); - info->port->set_mctrl(info->port, info->mctrl); - - /* kill off our tasklet */ - tasklet_kill(&info->tlet); - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); -} - -static void ambauart_change_speed(struct amba_info *info, struct termios *old_termios) -{ - unsigned int lcr_h, baud, quot, cflag, old_cr, bits; - unsigned long flags; - - if (!info->tty || !info->tty->termios) - return; - - cflag = info->tty->termios->c_cflag; - -#if DEBUG - printk("ambauart_set_cflag(0x%x) called\n", cflag); -#endif - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: lcr_h = AMBA_UARTLCR_H_WLEN_5; bits = 7; break; - case CS6: lcr_h = AMBA_UARTLCR_H_WLEN_6; bits = 8; break; - case CS7: lcr_h = AMBA_UARTLCR_H_WLEN_7; bits = 9; break; - default: lcr_h = AMBA_UARTLCR_H_WLEN_8; bits = 10; break; // CS8 - } - if (cflag & CSTOPB) { - lcr_h |= AMBA_UARTLCR_H_STP2; - bits ++; - } - if (cflag & PARENB) { - lcr_h |= AMBA_UARTLCR_H_PEN; - bits++; - if (!(cflag & PARODD)) - lcr_h |= AMBA_UARTLCR_H_EPS; - } - if (info->port->fifosize > 1) - lcr_h |= AMBA_UARTLCR_H_FEN; - - do { - /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(info->tty); - if (!baud) - baud = 9600; - - if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; - else - quot = (info->port->uartclk / (16 * baud)) - 1; - - if (!quot && old_termios) { - info->tty->termios->c_cflag &= ~CBAUD; - info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); - old_termios = NULL; - } - } while (quot == 0 && old_termios); - - /* As a last resort, if the quotient is zero, default to 9600 bps */ - if (!quot) - quot = (info->port->uartclk / (16 * 9600)) - 1; - - info->timeout = (info->port->fifosize * HZ * bits * quot) / - (info->port->uartclk / 16); - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - if (cflag & CRTSCTS) - info->flags |= ASYNC_CTS_FLOW; - else - info->flags &= ~ASYNC_CTS_FLOW; - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else - info->flags |= ASYNC_CHECK_CD; - - /* - * Set up parity check flag - */ -#define RELEVENT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - - info->read_status_mask = AMBA_UARTRSR_OE; - if (I_INPCK(info->tty)) - info->read_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; - if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) - info->read_status_mask |= AMBA_UARTRSR_BE; - - /* - * Characters to ignore - */ - info->ignore_status_mask = 0; - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= AMBA_UARTRSR_FE | AMBA_UARTRSR_PE; - if (I_IGNBRK(info->tty)) { - info->ignore_status_mask |= AMBA_UARTRSR_BE; - /* - * If we're ignoring parity and break indicators, - * ignore overruns to (for real raw support). - */ - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= AMBA_UARTRSR_OE; - } - - /* first, disable everything */ - save_flags(flags); cli(); - old_cr = UART_GET_CR(info->port) &= ~AMBA_UARTCR_MSIE; - - if ((info->flags & ASYNC_HARDPPS_CD) || - (cflag & CRTSCTS) || - !(cflag & CLOCAL)) - old_cr |= AMBA_UARTCR_MSIE; - - UART_PUT_CR(info->port, 0); - restore_flags(flags); - - /* Set baud rate */ - UART_PUT_LCRM(info->port, ((quot & 0xf00) >> 8)); - UART_PUT_LCRL(info->port, (quot & 0xff)); - - /* - * ----------v----------v----------v----------v----- - * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L - * ----------^----------^----------^----------^----- - */ - UART_PUT_LCRH(info->port, lcr_h); - UART_PUT_CR(info->port, old_cr); -} - -static void ambauart_put_char(struct tty_struct *tty, u_char ch) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - if (!tty || !info->xmit.buf) - return; - - save_flags(flags); cli(); - if (CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE) != 0) { - info->xmit.buf[info->xmit.head] = ch; - info->xmit.head = (info->xmit.head + 1) & (AMBA_XMIT_SIZE - 1); - } - restore_flags(flags); -} - -static void ambauart_flush_chars(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - if (info->xmit.head == info->xmit.tail - || tty->stopped - || tty->hw_stopped - || !info->xmit.buf) - return; - - save_flags(flags); cli(); - ambauart_enable_tx_interrupt(info); - restore_flags(flags); -} - -static int ambauart_write(struct tty_struct *tty, int from_user, - const u_char * buf, int count) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - int c, ret = 0; - - if (!tty || !info->xmit.buf || !tmp_buf) - return 0; - - save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - AMBA_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - AMBA_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = (info->xmit.head + c) & - (AMBA_XMIT_SIZE - 1); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - cli(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - AMBA_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = (info->xmit.head + c) & - (AMBA_XMIT_SIZE - 1); - buf += c; - count -= c; - ret += c; - } - restore_flags(flags); - } - if (info->xmit.head != info->xmit.tail - && !tty->stopped - && !tty->hw_stopped) - ambauart_enable_tx_interrupt(info); - return ret; -} - -static int ambauart_write_room(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - - return CIRC_SPACE(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE); -} - -static int ambauart_chars_in_buffer(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - - return CIRC_CNT(info->xmit.head, info->xmit.tail, AMBA_XMIT_SIZE); -} - -static void ambauart_flush_buffer(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - -#if DEBUG - printk("ambauart_flush_buffer(%d) called\n", - minor(tty->device) - tty->driver.minor_start); -#endif - save_flags(flags); cli(); - info->xmit.head = info->xmit.tail = 0; - restore_flags(flags); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void ambauart_send_xchar(struct tty_struct *tty, char ch) -{ - struct amba_info *info = tty->driver_data; - - info->x_char = ch; - if (ch) - ambauart_enable_tx_interrupt(info); -} - -static void ambauart_throttle(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - - if (I_IXOFF(tty)) - ambauart_send_xchar(tty, STOP_CHAR(tty)); - - if (tty->termios->c_cflag & CRTSCTS) { - save_flags(flags); cli(); - info->mctrl &= ~TIOCM_RTS; - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - } -} - -static void ambauart_unthrottle(struct tty_struct *tty) -{ - struct amba_info *info = (struct amba_info *) tty->driver_data; - unsigned long flags; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - ambauart_send_xchar(tty, START_CHAR(tty)); - } - - if (tty->termios->c_cflag & CRTSCTS) { - save_flags(flags); cli(); - info->mctrl |= TIOCM_RTS; - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - } -} - -static int get_serial_info(struct amba_info *info, struct serial_struct *retinfo) -{ - struct amba_state *state = info->state; - struct amba_port *port = info->port; - struct serial_struct tmp; - - memset(&tmp, 0, sizeof(tmp)); - tmp.type = 0; - tmp.line = state->line; - tmp.port = port->uart_base; - if (HIGH_BITS_OFFSET) - tmp.port_high = port->uart_base >> HIGH_BITS_OFFSET; - tmp.irq = port->irq; - tmp.flags = 0; - tmp.xmit_fifo_size = port->fifosize; - tmp.baud_base = port->uartclk / 16; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; - tmp.custom_divisor = state->custom_divisor; - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int set_serial_info(struct amba_info *info, - struct serial_struct *newinfo) -{ - struct serial_struct new_serial; - struct amba_state *state, old_state; - struct amba_port *port; - unsigned long new_port; - unsigned int i, change_irq, change_port; - int retval = 0; - - if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) - return -EFAULT; - - state = info->state; - old_state = *state; - port = info->port; - - new_port = new_serial.port; - if (HIGH_BITS_OFFSET) - new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; - - change_irq = new_serial.irq != port->irq; - change_port = new_port != port->uart_base; - - if (!capable(CAP_SYS_ADMIN)) { - if (change_irq || change_port || - (new_serial.baud_base != port->uartclk / 16) || - (new_serial.close_delay != state->close_delay) || - (new_serial.xmit_fifo_size != port->fifosize) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (state->flags & ~ASYNC_USR_MASK))) - return -EPERM; - state->flags = ((state->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - state->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || - (new_serial.baud_base < 9600)) - return -EINVAL; - - if (new_serial.type && change_port) { - for (i = 0; i < SERIAL_AMBA_NR; i++) - if ((port != amba_ports + i) && - amba_ports[i].uart_base != new_port) - return -EADDRINUSE; - } - - if ((change_port || change_irq) && (state->count > 1)) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - port->uartclk = new_serial.baud_base * 16; - state->flags = ((state->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | - (info->flags & ASYNC_INTERNAL_FLAGS)); - state->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ / 100; - state->closing_wait = new_serial.closing_wait * HZ / 100; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - port->fifosize = new_serial.xmit_fifo_size; - - if (change_port || change_irq) { - /* - * We need to shutdown the serial port at the old - * port/irq combination. - */ - ambauart_shutdown(info); - port->irq = new_serial.irq; - port->uart_base = new_port; - } - -check_and_exit: - if (!port->uart_base) - return 0; - if (info->flags & ASYNC_INITIALIZED) { - if ((old_state.flags & ASYNC_SPD_MASK) != - (state->flags & ASYNC_SPD_MASK) || - (old_state.custom_divisor != state->custom_divisor)) { - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - ambauart_change_speed(info, NULL); - } - } else - retval = ambauart_startup(info); - return retval; -} - - -/* - * get_lsr_info - get line status register info - */ -static int get_lsr_info(struct amba_info *info, unsigned int *value) -{ - unsigned int result, status; - unsigned long flags; - - save_flags(flags); cli(); - status = UART_GET_FR(info->port); - restore_flags(flags); - result = status & AMBA_UARTFR_BUSY ? TIOCSER_TEMT : 0; - - /* - * If we're about to load something into the transmit - * register, we'll pretend the transmitter isn't empty to - * avoid a race condition (depending on when the transmit - * interrupt happens). - */ - if (info->x_char || - ((CIRC_CNT(info->xmit.head, info->xmit.tail, - AMBA_XMIT_SIZE) > 0) && - !info->tty->stopped && !info->tty->hw_stopped)) - result &= TIOCSER_TEMT; - - return put_user(result, value); -} - -static int get_modem_info(struct amba_info *info, unsigned int *value) -{ - unsigned int result = info->mctrl; - unsigned int status; - - status = UART_GET_FR(info->port); - if (status & AMBA_UARTFR_DCD) - result |= TIOCM_CAR; - if (status & AMBA_UARTFR_DSR) - result |= TIOCM_DSR; - if (status & AMBA_UARTFR_CTS) - result |= TIOCM_CTS; - - return put_user(result, value); -} - -static int set_modem_info(struct amba_info *info, unsigned int cmd, - unsigned int *value) -{ - unsigned int arg, old; - unsigned long flags; - - if (get_user(arg, value)) - return -EFAULT; - - old = info->mctrl; - switch (cmd) { - case TIOCMBIS: - info->mctrl |= arg; - break; - - case TIOCMBIC: - info->mctrl &= ~arg; - break; - - case TIOCMSET: - info->mctrl = arg; - break; - - default: - return -EINVAL; - } - save_flags(flags); cli(); - if (old != info->mctrl) - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - return 0; -} - -static void ambauart_break_ctl(struct tty_struct *tty, int break_state) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - unsigned int lcr_h; - - save_flags(flags); cli(); - lcr_h = UART_GET_LCRH(info->port); - if (break_state == -1) - lcr_h |= AMBA_UARTLCR_H_BRK; - else - lcr_h &= ~AMBA_UARTLCR_H_BRK; - UART_PUT_LCRH(info->port, lcr_h); - restore_flags(flags); -} - -static int ambauart_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct amba_info *info = tty->driver_data; - struct amba_icount cprev, cnow; - struct serial_icounter_struct icount; - unsigned long flags; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *)arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *)arg); - case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *)arg); - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *)arg); - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *)arg); - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - save_flags(flags); cli(); - /* note the counters on entry */ - cprev = info->state->icount; - /* Force modem status interrupts on */ - UART_PUT_CR(info->port, UART_GET_CR(info->port) | AMBA_UARTCR_MSIE); - restore_flags(flags); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - save_flags(flags); cli(); - cnow = info->state->icount; /* atomic copy */ - restore_flags(flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - save_flags(flags); cli(); - cnow = info->state->icount; - restore_flags(flags); - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; - - return copy_to_user((void *)arg, &icount, sizeof(icount)) - ? -EFAULT : 0; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void ambauart_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - struct amba_info *info = tty->driver_data; - unsigned long flags; - unsigned int cflag = tty->termios->c_cflag; - - if ((cflag ^ old_termios->c_cflag) == 0 && - RELEVENT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) - return; - - ambauart_change_speed(info, old_termios); - - /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { - save_flags(flags); cli(); - info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR); - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { - save_flags(flags); cli(); - info->mctrl |= TIOCM_DTR; - if (!(cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) - info->mctrl |= TIOCM_RTS; - info->port->set_mctrl(info->port, info->mctrl); - restore_flags(flags); - } - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(cflag & CRTSCTS)) { - tty->hw_stopped = 0; - ambauart_start(tty); - } - -#if 0 - /* - * No need to wake up processes in open wait, since they - * sample the CLOCAL flag once, and don't recheck it. - * XXX It's not clear whether the current behavior is correct - * or not. Hence, this may change..... - */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); -#endif -} - -static void ambauart_close(struct tty_struct *tty, struct file *filp) -{ - struct amba_info *info = tty->driver_data; - struct amba_state *state; - unsigned long flags; - - if (!info) - return; - - state = info->state; - -#if DEBUG - printk("ambauart_close() called\n"); -#endif - - save_flags(flags); cli(); - - if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - - if ((tty->count == 1) && (state->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("ambauart_close: bad serial port count; tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; - } - if (--state->count < 0) { - printk("rs_close: bad serial port count for %s%d: %d\n", - tty->driver.name, info->state->line, state->count); - state->count = 0; - } - if (state->count) { - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - info->flags |= ASYNC_CLOSING; - restore_flags(flags); - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - */ - if (info->flags & ASYNC_NORMAL_ACTIVE) - info->state->normal_termios = *tty->termios; - if (info->flags & ASYNC_CALLOUT_ACTIVE) - info->state->callout_termios = *tty->termios; - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (info->state->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->state->closing_wait); - /* - * At this point, we stop accepting input. To do this, we - * disable the receive line status interrupts. - */ - if (info->flags & ASYNC_INITIALIZED) { - ambauart_disable_rx_interrupt(info); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - ambauart_wait_until_sent(tty, info->timeout); - } - ambauart_shutdown(info); - if (tty->driver.flush_buffer) - tty->driver.flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - info->event = 0; - info->tty = NULL; - if (info->blocked_open) { - if (info->state->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->state->close_delay); - } - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| - ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; -} - -static void ambauart_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct amba_info *info = (struct amba_info *) tty->driver_data; - unsigned long char_time, expire; - unsigned int status; - - if (info->port->fifosize == 0) - return; - - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ/50) / info->port->fifosize; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; - if (timeout && timeout < char_time) - char_time = timeout; - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than info->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*info->timeout. - */ - if (!timeout || timeout > 2 * info->timeout) - timeout = 2 * info->timeout; - - expire = jiffies + timeout; -#if DEBUG - printk("ambauart_wait_until_sent(%d), jiff=%lu, expire=%lu...\n", - minor(tty->device) - tty->driver.minor_start, jiffies, - expire); -#endif - while (UART_GET_FR(info->port) & AMBA_UARTFR_BUSY) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, expire)) - break; - status = UART_GET_FR(info->port); - } - set_current_state(TASK_RUNNING); -} - -static void ambauart_hangup(struct tty_struct *tty) -{ - struct amba_info *info = tty->driver_data; - struct amba_state *state = info->state; - - ambauart_flush_buffer(tty); - if (info->flags & ASYNC_CLOSING) - return; - ambauart_shutdown(info); - info->event = 0; - state->count = 0; - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); - info->tty = NULL; - wake_up_interruptible(&info->open_wait); -} - -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct amba_info *info) -{ - DECLARE_WAITQUEUE(wait, current); - struct amba_state *state = info->state; - unsigned long flags; - int do_clocal = 0, extra_count = 0, retval; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - return (info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS; - } - - /* - * If this is a callout device, then just make sure the normal - * device isn't being used. - */ - if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { - if (info->flags & ASYNC_NORMAL_ACTIVE) - return -EBUSY; - if ((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_SESSION_LOCKOUT) && - (info->session != current->session)) - return -EBUSY; - if ((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_PGRP_LOCKOUT) && - (info->pgrp != current->pgrp)) - return -EBUSY; - info->flags |= ASYNC_CALLOUT_ACTIVE; - return 0; - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - if (info->flags & ASYNC_CALLOUT_ACTIVE) - return -EBUSY; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (info->flags & ASYNC_CALLOUT_ACTIVE) { - if (state->normal_termios.c_cflag & CLOCAL) - do_clocal = 1; - } else { - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - } - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, state->count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); - save_flags(flags); cli(); - if (!tty_hung_up_p(filp)) { - extra_count = 1; - state->count--; - } - restore_flags(flags); - info->blocked_open++; - while (1) { - save_flags(flags); cli(); - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && - (tty->termios->c_cflag & CBAUD)) { - info->mctrl = TIOCM_DTR | TIOCM_RTS; - info->port->set_mctrl(info->port, info->mctrl); - } - restore_flags(flags); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { - if (info->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; - break; - } - if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && - !(info->flags & ASYNC_CLOSING) && - (do_clocal || (UART_GET_FR(info->port) & AMBA_UARTFR_DCD))) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); - if (extra_count) - state->count++; - info->blocked_open--; - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} - -static struct amba_info *ambauart_get(int line) -{ - struct amba_info *info; - struct amba_state *state = amba_state + line; - - state->count++; - if (state->info) - return state->info; - info = kmalloc(sizeof(struct amba_info), GFP_KERNEL); - if (info) { - memset(info, 0, sizeof(struct amba_info)); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->delta_msr_wait); - info->flags = state->flags; - info->state = state; - info->port = amba_ports + line; - tasklet_init(&info->tlet, ambauart_tasklet_action, - (unsigned long)info); - } - if (state->info) { - kfree(info); - return state->info; - } - state->info = info; - return info; -} - -static int ambauart_open(struct tty_struct *tty, struct file *filp) -{ - struct amba_info *info; - int retval, line = minor(tty->device) - tty->driver.minor_start; - -#if DEBUG - printk("ambauart_open(%d) called\n", line); -#endif - - // is this a line that we've got? - MOD_INC_USE_COUNT; - if (line >= SERIAL_AMBA_NR) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - - info = ambauart_get(line); - if (!info) - return -ENOMEM; - - tty->driver_data = info; - info->tty = tty; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - /* - * Make sure we have the temporary buffer allocated - */ - if (!tmp_buf) { - unsigned long page = get_zeroed_page(GFP_KERNEL); - if (tmp_buf) - free_page(page); - else if (!page) { - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - tmp_buf = (u_char *)page; - } - - /* - * If the port is in the middle of closing, bail out now. - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - MOD_DEC_USE_COUNT; - return -EAGAIN; - } - - /* - * Start up the serial port - */ - retval = ambauart_startup(info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - - if ((info->state->count == 1) && - (info->flags & ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == SERIAL_TYPE_NORMAL) - *tty->termios = info->state->normal_termios; - else - *tty->termios = info->state->callout_termios; - } -#ifdef CONFIG_SERIAL_AMBA_CONSOLE - if (ambauart_cons.cflag && ambauart_cons.index == line) { - tty->termios->c_cflag = ambauart_cons.cflag; - ambauart_cons.cflag = 0; - } -#endif - ambauart_change_speed(info, NULL); - info->session = current->session; - info->pgrp = current->pgrp; - return 0; -} - -int __init ambauart_init(void) -{ - int i; - - ambanormal_driver.magic = TTY_DRIVER_MAGIC; - ambanormal_driver.driver_name = "serial_amba"; - ambanormal_driver.name = SERIAL_AMBA_NAME; - ambanormal_driver.major = SERIAL_AMBA_MAJOR; - ambanormal_driver.minor_start = SERIAL_AMBA_MINOR; - ambanormal_driver.num = SERIAL_AMBA_NR; - ambanormal_driver.type = TTY_DRIVER_TYPE_SERIAL; - ambanormal_driver.subtype = SERIAL_TYPE_NORMAL; - ambanormal_driver.init_termios = tty_std_termios; - ambanormal_driver.init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL; - ambanormal_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; - ambanormal_driver.refcount = &ambauart_refcount; - ambanormal_driver.table = ambauart_table; - ambanormal_driver.termios = ambauart_termios; - ambanormal_driver.termios_locked = ambauart_termios_locked; - - ambanormal_driver.open = ambauart_open; - ambanormal_driver.close = ambauart_close; - ambanormal_driver.write = ambauart_write; - ambanormal_driver.put_char = ambauart_put_char; - ambanormal_driver.flush_chars = ambauart_flush_chars; - ambanormal_driver.write_room = ambauart_write_room; - ambanormal_driver.chars_in_buffer = ambauart_chars_in_buffer; - ambanormal_driver.flush_buffer = ambauart_flush_buffer; - ambanormal_driver.ioctl = ambauart_ioctl; - ambanormal_driver.throttle = ambauart_throttle; - ambanormal_driver.unthrottle = ambauart_unthrottle; - ambanormal_driver.send_xchar = ambauart_send_xchar; - ambanormal_driver.set_termios = ambauart_set_termios; - ambanormal_driver.stop = ambauart_stop; - ambanormal_driver.start = ambauart_start; - ambanormal_driver.hangup = ambauart_hangup; - ambanormal_driver.break_ctl = ambauart_break_ctl; - ambanormal_driver.wait_until_sent = ambauart_wait_until_sent; - ambanormal_driver.read_proc = NULL; - - /* - * The callout device is just like the normal device except for - * the major number and the subtype code. - */ - ambacallout_driver = ambanormal_driver; - ambacallout_driver.name = CALLOUT_AMBA_NAME; - ambacallout_driver.major = CALLOUT_AMBA_MAJOR; - ambacallout_driver.subtype = SERIAL_TYPE_CALLOUT; - ambacallout_driver.read_proc = NULL; - ambacallout_driver.proc_entry = NULL; - - if (tty_register_driver(&ambanormal_driver)) - panic("Couldn't register AMBA serial driver\n"); - if (tty_register_driver(&ambacallout_driver)) - panic("Couldn't register AMBA callout driver\n"); - - for (i = 0; i < SERIAL_AMBA_NR; i++) { - struct amba_state *state = amba_state + i; - state->line = i; - state->close_delay = 5 * HZ / 10; - state->closing_wait = 30 * HZ; - state->callout_termios = ambacallout_driver.init_termios; - state->normal_termios = ambanormal_driver.init_termios; - } - - return 0; -} - -__initcall(ambauart_init); - -#ifdef CONFIG_SERIAL_AMBA_CONSOLE -/************** console driver *****************/ - -/* - * This code is currently never used; console->read is never called. - * Therefore, although we have an implementation, we don't use it. - * FIXME: the "const char *s" should be fixed to "char *s" some day. - * (when the definition in include/linux/console.h is also fixed) - */ -#ifdef used_and_not_const_char_pointer -static int ambauart_console_read(struct console *co, const char *s, u_int count) -{ - struct amba_port *port = &amba_ports[co->index]; - unsigned int status; - char *w; - int c; -#if DEBUG - printk("ambauart_console_read() called\n"); -#endif - - c = 0; - w = s; - while (c < count) { - status = UART_GET_FR(port); - if (UART_RX_DATA(status)) { - *w++ = UART_GET_CHAR(port); - c++; - } else { - // nothing more to get, return - return c; - } - } - // return the count - return c; -} -#endif - -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - * - * The console must be locked when we get here. - */ -static void ambauart_console_write(struct console *co, const char *s, u_int count) -{ - struct amba_port *port = &amba_ports[co->index]; - unsigned int status, old_cr; - int i; - - /* - * First save the CR then disable the interrupts - */ - old_cr = UART_GET_CR(port); - UART_PUT_CR(port, AMBA_UARTCR_UARTEN); - - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, s[i]); - if (s[i] == '\n') { - do { - status = UART_GET_FR(port); - } while (!UART_TX_READY(status)); - UART_PUT_CHAR(port, '\r'); - } - } - - /* - * Finally, wait for transmitter to become empty - * and restore the TCR - */ - do { - status = UART_GET_FR(port); - } while (status & AMBA_UARTFR_BUSY); - UART_PUT_CR(port, old_cr); -} - -static kdev_t ambauart_console_device(struct console *c) -{ - return mk_kdev(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR + c->index); -} - -static int __init ambauart_console_setup(struct console *co, char *options) -{ - struct amba_port *port; - int baud = 38400; - int bits = 8; - int parity = 'n'; - u_int cflag = CREAD | HUPCL | CLOCAL; - u_int lcr_h, quot; - - if (co->index >= SERIAL_AMBA_NR) - co->index = 0; - - port = &amba_ports[co->index]; - - if (options) { - char *s = options; - baud = simple_strtoul(s, NULL, 10); - while (*s >= '0' && *s <= '9') - s++; - if (*s) parity = *s++; - if (*s) bits = *s - '0'; - } - - /* - * Now construct a cflag setting. - */ - switch (baud) { - case 1200: cflag |= B1200; break; - case 2400: cflag |= B2400; break; - case 4800: cflag |= B4800; break; - default: cflag |= B9600; baud = 9600; break; - case 19200: cflag |= B19200; break; - case 38400: cflag |= B38400; break; - case 57600: cflag |= B57600; break; - case 115200: cflag |= B115200; break; - } - switch (bits) { - case 7: cflag |= CS7; lcr_h = AMBA_UARTLCR_H_WLEN_7; break; - default: cflag |= CS8; lcr_h = AMBA_UARTLCR_H_WLEN_8; break; - } - switch (parity) { - case 'o': - case 'O': cflag |= PARODD; lcr_h |= AMBA_UARTLCR_H_PEN; break; - case 'e': - case 'E': cflag |= PARENB; lcr_h |= AMBA_UARTLCR_H_PEN | - AMBA_UARTLCR_H_EPS; break; - } - - co->cflag = cflag; - - if (port->fifosize > 1) - lcr_h |= AMBA_UARTLCR_H_FEN; - - quot = (port->uartclk / (16 * baud)) - 1; - - UART_PUT_LCRL(port, (quot & 0xff)); - UART_PUT_LCRM(port, (quot >> 8)); - UART_PUT_LCRH(port, lcr_h); - - /* we will enable the port as we need it */ - UART_PUT_CR(port, 0); - - return 0; -} - -static struct console ambauart_cons = -{ - name: SERIAL_AMBA_NAME, - write: ambauart_console_write, -#ifdef used_and_not_const_char_pointer - read: ambauart_console_read, -#endif - device: ambauart_console_device, - setup: ambauart_console_setup, - flags: CON_PRINTBUFFER, - index: -1, -}; - -void __init ambauart_console_init(void) -{ - register_console(&ambauart_cons); -} - -#endif /* CONFIG_SERIAL_AMBA_CONSOLE */ - -MODULE_LICENSE("GPL"); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 52ab887430e3..501ec0c753f3 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -545,6 +545,7 @@ void tty_vhangup(struct tty_struct * tty) #endif do_tty_hangup((void *) tty); } +EXPORT_SYMBOL(tty_vhangup); int tty_hung_up_p(struct file * filp) { diff --git a/drivers/ide/Config.help b/drivers/ide/Config.help index 74668ed23673..3375dee859dc 100644 --- a/drivers/ide/Config.help +++ b/drivers/ide/Config.help @@ -84,6 +84,16 @@ CONFIG_BLK_DEV_IDECS Support for outboard IDE disks, tape drives, and CD-ROM drives connected through a PCMCIA card. +CONFIG_ATAPI + If you wish to enable basic support for devices attached to the system + through the ATA interface, and which are using using the ATAPI protocol + (CD-ROM, CD-RW, DVD, DVD-RW, LS120, ZIP, ...), say Y. + + If you want to compile the driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called atapi.o. + CONFIG_BLK_DEV_IDECD If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is a newer protocol used by IDE CD-ROM and TAPE drives, similar to the diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in index f2c8fe680de1..5a48bc9a7b78 100644 --- a/drivers/ide/Config.in +++ b/drivers/ide/Config.in @@ -1,40 +1,37 @@ # -# IDE ATA ATAPI Block device driver configuration +# ATA/ATAPI block device driver configuration # -# Andre Hedrick <andre@linux-ide.org> -# -mainmenu_option next_comment -comment 'ATA and ATAPI Block devices' - -dep_tristate 'Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support' CONFIG_BLK_DEV_IDE $CONFIG_IDE -comment 'Please see Documentation/ide.txt for help/info on IDE drives' +dep_tristate 'Enhanced ATA/ATAPI device (disk,cdrom,...) support' CONFIG_BLK_DEV_IDE $CONFIG_IDE if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then dep_bool ' Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE $CONFIG_X86 define_bool CONFIG_BLK_DEV_HD $CONFIG_BLK_DEV_HD_IDE - dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE - dep_mbool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK - dep_mbool ' Auto-Geometry Resizing support' CONFIG_IDEDISK_STROKE $CONFIG_BLK_DEV_IDEDISK - dep_tristate ' PCMCIA IDE support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA - dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE - dep_tristate ' Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE - dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI + dep_tristate ' ATA disk support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE + dep_bool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK + dep_bool ' Auto-Geometry Resizing support' CONFIG_IDEDISK_STROKE $CONFIG_BLK_DEV_IDEDISK + + dep_tristate ' ATAPI device support (CD-ROM, floppy)' CONFIG_ATAPI $CONFIG_BLK_DEV_IDE + dep_tristate ' CD-ROM support' CONFIG_BLK_DEV_IDECD $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE + dep_tristate ' Tape support' CONFIG_BLK_DEV_IDETAPE $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE + dep_tristate ' Floppy support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE + dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_ATAPI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI + + dep_tristate ' PCMCIA/CardBus support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA - comment 'ATA host chip set support' - dep_bool ' CMD640 chip set bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86 + comment 'ATA host controller support' + dep_bool ' RZ1000 bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86 + dep_bool ' CMD640 bugfix/support' CONFIG_BLK_DEV_CMD640 $CONFIG_X86 dep_bool ' CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED $CONFIG_BLK_DEV_CMD640 dep_bool ' ISA-PNP support' CONFIG_BLK_DEV_ISAPNP $CONFIG_ISAPNP - if [ "$CONFIG_PCI" = "y" ]; then - dep_bool ' RZ1000 chip set bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86 - comment ' PCI host chip set support' - dep_bool ' Boot off-board chip sets first support' CONFIG_BLK_DEV_OFFBOARD $CONFIG_PCI - dep_bool ' Sharing PCI ATA interrupts support' CONFIG_IDEPCI_SHARE_IRQ $CONFIG_PCI + if [ "$CONFIG_PCI" != "n" ]; then + comment ' PCI host controller support' + dep_bool ' Boot off-board controllers first' CONFIG_BLK_DEV_OFFBOARD $CONFIG_PCI + dep_bool ' Sharing PCI ATA interrupts' CONFIG_IDEPCI_SHARE_IRQ $CONFIG_PCI dep_bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_PCI dep_bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO $CONFIG_BLK_DEV_IDEDMA_PCI dep_bool ' Enable DMA only for disks ' CONFIG_IDEDMA_ONLYDISK $CONFIG_IDEDMA_PCI_AUTO define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PCI - dep_bool ' ATA tagged command queueing (DANGEROUS)' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL + dep_bool ' Tagged command queueing (DANGEROUS)' CONFIG_BLK_DEV_IDE_TCQ $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL dep_bool ' TCQ on by default' CONFIG_BLK_DEV_IDE_TCQ_DEFAULT $CONFIG_BLK_DEV_IDE_TCQ if [ "$CONFIG_BLK_DEV_IDE_TCQ" != "n" ]; then int ' Default queue depth' CONFIG_BLK_DEV_IDE_TCQ_DEPTH 32 @@ -110,7 +107,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then fi # assume no ISA -> also no VLB - dep_bool ' Other ISA/VLB IDE chipset support' CONFIG_IDE_CHIPSETS $CONFIG_ISA + dep_bool ' ISA/VLB IDE chipset support' CONFIG_IDE_CHIPSETS $CONFIG_ISA if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then comment 'Note: most of these also require special kernel boot parameters' bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX @@ -122,15 +119,13 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then dep_tristate ' QDI QD65xx support' CONFIG_BLK_DEV_QD65XX $CONFIG_BLK_DEV_IDE bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672 fi - if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" -o \ - "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" -o \ - "$CONFIG_BLK_DEV_IDEDMA_ICS" = "y" ]; then + if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" != "n" -o \ + "$CONFIG_BLK_DEV_IDEDMA_PMAC" != "n" -o \ + "$CONFIG_BLK_DEV_IDEDMA_ICS" != "n" ]; then bool ' IGNORE word93 Validation BITS' CONFIG_IDEDMA_IVB fi - - define_bool CONFIG_ATAPI y else - bool 'Old hard disk (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY + bool 'Old disk only (MFM/RLL/IDE) driver' CONFIG_BLK_DEV_HD_ONLY define_bool CONFIG_BLK_DEV_HD $CONFIG_BLK_DEV_HD_ONLY fi @@ -142,8 +137,6 @@ else define_bool CONFIG_IDEDMA_AUTO n fi -dep_tristate 'Support for IDE Raid controllers (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL -dep_tristate ' Support Promise software RAID (Fasttrak(tm)) (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID -dep_tristate ' Highpoint 370 software RAID (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID - -endmenu +dep_tristate 'Support for software RAID controllers (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL +dep_tristate ' Support Promise (Fasttrak(tm)) (EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_PDC $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID +dep_tristate ' Highpoint 370 EXPERIMENTAL)' CONFIG_BLK_DEV_ATARAID_HPT $CONFIG_BLK_DEV_IDE $CONFIG_EXPERIMENTAL $CONFIG_BLK_DEV_ATARAID diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 010311bd8fec..57aaeb7a3ce8 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_BLK_DEV_HD) += hd.o obj-$(CONFIG_BLK_DEV_IDE) += ide-mod.o obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o -# obj-$(CONFIG_ATAPI) += atapi.o +obj-$(CONFIG_ATAPI) += atapi.o obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy.o @@ -69,6 +69,6 @@ obj-$(CONFIG_BLK_DEV_ATARAID_PDC) += pdcraid.o obj-$(CONFIG_BLK_DEV_ATARAID_HPT) += hptraid.o ide-mod-objs := device.o ide-taskfile.o main.o ide.o probe.o \ - ioctl.o atapi.o ata-timing.o $(ide-obj-y) + ioctl.o ata-timing.o $(ide-obj-y) include $(TOPDIR)/Rules.make diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c index d2dca5e1a1a4..468a4b788644 100644 --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c @@ -42,10 +42,11 @@ #include <linux/blkdev.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #define AEC_DRIVE_TIMING 0x40 @@ -167,7 +168,7 @@ static void aec62xx_tune_drive(struct ata_device *drive, unsigned char pio) return; } - aec_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5)); + aec_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5)); } #ifdef CONFIG_BLK_DEV_IDEDMA diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c index 33f175c92e0b..9d2e97c47d36 100644 --- a/drivers/ide/ali14xx.c +++ b/drivers/ide/ali14xx.c @@ -37,12 +37,13 @@ #include <linux/types.h> #include <linux/kernel.h> -#include <linux/ide.h> #include <linux/init.h> +#include <linux/hdreg.h> +#include <linux/ide.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" /* port addresses for auto-detection */ #define ALI_NUM_PORTS 4 diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index f8422ad5e897..e862b5c98dfd 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -26,30 +26,30 @@ #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" -static byte m5229_revision; -static byte chip_is_1543c_e; +static u8 m5229_revision; +static int chip_is_1543c_e; static struct pci_dev *isa_dev; -static void ali15x3_tune_drive(struct ata_device *drive, byte pio) +static void ali15x3_tune_drive(struct ata_device *drive, u8 pio) { struct ata_timing *t; struct ata_channel *hwif = drive->channel; struct pci_dev *dev = hwif->pci_dev; int s_time, a_time, c_time; - byte s_clc, a_clc, r_clc; + u8 s_clc, a_clc, r_clc; unsigned long flags; int port = hwif->unit ? 0x5c : 0x58; int portFIFO = hwif->unit ? 0x55 : 0x54; - byte cd_dma_fifo = 0; + u8 cd_dma_fifo = 0; if (pio == 255) pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); else - pio = XFER_PIO_0 + min_t(byte, pio, 4); + pio = XFER_PIO_0 + min_t(u8, pio, 4); t = ata_timing_data(pio); @@ -100,15 +100,15 @@ static void ali15x3_tune_drive(struct ata_device *drive, byte pio) local_irq_restore(flags); } -static int ali15x3_tune_chipset(struct ata_device *drive, byte speed) +static int ali15x3_tune_chipset(struct ata_device *drive, u8 speed) { struct pci_dev *dev = drive->channel->pci_dev; - byte unit = (drive->select.b.unit & 0x01); - byte tmpbyte = 0x00; - int m5229_udma = drive->channel->unit ? 0x57 : 0x56; + u8 unit = (drive->select.b.unit & 0x01); + u8 tmpbyte = 0x00; + int m5229_udma = drive->channel->unit ? 0x57 : 0x56; if (speed < XFER_UDMA_0) { - byte ultra_enable = (unit) ? 0x7f : 0xf7; + u8 ultra_enable = unit ? 0x7f : 0xf7; /* * clear "ultra enable" bit */ @@ -135,7 +135,7 @@ static int ali15x3_tune_chipset(struct ata_device *drive, byte speed) pci_write_config_byte(dev, 0x4b, tmpbyte); } } -#endif /* CONFIG_BLK_DEV_IDEDMA */ +#endif return ide_config_drive_speed(drive, speed); } @@ -212,10 +212,10 @@ static unsigned int __init ali15x3_ata66_check(struct ata_channel *hwif) { struct pci_dev *dev = hwif->pci_dev; unsigned int ata66 = 0; - byte cable_80_pin[2] = { 0, 0 }; + u8 cable_80_pin[2] = { 0, 0 }; unsigned long flags; - byte tmpbyte; + u8 tmpbyte; local_irq_save(flags); @@ -305,8 +305,8 @@ static unsigned int __init ali15x3_ata66_check(struct ata_channel *hwif) static void __init ali15x3_init_channel(struct ata_channel *hwif) { #ifndef CONFIG_SPARC64 - byte ideic, inmir; - byte irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, + u8 ideic, inmir; + u8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; hwif->irq = hwif->unit ? 15 : 14; diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 485f31e3f4cb..5e2e1e27e850 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -42,11 +42,12 @@ #include <linux/blkdev.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #define AMD_IDE_ENABLE (0x00 + amd_config->base) @@ -171,7 +172,7 @@ static void amd74xx_tune_drive(struct ata_device *drive, u8 pio) return; } - amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5)); + amd_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5)); } #ifdef CONFIG_BLK_DEV_IDEDMA diff --git a/drivers/ide/ata-timing.c b/drivers/ide/ata-timing.c index 01a312044242..f713a15b047a 100644 --- a/drivers/ide/ata-timing.c +++ b/drivers/ide/ata-timing.c @@ -23,7 +23,10 @@ */ #include <linux/kernel.h> -#include "ata-timing.h" +#include <linux/hdreg.h> +#include <linux/ide.h> + +#include "timing.h" /* * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds). These were taken diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c index 0c5f45be113a..e8325b9e7690 100644 --- a/drivers/ide/cmd640.c +++ b/drivers/ide/cmd640.c @@ -106,13 +106,13 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> +#include <linux/init.h> #include <linux/hdreg.h> #include <linux/ide.h> -#include <linux/init.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" /* * This flag is set in ide.c by the parameter: ide0=cmd640_vlb @@ -200,7 +200,7 @@ static struct ata_device *cmd_drives[4]; * Interface to access cmd640x registers */ static unsigned int cmd640_key; -static void (*put_cmd640_reg)(unsigned short reg, byte val); +static void (*put_cmd640_reg)(unsigned short reg, u8 val); static u8 (*get_cmd640_reg)(unsigned short reg); /* @@ -214,17 +214,19 @@ static unsigned int cmd640_chip_version; * Therefore, we must use direct IO instead. */ +/* This is broken, but no more so than the old code.. */ +static spinlock_t cmd640_lock = SPIN_LOCK_UNLOCKED; + /* PCI method 1 access */ -static void put_cmd640_reg_pci1 (unsigned short reg, byte val) +static void put_cmd640_reg_pci1 (unsigned short reg, u8 val) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&cmd640_lock, flags); outl_p((reg & 0xfc) | cmd640_key, 0xcf8); outb_p(val, (reg & 3) | 0xcfc); - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); } static u8 get_cmd640_reg_pci1 (unsigned short reg) @@ -232,11 +234,10 @@ static u8 get_cmd640_reg_pci1 (unsigned short reg) u8 b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&cmd640_lock, flags); outl_p((reg & 0xfc) | cmd640_key, 0xcf8); b = inb_p((reg & 3) | 0xcfc); - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return b; } @@ -246,12 +247,11 @@ static void put_cmd640_reg_pci2 (unsigned short reg, u8 val) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&cmd640_lock, flags); outb_p(0x10, 0xcf8); outb_p(val, cmd640_key + reg); outb_p(0, 0xcf8); - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); } static u8 get_cmd640_reg_pci2 (unsigned short reg) @@ -259,12 +259,11 @@ static u8 get_cmd640_reg_pci2 (unsigned short reg) u8 b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&cmd640_lock, flags); outb_p(0x10, 0xcf8); b = inb_p(cmd640_key + reg); outb_p(0, 0xcf8); - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return b; } @@ -274,11 +273,10 @@ static void put_cmd640_reg_vlb (unsigned short reg, u8 val) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&cmd640_lock, flags); outb_p(reg, cmd640_key); outb_p(val, cmd640_key + 4); - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); } static u8 get_cmd640_reg_vlb (unsigned short reg) @@ -286,11 +284,10 @@ static u8 get_cmd640_reg_vlb (unsigned short reg) u8 b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&cmd640_lock, flags); outb_p(reg, cmd640_key); b = inb_p(cmd640_key + 4); - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return b; } @@ -367,8 +364,7 @@ static int __init secondary_port_responding (void) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&cmd640_lock, flags); outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ udelay(100); @@ -376,11 +372,11 @@ static int __init secondary_port_responding (void) outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ udelay(100); if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return 0; /* nothing responded */ } } - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); return 1; /* success */ } @@ -461,8 +457,7 @@ static void set_prefetch_mode (unsigned int index, int mode) u8 b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&cmd640_lock, flags); b = get_cmd640_reg(reg); if (mode) { /* want prefetch on? */ # if CMD640_PREFETCH_MASKS @@ -478,7 +473,7 @@ static void set_prefetch_mode (unsigned int index, int mode) b |= prefetch_masks[index]; /* disable prefetch */ } put_cmd640_reg(reg, b); - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); } /* @@ -579,8 +574,7 @@ static void program_drive_counts (unsigned int index) /* * Now that everything is ready, program the new timings */ - save_flags (flags); - cli(); + spin_lock(&cmd640_lock, flags); /* * Program the address_setup clocks into ARTTIM reg, * and then the active/recovery counts into the DRWTIM reg @@ -589,7 +583,7 @@ static void program_drive_counts (unsigned int index) setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f; put_cmd640_reg(arttim_regs[index], setup_count); put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); - restore_flags(flags); + spin_unlock_irqrestore(&cmd640_lock, flags); } /* @@ -647,7 +641,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle /* * Drive PIO mode selection: */ -static void cmd640_tune_drive(struct ata_device *drive, byte mode_wanted) +static void cmd640_tune_drive(struct ata_device *drive, u8 mode_wanted) { u8 b; struct ata_timing *t; diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index 188aeac9074c..0d6c087b361f 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -18,13 +18,13 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/delay.h> -#include <linux/hdreg.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #define CMD_DEBUG 0 @@ -81,8 +81,8 @@ * Registers and masks for easy access by drive index: */ #if 0 -static byte prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; -static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; +static u8 prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; +static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; #endif /* @@ -93,15 +93,15 @@ static void program_drive_counts(struct ata_device *drive, int setup_count, int { unsigned long flags; struct ata_device *drives = drive->channel->drives; - byte temp_b; - static const byte setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; - static const byte recovery_counts[] = + u8 temp_b; + static const u8 setup_counts[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0}; + static const u8 recovery_counts[] = {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0}; - static const byte arttim_regs[2][2] = { + static const u8 arttim_regs[2][2] = { { ARTTIM0, ARTTIM1 }, { ARTTIM23, ARTTIM23 } }; - static const byte drwtim_regs[2][2] = { + static const u8 drwtim_regs[2][2] = { { DRWTIM0, DRWTIM1 }, { DRWTIM2, DRWTIM3 } }; @@ -142,11 +142,11 @@ static void program_drive_counts(struct ata_device *drive, int setup_count, int */ (void) pci_read_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave], &temp_b); (void) pci_write_config_byte(drive->channel->pci_dev, arttim_regs[channel][slave], - ((byte) setup_count) | (temp_b & 0x3f)); + ((u8) setup_count) | (temp_b & 0x3f)); (void) pci_write_config_byte(drive->channel->pci_dev, drwtim_regs[channel][slave], - (byte) ((active_count << 4) | recovery_count)); - cmdprintk ("Write %x to %x\n", ((byte) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]); - cmdprintk ("Write %x to %x\n", (byte) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]); + (u8) ((active_count << 4) | recovery_count)); + cmdprintk ("Write %x to %x\n", ((u8) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]); + cmdprintk ("Write %x to %x\n", (u8) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]); local_irq_restore(flags); } @@ -405,7 +405,7 @@ static int cmd64x_tune_chipset(struct ata_device *drive, u8 speed) return ide_config_drive_speed(drive, speed); } -static int cmd680_tune_chipset(struct ata_device *drive, byte speed) +static int cmd680_tune_chipset(struct ata_device *drive, u8 speed) { struct ata_channel *hwif = drive->channel; struct pci_dev *dev = hwif->pci_dev; @@ -520,9 +520,9 @@ static int cmd64x_udma_stop(struct ata_device *drive) dma_stat = inb(dma_base+2); /* get DMA status */ outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ if (jack_slap) { - byte dma_intr = 0; - byte dma_mask = (ch->unit) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; - byte dma_reg = (ch->unit) ? ARTTIM2 : CFR; + u8 dma_intr = 0; + u8 dma_mask = (ch->unit) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; + u8 dma_reg = (ch->unit) ? ARTTIM2 : CFR; (void) pci_read_config_byte(dev, dma_reg, &dma_intr); /* * DAMN BMIDE is not connected to PCI space! diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c index b761e7896385..89ee79cfcda3 100644 --- a/drivers/ide/cs5530.c +++ b/drivers/ide/cs5530.c @@ -20,22 +20,22 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> -#include <linux/hdreg.h> #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> #include <asm/irq.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" /* * Set a new transfer mode at the drive */ -int cs5530_set_xfer_mode(struct ata_device *drive, byte mode) +int cs5530_set_xfer_mode(struct ata_device *drive, u8 mode) { int error = 0; @@ -67,7 +67,7 @@ static unsigned int cs5530_pio_timings[2][5] = * The ide_init_cs5530() routine guarantees that all drives * will have valid default PIO timings set up before we get here. */ -static void cs5530_tuneproc(struct ata_device *drive, byte pio) /* pio=255 means "autotune" */ +static void cs5530_tuneproc(struct ata_device *drive, u8 pio) { struct ata_channel *hwif = drive->channel; unsigned int format, basereg = CS5530_BASEREG(hwif); @@ -75,7 +75,7 @@ static void cs5530_tuneproc(struct ata_device *drive, byte pio) /* pio=255 means if (pio == 255) pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); else - pio = XFER_PIO_0 + min_t(byte, pio, 4); + pio = XFER_PIO_0 + min_t(u8, pio, 4); if (!cs5530_set_xfer_mode(drive, pio)) { format = (inl(basereg+4) >> 31) & 1; @@ -206,7 +206,7 @@ static unsigned int __init pci_init_cs5530(struct pci_dev *dev) unsigned short pcicmd = 0; unsigned long flags; - pci_for_each_dev (dev) { + pci_for_each_dev(dev) { if (dev->vendor == PCI_VENDOR_ID_CYRIX) { switch (dev->device) { case PCI_DEVICE_ID_CYRIX_PCI_MASTER: @@ -256,7 +256,7 @@ static unsigned int __init pci_init_cs5530(struct pci_dev *dev) */ pci_write_config_byte(master_0, 0x40, 0x1e); - /* + /* * Set max PCI burst size (16-bytes seems to work best): * 16bytes: set bit-1 at 0x41 (reg value of 0x16) * all others: clear bit-1 at 0x41, and do: diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c index 297b55d18ce2..acf889aad4dd 100644 --- a/drivers/ide/cy82c693.c +++ b/drivers/ide/cy82c693.c @@ -47,11 +47,12 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" /* the current version */ @@ -141,7 +142,7 @@ static u8 calc_clk(int time, int bus_speed) * for mode 3 and 4 drives 8 and 16-bit timings are the same * */ -/* FIXME: use generic ata-timings library --bkz */ +/* FIXME: use generic timings library --bkz */ static void compute_clocks(u8 pio, pio_clocks_t *p_pclk) { struct ata_timing *t; @@ -186,8 +187,8 @@ static void compute_clocks(u8 pio, pio_clocks_t *p_pclk) */ static void cy82c693_dma_enable(struct ata_device *drive, int mode, int single) { - byte index; - byte data; + u8 index; + u8 data; if (mode>2) /* make sure we set a valid mode */ mode = 2; @@ -206,7 +207,7 @@ static void cy82c693_dma_enable(struct ata_device *drive, int mode, int single) printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, drive->channel->unit, drive->select.b.unit, (data&0x3), ((data>>2)&1)); #endif - data = (byte)mode|(byte)(single<<2); + data = (u8) mode | (u8) (single << 2); OUT_BYTE(index, CY82_INDEX_PORT); OUT_BYTE(data, CY82_DATA_PORT); @@ -271,7 +272,7 @@ static int cy82c693_udma_setup(struct ata_device *drive, int map) /* * tune ide drive - set PIO mode */ -static void cy82c693_tune_drive(struct ata_device *drive, byte pio) +static void cy82c693_tune_drive(struct ata_device *drive, u8 pio) { struct ata_channel *hwif = drive->channel; struct pci_dev *dev = hwif->pci_dev; diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c index 45cd4d9c7f81..8d947231d2ab 100644 --- a/drivers/ide/dtc2278.c +++ b/drivers/ide/dtc2278.c @@ -9,13 +9,13 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> +#include <linux/init.h> #include <linux/hdreg.h> #include <linux/ide.h> -#include <linux/init.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" /* * Changing this #undef to #define may solve start up problems in some systems. @@ -66,7 +66,7 @@ static void sub22 (char b, char c) } } -static void tune_dtc2278(struct ata_device *drive, byte pio) +static void tune_dtc2278(struct ata_device *drive, u8 pio) { unsigned long flags; diff --git a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c index 9f5d08d42f2c..8fb181800602 100644 --- a/drivers/ide/hpt34x.c +++ b/drivers/ide/hpt34x.c @@ -21,16 +21,16 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> -#include <linux/hdreg.h> #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> #include <asm/irq.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #define HPT343_DEBUG_DRIVE_INFO 0 diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index a24e170bee2e..c2204b5b7ef4 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -53,18 +53,17 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> -#include <linux/hdreg.h> - #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/irq.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" diff --git a/drivers/ide/hptraid.c b/drivers/ide/hptraid.c index 43b45c6e06eb..d4742834b864 100644 --- a/drivers/ide/hptraid.c +++ b/drivers/ide/hptraid.c @@ -105,10 +105,10 @@ static int hptraid_ioctl(struct inode *inode, struct file *file, if (!loc) return -EINVAL; val = 255; - if (put_user(val, (byte *) & loc->heads)) + if (put_user(val, (u8 *) & loc->heads)) return -EFAULT; val = 63; - if (put_user(val, (byte *) & loc->sectors)) + if (put_user(val, (u8 *) & loc->sectors)) return -EFAULT; bios_cyl = raid[minor].sectors / 63 / 255; if (put_user diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c index 55f39b8c506e..34207cd5d911 100644 --- a/drivers/ide/ht6560b.c +++ b/drivers/ide/ht6560b.c @@ -38,13 +38,13 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> +#include <linux/init.h> #include <linux/hdreg.h> #include <linux/ide.h> -#include <linux/init.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" /* #define DEBUG */ /* remove comments for DEBUG messages */ @@ -61,7 +61,7 @@ * bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?) */ #define HT_CONFIG_PORT 0x3e6 -#define HT_CONFIG(drivea) (byte)(((drivea)->drive_data & 0xff00) >> 8) +#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8) /* * FIFO + PREFETCH (both a/b-model) */ @@ -107,7 +107,7 @@ * Active Time for each drive. Smaller value gives higher speed. * In case of failures you should probably fall back to a higher value. */ -#define HT_TIMING(drivea) (byte)((drivea)->drive_data & 0x00ff) +#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff) #define HT_TIMING_DEFAULT 0xff /* @@ -194,7 +194,7 @@ static int __init try_to_init_ht6560b(void) return 1; } -static byte ht_pio2timings(struct ata_device *drive, byte pio) +static u8 ht_pio2timings(struct ata_device *drive, u8 pio) { int active_time, recovery_time; int active_cycles, recovery_cycles; @@ -204,7 +204,7 @@ static byte ht_pio2timings(struct ata_device *drive, byte pio) if (pio == 255) pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); else - pio = XFER_PIO_0 + min_t(byte, pio, 4); + pio = XFER_PIO_0 + min_t(u8, pio, 4); t = ata_timing_data(pio); @@ -233,7 +233,7 @@ static byte ht_pio2timings(struct ata_device *drive, byte pio) drive->name, pio - XFER_PIO_0, recovery_cycles, recovery_time, active_cycles, active_time); #endif - return (byte)((recovery_cycles << 4) | active_cycles); + return (u8)((recovery_cycles << 4) | active_cycles); } else { #ifdef DEBUG @@ -247,7 +247,7 @@ static byte ht_pio2timings(struct ata_device *drive, byte pio) /* * Enable/Disable so called prefetch mode */ -static void ht_set_prefetch(struct ata_device *drive, byte state) +static void ht_set_prefetch(struct ata_device *drive, u8 state) { unsigned long flags; int t = HT_PREFETCH_MODE << 8; @@ -274,10 +274,10 @@ static void ht_set_prefetch(struct ata_device *drive, byte state) #endif } -static void tune_ht6560b(struct ata_device *drive, byte pio) +static void tune_ht6560b(struct ata_device *drive, u8 pio) { unsigned long flags; - byte timing; + u8 timing; switch (pio) { case 8: /* set prefetch off */ diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index cd2af4ca8faa..a93846b806a6 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -377,7 +377,7 @@ icside_config_if(struct ata_device *drive, int xfer_mode) return on; } -static int icside_set_speed(struct ata_device *drive, byte speed) +static int icside_set_speed(struct ata_device *drive, u8 speed) { return icside_config_if(drive, speed); } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 166971c7307d..1e4dbbebcec7 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1716,7 +1716,7 @@ void msf_from_bcd (struct atapi_msf *msf) static inline -void lba_to_msf (int lba, byte *m, byte *s, byte *f) +void lba_to_msf(int lba, u8 *m, u8 *s, u8 *f) { lba += CD_MSF_OFFSET; lba &= 0xffffff; /* negative lbas use only 24 bits */ @@ -1728,7 +1728,7 @@ void lba_to_msf (int lba, byte *m, byte *s, byte *f) static inline -int msf_to_lba (byte m, byte s, byte f) +int msf_to_lba(u8 m, u8 s, u8 f) { return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET; } diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index dcd660ce6ce1..7f4ac20a5b5a 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -80,7 +80,7 @@ struct ide_cd_config_flags { __u8 close_tray : 1; /* can close the tray */ __u8 writing : 1; /* pseudo write in progress */ __u8 reserved : 3; - byte max_speed; /* Max speed of the drive */ + u8 max_speed; /* Max speed of the drive */ }; #define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags)) @@ -92,7 +92,7 @@ struct ide_cd_state_flags { __u8 door_locked : 1; /* We think that the drive door is locked. */ __u8 writing : 1; /* the drive is currently writing */ __u8 reserved : 4; - byte current_speed; /* Current speed of the drive */ + u8 current_speed; /* Current speed of the drive */ }; #define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags)) @@ -132,7 +132,7 @@ struct atapi_toc_header { } __attribute__((packed)); struct atapi_toc_entry { - byte reserved1; + u8 reserved1; #if defined(__BIG_ENDIAN_BITFIELD) __u8 adr : 4; __u8 control : 4; @@ -142,8 +142,8 @@ struct atapi_toc_entry { #else #error "Please fix <asm/byteorder.h>" #endif - byte track; - byte reserved2; + u8 track; + u8 reserved2; union { unsigned lba; struct atapi_msf msf; @@ -176,8 +176,8 @@ struct atapi_cdrom_subchnl { #else #error "Please fix <asm/byteorder.h>" #endif - u_char acdsc_trk; - u_char acdsc_ind; + u8 acdsc_trk; + u8 acdsc_ind; union { struct atapi_msf msf; int lba; @@ -207,7 +207,7 @@ struct atapi_capabilities_page { #error "Please fix <asm/byteorder.h>" #endif - byte page_length; + u8 page_length; #if defined(__BIG_ENDIAN_BITFIELD) __u8 reserved2 : 2; @@ -435,8 +435,8 @@ struct atapi_mechstat_header { #error "Please fix <asm/byteorder.h>" #endif - byte curlba[3]; - byte nslots; + u8 curlba[3]; + u8 nslots; __u16 slot_tablelen; }; @@ -454,7 +454,7 @@ struct atapi_slot { #error "Please fix <asm/byteorder.h>" #endif - byte reserved2[3]; + u8 reserved2[3]; }; struct atapi_changer_info { @@ -514,13 +514,11 @@ struct cdrom_info { #define ABORTED_COMMAND 0x0b #define MISCOMPARE 0x0e - - /* This stuff should be in cdrom.h, since it is now generic... */ #if VERBOSE_IDE_CD_ERRORS /* The generic packet command opcodes for CD/DVD Logical Units, - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ const struct { unsigned short packet_command; const char * const text; diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index cd3fd43b4b23..4070de3d2832 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -24,8 +24,9 @@ #include <linux/genhd.h> #include <linux/slab.h> #include <linux/delay.h> -#include <linux/ide.h> #include <linux/buffer_head.h> /* for invalidate_bdev() */ +#include <linux/hdreg.h> +#include <linux/ide.h> #include <asm/byteorder.h> #include <asm/irq.h> diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index a05c8b00c9ce..e346d1d12b58 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -245,8 +245,8 @@ typedef struct { /* * Last error information */ - byte sense_key, asc, ascq; - byte ticks; /* delay this long before sending packet command */ + u8 sense_key, asc, ascq; + u8 ticks; /* delay this long before sending packet command */ int progress_indication; /* diff --git a/drivers/ide/ide-m8xx.c b/drivers/ide/ide-m8xx.c index a04398c9e12c..c842699af329 100644 --- a/drivers/ide/ide-m8xx.c +++ b/drivers/ide/ide-m8xx.c @@ -29,8 +29,9 @@ #include <linux/init.h> #include <linux/blk.h> #include <linux/ioport.h> -#include <linux/ide.h> #include <linux/bootmem.h> +#include <linux/hdreg.h> +#include <linux/ide.h> #include <asm/mpc8xx.h> #include <asm/mmu.h> @@ -43,7 +44,7 @@ #include <asm/machdep.h> #include <asm/irq.h> -#include "ata-timing.h" +#include "timing.h" static int identify (volatile unsigned char *p); static void print_fixed (volatile unsigned char *p); @@ -51,7 +52,7 @@ static void print_funcid (int func); static int check_ide_device (unsigned long base); static int ide_interrupt_ack(struct ata_channel *); -static void m8xx_ide_tuneproc(struct ata_device *drive, byte pio); +static void m8xx_ide_tuneproc(struct ata_device *drive, u8 pio); typedef struct ide_ioport_desc { unsigned long base_off; /* Offset to PCMCIA memory */ @@ -437,7 +438,7 @@ void m8xx_ide_init_hwif_ports (hw_regs_t *hw, /* Calculate PIO timings */ static void -m8xx_ide_tuneproc(struct ata_device *drive, byte pio) +m8xx_ide_tuneproc(struct ata_device *drive, u8 pio) { #if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT) volatile pcmconf8xx_t *pcmp; diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c index e9076cb4869c..a9173ffad2dd 100644 --- a/drivers/ide/ide-pci.c +++ b/drivers/ide/ide-pci.c @@ -20,6 +20,7 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> @@ -30,7 +31,7 @@ /* * This is the list of registered PCI chipset driver data structures. */ -static struct ata_pci_device *ata_pci_device_list = NULL; +static struct ata_pci_device *ata_pci_device_list; /* = NULL */ /* * This function supplies the data necessary to detect the particular chipset. diff --git a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c index 5a52c4fa4169..4630dbc4fe5d 100644 --- a/drivers/ide/ide-pmac.c +++ b/drivers/ide/ide-pmac.c @@ -34,8 +34,9 @@ #include <linux/jiffies.h> #include <linux/init.h> #include <linux/delay.h> -#include <linux/ide.h> #include <linux/pci.h> +#include <linux/hdreg.h> +#include <linux/ide.h> #include <asm/prom.h> #include <asm/io.h> @@ -51,7 +52,7 @@ #include <linux/adb.h> #include <linux/pmu.h> #endif -#include "ata-timing.h" +#include "timing.h" #undef IDE_PMAC_DEBUG @@ -262,8 +263,8 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq); static int pmac_udma_irq_status(struct ata_device *drive); static int pmac_udma_setup(struct ata_device *drive, int map); static int pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, int wr); -static int pmac_ide_tune_chipset(struct ata_device *drive, byte speed); -static void pmac_ide_tuneproc(struct ata_device *drive, byte pio); +static int pmac_ide_tune_chipset(struct ata_device *drive, u8 speed); +static void pmac_ide_tuneproc(struct ata_device *drive, u8 pio); static void pmac_ide_selectproc(struct ata_device *drive); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ @@ -457,7 +458,7 @@ out: /* Calculate PIO timings */ static void __pmac -pmac_ide_tuneproc(struct ata_device *drive, byte pio) +pmac_ide_tuneproc(struct ata_device *drive, u8 pio) { struct ata_timing *t; int i; @@ -472,7 +473,7 @@ pmac_ide_tuneproc(struct ata_device *drive, byte pio) if (pio == 255) pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); else - pio = XFER_PIO_0 + min_t(byte, pio, 4); + pio = XFER_PIO_0 + min_t(u8, pio, 4); t = ata_timing_data(pio); @@ -523,8 +524,7 @@ pmac_ide_tuneproc(struct ata_device *drive, byte pio) } #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC -static int __pmac -set_timings_udma(u32 *timings, byte speed) +static int __pmac set_timings_udma(u32 *timings, u8 speed) { unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks; @@ -546,7 +546,7 @@ set_timings_udma(u32 *timings, byte speed) } static int __pmac -set_timings_mdma(int intf_type, u32 *timings, byte speed, int drive_cycle_time) +set_timings_mdma(int intf_type, u32 *timings, u8 speed, int drive_cycle_time) { int cycleTime, accessTime, recTime; unsigned accessTicks, recTicks; @@ -659,7 +659,7 @@ set_timings_mdma(int intf_type, u32 *timings, byte speed, int drive_cycle_time) * our, normal mdma function is supposed to be more precise */ static int __pmac -pmac_ide_tune_chipset (struct ata_device *drive, byte speed) +pmac_ide_tune_chipset (struct ata_device *drive, u8 speed) { int intf = pmac_ide_find(drive); int unit = (drive->select.b.unit & 0x01); @@ -1211,8 +1211,8 @@ udma_bits_to_command(unsigned char bits, int high_speed) static int __pmac pmac_ide_mdma_enable(struct ata_device *drive, int idx) { - byte bits = drive->id->dma_mword & 0x07; - byte feature = dma_bits_to_command(bits); + u8 bits = drive->id->dma_mword & 0x07; + u8 feature = dma_bits_to_command(bits); u32 *timings; int drive_cycle_time; struct hd_driveid *id = drive->id; @@ -1249,8 +1249,8 @@ pmac_ide_mdma_enable(struct ata_device *drive, int idx) static int __pmac pmac_ide_udma_enable(struct ata_device *drive, int idx, int high_speed) { - byte bits = drive->id->dma_ultra & 0x1f; - byte feature = udma_bits_to_command(bits, high_speed); + u8 bits = drive->id->dma_ultra & 0x1f; + u8 feature = udma_bits_to_command(bits, high_speed); u32 *timings; int ret; diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 2c1fe77c4cb2..4dc463ba33fa 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -827,7 +827,7 @@ typedef struct { /* * Read position information */ - byte partition; + u8 partition; unsigned int first_frame_position; /* Current block */ unsigned int last_frame_position; unsigned int blocks_in_buffer; @@ -835,7 +835,7 @@ typedef struct { /* * Last error information */ - byte sense_key, asc, ascq; + u8 sense_key, asc, ascq; /* * Character device operation @@ -1237,7 +1237,7 @@ static int idetape_chrdev_present = 0; * DO NOT REMOVE, BUILDING A VERBOSE DEBUG SCHEME FOR ATAPI */ -char *idetape_sense_key_verbose (byte idetape_sense_key) +char *idetape_sense_key_verbose(u8 idetape_sense_key) { switch (idetape_sense_key) { default: { diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 230bad45d91d..0c9d9a41b390 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -49,12 +49,13 @@ #endif #include <linux/pci.h> #include <linux/delay.h> -#include <linux/ide.h> #include <linux/devfs_fs_kernel.h> #include <linux/reboot.h> #include <linux/cdrom.h> #include <linux/device.h> #include <linux/kmod.h> +#include <linux/hdreg.h> +#include <linux/ide.h> #include <asm/byteorder.h> #include <asm/irq.h> @@ -62,7 +63,7 @@ #include <asm/io.h> #include <asm/bitops.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #include "ioctl.h" @@ -258,7 +259,7 @@ static struct ata_bit_messages ata_error_msgs[] = { { MARK_ERR, MARK_ERR, "addr mark not found" } }; -static void dump_bits(struct ata_bit_messages *msgs, int nr, byte bits) +static void dump_bits(struct ata_bit_messages *msgs, int nr, u8 bits) { int i; int first = 1; @@ -516,49 +517,21 @@ void ide_stall_queue(struct ata_device *drive, unsigned long timeout) * Issue a new request. * Caller must have already done spin_lock_irqsave(channel->lock, ...) */ -static void do_request(struct ata_channel *channel) +void do_ide_request(request_queue_t *q) { - struct ata_channel *ch; - struct ata_device *drive = NULL; - unsigned int unit; - ide_startstop_t ret; + struct ata_channel *channel = q->queuedata; - local_irq_disable(); /* necessary paranoia */ - - /* - * Select the next device which will be serviced. This selects - * only between devices on the same channel, since everything - * else will be scheduled on the queue level. - */ - - for (unit = 0; unit < MAX_DRIVES; ++unit) { - struct ata_device *tmp = &channel->drives[unit]; - - if (!tmp->present) - continue; - - /* There are no requests pending for this device. - */ - if (blk_queue_empty(&tmp->queue)) - continue; - - - /* This device still wants to remain idle. - */ - if (tmp->sleep && time_after(tmp->sleep, jiffies)) - continue; + while (!test_and_set_bit(IDE_BUSY, channel->active)) { + struct ata_channel *ch; + struct ata_device *drive = NULL; + unsigned int unit; + ide_startstop_t ret; - /* Take this device, if there is no device choosen thus - * far or which is more urgent. + /* + * Select the next device which will be serviced. This selects + * only between devices on the same channel, since everything + * else will be scheduled on the queue level. */ - if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) { - if (!blk_queue_plugged(&tmp->queue)) - drive = tmp; - } - } - - if (!drive) { - unsigned long sleep = 0; for (unit = 0; unit < MAX_DRIVES; ++unit) { struct ata_device *tmp = &channel->drives[unit]; @@ -566,208 +539,229 @@ static void do_request(struct ata_channel *channel) if (!tmp->present) continue; - /* This device is sleeping and waiting to be serviced - * earlier than any other device we checked thus far. - */ - if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep))) - sleep = tmp->sleep; - } - - if (sleep) { - /* - * Take a short snooze, and then wake up again. Just - * in case there are big differences in relative - * throughputs.. don't want to hog the cpu too much. + /* There are no requests pending for this device. */ + if (blk_queue_empty(&tmp->queue)) + continue; - if (time_after(jiffies, sleep - WAIT_MIN_SLEEP)) - sleep = jiffies + WAIT_MIN_SLEEP; -#if 1 - if (timer_pending(&channel->timer)) - printk(KERN_ERR "%s: timer already active\n", __FUNCTION__); -#endif - set_bit(IDE_SLEEP, channel->active); - mod_timer(&channel->timer, sleep); - /* - * We purposely leave us busy while sleeping becouse we - * are prepared to handle the IRQ from it. - * - * FIXME: Make sure sleeping can't interferre with - * operations of other devices on the same channel. - */ - } else { - /* FIXME: use queue plugging instead of active to block - * upper layers from stomping on us */ - /* Ugly, but how can we sleep for the lock otherwise? - * */ - - ide_release_lock(&ide_irq_lock);/* for atari only */ - clear_bit(IDE_BUSY, channel->active); - - /* All requests are done. - * - * Disable IRQs from the last drive on this channel, to - * make sure that it wan't throw stones at us when we - * are not prepared to take them. + /* This device still wants to remain idle. */ + if (tmp->sleep && time_after(tmp->sleep, jiffies)) + continue; - if (channel->drive && !channel->drive->using_tcq) - ata_irq_enable(channel->drive, 0); + /* Take this device, if there is no device choosen thus + * far or which is more urgent. + */ + if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) { + if (!blk_queue_plugged(&tmp->queue)) + drive = tmp; + } } - return; - } + if (!drive) { + unsigned long sleep = 0; - /* Remember the last drive we where acting on. - */ - ch = drive->channel; - ch->drive = drive; + for (unit = 0; unit < MAX_DRIVES; ++unit) { + struct ata_device *tmp = &channel->drives[unit]; - /* Feed commands to a drive until it barfs. - */ - do { - struct request *rq = NULL; - sector_t block; - - /* Abort early if we can't queue another command. for non tcq, - * ata_can_queue is always 1 since we never get here unless the - * drive is idle. - */ + if (!tmp->present) + continue; - if (!ata_can_queue(drive)) { - if (!ata_pending_commands(drive)) { - clear_bit(IDE_BUSY, ch->active); - if (drive->using_tcq) - ata_irq_enable(drive, 0); + /* This device is sleeping and waiting to be serviced + * earlier than any other device we checked thus far. + */ + if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep))) + sleep = tmp->sleep; } - break; - } - drive->sleep = 0; + if (sleep) { + /* + * Take a short snooze, and then wake up again. Just + * in case there are big differences in relative + * throughputs.. don't want to hog the cpu too much. + */ + + if (time_after(jiffies, sleep - WAIT_MIN_SLEEP)) + sleep = jiffies + WAIT_MIN_SLEEP; +#if 1 + if (timer_pending(&channel->timer)) + printk(KERN_ERR "%s: timer already active\n", __FUNCTION__); +#endif + set_bit(IDE_SLEEP, channel->active); + mod_timer(&channel->timer, sleep); + + /* + * We purposely leave us busy while sleeping becouse we + * are prepared to handle the IRQ from it. + * + * FIXME: Make sure sleeping can't interferre with + * operations of other devices on the same channel. + */ + } else { + /* FIXME: use queue plugging instead of active to block + * upper layers from stomping on us */ + /* Ugly, but how can we sleep for the lock otherwise? + * */ + + ide_release_lock(&ide_irq_lock);/* for atari only */ + clear_bit(IDE_BUSY, channel->active); + + /* All requests are done. + * + * Disable IRQs from the last drive on this channel, to + * make sure that it wan't throw stones at us when we + * are not prepared to take them. + */ + + if (channel->drive && !channel->drive->using_tcq) + ata_irq_enable(channel->drive, 0); + } - if (test_bit(IDE_DMA, ch->active)) { - printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name); - break; + return; } - /* There's a small window between where the queue could be - * replugged while we are in here when using tcq (in which case - * the queue is probably empty anyways...), so check and leave - * if appropriate. When not using tcq, this is still a severe - * BUG! + /* Remember the last drive we where acting on. */ + ch = drive->channel; + ch->drive = drive; - if (blk_queue_plugged(&drive->queue)) { - BUG_ON(!drive->using_tcq); - break; - } + /* Feed commands to a drive until it barfs. + */ + do { + struct request *rq = NULL; + sector_t block; + + /* Abort early if we can't queue another command. for non tcq, + * ata_can_queue is always 1 since we never get here unless the + * drive is idle. + */ - if (!(rq = elv_next_request(&drive->queue))) { - if (!ata_pending_commands(drive)) { - clear_bit(IDE_BUSY, ch->active); - if (drive->using_tcq) - ata_irq_enable(drive, 0); + if (!ata_can_queue(drive)) { + if (!ata_pending_commands(drive)) { + clear_bit(IDE_BUSY, ch->active); + if (drive->using_tcq) + ata_irq_enable(drive, 0); + } + break; } - drive->rq = NULL; - break; - } + drive->sleep = 0; - /* If there are queued commands, we can't start a - * non-fs request (really, a non-queuable command) - * until the queue is empty. - */ - if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive)) - break; + if (test_bit(IDE_DMA, ch->active)) { + printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name); + break; + } - drive->rq = rq; + /* There's a small window between where the queue could be + * replugged while we are in here when using tcq (in which case + * the queue is probably empty anyways...), so check and leave + * if appropriate. When not using tcq, this is still a severe + * BUG! + */ - spin_unlock(ch->lock); - /* allow other IRQs while we start this request */ - local_irq_enable(); + if (blk_queue_plugged(&drive->queue)) { + BUG_ON(!drive->using_tcq); + break; + } - /* - * This initiates handling of a new I/O request. - */ + if (!(rq = elv_next_request(&drive->queue))) { + if (!ata_pending_commands(drive)) { + clear_bit(IDE_BUSY, ch->active); + if (drive->using_tcq) + ata_irq_enable(drive, 0); + } + drive->rq = NULL; + + break; + } + + /* If there are queued commands, we can't start a + * non-fs request (really, a non-queuable command) + * until the queue is empty. + */ + if (!(rq->flags & REQ_CMD) && ata_pending_commands(drive)) + break; + + drive->rq = rq; + + spin_unlock(ch->lock); + /* allow other IRQs while we start this request */ + local_irq_enable(); + + /* + * This initiates handling of a new I/O request. + */ - BUG_ON(!(rq->flags & REQ_STARTED)); + BUG_ON(!(rq->flags & REQ_STARTED)); #ifdef DEBUG - printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq); + printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq); #endif - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) - goto kill_rq; + /* bail early if we've exceeded max_failures */ + if (drive->max_failures && (drive->failures > drive->max_failures)) + goto kill_rq; - block = rq->sector; + block = rq->sector; - /* Strange disk manager remap. - */ - if (rq->flags & REQ_CMD) - if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY) - block += drive->sect0; + /* Strange disk manager remap. + */ + if (rq->flags & REQ_CMD) + if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY) + block += drive->sect0; - /* Yecch - this will shift the entire interval, possibly killing some - * innocent following sector. - */ - if (block == 0 && drive->remap_0_to_1 == 1) - block = 1; /* redirect MBR access to EZ-Drive partn table */ + /* Yecch - this will shift the entire interval, possibly killing some + * innocent following sector. + */ + if (block == 0 && drive->remap_0_to_1 == 1) + block = 1; /* redirect MBR access to EZ-Drive partn table */ - ata_select(drive, 0); - ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT, - WAIT_READY, rq); + ata_select(drive, 0); + ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT, + WAIT_READY, rq); - if (ret != ATA_OP_READY) { - printk(KERN_ERR "%s: drive not ready for command\n", drive->name); + if (ret != ATA_OP_READY) { + printk(KERN_ERR "%s: drive not ready for command\n", drive->name); - goto kill_rq; - } + goto kill_rq; + } - if (!ata_ops(drive)) { - printk(KERN_WARNING "%s: device type %d not supported\n", - drive->name, drive->type); - goto kill_rq; - } + if (!ata_ops(drive)) { + printk(KERN_WARNING "%s: device type %d not supported\n", + drive->name, drive->type); + goto kill_rq; + } - /* The normal way of execution is to pass and execute the request - * handler down to the device type driver. - */ + /* The normal way of execution is to pass and execute the request + * handler down to the device type driver. + */ - if (ata_ops(drive)->do_request) { - ret = ata_ops(drive)->do_request(drive, rq, block); - } else { + if (ata_ops(drive)->do_request) { + ret = ata_ops(drive)->do_request(drive, rq, block); + } else { kill_rq: - if (ata_ops(drive) && ata_ops(drive)->end_request) - ata_ops(drive)->end_request(drive, rq, 0); - else - ata_end_request(drive, rq, 0, 0); - ret = ATA_OP_FINISHED; + if (ata_ops(drive) && ata_ops(drive)->end_request) + ata_ops(drive)->end_request(drive, rq, 0); + else + ata_end_request(drive, rq, 0, 0); + ret = ATA_OP_FINISHED; - } - spin_lock_irq(ch->lock); - - /* continue if command started, so we are busy */ - } while (ret != ATA_OP_CONTINUES); - /* make sure the BUSY bit is set */ - /* FIXME: perhaps there is some place where we miss to set it? */ -// set_bit(IDE_BUSY, ch->active); -} - -void do_ide_request(request_queue_t *q) -{ - struct ata_channel *ch = q->queuedata; + } + spin_lock_irq(ch->lock); - while (!test_and_set_bit(IDE_BUSY, ch->active)) { - do_request(ch); + /* continue if command started, so we are busy */ + } while (ret != ATA_OP_CONTINUES); + /* make sure the BUSY bit is set */ + /* FIXME: perhaps there is some place where we miss to set it? */ + // set_bit(IDE_BUSY, ch->active); } } /* * This is our timeout function for all drive operations. But note that it can * also be invoked as a result of a "sleep" operation triggered by the - * mod_timer() call in do_request. + * mod_timer() call in do_ide_request. * * FIXME: This should take a drive context instead of a channel. * FIXME: This should not explicitly reenter the request handling engine. @@ -892,7 +886,8 @@ void ide_timer_expiry(unsigned long data) if (ret == ATA_OP_FINISHED) { /* Reenter the request handling engine. */ - do_request(ch); + clear_bit(IDE_BUSY, ch->active); + do_ide_request(&drive->queue); } } spin_unlock_irqrestore(ch->lock, flags); @@ -1049,9 +1044,10 @@ void ata_irq_request(int irq, void *data, struct pt_regs *regs) * another interrupt. */ - if (!ch->handler) - do_request(ch); - else + if (!ch->handler) { + clear_bit(IDE_BUSY, ch->active); + do_ide_request(&drive->queue); + } else printk("%s: %s: huh? expected NULL handler on exit\n", drive->name, __FUNCTION__); } diff --git a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c index 003b743b4772..d1b5f6f8d4ad 100644 --- a/drivers/ide/ioctl.c +++ b/drivers/ide/ioctl.c @@ -26,7 +26,7 @@ #include <linux/delay.h> #include <linux/cdrom.h> #include <linux/device.h> - +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/uaccess.h> @@ -230,13 +230,13 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY)) return -EINVAL; - if (put_user(drive->bios_head, (byte *) &loc->heads)) + if (put_user(drive->bios_head, (u8 *) &loc->heads)) return -EFAULT; - if (put_user(drive->bios_sect, (byte *) &loc->sectors)) + if (put_user(drive->bios_sect, (u8 *) &loc->sectors)) return -EFAULT; - if (put_user(bios_cyl, (unsigned short *) &loc->cylinders)) + if (put_user(bios_cyl, (u16 *) &loc->cylinders)) return -EFAULT; if (put_user((unsigned)drive->part[minor(inode->i_rdev)&PARTN_MASK].start_sect, @@ -283,18 +283,18 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned case HDIO_GET_NICE: - return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP | - drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP, + return put_user(drive->dsc_overlap | drive->atapi_overlap << 1, (long *) arg); case HDIO_SET_NICE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP)))) + if (arg != (arg & 1)) return -EPERM; - drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; + drive->dsc_overlap = arg & 1; + /* Only CD-ROM's and tapes support DSC overlap. */ if (drive->dsc_overlap && !(drive->type == ATA_ROM || drive->type == ATA_TAPE)) { drive->dsc_overlap = 0; diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c index 002dc1766fd0..838718764c4f 100644 --- a/drivers/ide/it8172.c +++ b/drivers/ide/it8172.c @@ -33,16 +33,15 @@ #include <linux/kernel.h> #include <linux/ioport.h> #include <linux/pci.h> -#include <linux/hdreg.h> -#include <linux/ide.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> #include <asm/it8172/it8172_int.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" diff --git a/drivers/ide/main.c b/drivers/ide/main.c index a3e134deef6b..50bc8732e38b 100644 --- a/drivers/ide/main.c +++ b/drivers/ide/main.c @@ -35,12 +35,13 @@ #endif #include <linux/pci.h> #include <linux/delay.h> -#include <linux/ide.h> #include <linux/devfs_fs_kernel.h> #include <linux/reboot.h> #include <linux/cdrom.h> #include <linux/device.h> #include <linux/kmod.h> +#include <linux/hdreg.h> +#include <linux/ide.h> #include <asm/byteorder.h> #include <asm/irq.h> @@ -48,7 +49,7 @@ #include <asm/io.h> #include <asm/bitops.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #include "ioctl.h" @@ -1068,7 +1069,6 @@ int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driv } drive->revalidate = 1; - drive->suspend_reset = 0; return 0; } diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 379bde73032d..61f9b75eef67 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c @@ -126,7 +126,7 @@ static void __init ide_init_ns87415(struct ata_channel *hwif) { struct pci_dev *dev = hwif->pci_dev; unsigned int ctrl, using_inta; - byte progif; + u8 progif; /* Set a good latency timer and cache line size value. */ (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c index 6b025f3e93ce..c141def6663d 100644 --- a/drivers/ide/opti621.c +++ b/drivers/ide/opti621.c @@ -99,7 +99,7 @@ #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #define OPTI621_MAX_PIO 3 @@ -137,7 +137,7 @@ int reg_base; /* there are stored pio numbers from other calls of opti621_tune_drive */ -static void compute_pios(struct ata_device *drive, byte pio) +static void compute_pios(struct ata_device *drive, u8 pio) /* Store values into drive->drive_data * second_contr - 0 for primary controller, 1 for secondary * slave_drive - 0 -> pio is for master, 1 -> pio is for slave @@ -178,7 +178,7 @@ static int cmpt_clk(int time, int bus_speed) return ((time*bus_speed+999999)/1000000); } -static void write_reg(byte value, int reg) +static void write_reg(u8 value, int reg) /* Write value to register reg, base of register * is at reg_base (0x1f0 primary, 0x170 secondary, * if not changed by PCI configuration). @@ -192,14 +192,14 @@ static void write_reg(byte value, int reg) outb(0x83, reg_base+2); } -static byte read_reg(int reg) +static u8 read_reg(int reg) /* Read value from register reg, base of register * is at reg_base (0x1f0 primary, 0x170 secondary, * if not changed by PCI configuration). * This is from setupvic.exe program. */ { - byte ret; + u8 ret; inw(reg_base+1); inw(reg_base+1); outb(3, reg_base+2); @@ -245,16 +245,16 @@ static void compute_clocks(int pio, pio_clocks_t *clks) } /* Main tune procedure, called from tuneproc. */ -static void opti621_tune_drive(struct ata_device *drive, byte pio) +static void opti621_tune_drive(struct ata_device *drive, u8 pio) { /* primary and secondary drives share some registers, * so we have to program both drives */ unsigned long flags; - byte pio1, pio2; + u8 pio1, pio2; pio_clocks_t first, second; int ax, drdy; - byte cycle1, cycle2, misc; + u8 cycle1, cycle2, misc; struct ata_channel *hwif = drive->channel; /* sets drive->drive_data for both drives */ diff --git a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c index a476693a3820..2674e69327dc 100644 --- a/drivers/ide/pcidma.c +++ b/drivers/ide/pcidma.c @@ -24,10 +24,11 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> -#include <linux/ide.h> #include <linux/delay.h> +#include <linux/hdreg.h> +#include <linux/ide.h> -#include "ata-timing.h" +#include "timing.h" #include <asm/io.h> #include <asm/irq.h> diff --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c index 28f888d4a9c4..1d871fdcc1d2 100644 --- a/drivers/ide/pdc202xx.c +++ b/drivers/ide/pdc202xx.c @@ -48,16 +48,16 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> -#include <linux/hdreg.h> #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> #include <asm/irq.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #define PDC202XX_DEBUG_DRIVE_INFO 0 @@ -105,7 +105,7 @@ static struct pdc_bit_messages pdc_reg_C[] = { /* MC3-MC0 - DMA "C" timing */ }; -static void pdc_dump_bits(struct pdc_bit_messages *msgs, byte bits) +static void pdc_dump_bits(struct pdc_bit_messages *msgs, u8 bits) { int i; @@ -174,7 +174,7 @@ static int __init pdc202xx_modes_map(struct ata_channel *ch) return map; } -static int pdc202xx_tune_chipset(struct ata_device *drive, byte speed) +static int pdc202xx_tune_chipset(struct ata_device *drive, u8 speed) { struct pci_dev *dev = drive->channel->pci_dev; u32 drive_conf; @@ -315,7 +315,7 @@ static int pdc202xx_tune_chipset(struct ata_device *drive, byte speed) OUT_BYTE(value, reg); \ mdelay(delay); -static int pdc202xx_new_tune_chipset(struct ata_device *drive, byte speed) +static int pdc202xx_new_tune_chipset(struct ata_device *drive, u8 speed) { struct ata_channel *hwif = drive->channel; u32 high_16 = pci_resource_start(hwif->pci_dev, 4); @@ -453,7 +453,7 @@ static void pdc202xx_tune_drive(struct ata_device *drive, u8 pio) if (pio == 255) speed = ata_best_pio_mode(drive); else - speed = XFER_PIO_0 + min_t(byte, pio, 4); + speed = XFER_PIO_0 + min_t(u8, pio, 4); pdc202xx_tune_chipset(drive, speed); } @@ -695,7 +695,7 @@ static unsigned int __init pdc202xx_init_chipset(struct pci_dev *dev) break; default: if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { - byte irq = 0, irq2 = 0; + u8 irq = 0, irq2 = 0; pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); pci_read_config_byte(dev, (PCI_INTERRUPT_LINE) | 0x80, &irq2); /* 0xbc */ diff --git a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c index 323be48b0e30..c08a6914c7ff 100644 --- a/drivers/ide/pdc4030.c +++ b/drivers/ide/pdc4030.c @@ -175,10 +175,10 @@ static void promise_selectproc(struct ata_device *drive) * by command F0. They all have the same success/failure notification - * 'P' (=0x50) on success, 'p' (=0x70) on failure. */ -int pdc4030_cmd(struct ata_device *drive, byte cmd) +int pdc4030_cmd(struct ata_device *drive, u8 cmd) { unsigned long timeout, timer; - byte status_val; + u8 status_val; promise_selectproc(drive); /* redundant? */ outb(0xF3, IDE_SECTOR_REG); diff --git a/drivers/ide/pdcraid.c b/drivers/ide/pdcraid.c index d1bd67ba7f45..f4b7fc0f82e1 100644 --- a/drivers/ide/pdcraid.c +++ b/drivers/ide/pdcraid.c @@ -135,11 +135,11 @@ static int pdcraid_ioctl(struct inode *inode, struct file *file, return -EINVAL; if (put_user (raid[minor].geom.heads, - (byte *) & loc->heads)) + (u8 *) & loc->heads)) return -EFAULT; if (put_user (raid[minor].geom.sectors, - (byte *) & loc->sectors)) + (u8 *) & loc->sectors)) return -EFAULT; if (put_user (bios_cyl, (unsigned short *) &loc->cylinders)) diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index a5fb9998bf56..b56759830069 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -45,11 +45,12 @@ #include <linux/blkdev.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #define PIIX_IDETIM0 0x40 @@ -240,7 +241,7 @@ static void piix_tune_drive(struct ata_device *drive, unsigned char pio) return; } - piix_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5)); + piix_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5)); } #ifdef CONFIG_BLK_DEV_IDEDMA diff --git a/drivers/ide/probe.c b/drivers/ide/probe.c index abe93fece6cf..3766b7531c78 100644 --- a/drivers/ide/probe.c +++ b/drivers/ide/probe.c @@ -28,9 +28,10 @@ #include <linux/genhd.h> #include <linux/slab.h> #include <linux/delay.h> -#include <linux/ide.h> #include <linux/spinlock.h> #include <linux/pci.h> +#include <linux/hdreg.h> +#include <linux/ide.h> #include <asm/byteorder.h> #include <asm/irq.h> @@ -302,18 +303,18 @@ void ide_fixstring(char *s, const int bytecount, const int byteswap) /* * All hosts that use the 80c ribbon must use this! */ -byte eighty_ninty_three(struct ata_device *drive) +int eighty_ninty_three(struct ata_device *drive) { - return ((u8) ((drive->channel->udma_four) && + return ((drive->channel->udma_four) && #ifndef CONFIG_IDEDMA_IVB (drive->id->hw_config & 0x4000) && #endif - (drive->id->hw_config & 0x6000)) ? 1 : 0); + (drive->id->hw_config & 0x6000)) ? 1 : 0; } /* FIXME: Channel lock should be held. */ -int ide_config_drive_speed(struct ata_device *drive, byte speed) +int ide_config_drive_speed(struct ata_device *drive, u8 speed) { struct ata_channel *ch = drive->channel; int ret; diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c index 6fce3b4bf491..633a75950d60 100644 --- a/drivers/ide/qd65xx.c +++ b/drivers/ide/qd65xx.c @@ -29,12 +29,13 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> +#include <linux/init.h> #include <linux/hdreg.h> #include <linux/ide.h> -#include <linux/init.h> + #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "qd65xx.h" /* @@ -85,7 +86,7 @@ static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ -static void qd_write_reg(byte content, byte reg) +static void qd_write_reg(u8 content, unsigned int reg) { unsigned long flags; @@ -95,10 +96,10 @@ static void qd_write_reg(byte content, byte reg) restore_flags(flags); /* all CPUs */ } -byte __init qd_read_reg(byte reg) +static u8 __init qd_read_reg(unsigned int reg) { unsigned long flags; - byte read; + u8 read; save_flags(flags); /* all CPUs */ cli(); /* all CPUs */ @@ -115,8 +116,8 @@ byte __init qd_read_reg(byte reg) static void qd_select(struct ata_device *drive) { - byte index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | - (QD_TIMREG(drive) & 0x02); + u8 index = (((QD_TIMREG(drive)) & 0x80 ) >> 7) | + (QD_TIMREG(drive) & 0x02); if (timings[index] != QD_TIMING(drive)) qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); @@ -130,9 +131,9 @@ static void qd_select(struct ata_device *drive) * upper nibble represents recovery time, in count of VLB clocks */ -static byte qd6500_compute_timing(struct ata_channel *hwif, int active_time, int recovery_time) +static u8 qd6500_compute_timing(struct ata_channel *hwif, int active_time, int recovery_time) { - byte active_cycle,recovery_cycle; + u8 active_cycle,recovery_cycle; if (system_bus_speed <= 33333) { active_cycle = 9 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 9); @@ -151,12 +152,12 @@ static byte qd6500_compute_timing(struct ata_channel *hwif, int active_time, int * idem for qd6580 */ -static byte qd6580_compute_timing(int active_time, int recovery_time) +static u8 qd6580_compute_timing(int active_time, int recovery_time) { - byte active_cycle = 17 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 17); - byte recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_speed / 1000000 + 1, 2, 15); + u8 active_cycle = 17 - IDE_IN(active_time * system_bus_speed / 1000000 + 1, 2, 17); + u8 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_speed / 1000000 + 1, 2, 15); - return((recovery_cycle<<4) | active_cycle); + return (recovery_cycle<<4) | active_cycle; } /* @@ -205,7 +206,7 @@ static int qd_timing_ok(struct ata_device drives[]) * records the timing, and enables selectproc as needed */ -static void qd_set_timing(struct ata_device *drive, byte timing) +static void qd_set_timing(struct ata_device *drive, u8 timing) { struct ata_channel *hwif = drive->channel; @@ -224,7 +225,7 @@ static void qd_set_timing(struct ata_device *drive, byte timing) * qd6500_tune_drive */ -static void qd6500_tune_drive(struct ata_device *drive, byte pio) +static void qd6500_tune_drive(struct ata_device *drive, u8 pio) { int active_time = 175; int recovery_time = 415; /* worst case values from the dos driver */ @@ -245,7 +246,7 @@ static void qd6500_tune_drive(struct ata_device *drive, byte pio) * qd6580_tune_drive */ -static void qd6580_tune_drive(struct ata_device *drive, byte pio) +static void qd6580_tune_drive(struct ata_device *drive, u8 pio) { struct ata_timing *t; int base = drive->channel->select_data; @@ -257,7 +258,7 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio) if (pio == 255) pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); else - pio = XFER_PIO_0 + min_t(byte, pio, 4); + pio = XFER_PIO_0 + min_t(u8, pio, 4); t = ata_timing_data(pio); @@ -305,8 +306,8 @@ static void qd6580_tune_drive(struct ata_device *drive, byte pio) static int __init qd_testreg(int port) { - byte savereg; - byte readreg; + u8 savereg; + u8 readreg; unsigned long flags; save_flags(flags); /* all CPUs */ @@ -333,7 +334,7 @@ static int __init qd_testreg(int port) * called to setup an ata channel : adjusts attributes & links for tuning */ -void __init qd_setup(int unit, int base, int config, unsigned int data0, unsigned int data1, void (*tuneproc) (struct ata_device *, byte pio)) +void __init qd_setup(int unit, int base, int config, unsigned int data0, unsigned int data1, void (*tuneproc) (struct ata_device *, u8 pio)) { struct ata_channel *hwif = &ide_hwifs[unit]; @@ -354,7 +355,7 @@ void __init qd_setup(int unit, int base, int config, unsigned int data0, unsigne */ void __init qd_unsetup(int unit) { struct ata_channel *hwif = &ide_hwifs[unit]; - byte config = hwif->config_data; + u8 config = hwif->config_data; int base = hwif->select_data; void *tuneproc = (void *) hwif->tuneproc; @@ -390,7 +391,7 @@ void __init qd_unsetup(int unit) { int __init qd_probe(int base) { - byte config; + u8 config; int unit; config = qd_read_reg(QD_CONFIG_PORT); @@ -417,7 +418,7 @@ int __init qd_probe(int base) } if (((config & 0xf0) == QD_CONFIG_QD6580_A) || ((config & 0xf0) == QD_CONFIG_QD6580_B)) { - byte control; + u8 control; if (qd_testreg(base) || qd_testreg(base+0x02)) return 1; /* bad registers */ diff --git a/drivers/ide/qd65xx.h b/drivers/ide/qd65xx.h index 73a7d76bbf6e..e0136907954c 100644 --- a/drivers/ide/qd65xx.h +++ b/drivers/ide/qd65xx.h @@ -34,8 +34,8 @@ #define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff) #define QD_CONTROL(hwif) (((hwif)->config_data & 0xff00) >> 8) -#define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff) -#define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8) +#define QD_TIMING(drive) (u8)(((drive)->drive_data) & 0x00ff) +#define QD_TIMREG(drive) (u8)((((drive)->drive_data) & 0xff00) >> 8) #define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08)) #define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00)) diff --git a/drivers/ide/quirks.c b/drivers/ide/quirks.c index d4cd05578193..740cfe5632fe 100644 --- a/drivers/ide/quirks.c +++ b/drivers/ide/quirks.c @@ -24,8 +24,9 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> -#include <linux/ide.h> #include <linux/delay.h> +#include <linux/hdreg.h> +#include <linux/ide.h> #include <asm/io.h> #include <asm/irq.h> @@ -153,14 +154,14 @@ int check_drive_lists(struct ata_device *drive, int good_bad) /* Consult the list of known "good" drives */ list = good_dma_drives; while (*list) { - if (!strcmp(*list++,id->model)) + if (!strcmp(*list++, id->model)) return 1; } } else { /* Consult the list of known "bad" drives */ list = bad_dma_drives; while (*list) { - if (!strcmp(*list++,id->model)) { + if (!strcmp(*list++, id->model)) { printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model); return 1; diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index ff8e39ef3b9f..1aa9c7199d71 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -85,14 +85,14 @@ #include <linux/kernel.h> #include <linux/ioport.h> #include <linux/pci.h> -#include <linux/hdreg.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #undef SVWKS_DEBUG_DRIVE_INFO diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index fb1a56cd0140..efe3d4a882ad 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -44,13 +44,13 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> -#include <linux/ide.h> #include <linux/hdreg.h> +#include <linux/ide.h> #include <asm/io.h> #include <asm/irq.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" /* When DEBUG is defined it outputs initial PCI config register @@ -84,7 +84,7 @@ static unsigned char chipset_family; Fewer might be used depending on the actual chipset */ static unsigned char ide_regs_copy[0x58]; -static byte sis5513_max_config_register(void) { +static u8 sis5513_max_config_register(void) { switch(chipset_family) { case ATA_00: case ATA_16: return 0x4f; @@ -100,9 +100,9 @@ static byte sis5513_max_config_register(void) { /* Read config registers, print differences from previous read */ static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) { int i; - byte reg_val; - byte changed=0; - byte max = sis5513_max_config_register(); + u8 reg_val; + u8 changed = 0; + u8 max = sis5513_max_config_register(); printk("SIS5513: %s, changed registers:\n", info); for(i=0; i<=max; i++) { @@ -121,9 +121,10 @@ static void sis5513_load_verify_registers(struct pci_dev* dev, char* info) { } /* Load config registers, no printing */ -static void sis5513_load_registers(struct pci_dev* dev) { +static void sis5513_load_registers(struct pci_dev* dev) +{ int i; - byte max = sis5513_max_config_register(); + u8 max = sis5513_max_config_register(); for(i=0; i<=max; i++) { pci_read_config_byte(dev, i, &(ide_regs_copy[i])); @@ -131,14 +132,15 @@ static void sis5513_load_registers(struct pci_dev* dev) { } /* Print a register */ -static void sis5513_print_register(int reg) { +static void sis5513_print_register(int reg) +{ printk(" %0#x:%0#x", reg, ide_regs_copy[reg]); } /* Print valuable registers */ static void sis5513_print_registers(struct pci_dev* dev, char* marker) { int i; - byte max = sis5513_max_config_register(); + u8 max = sis5513_max_config_register(); sis5513_load_registers(dev); printk("SIS5513 %s\n", marker); @@ -193,9 +195,9 @@ static const struct { /* Cycle time bits and values vary accross chip dma capabilities These three arrays hold the register layout and the values to set. Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ -static byte cycle_time_offset[] = {0,0,5,4,4,0,0}; -static byte cycle_time_range[] = {0,0,2,3,3,4,4}; -static byte cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = { +static u8 cycle_time_offset[] = {0,0,5,4,4,0,0}; +static u8 cycle_time_range[] = {0,0,2,3,3,4,4}; +static u8 cycle_time_value[][XFER_UDMA_5 - XFER_UDMA_0 + 1] = { {0,0,0,0,0,0}, /* no udma */ {0,0,0,0,0,0}, /* no udma */ {3,2,1,0,0,0}, @@ -317,7 +319,7 @@ static int sis5513_tune_chipset(struct ata_device *drive, u8 speed) struct ata_channel *hwif = drive->channel; struct pci_dev *dev = hwif->pci_dev; - byte drive_pci, reg; + u8 drive_pci, reg; #ifdef DEBUG sis5513_load_verify_registers(dev, "sis5513_tune_chipset start"); @@ -418,7 +420,7 @@ static unsigned int __init pci_init_sis5513(struct pci_dev *dev) #endif if (SiSHostChipInfo[i].flags & SIS5513_LATENCY) { - byte latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */ + u8 latency = (chipset_family == ATA_100)? 0x80 : 0x10; /* Lacking specs */ pci_write_config_byte(dev, PCI_LATENCY_TIMER, latency); } } @@ -427,7 +429,7 @@ static unsigned int __init pci_init_sis5513(struct pci_dev *dev) 1/ tell IDE channels to operate in Compabitility mode only 2/ tell old chips to allow per drive IDE timings */ if (host_dev) { - byte reg; + u8 reg; switch(chipset_family) { case ATA_133: case ATA_100: diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index 488b0018bb43..d348331d2006 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c @@ -19,14 +19,14 @@ #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/blkdev.h> -#include <linux/hdreg.h> #include <linux/pci.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> #include <asm/dma.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" /* @@ -82,7 +82,7 @@ static void config_for_pio(struct ata_device *drive, int pio, int report) if (pio == 255) xfer_mode = ata_timing_mode(drive, XFER_PIO | XFER_EPIO); else - xfer_mode = XFER_PIO_0 + min_t(byte, pio, 4); + xfer_mode = XFER_PIO_0 + min_t(u8, pio, 4); t = ata_timing_data(xfer_mode); @@ -258,7 +258,7 @@ static void sl82c105_lostirq(struct ata_device *drive) * We only deal with PIO mode here - DMA mode 'using_dma' is not * initialised at the point that this function is called. */ -static void tune_sl82c105(struct ata_device *drive, byte pio) +static void tune_sl82c105(struct ata_device *drive, u8 pio) { config_for_pio(drive, pio, 1); @@ -320,7 +320,7 @@ static unsigned int __init sl82c105_init_chipset(struct pci_dev *dev) static void __init sl82c105_init_dma(struct ata_channel *ch, unsigned long dma_base) { unsigned int bridge_rev; - byte dma_state; + u8 dma_state; dma_state = inb(dma_base + 2); bridge_rev = sl82c105_bridge_revision(ch->pci_dev); diff --git a/drivers/ide/tcq.c b/drivers/ide/tcq.c index 83c63ff13f7d..f6ce02e194e2 100644 --- a/drivers/ide/tcq.c +++ b/drivers/ide/tcq.c @@ -25,6 +25,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/delay.h> diff --git a/drivers/ide/ata-timing.h b/drivers/ide/timing.h index 9f01f07e8329..f413a85723d0 100644 --- a/drivers/ide/ata-timing.h +++ b/drivers/ide/timing.h @@ -1,14 +1,7 @@ -#ifndef _ATA_TIMING_H -#define _ATA_TIMING_H - /* - * $Id: ata-timing.h,v 2.0 2002/03/12 13:02:22 vojtech Exp $ - * * Copyright (C) 1996 Linus Torvalds, Igor Abramov, and Mark Lord * Copyright (C) 1999-2001 Vojtech Pavlik - */ - -/* + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -24,9 +17,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/hdreg.h> -#include <linux/ide.h> - #define XFER_PIO_5 0x0d #define XFER_UDMA_SLOW 0x4f @@ -91,5 +81,3 @@ extern struct ata_timing* ata_timing_data(short speed); extern int ata_timing_compute(struct ata_device *drive, short speed, struct ata_timing *t, int T, int UT); extern u8 ata_best_pio_mode(struct ata_device *drive); - -#endif diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c index 4e1995b62a47..d37b405e4759 100644 --- a/drivers/ide/trm290.c +++ b/drivers/ide/trm290.c @@ -251,7 +251,7 @@ static void __init trm290_init_channel(struct ata_channel *hwif) { unsigned int cfgbase = 0; unsigned long flags; - byte reg; + u8 reg; struct pci_dev *dev = hwif->pci_dev; hwif->chipset = ide_trm290; diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c index fb7f1a6116b9..61c986d226b3 100644 --- a/drivers/ide/umc8672.c +++ b/drivers/ide/umc8672.c @@ -46,13 +46,13 @@ #include <linux/mm.h> #include <linux/ioport.h> #include <linux/blkdev.h> +#include <linux/init.h> #include <linux/hdreg.h> #include <linux/ide.h> -#include <linux/init.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" /* * Default speeds. These can be changed with "auto-tune" and/or hdparm. @@ -62,11 +62,11 @@ #define UMC_DRIVE2 1 /* 11 = Fastest Speed */ #define UMC_DRIVE3 1 /* In case of crash reduce speed */ -static byte current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; -static const byte pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */ +static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; +static const u8 pio_to_umc[5] = {0,3,7,10,11}; /* rough guesses */ /* 0 1 2 3 4 5 6 7 8 9 10 11 */ -static const byte speedtab [3][12] = { +static const u8 speedtab[3][12] = { {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}}; @@ -77,13 +77,13 @@ static void out_umc (char port,char wert) outb_p (wert,0x109); } -static inline byte in_umc (char port) +static inline u8 in_umc (char port) { outb_p (port,0x108); return inb_p (0x109); } -static void umc_set_speeds (byte speeds[]) +static void umc_set_speeds(u8 speeds[]) { int i, tmp; @@ -106,14 +106,14 @@ static void umc_set_speeds (byte speeds[]) speeds[0], speeds[1], speeds[2], speeds[3]); } -static void tune_umc(struct ata_device *drive, byte pio) +static void tune_umc(struct ata_device *drive, u8 pio) { unsigned long flags; if (pio == 255) pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0; else - pio = min_t(byte, pio, 4); + pio = min_t(u8, pio, 4); printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]); save_flags(flags); /* all CPUs */ diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index 54838f9a8975..45cc8fd3fa80 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -65,11 +65,12 @@ #include <linux/blkdev.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> -#include "ata-timing.h" +#include "timing.h" #include "pcihost.h" #define VIA_IDE_ENABLE 0x40 @@ -217,7 +218,7 @@ static void via82cxxx_tune_drive(struct ata_device *drive, unsigned char pio) return; } - via_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5)); + via_set_drive(drive, XFER_PIO_0 + min_t(u8, pio, 5)); } #ifdef CONFIG_BLK_DEV_IDEDMA diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 37552f09dd46..2ef1d9a2d4e5 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -2058,7 +2058,6 @@ static int __devinit irq_probe_ECP(struct parport *pb) int i; unsigned long irqs; - sti(); irqs = probe_irq_on(); ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */ @@ -2093,7 +2092,6 @@ static int __devinit irq_probe_EPP(struct parport *pb) if (pb->modes & PARPORT_MODE_PCECR) oecr = inb (ECONTROL (pb)); - sti(); irqs = probe_irq_on(); if (pb->modes & PARPORT_MODE_PCECR) diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 49ab78ba1413..4985f18b9d1f 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -1006,14 +1006,20 @@ int parport_claim_or_block(struct pardevice *dev) #ifdef PARPORT_DEBUG_SHARING printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n", dev->name); #endif - save_flags (flags); - cli(); + /* + * FIXME!!! Use the proper locking for dev->waiting, + * and make this use the "wait_event_interruptible()" + * interfaces. The cli/sti that used to be here + * did nothing. + * + * See also parport_release() + */ + /* If dev->waiting is clear now, an interrupt gave us the port and we would deadlock if we slept. */ if (dev->waiting) { interruptible_sleep_on (&dev->wait_q); if (signal_pending (current)) { - restore_flags (flags); return -EINTR; } r = 1; @@ -1024,7 +1030,7 @@ int parport_claim_or_block(struct pardevice *dev) dev->name); #endif } - restore_flags(flags); + #ifdef PARPORT_DEBUG_SHARING if (dev->port->physport->cad != dev) printk(KERN_DEBUG "%s: exiting parport_claim_or_block " diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 0bbb215e7a8d..9f516d0d204d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -51,53 +51,6 @@ */ /* - * Function: __scsi_insert_special() - * - * Purpose: worker for scsi_insert_special_*() - * - * Arguments: q - request queue where request should be inserted - * rq - request to be inserted - * data - private data - * at_head - insert request at head or tail of queue - * - * Lock status: Assumed that queue lock is not held upon entry. - * - * Returns: Nothing - */ -static void __scsi_insert_special(request_queue_t *q, struct request *rq, - void *data, int at_head) -{ - unsigned long flags; - - ASSERT_LOCK(q->queue_lock, 0); - - /* - * tell I/O scheduler that this isn't a regular read/write (ie it - * must not attempt merges on this) and that it acts as a soft - * barrier - */ - rq->flags &= REQ_QUEUED; - rq->flags |= REQ_SPECIAL | REQ_BARRIER; - - rq->special = data; - - /* - * We have the option of inserting the head or the tail of the queue. - * Typically we use the tail for new ioctls and so forth. We use the - * head of the queue for things like a QUEUE_FULL message from a - * device, or a host that is unable to accept a particular command. - */ - spin_lock_irqsave(q->queue_lock, flags); - /* If command is tagged, release the tag */ - if(blk_rq_tagged(rq)) - blk_queue_end_tag(q, rq); - _elv_add_request(q, rq, !at_head, 0); - q->request_fn(q); - spin_unlock_irqrestore(q->queue_lock, flags); -} - - -/* * Function: scsi_insert_special_cmd() * * Purpose: Insert pre-formed command into request queue. @@ -121,7 +74,7 @@ int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int at_head) { request_queue_t *q = &SCpnt->device->request_queue; - __scsi_insert_special(q, SCpnt->request, SCpnt, at_head); + blk_insert_request(q, SCpnt->request, at_head, SCpnt); return 0; } @@ -149,7 +102,7 @@ int scsi_insert_special_req(Scsi_Request * SRpnt, int at_head) { request_queue_t *q = &SRpnt->sr_device->request_queue; - __scsi_insert_special(q, SRpnt->sr_request, SRpnt, at_head); + blk_insert_request(q, SRpnt->sr_request, at_head, SRpnt); return 0; } diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 369e6cceb574..cc0b6ef0f1d1 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -344,33 +344,33 @@ static int serial21285_verify_port(struct uart_port *port, struct serial_struct } static struct uart_ops serial21285_ops = { - tx_empty: serial21285_tx_empty, - get_mctrl: serial21285_get_mctrl, - set_mctrl: serial21285_set_mctrl, - stop_tx: serial21285_stop_tx, - start_tx: serial21285_start_tx, - stop_rx: serial21285_stop_rx, - enable_ms: serial21285_enable_ms, - break_ctl: serial21285_break_ctl, - startup: serial21285_startup, - shutdown: serial21285_shutdown, - change_speed: serial21285_change_speed, - type: serial21285_type, - release_port: serial21285_release_port, - request_port: serial21285_request_port, - config_port: serial21285_config_port, - verify_port: serial21285_verify_port, + .tx_empty = serial21285_tx_empty, + .get_mctrl = serial21285_get_mctrl, + .set_mctrl = serial21285_set_mctrl, + .stop_tx = serial21285_stop_tx, + .start_tx = serial21285_start_tx, + .stop_rx = serial21285_stop_rx, + .enable_ms = serial21285_enable_ms, + .break_ctl = serial21285_break_ctl, + .startup = serial21285_startup, + .shutdown = serial21285_shutdown, + .change_speed = serial21285_change_speed, + .type = serial21285_type, + .release_port = serial21285_release_port, + .request_port = serial21285_request_port, + .config_port = serial21285_config_port, + .verify_port = serial21285_verify_port, }; static struct uart_port serial21285_port = { - membase: 0, - mapbase: 0x42000160, - iotype: SERIAL_IO_MEM, - irq: NO_IRQ, - uartclk: 0, - fifosize: 16, - ops: &serial21285_ops, - flags: ASYNC_BOOT_AUTOCONF, + .membase = 0, + .mapbase = 0x42000160, + .iotype = SERIAL_IO_MEM, + .irq = NO_IRQ, + .uartclk = 0, + .fifosize = 16, + .ops = &serial21285_ops, + .flags = ASYNC_BOOT_AUTOCONF, }; static void serial21285_setup_ports(void) @@ -466,23 +466,23 @@ static int __init serial21285_console_setup(struct console *co, char *options) #ifdef CONFIG_SERIAL_21285_OLD static struct console serial21285_old_cons = { - name: SERIAL_21285_OLD_NAME, - write: serial21285_console_write, - device: serial21285_console_device, - setup: serial21285_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = SERIAL_21285_OLD_NAME, + .write = serial21285_console_write, + .device = serial21285_console_device, + .setup = serial21285_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; #endif static struct console serial21285_console = { - name: SERIAL_21285_NAME, - write: serial21285_console_write, - device: serial21285_console_device, - setup: serial21285_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = SERIAL_21285_NAME, + .write = serial21285_console_write, + .device = serial21285_console_device, + .setup = serial21285_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; void __init rs285_console_init(void) @@ -497,17 +497,17 @@ void __init rs285_console_init(void) #endif static struct uart_driver serial21285_reg = { - owner: THIS_MODULE, - driver_name: "ttyFB", + .owner = THIS_MODULE, + .driver_name = "ttyFB", #ifdef CONFIG_DEVFS_FS - dev_name: "ttyFB%d", + .dev_name = "ttyFB%d", #else - dev_name: "ttyFB", + .dev_name = "ttyFB", #endif - major: SERIAL_21285_MAJOR, - minor: SERIAL_21285_MINOR, - nr: 1, - cons: SERIAL_21285_CONSOLE, + .major = SERIAL_21285_MAJOR, + .minor = SERIAL_21285_MINOR, + .nr = 1, + .cons = SERIAL_21285_CONSOLE, }; static int __init serial21285_init(void) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 51836215e1c3..141aa7c49718 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1336,7 +1336,7 @@ serial8250_change_speed(struct uart_port *port, unsigned int cflag, fcr |= UART_FCR7_64BYTE; up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; - if (iflag & IGNPAR) + if (iflag & INPCK) up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; if (iflag & (BRKINT | PARMRK)) up->port.read_status_mask |= UART_LSR_BI; @@ -1672,23 +1672,23 @@ serial8250_type(struct uart_port *port) } static struct uart_ops serial8250_pops = { - tx_empty: serial8250_tx_empty, - set_mctrl: serial8250_set_mctrl, - get_mctrl: serial8250_get_mctrl, - stop_tx: serial8250_stop_tx, - start_tx: serial8250_start_tx, - stop_rx: serial8250_stop_rx, - enable_ms: serial8250_enable_ms, - break_ctl: serial8250_break_ctl, - startup: serial8250_startup, - shutdown: serial8250_shutdown, - change_speed: serial8250_change_speed, - pm: serial8250_pm, - type: serial8250_type, - release_port: serial8250_release_port, - request_port: serial8250_request_port, - config_port: serial8250_config_port, - verify_port: serial8250_verify_port, + .tx_empty = serial8250_tx_empty, + .set_mctrl = serial8250_set_mctrl, + .get_mctrl = serial8250_get_mctrl, + .stop_tx = serial8250_stop_tx, + .start_tx = serial8250_start_tx, + .stop_rx = serial8250_stop_rx, + .enable_ms = serial8250_enable_ms, + .break_ctl = serial8250_break_ctl, + .startup = serial8250_startup, + .shutdown = serial8250_shutdown, + .change_speed = serial8250_change_speed, + .pm = serial8250_pm, + .type = serial8250_type, + .release_port = serial8250_release_port, + .request_port = serial8250_request_port, + .config_port = serial8250_config_port, + .verify_port = serial8250_verify_port, }; static struct uart_8250_port serial8250_ports[UART_NR]; @@ -1836,12 +1836,12 @@ static int __init serial8250_console_setup(struct console *co, char *options) } static struct console serial8250_console = { - name: "ttyS", - write: serial8250_console_write, - device: serial8250_console_device, - setup: serial8250_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = "ttyS", + .write = serial8250_console_write, + .device = serial8250_console_device, + .setup = serial8250_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; void __init serial8250_console_init(void) @@ -1856,17 +1856,17 @@ void __init serial8250_console_init(void) #endif static struct uart_driver serial8250_reg = { - owner: THIS_MODULE, - driver_name: "serial", + .owner = THIS_MODULE, + .driver_name = "serial", #ifdef CONFIG_DEVFS_FS - dev_name: "tts/%d", + .dev_name = "tts/%d", #else - dev_name: "ttyS", + .dev_name = "ttyS", #endif - major: TTY_MAJOR, - minor: 64, - nr: UART_NR, - cons: SERIAL8250_CONSOLE, + .major = TTY_MAJOR, + .minor = 64, + .nr = UART_NR, + .cons = SERIAL8250_CONSOLE, }; /* diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index ef925d32febe..d6dcbcff8680 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -1112,10 +1112,10 @@ static struct pci_device_id serial_pci_tbl[] __devinitdata = { #endif static struct pci_driver serial_pci_driver = { - name: "serial", - probe: pci_init_one, - remove: __devexit_p(pci_remove_one), - id_table: serial_pci_tbl, + .name = "serial", + .probe = pci_init_one, + .remove = __devexit_p(pci_remove_one), + .id_table = serial_pci_tbl, }; static int __init serial8250_pci_init(void) diff --git a/drivers/serial/amba.c b/drivers/serial/amba.c index c5d3157db265..b350a5598663 100644 --- a/drivers/serial/amba.c +++ b/drivers/serial/amba.c @@ -557,54 +557,54 @@ static int ambauart_verify_port(struct uart_port *port, struct serial_struct *se } static struct uart_ops amba_pops = { - tx_empty: ambauart_tx_empty, - set_mctrl: ambauart_set_mctrl, - get_mctrl: ambauart_get_mctrl, - stop_tx: ambauart_stop_tx, - start_tx: ambauart_start_tx, - stop_rx: ambauart_stop_rx, - enable_ms: ambauart_enable_ms, - break_ctl: ambauart_break_ctl, - startup: ambauart_startup, - shutdown: ambauart_shutdown, - change_speed: ambauart_change_speed, - type: ambauart_type, - release_port: ambauart_release_port, - request_port: ambauart_request_port, - config_port: ambauart_config_port, - verify_port: ambauart_verify_port, + .tx_empty = ambauart_tx_empty, + .set_mctrl = ambauart_set_mctrl, + .get_mctrl = ambauart_get_mctrl, + .stop_tx = ambauart_stop_tx, + .start_tx = ambauart_start_tx, + .stop_rx = ambauart_stop_rx, + .enable_ms = ambauart_enable_ms, + .break_ctl = ambauart_break_ctl, + .startup = ambauart_startup, + .shutdown = ambauart_shutdown, + .change_speed = ambauart_change_speed, + .type = ambauart_type, + .release_port = ambauart_release_port, + .request_port = ambauart_request_port, + .config_port = ambauart_config_port, + .verify_port = ambauart_verify_port, }; static struct uart_amba_port amba_ports[UART_NR] = { { - port: { - membase: (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), - mapbase: INTEGRATOR_UART0_BASE, - iotype: SERIAL_IO_MEM, - irq: IRQ_UARTINT0, - uartclk: 14745600, - fifosize: 16, - ops: &amba_pops, - flags: ASYNC_BOOT_AUTOCONF, - line: 0, + .port = { + .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), + .mapbase = INTEGRATOR_UART0_BASE, + .iotype = SERIAL_IO_MEM, + .irq = IRQ_UARTINT0, + .uartclk = 14745600, + .fifosize = 16, + .ops = &amba_pops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 0, }, - dtr_mask: 1 << 5, - rts_mask: 1 << 4, + .dtr_mask = 1 << 5, + .rts_mask = 1 << 4, }, { - port: { - membase: (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), - mapbase: INTEGRATOR_UART1_BASE, - iotype: SERIAL_IO_MEM, - irq: IRQ_UARTINT1, - uartclk: 14745600, - fifosize: 16, - ops: &amba_pops, - flags: ASYNC_BOOT_AUTOCONF, - line: 1, + .port = { + .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), + .mapbase = INTEGRATOR_UART1_BASE, + .iotype = SERIAL_IO_MEM, + .irq = IRQ_UARTINT1, + .uartclk = 14745600, + .fifosize = 16, + .ops = &amba_pops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 1, }, - dtr_mask: 1 << 7, - rts_mask: 1 << 6, + .dtr_mask = 1 << 7, + .rts_mask = 1 << 6, } }; @@ -706,12 +706,12 @@ static int __init ambauart_console_setup(struct console *co, char *options) } static struct console amba_console = { - name: "ttyAM", - write: ambauart_console_write, - device: ambauart_console_device, - setup: ambauart_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = "ttyAM", + .write = ambauart_console_write, + .device = ambauart_console_device, + .setup = ambauart_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; void __init ambauart_console_init(void) @@ -725,17 +725,17 @@ void __init ambauart_console_init(void) #endif static struct uart_driver amba_reg = { - owner: THIS_MODULE, - driver_name: "ttyAM", + .owner = THIS_MODULE, + .driver_name = "ttyAM", #ifdef CONFIG_DEVFS_FS - dev_name: "ttyAM%d", + .dev_name = "ttyAM%d", #else - dev_name: "ttyAM", + .dev_name = "ttyAM", #endif - major: SERIAL_AMBA_MAJOR, - minor: SERIAL_AMBA_MINOR, - nr: UART_NR, - cons: AMBA_CONSOLE, + .major = SERIAL_AMBA_MAJOR, + .minor = SERIAL_AMBA_MINOR, + .nr = UART_NR, + .cons = AMBA_CONSOLE, }; static int __init ambauart_init(void) diff --git a/drivers/serial/anakin.c b/drivers/serial/anakin.c index f01e383a2624..dcb19b6630c9 100644 --- a/drivers/serial/anakin.c +++ b/drivers/serial/anakin.c @@ -322,65 +322,65 @@ static const char *anakin_type(struct port *port) } static struct uart_ops anakin_pops = { - tx_empty: anakin_tx_empty, - set_mctrl: anakin_set_mctrl, - get_mctrl: anakin_get_mctrl, - stop_tx: anakin_stop_tx, - start_tx: anakin_start_tx, - stop_rx: anakin_stop_rx, - enable_ms: anakin_enable_ms, - break_ctl: anakin_break_ctl, - startup: anakin_startup, - shutdown: anakin_shutdown, - change_speed: anakin_change_speed, - type: anakin_type, + .tx_empty = anakin_tx_empty, + .set_mctrl = anakin_set_mctrl, + .get_mctrl = anakin_get_mctrl, + .stop_tx = anakin_stop_tx, + .start_tx = anakin_start_tx, + .stop_rx = anakin_stop_rx, + .enable_ms = anakin_enable_ms, + .break_ctl = anakin_break_ctl, + .startup = anakin_startup, + .shutdown = anakin_shutdown, + .change_speed = anakin_change_speed, + .type = anakin_type, }; static struct uart_port anakin_ports[UART_NR] = { { - base: IO_BASE + UART0, - irq: IRQ_UART0, - uartclk: 3686400, - fifosize: 0, - ops: &anakin_pops, - flags: ASYNC_BOOT_AUTOCONF, - line: 0, + .base = IO_BASE + UART0, + .irq = IRQ_UART0, + .uartclk = 3686400, + .fifosize = 0, + .ops = &anakin_pops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 0, }, { - base: IO_BASE + UART1, - irq: IRQ_UART1, - uartclk: 3686400, - fifosize: 0, - ops: &anakin_pops, - flags: ASYNC_BOOT_AUTOCONF, - line: 1, + .base = IO_BASE + UART1, + .irq = IRQ_UART1, + .uartclk = 3686400, + .fifosize = 0, + .ops = &anakin_pops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 1, }, { - base: IO_BASE + UART2, - irq: IRQ_UART2, - uartclk: 3686400, - fifosize: 0, - ops: &anakin_pops, - flags: ASYNC_BOOT_AUTOCONF, - line: 2, + .base = IO_BASE + UART2, + .irq = IRQ_UART2, + .uartclk = 3686400, + .fifosize = 0, + .ops = &anakin_pops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 2, }, { - base: IO_BASE + UART3, - irq: IRQ_UART3, - uartclk: 3686400, - fifosize: 0, - ops: &anakin_pops, - flags: ASYNC_BOOT_AUTOCONF, - line: 3, + .base = IO_BASE + UART3, + .irq = IRQ_UART3, + .uartclk = 3686400, + .fifosize = 0, + .ops = &anakin_pops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 3, }, { - base: IO_BASE + UART4, - irq: IRQ_UART4, - uartclk: 3686400, - fifosize: 0, - ops: &anakin_pops, - flags: ASYNC_BOOT_AUTOCONF, - line: 4, + .base = IO_BASE + UART4, + .irq = IRQ_UART4, + .uartclk = 3686400, + .fifosize = 0, + .ops = &anakin_pops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 4, }, }; @@ -485,12 +485,12 @@ anakin_console_setup(struct console *co, char *options) } static struct console anakin_console = { - name: SERIAL_ANAKIN_NAME, - write: anakin_console_write, - device: anakin_console_device, - setup: anakin_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = SERIAL_ANAKIN_NAME, + .write = anakin_console_write, + .device = anakin_console_device, + .setup = anakin_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; void __init @@ -505,12 +505,12 @@ anakin_console_init(void) #endif static struct uart_register anakin_reg = { - driver_name: SERIAL_ANAKIN_NAME, - dev_name: SERIAL_ANAKIN_NAME, - major: SERIAL_ANAKIN_MAJOR, - minor: SERIAL_ANAKIN_MINOR, - nr: UART_NR, - cons: ANAKIN_CONSOLE, + .driver_name = SERIAL_ANAKIN_NAME, + .dev_name = SERIAL_ANAKIN_NAME, + .major = SERIAL_ANAKIN_MAJOR, + .minor = SERIAL_ANAKIN_MINOR, + .nr = UART_NR, + .cons = ANAKIN_CONSOLE, }; static int __init diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index bc79f73a6a16..b67f857fa588 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -418,39 +418,39 @@ static int clps711xuart_request_port(struct uart_port *port) } static struct uart_ops clps711x_pops = { - tx_empty: clps711xuart_tx_empty, - set_mctrl: clps711xuart_set_mctrl_null, - get_mctrl: clps711xuart_get_mctrl, - stop_tx: clps711xuart_stop_tx, - start_tx: clps711xuart_start_tx, - stop_rx: clps711xuart_stop_rx, - enable_ms: clps711xuart_enable_ms, - break_ctl: clps711xuart_break_ctl, - startup: clps711xuart_startup, - shutdown: clps711xuart_shutdown, - change_speed: clps711xuart_change_speed, - type: clps711xuart_type, - config_port: clps711xuart_config_port, - release_port: clps711xuart_release_port, - request_port: clps711xuart_request_port, + .tx_empty = clps711xuart_tx_empty, + .set_mctrl = clps711xuart_set_mctrl_null, + .get_mctrl = clps711xuart_get_mctrl, + .stop_tx = clps711xuart_stop_tx, + .start_tx = clps711xuart_start_tx, + .stop_rx = clps711xuart_stop_rx, + .enable_ms = clps711xuart_enable_ms, + .break_ctl = clps711xuart_break_ctl, + .startup = clps711xuart_startup, + .shutdown = clps711xuart_shutdown, + .change_speed = clps711xuart_change_speed, + .type = clps711xuart_type, + .config_port = clps711xuart_config_port, + .release_port = clps711xuart_release_port, + .request_port = clps711xuart_request_port, }; static struct uart_port clps711x_ports[UART_NR] = { { - iobase: SYSCON1, - irq: IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */ - uartclk: 3686400, - fifosize: 16, - ops: &clps711x_pops, - flags: ASYNC_BOOT_AUTOCONF, + .iobase = SYSCON1, + .irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */ + .uartclk = 3686400, + .fifosize = 16, + .ops = &clps711x_pops, + .flags = ASYNC_BOOT_AUTOCONF, }, { - iobase: SYSCON2, - irq: IRQ_UTXINT2, /* IRQ_URXINT2 */ - uartclk: 3686400, - fifosize: 16, - ops: &clps711x_pops, - flags: ASYNC_BOOT_AUTOCONF, + .iobase = SYSCON2, + .irq = IRQ_UTXINT2, /* IRQ_URXINT2 */ + .uartclk = 3686400, + .fifosize = 16, + .ops = &clps711x_pops, + .flags = ASYNC_BOOT_AUTOCONF, } }; @@ -560,12 +560,12 @@ static int __init clps711xuart_console_setup(struct console *co, char *options) } static struct console clps711x_console = { - name: SERIAL_CLPS711X_NAME, - write: clps711xuart_console_write, - device: clps711xuart_console_device, - setup: clps711xuart_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = SERIAL_CLPS711X_NAME, + .write = clps711xuart_console_write, + .device = clps711xuart_console_device, + .setup = clps711xuart_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; void __init clps711xuart_console_init(void) @@ -579,18 +579,18 @@ void __init clps711xuart_console_init(void) #endif static struct uart_driver clps711x_reg = { - driver_name: "ttyCL", + .driver_name = "ttyCL", #ifdef CONFIG_DEVFS_FS - dev_name: SERIAL_CLPS711X_NAME, + .dev_name = SERIAL_CLPS711X_NAME, #else - dev_name: SERIAL_CLPS711X_NAME, + .dev_name = SERIAL_CLPS711X_NAME, #endif - major: SERIAL_CLPS711X_MAJOR, - minor: SERIAL_CLPS711X_MINOR, - nr: UART_NR, + .major = SERIAL_CLPS711X_MAJOR, + .minor = SERIAL_CLPS711X_MINOR, + .nr = UART_NR, - cons: CLPS711X_CONSOLE, + .cons = CLPS711X_CONSOLE, }; static int __init clps711xuart_init(void) diff --git a/drivers/serial/core.c b/drivers/serial/core.c index 026b54b191d6..b5910ea9d868 100644 --- a/drivers/serial/core.c +++ b/drivers/serial/core.c @@ -1450,6 +1450,9 @@ uart_block_til_ready(struct file *filp, struct uart_info *info) if (signal_pending(current)) return -ERESTARTSYS; + if (info->tty->flags & (1 << TTY_IO_ERROR)) + return 0; + if (tty_hung_up_p(filp) || !(info->flags & UIF_INITIALIZED)) return (port->flags & UPF_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; @@ -2425,7 +2428,7 @@ int uart_register_port(struct uart_driver *drv, struct uart_port *port) state->port->regshift = port->regshift; state->port->iotype = port->iotype; state->port->flags = port->flags; - state->port->line = drv->state - state; + state->port->line = state - drv->state; __uart_register_port(drv, state, state->port); @@ -2469,6 +2472,8 @@ EXPORT_SYMBOL(uart_register_driver); EXPORT_SYMBOL(uart_unregister_driver); EXPORT_SYMBOL(uart_register_port); EXPORT_SYMBOL(uart_unregister_port); +EXPORT_SYMBOL(uart_add_one_port); +EXPORT_SYMBOL(uart_remove_one_port); MODULE_DESCRIPTION("Serial driver core"); MODULE_LICENSE("GPL"); diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index b10ad6329dbe..aced0fa1b70b 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -602,22 +602,22 @@ sa1100_verify_port(struct uart_port *port, struct serial_struct *ser) } static struct uart_ops sa1100_pops = { - tx_empty: sa1100_tx_empty, - set_mctrl: sa1100_set_mctrl, - get_mctrl: sa1100_get_mctrl, - stop_tx: sa1100_stop_tx, - start_tx: sa1100_start_tx, - stop_rx: sa1100_stop_rx, - enable_ms: sa1100_enable_ms, - break_ctl: sa1100_break_ctl, - startup: sa1100_startup, - shutdown: sa1100_shutdown, - change_speed: sa1100_change_speed, - type: sa1100_type, - release_port: sa1100_release_port, - request_port: sa1100_request_port, - config_port: sa1100_config_port, - verify_port: sa1100_verify_port, + .tx_empty = sa1100_tx_empty, + .set_mctrl = sa1100_set_mctrl, + .get_mctrl = sa1100_get_mctrl, + .stop_tx = sa1100_stop_tx, + .start_tx = sa1100_start_tx, + .stop_rx = sa1100_stop_rx, + .enable_ms = sa1100_enable_ms, + .break_ctl = sa1100_break_ctl, + .startup = sa1100_startup, + .shutdown = sa1100_shutdown, + .change_speed = sa1100_change_speed, + .type = sa1100_type, + .release_port = sa1100_release_port, + .request_port = sa1100_request_port, + .config_port = sa1100_config_port, + .verify_port = sa1100_verify_port, }; static struct sa1100_port sa1100_ports[NR_PORTS]; @@ -820,12 +820,12 @@ sa1100_console_setup(struct console *co, char *options) } static struct console sa1100_console = { - name: "ttySA", - write: sa1100_console_write, - device: sa1100_console_device, - setup: sa1100_console_setup, - flags: CON_PRINTBUFFER, - index: -1, + .name = "ttySA", + .write = sa1100_console_write, + .device = sa1100_console_device, + .setup = sa1100_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; void __init sa1100_rs_console_init(void) @@ -840,17 +840,17 @@ void __init sa1100_rs_console_init(void) #endif static struct uart_driver sa1100_reg = { - owner: THIS_MODULE, - driver_name: "ttySA", + .owner = THIS_MODULE, + .driver_name = "ttySA", #ifdef CONFIG_DEVFS_FS - dev_name: "ttySA%d", + .dev_name = "ttySA%d", #else - dev_name: "ttySA", + .dev_name = "ttySA", #endif - major: SERIAL_SA1100_MAJOR, - minor: MINOR_START, - nr: NR_PORTS, - cons: SA1100_CONSOLE, + .major = SERIAL_SA1100_MAJOR, + .minor = MINOR_START, + .nr = NR_PORTS, + .cons = SA1100_CONSOLE, }; static int __init sa1100_serial_init(void) diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c index 41f09f633e55..18cdd391e82f 100644 --- a/drivers/serial/uart00.c +++ b/drivers/serial/uart00.c @@ -498,35 +498,35 @@ static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser) } static struct uart_ops uart00_pops = { - tx_empty: uart00_tx_empty, - set_mctrl: uart00_set_mctrl_null, - get_mctrl: uart00_get_mctrl, - stop_tx: uart00_stop_tx, - start_tx: uart00_start_tx, - stop_rx: uart00_stop_rx, - enable_ms: uart00_enable_ms, - break_ctl: uart00_break_ctl, - startup: uart00_startup, - shutdown: uart00_shutdown, - change_speed: uart00_change_speed, - type: uart00_type, - release_port: uart00_release_port, - request_port: uart00_request_port, - config_port: uart00_config_port, - verify_port: uart00_verify_port, + .tx_empty = uart00_tx_empty, + .set_mctrl = uart00_set_mctrl_null, + .get_mctrl = uart00_get_mctrl, + .stop_tx = uart00_stop_tx, + .start_tx = uart00_start_tx, + .stop_rx = uart00_stop_rx, + .enable_ms = uart00_enable_ms, + .break_ctl = uart00_break_ctl, + .startup = uart00_startup, + .shutdown = uart00_shutdown, + .change_speed = uart00_change_speed, + .type = uart00_type, + .release_port = uart00_release_port, + .request_port = uart00_request_port, + .config_port = uart00_config_port, + .verify_port = uart00_verify_port, }; #ifdef CONFIG_ARCH_CAMELOT static struct uart_port epxa10db_port = { - membase: (void*)IO_ADDRESS(EXC_UART00_BASE), - mapbase: EXC_UART00_BASE, - iotype: SERIAL_IO_MEM, - irq: IRQ_UART, - uartclk: EXC_AHB2_CLK_FREQUENCY, - fifosize: 16, - ops: &uart00_pops, - flags: ASYNC_BOOT_AUTOCONF, + .membase = (void*)IO_ADDRESS(EXC_UART00_BASE), + .mapbase = EXC_UART00_BASE, + .iotype = SERIAL_IO_MEM, + .irq = IRQ_UART, + .uartclk = EXC_AHB2_CLK_FREQUENCY, + .fifosize = 16, + .ops = &uart00_pops, + .flags = ASYNC_BOOT_AUTOCONF, }; #endif @@ -633,12 +633,12 @@ static int __init uart00_console_setup(struct console *co, char *options) } static struct console uart00_console = { - name: SERIAL_UART00_NAME, - write: uart00_console_write, - device: uart00_console_device, - setup: uart00_console_setup, - flags: CON_PRINTBUFFER, - index: 0, + .name = SERIAL_UART00_NAME, + .write = uart00_console_write, + .device = uart00_console_device, + .setup = uart00_console_setup, + .flags = CON_PRINTBUFFER, + .index = 0, }; void __init uart00_console_init(void) @@ -652,13 +652,13 @@ void __init uart00_console_init(void) #endif static struct uart_driver uart00_reg = { - owner: NULL, - driver_name: SERIAL_UART00_NAME, - dev_name: SERIAL_UART00_NAME, - major: SERIAL_UART00_MAJOR, - minor: SERIAL_UART00_MINOR, - nr: UART_NR, - cons: UART00_CONSOLE, + .owner = NULL, + .driver_name = SERIAL_UART00_NAME, + .dev_name = SERIAL_UART00_NAME, + .major = SERIAL_UART00_MAJOR, + .minor = SERIAL_UART00_MINOR, + .nr = UART_NR, + .cons = UART00_CONSOLE, }; struct dev_port_entry{ diff --git a/drivers/usb/Config.help b/drivers/usb/Config.help index fa161a19725b..034627ab0e43 100644 --- a/drivers/usb/Config.help +++ b/drivers/usb/Config.help @@ -11,13 +11,18 @@ CONFIG_USB to the PC via those ports. Say Y here if your computer has a USB port and you want to use USB - devices. You then need to say Y to at least one of "UHCI support" - or "OHCI support" below (the type of interface that the USB hardware + devices. You then need to say Y to at least one of "UHCI HCD support" + or "OHCI HCD support" below (the type of interface that the USB hardware in your computer provides to the operating system) and then choose - from among the drivers for USB peripherals. You may want to check + from amongst the drivers for USB peripherals. You may want to check out the information provided in <file:Documentation/usb/> and especially the links given in <file:Documentation/usb/usb-help.txt>. + If you have a new USB 2.0 High Speed system, you should also choose + "EHCI HCD (USB 2.0) support" as well as at least one of UHCI or OHCI. + + It doesn't normally hurt to select them all if you are not certain. + This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called usbcore.o. If you want to compile it as a @@ -39,7 +44,7 @@ CONFIG_USB_LONG_TIMEOUT CONFIG_USB_DEVICEFS If you say Y here (and to "/proc file system support" in the "File - systems section, above), you will get a file /proc/bus/usb/devices + systems" section, above), you will get a file /proc/bus/usb/devices which lists the devices currently connected to your USB bus or busses, a file /proc/bus/usb/drivers which lists the USB kernel client drivers currently loaded, and for every connected device a diff --git a/drivers/usb/class/Config.help b/drivers/usb/class/Config.help index 8387ea4b8f77..d745878ca6f6 100644 --- a/drivers/usb/class/Config.help +++ b/drivers/usb/class/Config.help @@ -3,6 +3,10 @@ CONFIG_USB_ACM Communication Device Class Abstract Control Model interface. Please read <file:Documentation/usb/acm.txt> for details. + If your modem only reports "Cls=ff(vend.)" in the descriptors in + /proc/bus/usb/devices, then your modem will not work with this + driver. + This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called acm.o. If you want to compile it as a diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c index 07c5ea5b7e81..1187e7b58ecc 100644 --- a/drivers/usb/class/audio.c +++ b/drivers/usb/class/audio.c @@ -2745,8 +2745,8 @@ static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum, static void usb_audio_disconnect(struct usb_device *dev, void *ptr); static struct usb_device_id usb_audio_ids [] = { - { match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS), - bInterfaceClass: USB_CLASS_AUDIO, bInterfaceSubClass: 1}, + { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS), + .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = 1}, { } /* Terminating entry */ }; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index f1884e5ec9c2..4f53715471fb 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -947,8 +947,8 @@ static void usb_find_drivers(struct usb_device *dev) /* register this interface with driverfs */ interface->dev.parent = &dev->dev; interface->dev.bus = &usb_bus_type; - sprintf (&interface->dev.bus_id[0], "%s:%d", - dev->devpath, + sprintf (&interface->dev.bus_id[0], "%s-%s:%d", + dev->bus->bus_name, dev->devpath, interface->altsetting->bInterfaceNumber); if (!desc->iInterface || usb_string (dev, desc->iInterface, diff --git a/drivers/usb/host/Config.help b/drivers/usb/host/Config.help index 7cfd9ff8e5aa..e344fde05e8f 100644 --- a/drivers/usb/host/Config.help +++ b/drivers/usb/host/Config.help @@ -12,7 +12,8 @@ CONFIG_USB_EHCI_HCD will connect to EHCI if it the device is high speed, otherwise they connect to a companion controller. If you configure EHCI, you should probably configure the OHCI (for NEC and some other vendors) USB Host - Controller Driver too. + Controller Driver or UHCI (for Via motherboards) Host Controller + Driver too. You may want to read <file:Documentation/usb/ehci.txt>. diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 74496b06a130..dcb10d5dc2cd 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -65,6 +65,8 @@ * * HISTORY: * + * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support, + * clean up HC run state handshaking. * 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts * 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other * missing pieces: enabling 64bit dma, handoff from BIOS/SMM. @@ -83,7 +85,7 @@ * 2001-June Works with usb-storage and NEC EHCI on 2.4 */ -#define DRIVER_VERSION "2002-May-24" +#define DRIVER_VERSION "2002-Jul-25" #define DRIVER_AUTHOR "David Brownell" #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" @@ -113,42 +115,105 @@ MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); /*-------------------------------------------------------------------------*/ /* + * handshake - spin reading hc until handshake completes or fails + * @ptr: address of hc register to be read + * @mask: bits to look at in result of read + * @done: value of those bits when handshake succeeds + * @usec: timeout in microseconds + * + * Returns negative errno, or zero on success + * + * Success happens when the "mask" bits have the specified value (hardware + * handshake done). There are two failure modes: "usec" have passed (major + * hardware flakeout), or the register reads as all-ones (hardware removed). + * + * That last failure should_only happen in cases like physical cardbus eject + * before driver shutdown. But it also seems to be caused by bugs in cardbus + * bridge shutdown: shutting down the bridge before the devices using it. + */ +static int handshake (u32 *ptr, u32 mask, u32 done, int usec) +{ + u32 result; + + do { + result = readl (ptr); + if (result == ~(u32)0) /* card removed */ + return -ENODEV; + result &= mask; + if (result == done) + return 0; + udelay (1); + usec--; + } while (usec > 0); + return -ETIMEDOUT; +} + +/* * hc states include: unknown, halted, ready, running * transitional states are messy just now * trying to avoid "running" unless urbs are active * a "ready" hc can be finishing prefetched work */ -/* halt a non-running controller */ -static void ehci_reset (struct ehci_hcd *ehci) +/* force HC to halt state from unknown (EHCI spec section 2.3) */ +static int ehci_halt (struct ehci_hcd *ehci) +{ + u32 temp = readl (&ehci->regs->status); + + if ((temp & STS_HALT) != 0) + return 0; + + temp = readl (&ehci->regs->command); + temp &= ~CMD_RUN; + writel (temp, &ehci->regs->command); + return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125); +} + +/* reset a non-running (STS_HALT == 1) controller */ +static int ehci_reset (struct ehci_hcd *ehci) { u32 command = readl (&ehci->regs->command); command |= CMD_RESET; dbg_cmd (ehci, "reset", command); writel (command, &ehci->regs->command); - while (readl (&ehci->regs->command) & CMD_RESET) - continue; ehci->hcd.state = USB_STATE_HALT; + return handshake (&ehci->regs->command, CMD_RESET, 0, 050); } /* idle the controller (from running) */ static void ehci_ready (struct ehci_hcd *ehci) { - u32 command; + u32 temp; #ifdef DEBUG if (!HCD_IS_RUNNING (ehci->hcd.state)) BUG (); #endif - while (!(readl (&ehci->regs->status) & (STS_ASS | STS_PSS))) - udelay (100); - command = readl (&ehci->regs->command); - command &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); - writel (command, &ehci->regs->command); + /* wait for any schedule enables/disables to take effect */ + temp = 0; + if (ehci->async) + temp = STS_ASS; + if (ehci->next_uframe != -1) + temp |= STS_PSS; + if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, + temp, 16 * 125) != 0) { + ehci->hcd.state = USB_STATE_HALT; + return; + } - // hardware can take 16 microframes to turn off ... + /* then disable anything that's still active */ + temp = readl (&ehci->regs->command); + temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); + writel (temp, &ehci->regs->command); + + /* hardware can take 16 microframes to turn off ... */ + if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, + 0, 16 * 125) != 0) { + ehci->hcd.state = USB_STATE_HALT; + return; + } ehci->hcd.state = USB_STATE_READY; } @@ -236,6 +301,10 @@ static int ehci_start (struct usb_hcd *hcd) /* cache this readonly data; minimize PCI reads */ ehci->hcs_params = readl (&ehci->caps->hcs_params); + /* force HC to halt state */ + if ((retval = ehci_halt (ehci)) != 0) + return retval; + /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. @@ -257,8 +326,10 @@ static int ehci_start (struct usb_hcd *hcd) /* controller state: unknown --> reset */ /* EHCI spec section 4.1 */ - // FIXME require STS_HALT before reset... - ehci_reset (ehci); + if ((retval = ehci_reset (ehci)) != 0) { + ehci_mem_cleanup (ehci); + return retval; + } writel (INTR_MASK, &ehci->regs->intr_enable); writel (ehci->periodic_dma, &ehci->regs->frame_list); @@ -335,8 +406,6 @@ done2: if (usb_register_root_hub (udev, &ehci->hcd.pdev->dev) != 0) { if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); - while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS)) - udelay (100); ehci_reset (ehci); hcd->self.root_hub = 0; usb_free_dev (udev); @@ -355,16 +424,14 @@ static void ehci_stop (struct usb_hcd *hcd) dbg ("%s: stop", hcd->self.bus_name); + /* no more interrupts ... */ if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); - while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS)) - udelay (100); ehci_reset (ehci); - // root hub is shut down separately (first, when possible) - scan_async (ehci); - if (ehci->next_uframe != -1) - scan_periodic (ehci); + /* root hub is shut down separately (first, when possible) */ + tasklet_disable (&ehci->tasklet); + ehci_tasklet ((unsigned long) ehci); ehci_mem_cleanup (ehci); dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); @@ -412,8 +479,6 @@ dbg ("%s: suspend port %d", hcd->self.bus_name, i); if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); - while (readl (&ehci->regs->status) & (STS_ASS | STS_PSS)) - udelay (100); writel (readl (&ehci->regs->command) & ~CMD_RUN, &ehci->regs->command); // save pci FLADJ value @@ -489,6 +554,12 @@ static void ehci_irq (struct usb_hcd *hcd) u32 status = readl (&ehci->regs->status); int bh; + /* e.g. cardbus physical eject */ + if (status == ~(u32) 0) { + dbg ("%s: device removed!", hcd->self.bus_name); + goto dead; + } + status &= INTR_MASK; if (!status) /* irq sharing? */ return; @@ -517,10 +588,13 @@ static void ehci_irq (struct usb_hcd *hcd) /* PCI errors [4.15.2.4] */ if (unlikely ((status & STS_FATAL) != 0)) { - err ("%s: fatal error, state %x", hcd->self.bus_name, hcd->state); + err ("%s: fatal error, state %x", + hcd->self.bus_name, hcd->state); +dead: ehci_reset (ehci); - // generic layer kills/unlinks all urbs - // then tasklet cleans up the rest + /* generic layer kills/unlinks all urbs, then + * uses ehci_stop to clean up the rest + */ bh = 1; } diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 53062380a93f..3057d75b0fed 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -718,8 +718,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) u32 cmd = readl (&ehci->regs->command); /* in case a clear of CMD_ASE didn't take yet */ - while (readl (&ehci->regs->status) & STS_ASS) - udelay (100); + (void) handshake (&ehci->regs->status, STS_ASS, 0, 150); qh->hw_info1 |= __constant_cpu_to_le32 (QH_HEAD); /* [4.8] */ qh->qh_next.qh = qh; @@ -917,11 +916,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) if (ehci->hcd.state != USB_STATE_HALT) { if (cmd & CMD_PSE) writel (cmd & ~CMD_ASE, &ehci->regs->command); - else { + else ehci_ready (ehci); - while (readl (&ehci->regs->status) & STS_ASS) - udelay (100); - } } qh->qh_next.qh = ehci->async = 0; diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index a2f25cd4d598..5e08204d34d9 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -171,15 +171,19 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) /*-------------------------------------------------------------------------*/ -static void enable_periodic (struct ehci_hcd *ehci) +static int enable_periodic (struct ehci_hcd *ehci) { u32 cmd; + int status; /* did clearing PSE did take effect yet? * takes effect only at frame boundaries... */ - while (readl (&ehci->regs->status) & STS_PSS) - udelay (20); + status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125); + if (status != 0) { + ehci->hcd.state = USB_STATE_HALT; + return status; + } cmd = readl (&ehci->regs->command) | CMD_PSE; writel (cmd, &ehci->regs->command); @@ -189,23 +193,29 @@ static void enable_periodic (struct ehci_hcd *ehci) /* make sure tasklet scans these */ ehci->next_uframe = readl (&ehci->regs->frame_index) % (ehci->periodic_size << 3); + return 0; } -static void disable_periodic (struct ehci_hcd *ehci) +static int disable_periodic (struct ehci_hcd *ehci) { u32 cmd; + int status; /* did setting PSE not take effect yet? * takes effect only at frame boundaries... */ - while (!(readl (&ehci->regs->status) & STS_PSS)) - udelay (20); + status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125); + if (status != 0) { + ehci->hcd.state = USB_STATE_HALT; + return status; + } cmd = readl (&ehci->regs->command) & ~CMD_PSE; writel (cmd, &ehci->regs->command); /* posted write ... */ ehci->next_uframe = -1; + return 0; } /*-------------------------------------------------------------------------*/ @@ -217,6 +227,7 @@ static void intr_deschedule ( unsigned period ) { unsigned long flags; + int status; period >>= 3; // FIXME microframe periods not handled yet @@ -234,9 +245,11 @@ static void intr_deschedule ( /* maybe turn off periodic schedule */ if (!ehci->periodic_urbs) - disable_periodic (ehci); - else + status = disable_periodic (ehci); + else { + status = 0; vdbg ("periodic schedule still enabled"); + } spin_unlock_irqrestore (&ehci->lock, flags); @@ -245,7 +258,7 @@ static void intr_deschedule ( * (yeech!) to be sure it's done. * No other threads may be mucking with this qh. */ - if (((ehci_get_frame (&ehci->hcd) - frame) % period) == 0) + if (!status && ((ehci_get_frame (&ehci->hcd) - frame) % period) == 0) udelay (125); qh->qh_state = QH_STATE_IDLE; @@ -501,7 +514,7 @@ static int intr_submit ( /* maybe enable periodic schedule processing */ if (!ehci->periodic_urbs++) - enable_periodic (ehci); + status = enable_periodic (ehci); break; } while (frame); @@ -913,8 +926,12 @@ itd_schedule (struct ehci_hcd *ehci, struct urb *urb) usb_claim_bandwidth (urb->dev, urb, usecs, 1); /* maybe enable periodic schedule processing */ - if (!ehci->periodic_urbs++) - enable_periodic (ehci); + if (!ehci->periodic_urbs++) { + if ((status = enable_periodic (ehci)) != 0) { + // FIXME deschedule right away + err ("itd_schedule, enable = %d", status); + } + } return 0; @@ -994,7 +1011,7 @@ itd_complete ( /* defer stopping schedule; completion can submit */ ehci->periodic_urbs--; if (!ehci->periodic_urbs) - disable_periodic (ehci); + (void) disable_periodic (ehci); return flags; } diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index b968cfe92d35..4545a999df90 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -281,16 +281,21 @@ static void ohci_dump_td (char *label, struct td *td) cbp ? (be + 1 - cbp) : 0); } else { unsigned i; - dbg (" info %08x CC=%x DI=%d START=%04x", tmp, - TD_CC_GET(tmp), /* FC, */ + dbg (" info %08x CC=%x FC=%d DI=%d SF=%04x", tmp, + TD_CC_GET(tmp), + (tmp >> 24) & 0x07, (tmp & TD_DI) >> 21, tmp & 0x0000ffff); dbg (" bp0 %08x be %08x", le32_to_cpup (&td->hwCBP) & ~0x0fff, le32_to_cpup (&td->hwBE)); for (i = 0; i < MAXPSW; i++) { - dbg (" psw [%d] = %2x", i, - le16_to_cpu (td->hwPSW [i])); + u16 psw = le16_to_cpup (&td->hwPSW [i]); + int cc = (psw >> 12) & 0x0f; + dbg (" psw [%d] = %2x, CC=%x %s=%d", i, + psw, cc, + (cc >= 0x0e) ? "OFFSET" : "SIZE", + psw & 0x0fff); } } } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 2ee09b0a3bcd..d7cc8c544068 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -10,8 +10,15 @@ * [ (C) Copyright 1999 Gregory P. Smith] * * + * OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller + * interfaces (though some non-x86 Intel chips use it). It supports + * smarter hardware than UHCI. A download link for the spec available + * through the http://www.usb.org website. + * * History: * + * 2002/07/19 fixes to management of ED and schedule state. + * 2002/06/09 SA-1111 support (Christopher Hoover) * 2002/06/01 remember frame when HC won't see EDs any more; use that info * to fix urb unlink races caused by interrupt latency assumptions; * minor ED field and function naming updates @@ -95,12 +102,12 @@ /* * TO DO: * - * - "disabled" should be the hcd state + * - "disabled" and "sleeping" should be in hcd->state * - bandwidth alloc to generic code * - lots more testing!! */ -#define DRIVER_VERSION "2002-Jun-15" +#define DRIVER_VERSION "2002-Jul-19" #define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" @@ -118,6 +125,12 @@ #include "ohci.h" +static inline void disable (struct ohci_hcd *ohci) +{ + ohci->disabled = 1; + ohci->hcd.state = USB_STATE_HALT; +} + #include "ohci-hub.c" #include "ohci-dbg.c" #include "ohci-mem.c" @@ -140,6 +153,7 @@ static int ohci_urb_enqueue ( int i, size = 0; unsigned long flags; int bustime = 0; + int retval = 0; #ifdef OHCI_VERBOSE_DEBUG urb_print (urb, "SUB", usb_pipein (pipe)); @@ -150,12 +164,18 @@ static int ohci_urb_enqueue ( return -ENOMEM; /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype (pipe)) { + switch (ed->type) { case PIPE_CONTROL: + /* td_submit_urb() doesn't yet handle these */ + if (urb->transfer_buffer_length > 4096) + return -EMSGSIZE; + /* 1 TD for setup, 1 for ACK, plus ... */ size = 2; /* FALLTHROUGH */ - case PIPE_BULK: + // case PIPE_INTERRUPT: + // case PIPE_BULK: + default: /* one TD for every 4096 Bytes (can be upto 8K) */ size += urb->transfer_buffer_length / 4096; /* ... and for any remaining bytes ... */ @@ -179,9 +199,6 @@ static int ohci_urb_enqueue ( urb->iso_frame_desc [i].status = -EXDEV; } break; - case PIPE_INTERRUPT: /* one TD */ - size = 1; - break; } /* allocate the private part of the URB */ @@ -191,19 +208,25 @@ static int ohci_urb_enqueue ( return -ENOMEM; memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *)); + spin_lock_irqsave (&ohci->lock, flags); + + /* don't submit to a dead HC */ + if (ohci->disabled || ohci->sleeping) { + retval = -ENODEV; + goto fail; + } + /* fill the private part of the URB */ urb_priv->length = size; urb_priv->ed = ed; /* allocate the TDs (updating hash chains) */ - spin_lock_irqsave (&ohci->lock, flags); for (i = 0; i < size; i++) { urb_priv->td [i] = td_alloc (ohci, SLAB_ATOMIC); if (!urb_priv->td [i]) { urb_priv->length = i; - urb_free_priv (ohci, urb_priv); - spin_unlock_irqrestore (&ohci->lock, flags); - return -ENOMEM; + retval = -ENOMEM; + goto fail; } } @@ -217,20 +240,19 @@ static int ohci_urb_enqueue ( switch (usb_pipetype (pipe)) { case PIPE_ISOCHRONOUS: if (urb->transfer_flags & USB_ISO_ASAP) { - urb->start_frame = ( (ed->state == ED_OPER) + urb->start_frame = ((ed->state != ED_IDLE) ? (ed->intriso.last_iso + 1) : (le16_to_cpu (ohci->hcca->frame_no) + 10)) & 0xffff; - } + } /* FALLTHROUGH */ case PIPE_INTERRUPT: if (urb->bandwidth == 0) { bustime = usb_check_bandwidth (urb->dev, urb); } if (bustime < 0) { - urb_free_priv (ohci, urb_priv); - spin_unlock_irqrestore (&ohci->lock, flags); - return bustime; + retval = bustime; + goto fail; } usb_claim_bandwidth (urb->dev, urb, bustime, usb_pipeisoc (urb->pipe)); @@ -238,18 +260,20 @@ static int ohci_urb_enqueue ( urb->hcpriv = urb_priv; - /* link the ed into a chain if is not already */ - if (ed->state != ED_OPER) - ep_link (ohci, ed); + /* schedule the ed if needed */ + if (ed->state == ED_IDLE) + ed_schedule (ohci, ed); /* fill the TDs and link them to the ed; and * enable that part of the schedule, if needed */ - td_submit_urb (urb); + td_submit_urb (ohci, urb); +fail: + if (retval) + urb_free_priv (ohci, urb_priv); spin_unlock_irqrestore (&ohci->lock, flags); - - return 0; + return retval; } /* @@ -270,19 +294,17 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) if (!ohci->disabled) { urb_priv_t *urb_priv; - /* flag the urb's data for deletion in some upcoming - * SF interrupt's delete list processing + /* Unless an IRQ completed the unlink while it was being + * handed to us, flag it for unlink and giveback, and force + * some upcoming INTR_SF to call finish_unlinks() */ spin_lock_irqsave (&ohci->lock, flags); urb_priv = urb->hcpriv; - - if (!urb_priv || (urb_priv->state == URB_DEL)) { - spin_unlock_irqrestore (&ohci->lock, flags); - return 0; + if (urb_priv) { + urb_priv->state = URB_DEL; + if (urb_priv->ed->state == ED_OPER) + start_urb_unlink (ohci, urb_priv->ed); } - - urb_priv->state = URB_DEL; - start_urb_unlink (ohci, urb_priv->ed); spin_unlock_irqrestore (&ohci->lock, flags); } else { /* @@ -290,12 +312,16 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) * any more ... just clean up every urb's memory. */ finish_urb (ohci, urb); - } + } return 0; } /*-------------------------------------------------------------------------*/ +/* frees config/altsetting state for endpoints, + * including ED memory, dummy TD, and bulk/intr data toggle + */ + static void ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev) { @@ -303,7 +329,11 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev) struct hcd_dev *dev = (struct hcd_dev *) udev->hcpriv; int i; unsigned long flags; +#ifdef DEBUG + int rescans = 0; +#endif +rescan: /* free any eds, and dummy tds, still hanging around */ spin_lock_irqsave (&ohci->lock, flags); for (i = 0; i < 32; i++) { @@ -312,27 +342,47 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev) if (!ed) continue; - ed->state &= ~ED_URB_DEL; - if (ohci->disabled && ed->state == ED_OPER) - ed->state = ED_UNLINK; + if (ohci->disabled && ed->state != ED_IDLE) + ed->state = ED_IDLE; switch (ed->state) { - case ED_NEW: - break; - case ED_UNLINK: + case ED_UNLINK: /* wait a frame? */ + goto do_rescan; + case ED_IDLE: /* fully unlinked */ td_free (ohci, ed->dummy); break; - - case ED_OPER: default: +#ifdef DEBUG err ("illegal ED %d state in free_config, %d", i, ed->state); -#ifdef DEBUG - BUG (); #endif + /* ED_OPER: some driver disconnect() is broken, + * it didn't even start its unlinks much less wait + * for their completions. + * OTHERWISE: hcd bug, ed is garbage + */ + BUG (); } ed_free (ohci, ed); } spin_unlock_irqrestore (&ohci->lock, flags); + return; + +do_rescan: +#ifdef DEBUG + /* a driver->disconnect() returned before its unlinks completed? */ + if (in_interrupt ()) { + dbg ("WARNING: spin in interrupt; driver->disconnect() bug"); + dbg ("dev usb-%s-%s ep 0x%x", + ohci->hcd.self.bus_name, udev->devpath, i); + } + BUG_ON (!(readl (&ohci->regs->intrenable) & OHCI_INTR_SF)); + BUG_ON (rescans >= 2); /* HWBUG */ + rescans++; +#endif + + spin_unlock_irqrestore (&ohci->lock, flags); + wait_ms (1); + goto rescan; } static int ohci_get_frame (struct usb_hcd *hcd) @@ -471,7 +521,7 @@ static int hc_start (struct ohci_hcd *ohci) ohci->hcd.self.root_hub = udev = usb_alloc_dev (NULL, &ohci->hcd.self); ohci->hcd.state = USB_STATE_READY; if (!udev) { - ohci->disabled = 1; + disable (ohci); ohci->hc_control &= ~OHCI_CTRL_HCFS; writel (ohci->hc_control, &ohci->regs->control); return -ENOMEM; @@ -481,7 +531,7 @@ static int hc_start (struct ohci_hcd *ohci) udev->speed = USB_SPEED_FULL; if (usb_register_root_hub (udev, ohci->parent_dev) != 0) { usb_free_dev (udev); - ohci->disabled = 1; + disable (ohci); ohci->hc_control &= ~OHCI_CTRL_HCFS; writel (ohci->hc_control, &ohci->regs->control); return -ENODEV; @@ -507,8 +557,8 @@ static void ohci_irq (struct usb_hcd *hcd) /* cardbus/... hardware gone before remove() */ } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { - ohci->disabled++; - err ("%s device removed!", hcd->self.bus_name); + disable (ohci); + dbg ("%s device removed!", hcd->self.bus_name); return; /* interrupt for some other device? */ @@ -520,7 +570,7 @@ static void ohci_irq (struct usb_hcd *hcd) // dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); if (ints & OHCI_INTR_UE) { - ohci->disabled++; + disable (ohci); err ("OHCI Unrecoverable Error, %s disabled", hcd->self.bus_name); // e.g. due to PCI Master/Target Abort diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index e38860089a8b..9fd76677717d 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -22,7 +22,9 @@ */ #define read_roothub(hc, register, mask) ({ \ u32 temp = readl (&hc->regs->roothub.register); \ - if (hc->flags & OHCI_QUIRK_AMD756) \ + if (temp == -1) \ + disable (hc); \ + else if (hc->flags & OHCI_QUIRK_AMD756) \ while (temp & mask) \ temp = readl (&hc->regs->roothub.register); \ temp; }) @@ -71,8 +73,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) ports = roothub_a (ohci) & RH_A_NDP; if (ports > MAX_ROOT_PORTS) { - err ("%s: bogus NDP=%d", hcd->self.bus_name, ports); - err ("rereads as NDP=%d", + if (ohci->disabled) + return -ESHUTDOWN; + err ("%s bogus NDP=%d, rereads as NDP=%d", + hcd->self.bus_name, ports, readl (&ohci->regs->roothub.a) & RH_A_NDP); /* retry later; "should not happen" */ return 0; diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 1d3de55b90b9..0fe88b71cc30 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -77,12 +77,12 @@ static void finish_urb (struct ohci_hcd *ohci, struct urb *urb) usb_hcd_giveback_urb (&ohci->hcd, urb); } -static void td_submit_urb (struct urb *urb); +static void td_submit_urb (struct ohci_hcd *ohci, struct urb *urb); /* Report interrupt transfer completion, maybe reissue */ -static void intr_resub (struct ohci_hcd *hc, struct urb *urb) +static inline void intr_resub (struct ohci_hcd *hc, struct urb *urb) { - urb_priv_t *urb_priv = urb->hcpriv; + struct urb_priv *urb_priv = urb->hcpriv; unsigned long flags; // FIXME rewrite this resubmit path. use pci_dma_sync_single() @@ -120,7 +120,7 @@ static void intr_resub (struct ohci_hcd *hc, struct urb *urb) spin_unlock (&urb->lock); spin_lock (&hc->lock); - td_submit_urb (urb); + td_submit_urb (hc, urb); spin_unlock_irqrestore (&hc->lock, flags); } @@ -170,50 +170,50 @@ static int ep_rev (int num_bits, int word) /* link an ed into one of the HC chains */ -static int ep_link (struct ohci_hcd *ohci, struct ed *edi) +static void ed_schedule (struct ohci_hcd *ohci, struct ed *ed) { int int_branch, i; int inter, interval, load; __u32 *ed_p; - volatile struct ed *ed = edi; ed->state = ED_OPER; + ed->hwNextED = 0; + wmb (); + + /* we care about rm_list when setting CLE/BLE in case the HC was at + * work on some TD when CLE/BLE was turned off, and isn't quiesced + * yet. finish_unlinks() restarts as needed, some upcoming INTR_SF. + */ switch (ed->type) { case PIPE_CONTROL: - ed->hwNextED = 0; if (ohci->ed_controltail == NULL) { writel (ed->dma, &ohci->regs->ed_controlhead); } else { ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); } ed->ed_prev = ohci->ed_controltail; - if (!ohci->ed_controltail - && !ohci->ed_rm_list - && !ohci->sleeping - ) { + if (!ohci->ed_controltail && !ohci->ed_rm_list) { ohci->hc_control |= OHCI_CTRL_CLE; + writel (0, &ohci->regs->ed_controlcurrent); writel (ohci->hc_control, &ohci->regs->control); } - ohci->ed_controltail = edi; + ohci->ed_controltail = ed; break; case PIPE_BULK: - ed->hwNextED = 0; if (ohci->ed_bulktail == NULL) { writel (ed->dma, &ohci->regs->ed_bulkhead); } else { ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); } ed->ed_prev = ohci->ed_bulktail; - if (!ohci->ed_bulktail - && !ohci->ed_rm_list - && !ohci->sleeping - ) { + if (!ohci->ed_bulktail && !ohci->ed_rm_list) { ohci->hc_control |= OHCI_CTRL_BLE; + writel (0, &ohci->regs->ed_bulkcurrent); writel (ohci->hc_control, &ohci->regs->control); } - ohci->ed_bulktail = edi; + ohci->ed_bulktail = ed; break; case PIPE_INTERRUPT: @@ -231,17 +231,16 @@ static int ep_link (struct ohci_hcd *ohci, struct ed *edi) ed->hwNextED = *ed_p; *ed_p = cpu_to_le32 (ed->dma); } + wmb (); #ifdef OHCI_VERBOSE_DEBUG ohci_dump_periodic (ohci, "LINK_INT"); #endif break; case PIPE_ISOCHRONOUS: - ed->hwNextED = 0; - ed->interval = 1; + ed->ed_prev = ohci->ed_isotail; if (ohci->ed_isotail != NULL) { ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma); - ed->ed_prev = ohci->ed_isotail; } else { for ( i = 0; i < NUM_INTS; i += inter) { inter = 1; @@ -251,15 +250,18 @@ static int ep_link (struct ohci_hcd *ohci, struct ed *edi) inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->interval); *ed_p = cpu_to_le32 (ed->dma); } - ed->ed_prev = NULL; } - ohci->ed_isotail = edi; + wmb (); + ohci->ed_isotail = ed; #ifdef OHCI_VERBOSE_DEBUG ohci_dump_periodic (ohci, "LINK_ISO"); #endif break; } - return 0; + + /* the HC may not see the schedule updates yet, but if it does + * then they'll be properly ordered. + */ } /*-------------------------------------------------------------------------*/ @@ -288,9 +290,8 @@ static void periodic_unlink ( * just the link to the ed is unlinked. * the link from the ed still points to another operational ed or 0 * so the HC can eventually finish the processing of the unlinked ed - * caller guarantees the ED has no active TDs. */ -static int start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) +static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) { int i; @@ -361,15 +362,14 @@ static int start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) break; } - /* FIXME ED's "unlink" state is indeterminate; - * the HC might still be caching it (till SOF). - * - use ed_rm_list and finish_unlinks(), adding some state that - * prevents clobbering hw linkage before the appropriate SOF - * - a speedup: when only one urb is queued on the ed, save 1msec - * by making start_urb_unlink() use this routine to deschedule. + /* FIXME Except for a couple of exceptionally clean unlink cases + * (like unlinking the only c/b ED, with no TDs) HCs may still be + * caching this (till SOF). + * + * To avoid racing with the hardware, this needs to use ED_UNLINK + * and delay til next INTR_SF. Merge with start_urb_unlink(). */ - ed->state = ED_UNLINK; - return 0; + ed->state = ED_IDLE; } @@ -403,35 +403,27 @@ static struct ed *ed_get ( spin_lock_irqsave (&ohci->lock, flags); if (!(ed = dev->ep [ep])) { + struct td *td; + ed = ed_alloc (ohci, SLAB_ATOMIC); if (!ed) { /* out of memory */ goto done; } dev->ep [ep] = ed; - } - if (ed->state & ED_URB_DEL) { - /* pending unlink request */ - ed = 0; - goto done; - } - - if (ed->state == ED_NEW) { - struct td *td; - - ed->hwINFO = ED_SKIP; /* dummy td; end of td list for ed */ td = td_alloc (ohci, SLAB_ATOMIC); if (!td) { /* out of memory */ + ed_free (ohci, ed); ed = 0; goto done; } ed->dummy = td; ed->hwTailP = cpu_to_le32 (td->td_dma); ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */ - ed->state = ED_UNLINK; + ed->state = ED_IDLE; ed->type = type; } @@ -439,7 +431,7 @@ static struct ed *ed_get ( * state/mode info. Currently the upper layers don't support such * guarantees; we're lucky changing config/altsetting is rare. */ - if (ed->state == ED_UNLINK) { + if (ed->state == ED_IDLE) { u32 info; info = usb_pipedevice (pipe); @@ -494,30 +486,13 @@ done: /*-------------------------------------------------------------------------*/ /* request unlinking of an endpoint from an operational HC. - * put the ep on the rm_list and stop the bulk or ctrl list + * put the ep on the rm_list * real work is done at the next start frame (SF) hardware interrupt */ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed) { - /* already pending? */ - if (ed->state & ED_URB_DEL) - return; - ed->state |= ED_URB_DEL; - - ed->hwINFO |= ED_SKIP; - - switch (ed->type) { - case PIPE_CONTROL: /* stop control list */ - ohci->hc_control &= ~OHCI_CTRL_CLE; - writel (ohci->hc_control, - &ohci->regs->control); - break; - case PIPE_BULK: /* stop bulk list */ - ohci->hc_control &= ~OHCI_CTRL_BLE; - writel (ohci->hc_control, - &ohci->regs->control); - break; - } + ed_deschedule (ohci, ed); + ed->state = ED_UNLINK; /* SF interrupt might get delayed; record the frame counter value that * indicates when the HC isn't looking at it, so concurrent unlinks @@ -526,7 +501,7 @@ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed) */ ed->tick = le16_to_cpu (ohci->hcca->frame_no) + 1; - ed->ed_rm_list = ohci->ed_rm_list; + ed->ed_next = ohci->ed_rm_list; ohci->ed_rm_list = ed; /* enable SOF interrupt */ @@ -543,12 +518,12 @@ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed) /* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ static void -td_fill (struct ohci_hcd *ohci, unsigned int info, +td_fill (unsigned int info, dma_addr_t data, int len, struct urb *urb, int index) { struct td *td, *td_pt; - urb_priv_t *urb_priv = urb->hcpriv; + struct urb_priv *urb_priv = urb->hcpriv; int is_iso = info & TD_ISO; if (index >= urb_priv->length) { @@ -607,28 +582,30 @@ td_fill (struct ohci_hcd *ohci, unsigned int info, /*-------------------------------------------------------------------------*/ -/* prepare all TDs of a transfer */ - -static void td_submit_urb (struct urb *urb) -{ - urb_priv_t *urb_priv = urb->hcpriv; - struct ohci_hcd *ohci = hcd_to_ohci (urb->dev->bus->hcpriv); +/* Prepare all TDs of a transfer, and queue them onto the ED. + * Caller guarantees HC is active. + * Usually the ED is already on the schedule, so TDs might be + * processed as soon as they're queued. + */ +static void td_submit_urb ( + struct ohci_hcd *ohci, + struct urb *urb +) { + struct urb_priv *urb_priv = urb->hcpriv; dma_addr_t data; int data_len = urb->transfer_buffer_length; - int cnt = 0; - __u32 info = 0; - unsigned int toggle = 0; + int cnt = 0; + u32 info = 0; int is_out = usb_pipeout (urb->pipe); - /* OHCI handles the DATA-toggles itself, we just use the - * USB-toggle bits for resetting + /* OHCI handles the bulk/interrupt data toggles itself. We just + * use the device toggle bits for resetting, and rely on the fact + * that resetting toggle is meaningless if the endpoint is active. */ - if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) { - toggle = TD_T_TOGGLE; - } else { - toggle = TD_T_DATA0; + if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) { usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out, 1); + urb_priv->ed->hwHeadP &= ~ED_C; } urb_priv->td_cnt = 0; @@ -644,91 +621,88 @@ static void td_submit_urb (struct urb *urb) /* NOTE: TD_CC is set so we can tell which TDs the HC processed by * using TD_CC_GET, as well as by seeing them on the done list. + * (CC = NotAccessed ... 0x0F, or 0x0E in PSWs for ISO.) */ - switch (usb_pipetype (urb->pipe)) { - case PIPE_BULK: - info = is_out - ? TD_CC | TD_DP_OUT - : TD_CC | TD_DP_IN ; - /* TDs _could_ transfer up to 8K each */ - while (data_len > 4096) { - td_fill (ohci, - info | (cnt? TD_T_TOGGLE:toggle), - data, 4096, urb, cnt); - data += 4096; data_len -= 4096; cnt++; - } - /* maybe avoid ED halt on final TD short read */ - if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) - info |= TD_R; - td_fill (ohci, info | (cnt ? TD_T_TOGGLE : toggle), - data, data_len, urb, cnt); + switch (urb_priv->ed->type) { + + /* Bulk and interrupt are identical except for where in the schedule + * their EDs live. + */ + // case PIPE_BULK: + // case PIPE_INTERRUPT: + default: + info = is_out + ? TD_T_TOGGLE | TD_CC | TD_DP_OUT + : TD_T_TOGGLE | TD_CC | TD_DP_IN; + /* TDs _could_ transfer up to 8K each */ + while (data_len > 4096) { + td_fill (info, data, 4096, urb, cnt); + data += 4096; + data_len -= 4096; cnt++; - if ((urb->transfer_flags & USB_ZERO_PACKET) - && cnt < urb_priv->length) { - td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), - 0, 0, urb, cnt); - cnt++; - } - /* start bulk list */ - if (!ohci->sleeping) { - wmb (); - writel (OHCI_BLF, &ohci->regs->cmdstatus); - } - break; + } + /* maybe avoid ED halt on final TD short read */ + if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) + info |= TD_R; + td_fill (info, data, data_len, urb, cnt); + cnt++; + if ((urb->transfer_flags & USB_ZERO_PACKET) + && cnt < urb_priv->length) { + td_fill (info, 0, 0, urb, cnt); + cnt++; + } + /* maybe kickstart bulk list */ + if (urb_priv->ed->type == PIPE_BULK) { + wmb (); + writel (OHCI_BLF, &ohci->regs->cmdstatus); + } + break; - case PIPE_INTERRUPT: - /* current policy: only one TD per request. - * otherwise identical to bulk, except for BLF - */ - info = TD_CC | toggle; - info |= is_out - ? TD_DP_OUT - : TD_R | TD_DP_IN; - td_fill (ohci, info, data, data_len, urb, cnt++); - break; - - case PIPE_CONTROL: - /* control requests don't use toggle state */ - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill (ohci, info, - pci_map_single (ohci->hcd.pdev, - urb->setup_packet, 8, - PCI_DMA_TODEVICE), - 8, urb, cnt++); - if (data_len > 0) { - info = TD_CC | TD_R | TD_T_DATA1; - info |= is_out ? TD_DP_OUT : TD_DP_IN; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill (ohci, info, data, data_len, - urb, cnt++); - } - info = is_out - ? TD_CC | TD_DP_IN | TD_T_DATA1 - : TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill (ohci, info, data, 0, urb, cnt++); - /* start control list */ - if (!ohci->sleeping) { - wmb (); - writel (OHCI_CLF, &ohci->regs->cmdstatus); - } - break; - - case PIPE_ISOCHRONOUS: - for (cnt = 0; cnt < urb->number_of_packets; cnt++) { - int frame = urb->start_frame; - - // FIXME scheduling should handle frame counter - // roll-around ... exotic case (and OHCI has - // a 2^16 iso range, vs other HCs max of 2^10) - frame += cnt * urb->interval; - frame &= 0xffff; - td_fill (ohci, TD_CC | TD_ISO | frame, - data + urb->iso_frame_desc [cnt].offset, - urb->iso_frame_desc [cnt].length, urb, cnt); - } - break; - } - if (urb_priv->length != cnt) + /* control manages DATA0/DATA1 toggle per-request; SETUP resets it, + * any DATA phase works normally, and the STATUS ack is special. + */ + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (info, + pci_map_single (ohci->hcd.pdev, + urb->setup_packet, 8, + PCI_DMA_TODEVICE), + 8, urb, cnt++); + if (data_len > 0) { + info = TD_CC | TD_R | TD_T_DATA1; + info |= is_out ? TD_DP_OUT : TD_DP_IN; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill (info, data, data_len, urb, cnt++); + } + info = is_out + ? TD_CC | TD_DP_IN | TD_T_DATA1 + : TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (info, data, 0, urb, cnt++); + /* maybe kickstart control list */ + wmb (); + writel (OHCI_CLF, &ohci->regs->cmdstatus); + break; + + /* ISO has no retransmit, so no toggle; and it uses special TDs. + * Each TD could handle multiple consecutive frames (interval 1); + * we could often reduce the number of TDs here. + */ + case PIPE_ISOCHRONOUS: + for (cnt = 0; cnt < urb->number_of_packets; cnt++) { + int frame = urb->start_frame; + + // FIXME scheduling should handle frame counter + // roll-around ... exotic case (and OHCI has + // a 2^16 iso range, vs other HCs max of 2^10) + frame += cnt * urb->interval; + frame &= 0xffff; + td_fill (TD_CC | TD_ISO | frame, + data + urb->iso_frame_desc [cnt].offset, + urb->iso_frame_desc [cnt].length, urb, cnt); + } + break; + } + if (urb_priv->length != cnt) dbg ("TD LENGTH %d != CNT %d", urb_priv->length, cnt); } @@ -744,13 +718,17 @@ static void td_done (struct urb *urb, struct td *td) u32 tdINFO = le32_to_cpup (&td->hwINFO); int cc = 0; - /* ISO ... drivers see per-TD length/status */ if (tdINFO & TD_ISO) { u16 tdPSW = le16_to_cpu (td->hwPSW [0]); int dlen = 0; + /* NOTE: assumes FC in tdINFO == 0 (and MAXPSW == 1) */ + cc = (tdPSW >> 12) & 0xF; + if (tdINFO & TD_CC) /* hc didn't touch? */ + return; + if (usb_pipeout (urb->pipe)) dlen = urb->iso_frame_desc [td->index].length; else @@ -759,9 +737,11 @@ static void td_done (struct urb *urb, struct td *td) urb->iso_frame_desc [td->index].actual_length = dlen; urb->iso_frame_desc [td->index].status = cc_to_error [cc]; - if (cc != 0) +#ifdef VERBOSE_DEBUG + if (cc != TD_CC_NOERROR) dbg (" urb %p iso TD %p (%d) len %d CC %d", urb, td, 1 + td->index, dlen, cc); +#endif /* BULK, INT, CONTROL ... drivers see aggregate length/status, * except that "setup" bytes aren't counted and "short" transfers @@ -783,7 +763,7 @@ static void td_done (struct urb *urb, struct td *td) if (cc == TD_DATAUNDERRUN && !(urb->transfer_flags & URB_SHORT_NOT_OK)) cc = TD_CC_NOERROR; - if (cc != TD_CC_NOERROR) { + if (cc != TD_CC_NOERROR && cc < 0x0E) { spin_lock (&urb->lock); if (urb->status == -EINPROGRESS) urb->status = cc_to_error [cc]; @@ -801,7 +781,7 @@ static void td_done (struct urb *urb, struct td *td) } #ifdef VERBOSE_DEBUG - if (cc != 0) + if (cc != TD_CC_NOERROR && cc < 0x0E) dbg (" urb %p TD %p (%d) CC %d, len=%d/%d", urb, td, 1 + td->index, cc, urb->actual_length, @@ -876,28 +856,39 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) static void finish_unlinks (struct ohci_hcd *ohci, u16 tick) { struct ed *ed, **last; - int ctrl = 0, bulk = 0; +rescan_all: for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) { struct td *td, *td_next, *tdHeadP, *tdTailP; u32 *td_p; - int unlinked; + int completed, modified; /* only take off EDs that the HC isn't using, accounting for - * frame counter wraps. completion callbacks might prepend - * EDs to the list, they'll be checked next irq. + * frame counter wraps. */ - if (tick_before (tick, ed->tick)) { - last = &ed->ed_rm_list; + if (tick_before (tick, ed->tick) && !ohci->disabled) { + last = &ed->ed_next; continue; } - *last = ed->ed_rm_list; - ed->ed_rm_list = 0; - unlinked = 0; - /* unlink urbs from first one requested to queue end; - * leave earlier urbs alone + /* reentrancy: if we drop the schedule lock, someone might + * have modified this list. normally it's just prepending + * entries (which we'd ignore), but paranoia won't hurt. */ + *last = ed->ed_next; + ed->ed_next = 0; + modified = 0; + + /* unlink urbs as requested, but rescan the list after + * we call a completion since it might have unlinked + * another (earlier) urb + * + * FIXME use td_list to scan, not ed hashtables. + * completely abolish ed hashtables! + */ +rescan_this: + completed = 0; + tdTailP = dma_to_td (ohci, le32_to_cpup (&ed->hwTailP)); tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP)); td_p = &ed->hwHeadP; @@ -908,21 +899,18 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick) td_next = dma_to_td (ohci, le32_to_cpup (&td->hwNextTD)); - if (unlinked || (urb_priv->state == URB_DEL)) { - u32 tdINFO = le32_to_cpup (&td->hwINFO); - - unlinked = 1; + if (urb_priv->state == URB_DEL) { /* HC may have partly processed this TD */ - if (TD_CC_GET (tdINFO) < 0xE) - td_done (urb, td); + td_done (urb, td); + urb_priv->td_cnt++; + *td_p = td->hwNextTD | (*td_p & __constant_cpu_to_le32 (0x3)); /* URB is done; clean up */ - if (++ (urb_priv->td_cnt) == urb_priv->length) { - if (urb->status == -EINPROGRESS) - urb->status = -ECONNRESET; + if (urb_priv->td_cnt == urb_priv->length) { + modified = completed = 1; spin_unlock (&ohci->lock); finish_urb (ohci, urb); spin_lock (&ohci->lock); @@ -932,49 +920,52 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick) } } - /* FIXME actually want four cases here: - * (a) finishing URB unlink - * [a1] no URBs queued, so start ED unlink - * [a2] some (earlier) URBs still linked, re-enable - * (b) finishing ED unlink - * [b1] no URBs queued, ED is truly idle now - * ... we could set state ED_NEW and free dummy - * [b2] URBs now queued, link ED back into schedule - * right now we only have (a) - */ - ed->state &= ~ED_URB_DEL; - tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP)); - - if (tdHeadP == tdTailP) { - if (ed->state == ED_OPER) - start_ed_unlink (ohci, ed); - } else - ed->hwINFO &= ~ED_SKIP; + /* ED's now officially unlinked, hc doesn't see */ + ed->state = ED_IDLE; + ed->hwINFO &= ~ED_SKIP; + ed->hwHeadP &= ~cpu_to_le32 (ED_H); + ed->hwNextED = 0; - switch (ed->type) { - case PIPE_CONTROL: - ctrl = 1; - break; - case PIPE_BULK: - bulk = 1; - break; + /* but if there's work queued, reschedule */ + tdHeadP = dma_to_td (ohci, le32_to_cpup (&ed->hwHeadP)); + if (tdHeadP != tdTailP) { + if (completed) + goto rescan_this; + if (!ohci->disabled && !ohci->sleeping) + ed_schedule (ohci, ed); } + + if (modified) + goto rescan_all; } /* maybe reenable control and bulk lists */ - if (!ohci->disabled) { - if (ctrl) /* reset control list */ - writel (0, &ohci->regs->ed_controlcurrent); - if (bulk) /* reset bulk list */ - writel (0, &ohci->regs->ed_bulkcurrent); - if (!ohci->ed_rm_list) { - if (ohci->ed_controltail) - ohci->hc_control |= OHCI_CTRL_CLE; - if (ohci->ed_bulktail) - ohci->hc_control |= OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); + if (!ohci->disabled && !ohci->ed_rm_list) { + u32 command = 0, control = 0; + + if (ohci->ed_controltail) { + command |= OHCI_CLF; + if (!(ohci->hc_control & OHCI_CTRL_CLE)) { + control |= OHCI_CTRL_CLE; + writel (0, &ohci->regs->ed_controlcurrent); + } } - } + if (ohci->ed_bulktail) { + command |= OHCI_BLF; + if (!(ohci->hc_control & OHCI_CTRL_BLE)) { + control |= OHCI_CTRL_BLE; + writel (0, &ohci->regs->ed_bulkcurrent); + } + } + + /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ + if (control) { + ohci->hc_control |= control; + writel (ohci->hc_control, &ohci->regs->control); + } + if (command) + writel (command, &ohci->regs->cmdstatus); + } } @@ -1026,7 +1017,7 @@ static void dl_done_list (struct ohci_hcd *ohci, struct td *td) if ((ed->hwHeadP & __constant_cpu_to_le32 (TD_MASK)) == ed->hwTailP && (ed->state == ED_OPER)) - start_ed_unlink (ohci, ed); + ed_deschedule (ohci, ed); td = td_next; } spin_unlock_irqrestore (&ohci->lock, flags); diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 7969e669052d..4af5cdf0aa34 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -31,15 +31,21 @@ struct ed { /* rest are purely for the driver's use */ dma_addr_t dma; /* addr of ED */ + struct td *dummy; /* next TD to activate */ + + /* host's view of schedule */ + struct ed *ed_next; /* on schedule or rm_list */ struct ed *ed_prev; /* for non-interrupt EDs */ - struct td *dummy; struct list_head td_list; /* "shadow list" of our TDs */ - u8 state; /* ED_{NEW,UNLINK,OPER} */ -#define ED_NEW 0x00 /* unused, no dummy td */ -#define ED_UNLINK 0x01 /* dummy td, maybe linked to hc */ -#define ED_OPER 0x02 /* dummy td, _is_ linked to hc */ -#define ED_URB_DEL 0x08 /* for unlinking; masked in */ + /* create --> IDLE --> OPER --> ... --> IDLE --> destroy + * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... + * some special cases : OPER --> IDLE ... + */ + u8 state; /* ED_{IDLE,UNLINK,OPER} */ +#define ED_IDLE 0x00 /* NOT linked to HC */ +#define ED_UNLINK 0x01 /* being unlinked from hc */ +#define ED_OPER 0x02 /* IS linked to hc */ u8 type; /* PIPE_{BULK,...} */ u16 interval; /* interrupt, isochronous */ @@ -53,7 +59,6 @@ struct ed { /* HC may see EDs on rm_list until next frame (frame_no == tick) */ u16 tick; - struct ed *ed_rm_list; } __attribute__ ((aligned(16))); #define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */ @@ -396,5 +401,5 @@ struct ohci_hcd { struct usb_hcd hcd; }; -#define hcd_to_ohci(hcd_ptr) list_entry(hcd_ptr, struct ohci_hcd, hcd) +#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd) diff --git a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h index 0fa9036358dc..6d726223090a 100644 --- a/drivers/usb/image/scanner.h +++ b/drivers/usb/image/scanner.h @@ -93,9 +93,12 @@ static struct usb_device_id scanner_device_ids [] = { { USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */ { USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */ /* Canon */ - { USB_DEVICE(0x04a9, 0x2202) }, /* FB620U */ + { USB_DEVICE(0x04a9, 0x2202) }, /* CanoScan FB620U */ + { USB_DEVICE(0x04a9, 0x2204) }, /* CanoScan FB630U/FB636U */ + { USB_DEVICE(0x04a9, 0x2206) }, /* CanoScan N650U/N656U */ + { USB_DEVICE(0x04a9, 0x2207) }, /* CanoScan N1220U */ + { USB_DEVICE(0x04a9, 0x2208) }, /* CanoScan D660U */ { USB_DEVICE(0x04a9, 0x220b) }, /* D646U */ - { USB_DEVICE(0x04a9, 0x2207) }, /* 1220U */ /* Colorado -- See Primax/Colorado below */ /* Epson -- See Seiko/Epson below */ /* Genius */ diff --git a/drivers/usb/input/Config.help b/drivers/usb/input/Config.help index aad9102e43ae..58370e3c6c46 100644 --- a/drivers/usb/input/Config.help +++ b/drivers/usb/input/Config.help @@ -18,28 +18,35 @@ CONFIG_USB_HID CONFIG_USB_HIDINPUT Say Y here if you want to use a USB keyboard, mouse or joystick, - or any other HID input device. You also need Input layer support, - (CONFIG_INPUT) which you select under "Input core support". + or any other HID input device. You also need "Input core support", + (CONFIG_INPUT), which you select under "Input device support", above. If unsure, say Y. CONFIG_HID_FF - Say Y here is you want force feedback support for a few hid devices. See + Say Y here is you want force feedback support for a few HID devices. See below for a list of supported devices. See Documentation/input/ff.txt for a description of the force feedback API. If unsure, say N. -CONFIG_LOGITECH_RUMBLE - Say Y here if you have a Logitech WingMan Cordless rumble pad and if you - want to enable force feedback. Note: if you say N here, this device will - still be supported, but without force feedback. +CONFIG_LOGITECH_FF + Say Y here if you have one of these devices: + - Logitech WingMan Cordless RumblePad + - Logitech WingMan Force 3D + and if you want to enable force feedback for them. + Note: if you say N here, this device will still be supported, but without + force feedback. CONFIG_HID_PID - Say Y yes if you have a PID-compliant joystick and wish to enable force + Say Y here if you have a PID-compliant joystick and wish to enable force feedback for it. The Microsoft Sidewinder Force Feedback 2 is one such device. +CONFIG_LOGITECH_3D + Say Y here if you have a Logitech force feedback device from the + *3D family. + CONFIG_USB_HIDDEV Say Y here if you want to support HID devices (from the USB specification standpoint) that aren't strictly user interface diff --git a/drivers/usb/input/Config.in b/drivers/usb/input/Config.in index 9c354df9e1a1..9eef9842e6b5 100644 --- a/drivers/usb/input/Config.in +++ b/drivers/usb/input/Config.in @@ -11,8 +11,7 @@ fi dep_mbool ' HID input layer support' CONFIG_USB_HIDINPUT $CONFIG_INPUT $CONFIG_USB_HID dep_mbool ' Force feedback support (EXPERIMENTAL)' CONFIG_HID_FF $CONFIG_USB_HIDINPUT $CONFIG_EXPERIMENTAL dep_mbool ' PID Devices' CONFIG_HID_PID $CONFIG_USB_HID $CONFIG_HID_FF -dep_mbool ' Logitech RumblePad support' CONFIG_LOGITECH_RUMBLE $CONFIG_USB_HID $CONFIG_HID_FF -dep_mbool ' Logitech WingMan Force 3D support' CONFIG_LOGITECH_3D $CONFIG_USB_HID $CONFIG_HID_FF +dep_mbool ' Logitech WingMan *3D support' CONFIG_LOGITECH_FF $CONFIG_USB_HID $CONFIG_HID_FF dep_mbool ' /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID if [ "$CONFIG_USB_HID" != "y" ]; then diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 610e68ca25dd..5e324c467793 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile @@ -16,12 +16,9 @@ endif ifeq ($(CONFIG_HID_PID),y) hid-objs += pid.o endif -ifeq ($(CONFIG_LOGITECH_RUMBLE),y) +ifeq ($(CONFIG_LOGITECH_FF),y) hid-objs += hid-lgff.o endif -ifeq ($(CONFIG_LOGITECH_3D),y) - hid-objs += hid-lg3dff.o -endif ifeq ($(CONFIG_HID_FF),y) hid-objs += hid-ff.o endif diff --git a/drivers/usb/input/fixp-arith.h b/drivers/usb/input/fixp-arith.h index 1b3066daea1f..e20fa1a44b35 100644 --- a/drivers/usb/input/fixp-arith.h +++ b/drivers/usb/input/fixp-arith.h @@ -66,7 +66,13 @@ inline fixp_t fixp_new16(s16 a) inline fixp_t fixp_cos(unsigned int degrees) { int quadrant = (degrees / 90) & 3; - unsigned int i = (degrees % 90) >> 1; + unsigned int i = degrees % 90; + + if (quadrant == 1 || quadrant == 3) { + i = 89 - i; + } + + i >>= 1; return (quadrant == 1 || quadrant == 2)? -cos_table[i] : cos_table[i]; } diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 8c941083376c..b5743d2ac59b 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1281,10 +1281,8 @@ void hid_init_reports(struct hid_device *hid) usb_unlink_urb(hid->urbout); } - if (err) { + if (err) warn("timeout initializing reports\n"); - return; - } report_enum = hid->report_enum + HID_INPUT_REPORT; list = report_enum->report_list.next; @@ -1551,8 +1549,8 @@ static void* hid_probe(struct usb_device *dev, unsigned int ifnum, } static struct usb_device_id hid_usb_ids [] = { - { match_flags: USB_DEVICE_ID_MATCH_INT_CLASS, - bInterfaceClass: USB_INTERFACE_CLASS_HID }, + { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, + .bInterfaceClass = USB_INTERFACE_CLASS_HID }, { } /* Terminating entry */ }; diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c index dc0fcaf424fa..ad6d27769db2 100644 --- a/drivers/usb/input/hid-ff.c +++ b/drivers/usb/input/hid-ff.c @@ -1,5 +1,5 @@ /* - * $Id: hid-ff.c,v 1.3 2002/06/09 11:06:38 jdeneux Exp $ + * $Id: hid-ff.c,v 1.2 2002/04/18 22:02:47 jdeneux Exp $ * * Force feedback support for hid devices. * Not all hid devices use the same protocol. For example, some use PID, @@ -44,17 +44,15 @@ extern int hid_pid_init(struct hid_device* hid); * devices, you need to add the USB vendor and product ids here. */ struct hid_ff_initializer { - __u16 idVendor; - __u16 idProduct; + u16 idVendor; + u16 idProduct; int (*init)(struct hid_device*); }; static struct hid_ff_initializer inits[] = { -#ifdef CONFIG_LOGITECH_RUMBLE +#ifdef CONFIG_LOGITECH_FF {0x46d, 0xc211, hid_lgff_init}, -#endif -#ifdef CONFIG_LOGITECH_3D - {0x46d, 0xc283, hid_lg3d_init}, + {0x46d, 0xc283, hid_lgff_init}, #endif #ifdef CONFIG_HID_PID {0x45e, 0x001b, hid_pid_init}, @@ -68,8 +66,8 @@ static struct hid_ff_initializer *hid_get_ff_init(__u16 idVendor, struct hid_ff_initializer *init; for (init = inits; init->idVendor - && !(init->idVendor == idVendor - && init->idProduct == idProduct); + && !(init->idVendor == idVendor + && init->idProduct == idProduct); init++); return init->idVendor? init : NULL; diff --git a/drivers/usb/input/hid-lg3dff.c b/drivers/usb/input/hid-lg3dff.c deleted file mode 100644 index b9f5636dd614..000000000000 --- a/drivers/usb/input/hid-lg3dff.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * $$ - * - * Force feedback support for hid-compliant devices of the Logitech *3D family - * - * Copyright (c) 2002 Johann Deneux - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so by - * e-mail - mail your message to <deneux@ifrance.com> - */ - -#include <linux/input.h> -#include <linux/sched.h> - -#define DEBUG -#include <linux/usb.h> - -#include <linux/circ_buf.h> - -#include "hid.h" -#include "fixp-arith.h" - -#define RUN_AT(t) (jiffies + (t)) - -/* Periodicity of the update */ -#define PERIOD (HZ/10) - -/* Effect status: lg3d_effect::flags */ -#define EFFECT_STARTED 0 /* Effect is going to play after some time - (ff_replay.delay) */ -#define EFFECT_PLAYING 1 /* Effect is being played */ -#define EFFECT_USED 2 - -/* Check that the current process can access an effect */ -#define CHECK_OWNERSHIP(i, l) \ - (i>=0 && i<N_EFFECTS \ - && test_bit(EFFECT_USED, l->effects[i].flags) \ - && (current->pid == 0 \ - || l->effects[i].owner == current->pid)) - -#define N_EFFECTS 8 - -struct lg3d_effect { - pid_t owner; - - struct ff_effect effect; /* Description of the effect */ - - unsigned int count; /* Number of times left to play */ - unsigned long flags[1]; - - unsigned long started_at; /* When the effect started to play */ -}; - -// For lg3d_device::flags -#define DEVICE_USB_XMIT 0 /* An URB is being sent */ -#define DEVICE_CLOSING 1 /* The driver is being unitialised */ - -struct lg3d_device { - struct hid_device* hid; - - struct urb* urbffout; /* Output URB used to send ff commands */ - struct usb_ctrlrequest ffcr; /* ff commands use control URBs */ - char buf[8]; - - struct lg3d_effect effects[N_EFFECTS]; - spinlock_t lock; /* device-level lock. Having locks on - a per-effect basis could be nice, but - isn't really necessary */ - struct timer_list timer; - unsigned long last_time; /* Last time the timer handler was - executed */ - - unsigned long flags[1]; /* Contains various information about the - state of the driver for this device */ -}; - -static void hid_lg3d_ctrl_out(struct urb *urb); -static void hid_lg3d_exit(struct hid_device* hid); -static int hid_lg3d_event(struct hid_device *hid, struct input_dev *input, - unsigned int type, unsigned int code, int value); -static int hid_lg3d_flush(struct input_dev *input, struct file *file); -static int hid_lg3d_upload_effect(struct input_dev *input, - struct ff_effect *effect); -static int hid_lg3d_erase(struct input_dev *input, int id); -static void hid_lg3d_timer(unsigned long timer_data); - - -int hid_lg3d_init(struct hid_device* hid) -{ - struct lg3d_device *private; - - /* Private data */ - private = kmalloc(sizeof(struct lg3d_device), GFP_KERNEL); - if (!private) return -1; - - memset(private, 0, sizeof(struct lg3d_device)); - - hid->ff_private = private; - - private->hid = hid; - spin_lock_init(&private->lock); - - /* Timer for the periodic update task */ - init_timer(&private->timer); - private->timer.data = (unsigned long)private; - private->timer.function = hid_lg3d_timer; - - /* Event and exit callbacks */ - hid->ff_exit = hid_lg3d_exit; - hid->ff_event = hid_lg3d_event; - - /* USB init */ - if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) { - kfree(hid->ff_private); - return -1; - } - - usb_fill_control_urb(private->urbffout, hid->dev, 0, - (void*) &private->ffcr, private->buf, 8, - hid_lg3d_ctrl_out, hid); - dbg("Created ff output control urb"); - - /* Input init */ - hid->input.upload_effect = hid_lg3d_upload_effect; - hid->input.flush = hid_lg3d_flush; - set_bit(FF_CONSTANT, hid->input.ffbit); - set_bit(EV_FF, hid->input.evbit); - hid->input.ff_effects_max = N_EFFECTS; - - printk(KERN_INFO "Force feedback for Logitech *3D devices by Johann Deneux <deneux@ifrance.com>\n"); - - /* Start the update task */ - private->timer.expires = RUN_AT(PERIOD); - add_timer(&private->timer); /*TODO: only run the timer when at least - one effect is playing */ - - return 0; -} - -static void hid_lg3d_exit(struct hid_device* hid) -{ - struct lg3d_device *lg3d = hid->ff_private; - unsigned long flags; - - spin_lock_irqsave(&lg3d->lock, flags); - set_bit(DEVICE_CLOSING, lg3d->flags); - spin_unlock_irqrestore(&lg3d->lock, flags); - - del_timer_sync(&lg3d->timer); - - if (lg3d->urbffout) { - usb_unlink_urb(lg3d->urbffout); - usb_free_urb(lg3d->urbffout); - } - - kfree(lg3d); -} - -static int hid_lg3d_event(struct hid_device *hid, struct input_dev* input, - unsigned int type, unsigned int code, int value) -{ - struct lg3d_device *lg3d = hid->ff_private; - struct lg3d_effect *effect = lg3d->effects + code; - unsigned long flags; - - if (type != EV_FF) return -EINVAL; - if (!CHECK_OWNERSHIP(code, lg3d)) return -EACCES; - if (value < 0) return -EINVAL; - - spin_lock_irqsave(&lg3d->lock, flags); - - if (value > 0) { - if (test_bit(EFFECT_STARTED, effect->flags)) { - spin_unlock_irqrestore(&lg3d->lock, flags); - return -EBUSY; - } - if (test_bit(EFFECT_PLAYING, effect->flags)) { - spin_unlock_irqrestore(&lg3d->lock, flags); - return -EBUSY; - } - - effect->count = value; - - if (effect->effect.replay.delay) { - set_bit(EFFECT_STARTED, effect->flags); - } else { - set_bit(EFFECT_PLAYING, effect->flags); - } - effect->started_at = jiffies; - } - else { /* value == 0 */ - clear_bit(EFFECT_STARTED, effect->flags); - clear_bit(EFFECT_PLAYING, effect->flags); - } - - spin_unlock_irqrestore(&lg3d->lock, flags); - - return 0; -} - -/* Erase all effects this process owns */ -static int hid_lg3d_flush(struct input_dev *dev, struct file *file) -{ - struct hid_device *hid = dev->private; - struct lg3d_device *lg3d = hid->ff_private; - int i; - - for (i=0; i<dev->ff_effects_max; ++i) { - - /*NOTE: no need to lock here. The only times EFFECT_USED is - modified is when effects are uploaded or when an effect is - erased. But a process cannot close its dev/input/eventX fd - and perform ioctls on the same fd all at the same time */ - if ( current->pid == lg3d->effects[i].owner - && test_bit(EFFECT_USED, lg3d->effects[i].flags)) { - - if (hid_lg3d_erase(dev, i)) - warn("erase effect %d failed", i); - } - - } - - return 0; -} - -static int hid_lg3d_erase(struct input_dev *dev, int id) -{ - struct hid_device *hid = dev->private; - struct lg3d_device *lg3d = hid->ff_private; - unsigned long flags; - - if (!CHECK_OWNERSHIP(id, lg3d)) return -EACCES; - - spin_lock_irqsave(&lg3d->lock, flags); - lg3d->effects[id].flags[0] = 0; - spin_unlock_irqrestore(&lg3d->lock, flags); - - return 0; -} - -static int hid_lg3d_upload_effect(struct input_dev* input, - struct ff_effect* effect) -{ - struct hid_device *hid = input->private; - struct lg3d_device *lg3d = hid->ff_private; - struct lg3d_effect new; - int id; - unsigned long flags; - - dbg("ioctl upload"); - - if (!test_bit(effect->type, input->ffbit)) return -EINVAL; - - if (effect->type != FF_CONSTANT) return -EINVAL; - - spin_lock_irqsave(&lg3d->lock, flags); - - if (effect->id == -1) { - int i; - - for (i=0; i<N_EFFECTS && test_bit(EFFECT_USED, lg3d->effects[i].flags); ++i); - if (i >= N_EFFECTS) { - spin_unlock_irqrestore(&lg3d->lock, flags); - return -ENOSPC; - } - - effect->id = i; - lg3d->effects[i].owner = current->pid; - lg3d->effects[i].flags[0] = 0; - set_bit(EFFECT_USED, lg3d->effects[i].flags); - } - else if (!CHECK_OWNERSHIP(effect->id, lg3d)) { - spin_unlock_irqrestore(&lg3d->lock, flags); - return -EACCES; - } - - id = effect->id; - new = lg3d->effects[id]; - - new.effect = *effect; - new.effect.replay = effect->replay; - - if (test_bit(EFFECT_STARTED, lg3d->effects[id].flags) - || test_bit(EFFECT_STARTED, lg3d->effects[id].flags)) { - - /* Changing replay parameters is not allowed (for the time - being) */ - if (new.effect.replay.delay != lg3d->effects[id].effect.replay.delay - || new.effect.replay.length != lg3d->effects[id].effect.replay.length) { - spin_unlock_irqrestore(&lg3d->lock, flags); - return -ENOSYS; - } - - lg3d->effects[id] = new; - - } else { - lg3d->effects[id] = new; - } - - spin_unlock_irqrestore(&lg3d->lock, flags); - return 0; -} - -static void hid_lg3d_ctrl_out(struct urb *urb) -{ - struct hid_device *hid = urb->context; - struct lg3d_device *lg3d = hid->ff_private; - unsigned long flags; - - spin_lock_irqsave(&lg3d->lock, flags); - - if (urb->status) - warn("hid_irq_ffout status %d received", urb->status); - clear_bit(DEVICE_USB_XMIT, lg3d->flags); - dbg("xmit = 0"); - - spin_unlock_irqrestore(&lg3d->lock, flags); -} - -static void hid_lg3d_timer(unsigned long timer_data) -{ - struct lg3d_device *lg3d = (struct lg3d_device*)timer_data; - struct hid_device *hid = lg3d->hid; - unsigned long flags; - int x, y; - int i; - int err; - - spin_lock_irqsave(&lg3d->lock, flags); - - if (test_bit(DEVICE_USB_XMIT, lg3d->flags)) { - if (lg3d->urbffout->status != -EINPROGRESS) { - warn("xmit *not* in progress"); - } - else { - dbg("xmit in progress"); - } - - spin_unlock_irqrestore(&lg3d->lock, flags); - - lg3d->timer.expires = RUN_AT(PERIOD); - add_timer(&lg3d->timer); - - return; - } - - x = 0x7f; - y = 0x7f; - - for (i=0; i<N_EFFECTS; ++i) { - struct lg3d_effect* effect = lg3d->effects +i; - - if (test_bit(EFFECT_PLAYING, effect->flags)) { - - if (effect->effect.type == FF_CONSTANT) { - //TODO: handle envelopes - int degrees = effect->effect.direction * 360 >> 16; - x += fixp_mult(fixp_sin(degrees), - fixp_new16(effect->effect.u.constant.level)); - y += fixp_mult(-fixp_cos(degrees), - fixp_new16(effect->effect.u.constant.level)); - } - - /* One run of the effect is finished playing */ - if (time_after(jiffies, - effect->started_at - + effect->effect.replay.delay*HZ/1000 - + effect->effect.replay.length*HZ/1000)) { - dbg("Finished playing once"); - if (--effect->count <= 0) { - dbg("Stopped"); - clear_bit(EFFECT_PLAYING, effect->flags); - } - else { - dbg("Start again"); - if (effect->effect.replay.length != 0) { - clear_bit(EFFECT_PLAYING, effect->flags); - set_bit(EFFECT_STARTED, effect->flags); - } - effect->started_at = jiffies; - } - } - - } else if (test_bit(EFFECT_STARTED, lg3d->effects[i].flags)) { - dbg("Started"); - /* Check if we should start playing the effect */ - if (time_after(jiffies, - lg3d->effects[i].started_at - + lg3d->effects[i].effect.replay.delay*HZ/1000)) { - dbg("Now playing"); - clear_bit(EFFECT_STARTED, lg3d->effects[i].flags); - set_bit(EFFECT_PLAYING, lg3d->effects[i].flags); - } - } - } - - if (x < 0) x = 0; - if (x > 0xff) x = 0xff; - if (y < 0) y = 0; - if (y > 0xff) y = 0xff; - - lg3d->urbffout->pipe = usb_sndctrlpipe(hid->dev, 0); - lg3d->ffcr.bRequestType = USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE; - lg3d->urbffout->transfer_buffer_length = lg3d->ffcr.wLength = 8; - lg3d->ffcr.bRequest = 9; - lg3d->ffcr.wValue = 0x0200; /*NOTE: Potential problem with - little/big endian */ - lg3d->ffcr.wIndex = 0; - - lg3d->urbffout->dev = hid->dev; - - lg3d->buf[0] = 0x51; - lg3d->buf[1] = 0x08; - lg3d->buf[2] = x; - lg3d->buf[3] = y; - - if ((err=usb_submit_urb(lg3d->urbffout, GFP_ATOMIC))) - warn("usb_submit_urb returned %d", err); - else - set_bit(DEVICE_USB_XMIT, lg3d->flags); - - if (!test_bit(DEVICE_CLOSING, lg3d->flags)) { - lg3d->timer.expires = RUN_AT(PERIOD); - add_timer(&lg3d->timer); - } - - spin_unlock_irqrestore(&lg3d->lock, flags); -} diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c index 8ae5cf004cfa..788c171c7b6f 100644 --- a/drivers/usb/input/hid-lgff.c +++ b/drivers/usb/input/hid-lgff.c @@ -4,6 +4,7 @@ * Force feedback support for hid-compliant for some of the devices from * Logitech, namely: * - WingMan Cordless RumblePad + * - WingMan Force 3D * * Copyright (c) 2002 Johann Deneux */ @@ -36,6 +37,11 @@ #include <linux/circ_buf.h> #include "hid.h" +#include "fixp-arith.h" + + +/* Periodicity of the update */ +#define PERIOD (HZ/10) #define RUN_AT(t) (jiffies + (t)) @@ -48,145 +54,243 @@ #define EFFECT_PLAYING 1 /* Effect is being played */ #define EFFECT_USED 2 +// For lgff_device::flags +#define DEVICE_CLOSING 0 /* The driver is being unitialised */ + /* Check that the current process can access an effect */ #define CHECK_OWNERSHIP(effect) (current->pid == 0 \ || effect.owner == current->pid) -/* **************************************************************************/ -/* Implements the protocol used by the Logitech WingMan Cordless RumblePad */ -/* **************************************************************************/ - #define LGFF_CHECK_OWNERSHIP(i, l) \ (i>=0 && i<LGFF_EFFECTS \ && test_bit(EFFECT_USED, l->effects[i].flags) \ && CHECK_OWNERSHIP(l->effects[i])) -#define LGFF_BUFFER_SIZE 64 #define LGFF_EFFECTS 8 -struct lgff_magnitudes { - unsigned char left; - unsigned char right; +struct device_type { + u16 idVendor; + u16 idProduct; + signed short *ff; }; struct lgff_effect { - int id; - struct hid_ff_logitech* lgff; - pid_t owner; - unsigned char left; /* Magnitude of vibration for left motor */ - unsigned char right; /* Magnitude of vibration for right motor */ - struct ff_replay replay; - unsigned int count; /* Number of times to play */ - struct timer_list timer; + + struct ff_effect effect; + unsigned long flags[1]; + unsigned int count; /* Number of times left to play */ + unsigned long started_at; /* When the effect started to play */ }; -struct hid_ff_logitech { +struct lgff_device { struct hid_device* hid; - struct urb* urbffout; /* Output URB used to send ff commands */ - struct usb_ctrlrequest ffcr; /* ff commands use control URBs */ - char buf[8]; - - spinlock_t xmit_lock; - unsigned int xmit_head, xmit_tail; - struct lgff_magnitudes xmit_data[LGFF_BUFFER_SIZE]; - long xmit_flags[1]; + struct hid_report* constant; + struct hid_report* rumble; + struct hid_report* condition; struct lgff_effect effects[LGFF_EFFECTS]; spinlock_t lock; /* device-level lock. Having locks on a per-effect basis could be nice, but isn't really necessary */ + + unsigned long flags[1]; /* Contains various information about the + state of the driver for this device */ + + struct timer_list timer; }; -static void hid_lgff_ctrl_out(struct urb *urb); +/* Callbacks */ static void hid_lgff_exit(struct hid_device* hid); static int hid_lgff_event(struct hid_device *hid, struct input_dev *input, unsigned int type, unsigned int code, int value); -static void hid_lgff_make_rumble(struct hid_device* hid); - static int hid_lgff_flush(struct input_dev *input, struct file *file); static int hid_lgff_upload_effect(struct input_dev *input, struct ff_effect *effect); static int hid_lgff_erase(struct input_dev *input, int id); -static void hid_lgff_ctrl_playback(struct hid_device* hid, struct lgff_effect*, - int play); + +/* Local functions */ +static void hid_lgff_input_init(struct hid_device* hid); static void hid_lgff_timer(unsigned long timer_data); +static struct hid_report* hid_lgff_duplicate_report(struct hid_report*); +static void hid_lgff_delete_report(struct hid_report*); + +static signed short ff_rumble[] = { + FF_RUMBLE, + -1 +}; + +static signed short ff_joystick[] = { + FF_CONSTANT, + -1 +}; +static struct device_type devices[] = { + {0x046d, 0xc211, ff_rumble}, + {0x046d, 0xc283, ff_joystick}, + {0x0000, 0x0000, ff_joystick} +}; int hid_lgff_init(struct hid_device* hid) { - struct hid_ff_logitech *private; - int i; - - /* Private data */ - private = kmalloc(sizeof(struct hid_ff_logitech), GFP_KERNEL); - if (!private) return -1; + struct lgff_device *private; + struct hid_report* report; + struct hid_field* field; - memset(private, 0, sizeof(struct hid_ff_logitech)); + /* Find the report to use */ + if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { + err("No output report found"); + return -1; + } + /* Check that the report looks ok */ + report = (struct hid_report*)hid->report_enum[HID_OUTPUT_REPORT].report_list.next; + if (!report) { + err("NULL output report"); + return -1; + } + field = report->field[0]; + if (!field) { + err("NULL field"); + return -1; + } + private = kmalloc(sizeof(struct lgff_device), GFP_KERNEL); + if (!private) return -1; + memset(private, 0, sizeof(struct lgff_device)); hid->ff_private = private; - private->hid = hid; - spin_lock_init(&private->lock); - spin_lock_init(&private->xmit_lock); + /* Input init */ + hid_lgff_input_init(hid); + - private->buf[0] = 0x03; - private->buf[1] = 0x42; + private->constant = hid_lgff_duplicate_report(report); + if (!private->constant) { + kfree(private); + return -1; + } + private->constant->field[0]->value[0] = 0x51; + private->constant->field[0]->value[1] = 0x08; + private->constant->field[0]->value[2] = 0x7f; + private->constant->field[0]->value[3] = 0x7f; + + private->rumble = hid_lgff_duplicate_report(report); + if (!private->rumble) { + hid_lgff_delete_report(private->constant); + kfree(private); + return -1; + } + private->rumble->field[0]->value[0] = 0x03; + private->rumble->field[0]->value[1] = 0x42; - for (i=0; i<LGFF_EFFECTS; ++i) { - struct lgff_effect* effect = &private->effects[i]; - struct timer_list* timer = &effect->timer; - init_timer(timer); - effect->id = i; - effect->lgff = private; - timer->data = (unsigned long)effect; - timer->function = hid_lgff_timer; + private->condition = hid_lgff_duplicate_report(report); + if (!private->condition) { + hid_lgff_delete_report(private->rumble); + hid_lgff_delete_report(private->constant); + kfree(private); + return -1; } + private->hid = hid; + + spin_lock_init(&private->lock); + init_timer(&private->timer); + private->timer.data = (unsigned long)private; + private->timer.function = hid_lgff_timer; + /* Event and exit callbacks */ hid->ff_exit = hid_lgff_exit; hid->ff_event = hid_lgff_event; - /* USB init */ - if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) { - kfree(hid->ff_private); - return -1; + /* Start the update task */ + private->timer.expires = RUN_AT(PERIOD); + add_timer(&private->timer); /*TODO: only run the timer when at least + one effect is playing */ + + printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <deneux@ifrance.com>\n"); + + return 0; +} + +static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) +{ + struct hid_report* ret; + + ret = kmalloc(sizeof(struct lgff_device), GFP_KERNEL); + if (!ret) return NULL; + *ret = *report; + + ret->field[0] = kmalloc(sizeof(struct hid_field), GFP_KERNEL); + if (!ret->field[0]) { + kfree(ret); + return NULL; } + *ret->field[0] = *report->field[0]; - usb_fill_control_urb(private->urbffout, hid->dev, 0, - (void*) &private->ffcr, private->buf, 8, - hid_lgff_ctrl_out, hid); - dbg("Created ff output control urb"); + ret->field[0]->value = kmalloc(sizeof(s32[8]), GFP_KERNEL); + if (!ret->field[0]->value) { + kfree(ret->field[0]); + kfree(ret); + return NULL; + } + memset(ret->field[0]->value, 0, sizeof(s32[8])); + + return ret; +} + +static void hid_lgff_delete_report(struct hid_report* report) +{ + if (report) { + kfree(report->field[0]->value); + kfree(report->field[0]); + kfree(report); + } +} + +static void hid_lgff_input_init(struct hid_device* hid) +{ + struct device_type* dev = devices; + signed short* ff; + u16 idVendor = hid->dev->descriptor.idVendor; + u16 idProduct = hid->dev->descriptor.idProduct; + + while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct)) + dev++; + + ff = dev->ff; + + while (*ff >= 0) { + set_bit(*ff, hid->input.ffbit); + ++ff; + } - /* Input init */ hid->input.upload_effect = hid_lgff_upload_effect; hid->input.flush = hid_lgff_flush; - set_bit(FF_RUMBLE, hid->input.ffbit); + set_bit(EV_FF, hid->input.evbit); hid->input.ff_effects_max = LGFF_EFFECTS; - - printk(KERN_INFO "Force feedback for Logitech rumble devices by Johann Deneux <deneux@ifrance.com>\n"); - - return 0; } static void hid_lgff_exit(struct hid_device* hid) { - struct hid_ff_logitech *lgff = hid->ff_private; + struct lgff_device *lgff = hid->ff_private; - if (lgff->urbffout) { - usb_unlink_urb(lgff->urbffout); - usb_free_urb(lgff->urbffout); - } + set_bit(DEVICE_CLOSING, lgff->flags); + del_timer_sync(&lgff->timer); + + hid_lgff_delete_report(lgff->condition); + hid_lgff_delete_report(lgff->rumble); + hid_lgff_delete_report(lgff->constant); + + kfree(lgff); } static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, unsigned int type, unsigned int code, int value) { - struct hid_ff_logitech *lgff = hid->ff_private; + struct lgff_device *lgff = hid->ff_private; struct lgff_effect *effect = lgff->effects + code; unsigned long flags; @@ -208,27 +312,16 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, effect->count = value; - if (effect->replay.delay) { + if (effect->effect.replay.delay) { set_bit(EFFECT_STARTED, effect->flags); - effect->timer.expires = RUN_AT(effect->replay.delay * HZ / 1000); } else { - hid_lgff_ctrl_playback(hid, effect, value); - effect->timer.expires = RUN_AT(effect->replay.length * HZ / 1000); + set_bit(EFFECT_PLAYING, effect->flags); } - - add_timer(&effect->timer); + effect->started_at = jiffies; } else { /* value == 0 */ - if (test_and_clear_bit(EFFECT_STARTED, effect->flags)) { - del_timer(&effect->timer); - - } else if (test_and_clear_bit(EFFECT_PLAYING, effect->flags)) { - del_timer(&effect->timer); - hid_lgff_ctrl_playback(hid, effect, value); - } - - if (test_bit(EFFECT_PLAYING, effect->flags)) - warn("Effect %d still playing", code); + clear_bit(EFFECT_STARTED, effect->flags); + clear_bit(EFFECT_PLAYING, effect->flags); } spin_unlock_irqrestore(&lgff->lock, flags); @@ -241,7 +334,7 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, static int hid_lgff_flush(struct input_dev *dev, struct file *file) { struct hid_device *hid = dev->private; - struct hid_ff_logitech *lgff = hid->ff_private; + struct lgff_device *lgff = hid->ff_private; int i; for (i=0; i<dev->ff_effects_max; ++i) { @@ -265,13 +358,12 @@ static int hid_lgff_flush(struct input_dev *dev, struct file *file) static int hid_lgff_erase(struct input_dev *dev, int id) { struct hid_device *hid = dev->private; - struct hid_ff_logitech *lgff = hid->ff_private; + struct lgff_device *lgff = hid->ff_private; unsigned long flags; if (!LGFF_CHECK_OWNERSHIP(id, lgff)) return -EACCES; spin_lock_irqsave(&lgff->lock, flags); - hid_lgff_ctrl_playback(hid, lgff->effects + id, 0); lgff->effects[id].flags[0] = 0; spin_unlock_irqrestore(&lgff->lock, flags); @@ -282,7 +374,7 @@ static int hid_lgff_upload_effect(struct input_dev* input, struct ff_effect* effect) { struct hid_device *hid = input->private; - struct hid_ff_logitech *lgff = hid->ff_private; + struct lgff_device *lgff = hid->ff_private; struct lgff_effect new; int id; unsigned long flags; @@ -291,8 +383,6 @@ static int hid_lgff_upload_effect(struct input_dev* input, if (!test_bit(effect->type, input->ffbit)) return -EINVAL; - if (effect->type != FF_RUMBLE) return -EINVAL; - spin_lock_irqsave(&lgff->lock, flags); if (effect->id == -1) { @@ -317,25 +407,20 @@ static int hid_lgff_upload_effect(struct input_dev* input, id = effect->id; new = lgff->effects[id]; - new.right = effect->u.rumble.strong_magnitude >> 9; - new.left = effect->u.rumble.weak_magnitude >> 9; - new.replay = effect->replay; + new.effect = *effect; - /* If we updated an effect that was being played, we need to remake - the rumble effect */ if (test_bit(EFFECT_STARTED, lgff->effects[id].flags) || test_bit(EFFECT_STARTED, lgff->effects[id].flags)) { /* Changing replay parameters is not allowed (for the time being) */ - if (new.replay.delay != lgff->effects[id].replay.delay - || new.replay.length != lgff->effects[id].replay.length) { + if (new.effect.replay.delay != lgff->effects[id].effect.replay.delay + || new.effect.replay.length != lgff->effects[id].effect.replay.length) { spin_unlock_irqrestore(&lgff->lock, flags); return -ENOSYS; } lgff->effects[id] = new; - hid_lgff_make_rumble(hid); } else { lgff->effects[id] = new; @@ -345,151 +430,99 @@ static int hid_lgff_upload_effect(struct input_dev* input, return 0; } -static void hid_lgff_xmit(struct hid_device* hid) +static void hid_lgff_timer(unsigned long timer_data) { - struct hid_ff_logitech *lgff = hid->ff_private; - int err; - int tail; + struct lgff_device *lgff = (struct lgff_device*)timer_data; + struct hid_device *hid = lgff->hid; unsigned long flags; - - spin_lock_irqsave(&lgff->xmit_lock, flags); - - tail = lgff->xmit_tail; - if (lgff->xmit_head == tail) { - clear_bit(XMIT_RUNNING, lgff->xmit_flags); - spin_unlock_irqrestore(&lgff->xmit_lock, flags); - return; - } - lgff->buf[3] = lgff->xmit_data[tail].left; - lgff->buf[4] = lgff->xmit_data[tail].right; - tail++; tail &= LGFF_BUFFER_SIZE -1; - lgff->xmit_tail = tail; - - spin_unlock_irqrestore(&lgff->xmit_lock, flags); - - lgff->urbffout->pipe = usb_sndctrlpipe(hid->dev, 0); - lgff->ffcr.bRequestType = USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE; - lgff->urbffout->transfer_buffer_length = lgff->ffcr.wLength = 8; - lgff->ffcr.bRequest = 9; - lgff->ffcr.wValue = 0x0203; /*NOTE: Potential problem with - little/big endian */ - lgff->ffcr.wIndex = 0; - - lgff->urbffout->dev = hid->dev; - - if ((err=usb_submit_urb(lgff->urbffout, GFP_ATOMIC))) - warn("usb_submit_urb returned %d", err); -} - -static void hid_lgff_make_rumble(struct hid_device* hid) -{ - struct hid_ff_logitech *lgff = hid->ff_private; - int left = 0, right = 0; + int x = 0x7f, y = 0x7f; // Coordinates of constant effects + unsigned int left = 0, right = 0; // Rumbling int i; - int head, tail; - unsigned long flags; - - for (i=0; i<LGFF_EFFECTS; ++i) { - if (test_bit(EFFECT_USED, lgff->effects[i].flags) - && test_bit(EFFECT_PLAYING, lgff->effects[i].flags)) { - left += lgff->effects[i].left; - right += lgff->effects[i].right; - } - } - - spin_lock_irqsave(&lgff->xmit_lock, flags); - head = lgff->xmit_head; - tail = lgff->xmit_tail; - - if (CIRC_SPACE(head, tail, LGFF_BUFFER_SIZE) < 1) { - warn("not enough space in xmit buffer to send new packet"); - spin_unlock_irqrestore(&lgff->xmit_lock, flags); - return; - } + spin_lock_irqsave(&lgff->lock, flags); - lgff->xmit_data[head].left = left > 0x7f ? 0x7f : left; - lgff->xmit_data[head].right = right > 0x7f ? 0x7f : right; - head++; head &= LGFF_BUFFER_SIZE -1; - lgff->xmit_head = head; + for (i=0; i<LGFF_EFFECTS; ++i) { + struct lgff_effect* effect = lgff->effects +i; - if (test_and_set_bit(XMIT_RUNNING, lgff->xmit_flags)) - spin_unlock_irqrestore(&lgff->xmit_lock, flags); - else { - spin_unlock_irqrestore(&lgff->xmit_lock, flags); - hid_lgff_xmit(hid); - } -} + if (test_bit(EFFECT_PLAYING, effect->flags)) { -static void hid_lgff_ctrl_out(struct urb *urb) -{ - struct hid_device *hid = urb->context; + switch (effect->effect.type) { + case FF_CONSTANT: { + //TODO: handle envelopes + int degrees = effect->effect.direction * 360 >> 16; + x += fixp_mult(fixp_sin(degrees), + fixp_new16(effect->effect.u.constant.level)); + y += fixp_mult(-fixp_cos(degrees), + fixp_new16(effect->effect.u.constant.level)); + } break; + case FF_RUMBLE: + right += effect->effect.u.rumble.strong_magnitude; + left += effect->effect.u.rumble.weak_magnitude; + break; + }; + + /* One run of the effect is finished playing */ + if (time_after(jiffies, + effect->started_at + + effect->effect.replay.delay*HZ/1000 + + effect->effect.replay.length*HZ/1000)) { + dbg("Finished playing once %d", i); + if (--effect->count <= 0) { + dbg("Stopped %d", i); + clear_bit(EFFECT_PLAYING, effect->flags); + } + else { + dbg("Start again %d", i); + if (effect->effect.replay.length != 0) { + clear_bit(EFFECT_PLAYING, effect->flags); + set_bit(EFFECT_STARTED, effect->flags); + } + effect->started_at = jiffies; + } + } + + } else if (test_bit(EFFECT_STARTED, lgff->effects[i].flags)) { + /* Check if we should start playing the effect */ + if (time_after(jiffies, + lgff->effects[i].started_at + + lgff->effects[i].effect.replay.delay*HZ/1000)) { + dbg("Now playing %d", i); + clear_bit(EFFECT_STARTED, lgff->effects[i].flags); + set_bit(EFFECT_PLAYING, lgff->effects[i].flags); + } + } + } - if (urb->status) - warn("hid_irq_ffout status %d received", urb->status); +#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff - hid_lgff_xmit(hid); -} + // Clamp values + CLAMP(x); + CLAMP(y); + CLAMP(left); + CLAMP(right); -/* Lock must be held by caller */ -static void hid_lgff_ctrl_playback(struct hid_device *hid, - struct lgff_effect *effect, int play) -{ - if (play) { - set_bit(EFFECT_PLAYING, effect->flags); - hid_lgff_make_rumble(hid); +#undef CLAMP - } else { - clear_bit(EFFECT_PLAYING, effect->flags); - hid_lgff_make_rumble(hid); + if (x != lgff->constant->field[0]->value[2] + || y != lgff->constant->field[0]->value[3]) { + lgff->constant->field[0]->value[2] = x; + lgff->constant->field[0]->value[3] = y; + dbg("(x,y)=(%04x, %04x)", x, y); + hid_submit_report(hid, lgff->constant, USB_DIR_OUT); } -} - -static void hid_lgff_timer(unsigned long timer_data) -{ - struct lgff_effect *effect = (struct lgff_effect*) timer_data; - struct hid_ff_logitech* lgff = effect->lgff; - int id = effect->id; - unsigned long flags; - - dbg("in hid_lgff_timer"); - - if (id < 0 || id >= LGFF_EFFECTS) { - warn("Bad effect id %d", id); - return; + if (left != lgff->rumble->field[0]->value[3] + || right != lgff->rumble->field[0]->value[4]) { + lgff->rumble->field[0]->value[3] = left; + lgff->rumble->field[0]->value[4] = right; + dbg("(left,right)=(%04x, %04x)", left, right); + hid_submit_report(hid, lgff->rumble, USB_DIR_OUT); } - effect = lgff->effects + id; - - spin_lock_irqsave(&lgff->lock, flags); - - if (!test_bit(EFFECT_USED, effect->flags)) { - warn("Unused effect id %d", id); - - } else if (test_bit(EFFECT_STARTED, effect->flags)) { - clear_bit(EFFECT_STARTED, effect->flags); - set_bit(EFFECT_PLAYING, effect->flags); - hid_lgff_ctrl_playback(lgff->hid, effect, 1); - effect->timer.expires = RUN_AT(effect->replay.length * HZ / 1000); - add_timer(&effect->timer); - - dbg("Effect %d starts playing", id); - } else if (test_bit(EFFECT_PLAYING, effect->flags)) { - clear_bit(EFFECT_PLAYING, effect->flags); - hid_lgff_ctrl_playback(lgff->hid, effect, 0); - if (--effect->count > 0) { - /*TODO: check that replay.delay is non-null */ - set_bit(EFFECT_STARTED, effect->flags); - effect->timer.expires = RUN_AT(effect->replay.delay * HZ / 1000); - add_timer(&effect->timer); - dbg("Effect %d restarted", id); - } else { - dbg("Effect %d stopped", id); - } - } else { - warn("Effect %d is not started nor playing", id); + if (!test_bit(DEVICE_CLOSING, lgff->flags)) { + lgff->timer.expires = RUN_AT(PERIOD); + add_timer(&lgff->timer); } - spin_unlock_irqrestore(&lgff->lock, flags); + spin_unlock_irqrestore(&lgff->lock, flags); } diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index e4a3b59f5668..b204affb8954 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c @@ -321,13 +321,13 @@ struct wacom_features wacom_features[] = { }; struct usb_device_id wacom_ids[] = { - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10), driver_info: 0 }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20), driver_info: 1 }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21), driver_info: 2 }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22), driver_info: 3 }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23), driver_info: 4 }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24), driver_info: 5 }, - { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31), driver_info: 6 }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10), .driver_info = 0 }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20), .driver_info = 1 }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21), .driver_info = 2 }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22), .driver_info = 3 }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23), .driver_info = 4 }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24), .driver_info = 5 }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31), .driver_info = 6 }, { } }; diff --git a/drivers/usb/misc/Config.help b/drivers/usb/misc/Config.help index 34bde6d406cd..6321df2998c1 100644 --- a/drivers/usb/misc/Config.help +++ b/drivers/usb/misc/Config.help @@ -7,7 +7,7 @@ CONFIG_USB_AUERSWALD The module will be called auerswald.o. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. -CONFIG_USB_BRLVOYAGER +CONFIG_USB_BRLVGER Say Y here if you want to use the Voyager USB Braille display from Tieman. See <file:Documentation/usb/brlvger.txt> for more information. diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index 2dd226a3a4c7..2440fa92405a 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -212,10 +212,10 @@ static void emi26_disconnect(struct usb_device *dev, void *drv_context) } struct usb_driver emi26_driver = { -name: "emi26 - firmware loader", -probe: emi26_probe, -disconnect: emi26_disconnect, -id_table: NULL, +.name = "emi26 - firmware loader", +.probe = emi26_probe, +.disconnect = emi26_disconnect, +.id_table = NULL, }; static int __init emi26_init (void) diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 6728f5cfd6ce..908d7b32ad59 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -62,7 +62,7 @@ static int multicast_filter_limit = 32; static struct usb_eth_dev usb_dev_id[] = { #define PEGASUS_DEV(pn, vid, pid, flags) \ - {name:pn, vendor:vid, device:pid, private:flags}, + {.name = pn, .vendor = vid, .device = pid, .private = flags}, #include "pegasus.h" #undef PEGASUS_DEV {NULL, 0, 0, 0} @@ -70,7 +70,7 @@ static struct usb_eth_dev usb_dev_id[] = { static struct usb_device_id pegasus_ids[] = { #define PEGASUS_DEV(pn, vid, pid, flags) \ - {match_flags: USB_DEVICE_ID_MATCH_DEVICE, idVendor:vid, idProduct:pid}, + {.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid}, #include "pegasus.h" #undef PEGASUS_DEV {} diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index c6ac7dd2821e..c5bc8e92c8cf 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -300,7 +300,7 @@ static const struct driver_info an2720_info = { // no reset available! // no check_connect available! - .in = 2, out: 2, // direction distinguishes these + .in = 2, .out = 2, // direction distinguishes these .epsize =64, }; @@ -321,7 +321,7 @@ static const struct driver_info an2720_info = { static const struct driver_info belkin_info = { .description = "Belkin, eTEK, or compatible", - .in = 1, out: 1, // direction distinguishes these + .in = 1, .out = 1, // direction distinguishes these .epsize =64, }; @@ -636,7 +636,7 @@ static const struct driver_info genelink_info = { .rx_fixup = genelink_rx_fixup, .tx_fixup = genelink_tx_fixup, - .in = 1, out: 2, + .in = 1, .out = 2, .epsize =64, #ifdef GENELINK_ACK @@ -674,7 +674,7 @@ static const struct driver_info linuxdev_info = { .description = "Linux Device", // no reset defined (yet?) .check_connect =linuxdev_check_connect, - .in = 2, out: 1, + .in = 2, .out = 1, .epsize =64, }; @@ -1125,7 +1125,7 @@ static const struct driver_info net1080_info = { .rx_fixup = net1080_rx_fixup, .tx_fixup = net1080_tx_fixup, - .in = 1, out: 1, // direction distinguishes these + .in = 1, .out = 1, // direction distinguishes these .epsize =64, }; @@ -1192,7 +1192,7 @@ static const struct driver_info prolific_info = { /* some PL-2302 versions seem to fail usb_set_interface() */ .reset = pl_reset, - .in = 3, out: 2, + .in = 3, .out = 2, .epsize =64, }; diff --git a/drivers/usb/serial/Config.help b/drivers/usb/serial/Config.help index a677b959551b..3a00c995da1b 100644 --- a/drivers/usb/serial/Config.help +++ b/drivers/usb/serial/Config.help @@ -268,6 +268,16 @@ CONFIG_USB_SERIAL_EDGEPORT The module will be called io_edgeport.o. If you want to compile it as a module, say M here and read <file:Documentation/modules.txt>. +CONFIG_USB_SERIAL_EDGEPORT_TI + Say Y here if you want to use any of the devices from Inside Out + Networks (Digi) that are not supported by the io_edgeport driver. + This includes the Edgeport/1 device. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called io_ti.o. If you want to compile it + as a module, say M here and read <file:Documentation/modules.txt>. + CONFIG_USB_SERIAL_KLSI Say Y here if you want to use a KL5KUSB105 - based single port serial adapter. The most widely known -- and currently the only diff --git a/drivers/usb/serial/Config.in b/drivers/usb/serial/Config.in index d8be99dbf624..d277619c0322 100644 --- a/drivers/usb/serial/Config.in +++ b/drivers/usb/serial/Config.in @@ -19,6 +19,7 @@ dep_tristate ' USB Handspring Visor / Palm m50x / Sony Clie Driver' CONFIG_USB_ dep_tristate ' USB Compaq iPAQ / HP Jornada / Casio EM500 Driver' CONFIG_USB_SERIAL_IPAQ $CONFIG_USB_SERIAL dep_tristate ' USB IR Dongle Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_IR $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB Inside Out Edgeport Serial Driver' CONFIG_USB_SERIAL_EDGEPORT $CONFIG_USB_SERIAL +dep_tristate ' USB Inside Out Edgeport Serial Driver (TI devices)' CONFIG_USB_SERIAL_EDGEPORT_TI $CONFIG_USB_SERIAL dep_tristate ' USB Keyspan PDA Single Port Serial Driver' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL dep_tristate ' USB Keyspan USA-xxx Serial Driver' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL dep_mbool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28 $CONFIG_USB_SERIAL_KEYSPAN diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 962d94746de6..1d6f5946bf27 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o +obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index eee56288d2ea..c7bebf111b96 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1263,7 +1263,7 @@ static int digi_write( struct usb_serial_port *port, int from_user, unsigned long flags = 0; -dbg( "digi_write: TOP: port=%d, count=%d, from_user=%d, in_interrupt=%d", +dbg( "digi_write: TOP: port=%d, count=%d, from_user=%d, in_interrupt=%ld", priv->dp_port_num, count, from_user, in_interrupt() ); /* copy user data (which can sleep) before getting spin lock */ @@ -1744,7 +1744,7 @@ static void digi_shutdown( struct usb_serial *serial ) int i; -dbg( "digi_shutdown: TOP, in_interrupt()=%d", in_interrupt() ); +dbg( "digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt() ); /* stop reads and writes on all ports */ for( i=0; i<serial->type->num_ports+1; i++ ) { diff --git a/drivers/usb/serial/io_fw_down3.h b/drivers/usb/serial/io_fw_down3.h new file mode 100644 index 000000000000..56d319f0163d --- /dev/null +++ b/drivers/usb/serial/io_fw_down3.h @@ -0,0 +1,799 @@ +//************************************************************** +//* Edgeport Binary Image (for TI based products) +//* Generated by TIBin2C v1.00 +//* Copyright(c) 2001 Inside Out Networks, All rights reserved. +//************************************************************** + + +static int IMAGE_SIZE = 12166; + +struct EDGE_FIRMWARE_VERSION_INFO +{ + unsigned char MajorVersion; + unsigned char MinorVersion; + unsigned short BuildNumber; +}; + +static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME = +{ + 4, 1, 0 // Major, Minor, Build + +}; + +static unsigned char IMAGE_ARRAY_NAME[] = +{ +// struct ImageHdr +// { +// WORD Length; +// BYTE CheckSum; +// }; +0x83, 0x2f, +0x33, + +0x02, 0x24, 0x84, 0x02, 0x1f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x45, +0x8c, 0x85, 0x46, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, +0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x44, +0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x44, 0x75, +0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x92, 0xe5, 0x81, +0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x1a, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, +0xfa, 0x74, 0x08, 0x25, 0x44, 0xf8, 0x05, 0x44, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x44, +0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x44, 0x00, 0x80, 0xef, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0x86, +0x81, 0xe5, 0x44, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, +0x78, 0x92, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07, +0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, +0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x30, 0x01, 0x4d, 0x30, 0xb4, 0x48, 0x10, +0x00, 0x45, 0x90, 0xff, 0x08, 0xe0, 0x54, 0x20, 0xf8, 0x90, 0xff, 0x48, 0xe0, 0x54, 0x20, 0xf9, +0x90, 0xff, 0x10, 0xe0, 0x54, 0x20, 0xfa, 0x90, 0xff, 0x50, 0xe0, 0x54, 0x20, 0xfb, 0x74, 0x00, +0xf5, 0x82, 0x74, 0xf8, 0xf5, 0x83, 0xe0, 0xc8, 0xf0, 0x68, 0x60, 0x02, 0x7e, 0x04, 0xa3, 0xe0, +0xc9, 0xf0, 0x69, 0x60, 0x02, 0x7e, 0x04, 0xa3, 0xe0, 0xca, 0xf0, 0x6a, 0x60, 0x02, 0x7e, 0x04, +0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, +0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, +0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, +0x02, 0x11, 0x1a, 0x85, 0x47, 0x8d, 0x85, 0x48, 0x8b, 0x74, 0xae, 0xf5, 0x82, 0x74, 0xfa, 0xf5, +0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, +0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, +0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25, +0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, +0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, +0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, +0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25, +0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, +0x20, 0x02, 0x03, 0x30, 0x01, 0x7b, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, +0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e, +0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x22, 0x12, 0x00, 0xc9, 0xee, 0x64, +0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02, +0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x22, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x22, +0x7c, 0x0a, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, +0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80, +0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2, +0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60, +0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x43, 0x60, +0x13, 0x14, 0xf5, 0x43, 0x70, 0x0e, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x10, 0x95, +0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, +0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90, +0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, +0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01, +0x7f, 0x08, 0x8e, 0x34, 0x8f, 0x35, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, +0xea, 0x90, 0xfa, 0xb9, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x18, 0x49, 0x78, 0x24, 0x7c, 0x00, 0x7d, +0x00, 0x12, 0x19, 0x6c, 0x7e, 0x00, 0x7f, 0x05, 0x12, 0x13, 0x8f, 0xe4, 0xf5, 0x53, 0xe5, 0x53, +0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x18, 0x2a, 0xe4, 0x12, 0x13, 0xfb, 0x05, 0x53, 0x04, 0x12, +0x18, 0x1b, 0x80, 0xea, 0x12, 0x18, 0x49, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0, +0x70, 0x03, 0x02, 0x08, 0xb8, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, +0xfe, 0x54, 0x0f, 0xf5, 0x53, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90, +0xff, 0x01, 0xe0, 0x12, 0x15, 0x0f, 0x03, 0x55, 0x00, 0x04, 0x28, 0x01, 0x05, 0x2f, 0x03, 0x05, +0xf6, 0x05, 0x06, 0x38, 0x06, 0x07, 0x9a, 0x08, 0x07, 0xe2, 0x09, 0x08, 0x3e, 0x0a, 0x08, 0x7e, +0x0b, 0x00, 0x00, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, +0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x02, 0x45, 0x34, +0x60, 0x03, 0x02, 0x0e, 0xac, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02, +0x60, 0x03, 0x02, 0x0e, 0xac, 0xee, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0x2a, 0x74, 0x01, +0x12, 0x13, 0xfb, 0x78, 0x6d, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x18, 0x2a, 0x74, 0x02, 0x12, 0x13, +0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb5, 0xe0, 0x60, +0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, +0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x60, +0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, +0xe5, 0x53, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, +0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, 0x80, 0x19, 0x15, 0x53, 0x30, +0x0a, 0x0b, 0x12, 0x18, 0xbd, 0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x80, 0x09, 0x12, 0x18, 0xcb, +0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0x60, 0x05, 0x74, 0x01, +0x12, 0x13, 0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, +0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, +0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, +0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, +0xac, 0x78, 0x6d, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, +0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb5, 0xe0, +0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, +0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, 0xb9, 0xe0, 0x70, +0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, +0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x07, +0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54, +0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x53, 0x24, 0xfe, 0x60, 0x1b, +0x04, 0x70, 0x2e, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, +0x80, 0x1f, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, 0x80, 0x16, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, +0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2a, 0xce, 0x80, 0x07, 0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2a, +0xce, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, +0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, +0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, +0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, +0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, +0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x78, 0x6d, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, +0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, +0x30, 0xe0, 0x07, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0a, 0xe5, +0x53, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, +0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xff, +0x12, 0x2f, 0x3b, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, +0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x19, 0x7a, 0x02, 0x19, 0x3e, +0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, +0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x44, 0x08, +0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, +0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, +0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x03, 0x02, 0x0e, 0xac, +0x90, 0xfa, 0xba, 0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x2c, 0x01, 0x80, 0x03, +0x53, 0x2c, 0xfe, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, +0xe5, 0x35, 0x45, 0x34, 0x70, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, +0xac, 0x90, 0xfa, 0xb9, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, +0x75, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xed, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, +0x49, 0x12, 0x19, 0x73, 0x7d, 0x03, 0x12, 0x0e, 0xf3, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, +0xb0, 0x90, 0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, +0x04, 0xae, 0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x18, 0x49, 0x90, 0xf9, 0x65, 0xe0, 0x30, +0xe4, 0x0d, 0x12, 0x19, 0x73, 0x7d, 0x14, 0x12, 0x0e, 0xf3, 0x60, 0x10, 0x02, 0x0e, 0xac, 0x12, +0x19, 0x73, 0x7d, 0x04, 0x12, 0x0f, 0x47, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, 0xb0, 0x90, +0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, 0x04, 0xae, +0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x19, 0x73, 0x7d, 0x05, 0x12, 0x0f, 0x47, 0x60, 0x03, +0x02, 0x0e, 0xac, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x12, 0x18, 0x90, 0x7d, 0x01, 0x12, 0x23, +0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xba, 0xe0, 0x90, +0xfa, 0xb1, 0xf0, 0xe4, 0xf5, 0x52, 0x90, 0xfa, 0xb1, 0xe0, 0xff, 0xe5, 0x52, 0xc3, 0x9f, 0x50, +0x24, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0xff, 0xfd, 0x90, 0xfa, 0xb3, 0xe4, 0x8d, 0xf0, 0x12, +0x14, 0x2f, 0x90, 0xfa, 0xb2, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0e, +0xac, 0x05, 0x52, 0x80, 0xd1, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0x24, 0xfe, 0xff, 0x90, 0xfa, +0xb2, 0xf0, 0xfd, 0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0x7a, 0xf9, 0x79, 0x6e, 0x7b, +0x01, 0x8b, 0x2d, 0x8a, 0x2e, 0x89, 0x2f, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x18, +0x90, 0x12, 0x23, 0xee, 0x8f, 0x52, 0x05, 0x52, 0x05, 0x52, 0x12, 0x18, 0x2a, 0xe5, 0x52, 0x12, +0x13, 0xfb, 0x12, 0x18, 0x2a, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x14, 0x0d, 0xaf, 0x52, 0x7e, +0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x50, 0x02, 0x80, 0x04, 0xae, 0x34, 0xaf, 0x35, +0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, +0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, +0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, +0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, +0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x00, 0x75, 0x2f, 0x29, 0x02, +0x0f, 0x2f, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, +0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, 0x90, 0xfa, 0xba, +0xe0, 0x94, 0x01, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, +0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0e, +0xac, 0x90, 0xfa, 0xba, 0xe0, 0xf5, 0x29, 0xe5, 0x29, 0x70, 0x08, 0x43, 0x2c, 0x01, 0x53, 0x2c, +0xfd, 0x80, 0x06, 0x53, 0x2c, 0xfe, 0x43, 0x2c, 0x02, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, +0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, +0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, +0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, +0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x7f, 0x01, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, +0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, +0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, +0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, +0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xff, 0x01, 0x12, 0x19, 0x8a, 0xef, 0x12, +0x13, 0xfb, 0x90, 0xfa, 0xb5, 0x12, 0x19, 0x8a, 0x90, 0x00, 0x01, 0xef, 0x12, 0x14, 0x0d, 0x90, +0x00, 0x02, 0xe4, 0x12, 0x14, 0x0d, 0x74, 0x03, 0x12, 0x18, 0x1b, 0x90, 0xfa, 0xb9, 0xe0, 0xff, +0xa3, 0xe0, 0x85, 0x2f, 0x82, 0x85, 0x2e, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, +0xe0, 0x12, 0x15, 0x0f, 0x09, 0x3d, 0x02, 0x09, 0x5f, 0x04, 0x09, 0x81, 0x05, 0x09, 0xad, 0x06, +0x09, 0xcb, 0x07, 0x09, 0xe9, 0x08, 0x0a, 0x07, 0x09, 0x0a, 0x25, 0x0b, 0x0a, 0xda, 0x80, 0x0c, +0xfa, 0x81, 0x0d, 0x1c, 0x82, 0x0b, 0x21, 0x83, 0x0b, 0x6a, 0x84, 0x0b, 0x89, 0x85, 0x0b, 0xc5, +0x86, 0x0c, 0x07, 0x87, 0x0c, 0x95, 0x88, 0x0c, 0xd0, 0x89, 0x0a, 0x43, 0x92, 0x0a, 0x43, 0x93, +0x0d, 0xcf, 0xc0, 0x0e, 0x00, 0xc1, 0x0e, 0x11, 0xc2, 0x00, 0x00, 0x0e, 0x9b, 0xe5, 0x2c, 0x20, +0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, +0xfd, 0x7c, 0x00, 0x7f, 0x07, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, 0xc0, 0xe5, +0x2c, 0x20, 0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, +0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, +0xc0, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x19, 0x99, 0x50, 0x06, 0xe5, 0x35, +0x45, 0x34, 0x70, 0x05, 0x7f, 0x02, 0x02, 0x2e, 0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x24, 0xfe, 0x24, +0xfd, 0x50, 0x02, 0x80, 0x03, 0x02, 0x2f, 0x28, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, +0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, +0x00, 0x7f, 0x08, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, +0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, +0x09, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, +0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, +0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, +0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x10, 0x9c, +0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, +0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x10, 0x9c, 0x7f, 0x07, +0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x56, 0x12, 0x18, 0xd9, 0x70, 0x4a, 0x90, 0xff, 0x02, +0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, 0x80, 0x12, 0xe5, 0x52, 0xb4, +0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x52, 0x12, +0x17, 0x8b, 0x12, 0x19, 0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x05, +0x12, 0x2f, 0x76, 0x80, 0x06, 0x85, 0x2a, 0x30, 0x85, 0x2b, 0x31, 0x75, 0x2d, 0x01, 0x75, 0x2e, +0xf9, 0x75, 0x2f, 0x71, 0x02, 0x29, 0x2d, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x12, 0x18, +0xd9, 0x60, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x19, 0x99, 0x40, 0x05, 0x7f, 0x03, 0x02, +0x2e, 0xa5, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, +0x80, 0x12, 0xe5, 0x52, 0xb4, 0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, +0xf0, 0x04, 0xf5, 0x52, 0x12, 0x17, 0x8b, 0x02, 0x2f, 0x28, 0x12, 0x19, 0xa3, 0x12, 0x27, 0x19, +0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x78, +0x6e, 0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, +0xe4, 0x12, 0x14, 0x0d, 0x90, 0xfa, 0xb6, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x82, 0xe6, 0xfc, +0x08, 0xe6, 0x8c, 0x83, 0x12, 0x18, 0xa3, 0xef, 0xf0, 0x12, 0x2f, 0x80, 0xe4, 0xff, 0x02, 0x2e, +0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, +0x70, 0x06, 0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, +0xba, 0xe0, 0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, 0x70, +0x06, 0xa3, 0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xba, +0xe0, 0x42, 0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x49, 0x90, 0xfa, 0xb5, +0xe0, 0xb4, 0x01, 0x0a, 0x12, 0x18, 0x2a, 0xe5, 0x90, 0x12, 0x13, 0xfb, 0x80, 0x08, 0x12, 0x18, +0x2a, 0xe5, 0xb0, 0x12, 0x13, 0xfb, 0x02, 0x0f, 0x2f, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x30, +0x12, 0x18, 0x53, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, +0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x19, 0xad, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb6, +0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x04, 0x12, 0x19, 0xb4, 0xf0, +0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x36, 0x12, 0x18, 0x53, 0x60, +0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, +0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, +0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, +0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x46, 0x04, 0x60, 0x03, 0x02, +0x0c, 0x90, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x04, 0xf0, 0x90, +0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x6a, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x61, 0x90, +0xff, 0xa4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x53, 0x30, 0x95, 0x09, +0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x47, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, +0x80, 0x3e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x04, 0xf0, 0x90, +0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x2a, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x21, 0x90, +0xff, 0xb4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x13, 0x30, 0x93, 0x09, +0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfd, 0xf0, +0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, +0xe0, 0x60, 0x09, 0x90, 0xff, 0xa2, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa2, 0xe0, +0x54, 0xbf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb2, 0xe0, 0x44, +0x40, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, +0x12, 0x18, 0x49, 0x12, 0x18, 0x5b, 0x60, 0x0f, 0x04, 0x70, 0x16, 0x90, 0xff, 0xa4, 0xe0, 0x12, +0x18, 0x2a, 0x12, 0x13, 0xfb, 0x80, 0x0a, 0x90, 0xff, 0xb4, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, +0xfb, 0x75, 0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x12, +0x19, 0x46, 0x7f, 0x03, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff, +0x7e, 0x00, 0x12, 0x2d, 0xee, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x54, 0xf5, +0x55, 0x90, 0xfa, 0xbb, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb3, 0xf0, 0xa3, 0x74, +0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xb8, 0xf0, 0xd3, 0x94, +0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, +0xd6, 0xe5, 0x23, 0x45, 0x22, 0x70, 0x73, 0x12, 0x18, 0x62, 0x90, 0xfa, 0xbb, 0x12, 0x19, 0x65, +0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xb8, 0x74, 0x40, +0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, 0xd6, 0xe5, 0x23, +0x45, 0x22, 0x70, 0x46, 0x12, 0x18, 0x62, 0x80, 0xd1, 0x75, 0x52, 0x02, 0x90, 0xfa, 0xbb, 0xe4, +0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb3, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a, +0x00, 0x79, 0x52, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x50, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x26, 0x25, +0x75, 0x22, 0x00, 0x8f, 0x23, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x40, 0xf5, 0x41, +0x7d, 0x01, 0x12, 0x23, 0xee, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0xaf, 0x23, 0x02, 0x2e, 0xa5, 0x90, +0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x62, +0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0f, +0x90, 0xf9, 0x61, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x2e, 0xa5, +0x12, 0x19, 0xa3, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x2e, +0xa5, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, +0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, +0x12, 0x19, 0xad, 0x12, 0x0e, 0xfe, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, +0x44, 0x10, 0x12, 0x0e, 0xfe, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, +0x19, 0xad, 0xf0, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, +0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, +0x92, 0x80, 0x23, 0x12, 0x19, 0xb4, 0x12, 0x0f, 0x1e, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, +0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x1e, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, +0xd2, 0x92, 0x12, 0x19, 0xb4, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x07, +0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x2f, 0x76, 0x22, +0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, +0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0xab, +0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x22, 0xaa, 0x54, 0xa9, 0x55, 0x7b, 0xff, 0x90, 0xfa, 0xb3, 0xe0, +0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xb8, 0xe0, 0xf5, 0x50, 0x12, 0x26, 0x25, 0x75, 0x22, 0x00, +0x8f, 0x23, 0x22, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, 0xef, 0x22, 0xf0, 0x7f, +0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x12, +0x23, 0xee, 0x8f, 0x52, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x22, 0xf0, 0x7f, +0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x75, +0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x02, 0x2f, 0x3b, +0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, +0xef, 0x22, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb0, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, +0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, +0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, +0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, +0x04, 0xc0, 0x05, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, +0x0f, 0xfe, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x49, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x19, 0xe0, 0x54, +0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, +0x49, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, +0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, +0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, +0x12, 0x10, 0x95, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, +0x4a, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x43, 0x22, 0xe5, 0x44, 0x24, 0x08, +0xf8, 0x76, 0x00, 0x12, 0x10, 0xec, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, +0xc0, 0x06, 0x7c, 0xff, 0x12, 0x0f, 0xfe, 0xe5, 0x49, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x19, 0xe0, +0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x49, 0x80, 0x07, +0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, +0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, +0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, +0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, +0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x10, 0x95, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, +0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x43, 0x00, 0x85, 0x4a, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, +0xc0, 0x83, 0xc3, 0xe5, 0x49, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf4, 0xef, 0x60, +0x31, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x0f, +0xfe, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x49, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x19, 0xf5, 0x82, +0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x49, 0x12, +0x10, 0x95, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0x1a, 0xc0, 0x04, 0x7c, 0x20, +0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, +0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, +0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, +0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, +0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, +0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0xd2, 0xb0, 0xd2, +0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, +0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, +0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x48, 0x8e, +0x47, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, +0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x46, 0x8e, 0x45, 0x22, 0xef, +0x70, 0x01, 0x22, 0xc0, 0x00, 0xe5, 0x44, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x44, 0x24, 0x08, +0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x10, 0xec, 0x80, +0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, +0x12, 0x10, 0xec, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, +0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0xa0, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, +0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, +0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x0e, 0xf5, 0x82, +0xe5, 0xf0, 0x34, 0x2e, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, +0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, +0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x44, 0x00, 0x75, 0x49, +0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, +0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, +0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, +0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x91, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, +0xe5, 0x49, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x19, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, +0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, +0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x11, 0xc1, 0xad, 0x07, 0xaf, 0x02, +0x12, 0x11, 0xd8, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x10, 0xec, 0x80, 0xc1, 0xe7, +0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, +0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, +0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, +0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, +0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, +0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, +0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, +0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, +0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, +0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, +0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, +0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, +0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, +0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, +0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, +0x23, 0x90, 0x13, 0x0f, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, +0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, +0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, +0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, +0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, +0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, +0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, +0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5, +0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, +0x83, 0xe0, 0x38, 0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, +0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, +0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, +0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, +0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, +0xe9, 0x93, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, +0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, +0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, +0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, +0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4, +0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa, +0x08, 0xe6, 0xf9, 0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3, +0xe0, 0xfa, 0xa3, 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, +0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, +0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, +0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, +0xff, 0xf9, 0x74, 0x02, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00, +0x7a, 0x00, 0x79, 0x37, 0x75, 0x40, 0x00, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0xe5, 0x37, +0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x37, 0x64, 0x07, 0x60, 0x0b, 0xe5, 0x37, 0x64, 0x06, +0x60, 0x05, 0xe5, 0x37, 0xb4, 0x14, 0x1b, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0xe5, +0x37, 0xb4, 0x07, 0x08, 0x90, 0xf9, 0x65, 0x74, 0x02, 0xf0, 0x80, 0x06, 0x90, 0xf9, 0x65, 0x74, +0x01, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x17, 0x71, 0x90, 0xff, +0xf5, 0xe5, 0x37, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, +0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x12, 0x17, 0x71, 0xe5, 0x37, 0x30, 0xe7, +0x02, 0xd2, 0x02, 0xe4, 0xf5, 0x2c, 0xf5, 0x2a, 0xf5, 0x2b, 0xf5, 0x29, 0x12, 0x19, 0x92, 0x12, +0x18, 0x49, 0x12, 0x19, 0x6c, 0x90, 0xf9, 0x66, 0x12, 0x15, 0x06, 0x90, 0xf9, 0x6b, 0x12, 0x15, +0x06, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 0x74, +0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0x12, +0x18, 0xbf, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x37, 0x12, 0x18, 0xcd, 0xf5, 0x83, 0xe4, 0xf0, 0x05, +0x37, 0xe5, 0x37, 0xb4, 0x07, 0xe7, 0x78, 0x80, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x2f, 0x06, +0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x2f, 0x13, 0xe4, 0x93, 0xff, 0x08, +0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x18, 0xaf, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 0x08, +0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 0x9f, +0x78, 0x81, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x18, 0x41, 0xce, 0xc3, 0x13, 0xce, 0x13, +0xd8, 0xf9, 0xff, 0xed, 0x12, 0x19, 0x07, 0xef, 0xf0, 0xed, 0x12, 0x19, 0x2d, 0xe4, 0xf5, 0x37, +0xe5, 0x37, 0x90, 0x2f, 0x00, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xe5, 0x37, 0x25, 0xe0, 0x24, +0x07, 0xf5, 0x82, 0xe4, 0x34, 0x2f, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 0x53, +0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xaf, 0x12, 0x19, 0x15, 0x24, 0x47, 0xf5, 0x82, 0xe4, +0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 0x19, +0x07, 0xef, 0xf0, 0x12, 0x18, 0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, +0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x19, 0x2d, 0xe9, +0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, +0x02, 0x17, 0x46, 0x78, 0x7e, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xf9, 0x12, 0x19, 0x15, 0x24, +0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, +0x12, 0x19, 0x1a, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x18, +0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, 0x24, 0x05, 0xf5, 0x82, 0xe4, +0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, +0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, +0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5, 0x37, 0x64, 0x04, 0x60, 0x03, 0x02, 0x16, +0x70, 0x90, 0x2f, 0x05, 0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0x12, 0x18, 0xf7, 0xe4, 0xf0, 0x90, +0x2f, 0x04, 0x93, 0xff, 0xf6, 0x12, 0x18, 0xad, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 0xf0, +0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, +0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, +0x2f, 0xe5, 0x52, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, +0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0x74, 0x11, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, +0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x06, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, +0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0xab, 0x2d, +0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, +0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, +0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x04, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, +0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x05, 0xe0, +0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, +0x35, 0x2e, 0xf5, 0x2e, 0x22, 0xf5, 0x83, 0xe0, 0x54, 0x08, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, +0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 0x78, 0x81, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, +0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 0x75, 0x2d, 0x01, 0x75, 0x2e, 0xf9, 0x75, +0x2f, 0x6e, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xfa, 0xb5, 0xe0, 0x24, +0xfc, 0x22, 0x90, 0xfa, 0xb8, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xbc, 0xe0, 0x9f, 0xf0, +0x90, 0xfa, 0xbb, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xb3, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, +0x25, 0x55, 0xf5, 0x55, 0xee, 0x35, 0x54, 0xf5, 0x54, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb0, +0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x22, 0x78, 0x82, 0xe6, 0xfe, 0x08, +0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, +0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x53, 0x75, +0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0xe5, 0x53, 0x75, 0xf0, 0x08, +0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, +0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x75, 0x2a, 0x00, 0x8f, 0x2b, 0x90, 0xf9, 0x6b, +0x12, 0x14, 0xfd, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, +0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 0xe4, +0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 0xa4, +0x22, 0x74, 0xae, 0x25, 0x36, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, +0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 0xff, +0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 0xfc, +0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x6d, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x65, +0xf0, 0x22, 0x12, 0x14, 0xdf, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xf9, +0x79, 0x6e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, +0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x66, 0x02, +0x14, 0xfd, 0x75, 0x30, 0x01, 0x75, 0x31, 0x09, 0x22, 0xd3, 0xe5, 0x35, 0x94, 0x08, 0xe5, 0x34, +0x94, 0x01, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0x22, 0x90, 0xff, 0xa4, +0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xef, 0x22, 0x8f, 0x38, 0x12, 0x27, 0x19, +0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xe0, 0xfd, +0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x12, 0x20, 0x7c, 0x24, +0x07, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x12, 0x20, 0xbe, 0x24, 0x09, 0x12, 0x20, 0x25, 0xef, 0xf0, +0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x20, 0x2f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, +0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0, +0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xe0, 0xfc, 0xa3, 0xe0, +0xfd, 0xec, 0xff, 0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xef, 0xf0, 0xed, +0x12, 0x20, 0xbe, 0x24, 0x07, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, +0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x20, 0x69, 0xa3, 0xe0, +0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, +0x2f, 0x4d, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x20, 0xae, 0x24, 0x06, 0x12, 0x20, 0x25, +0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x86, 0x12, 0x20, 0x96, 0x24, 0x04, +0x12, 0x20, 0x25, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x20, 0xa6, 0xf5, 0x82, 0x8a, 0x83, +0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x20, 0xbe, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x8d, 0x82, +0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, +0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, +0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x4c, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x42, +0x12, 0x20, 0xae, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, 0x60, 0x31, 0x14, 0x60, 0x29, 0x14, +0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, 0x38, 0xb4, 0x03, 0x0d, 0x30, 0x95, +0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07, +0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd, +0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x20, 0x94, 0x24, 0x04, 0x12, 0x20, 0x25, 0xef, 0xf0, 0x8d, +0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, +0x4a, 0xee, 0x30, 0xe1, 0x43, 0x08, 0x12, 0x20, 0xb0, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, +0x60, 0x2c, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, +0x38, 0xb4, 0x03, 0x0d, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x1f, 0x43, 0x07, 0x80, 0x80, +0x1a, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x12, 0x43, 0x07, 0x80, 0x80, 0x0d, 0x53, 0x07, +0x7f, 0x80, 0x08, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x86, 0x12, 0x20, 0x65, +0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, +0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, +0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, +0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, +0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, +0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x84, 0x12, 0x20, 0x65, 0xa3, 0xef, 0xf0, +0x12, 0x2f, 0x80, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x8e, 0xef, 0xf6, 0x12, 0x27, 0x19, +0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0xfd, 0x12, 0x20, 0x53, 0x90, +0x00, 0x0a, 0x12, 0x20, 0x78, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x14, +0x0d, 0x12, 0x20, 0x70, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x59, 0x12, 0x20, +0x7c, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xf5, 0x5a, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, +0xf5, 0x5b, 0xe5, 0x59, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x8e, 0xf6, 0xd3, 0x94, 0x00, +0x40, 0x06, 0xe5, 0x5a, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x8e, 0xe6, 0x12, 0x20, 0x52, 0x90, 0x00, +0x0c, 0xef, 0x12, 0x14, 0x0d, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, +0xff, 0x53, 0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x59, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, +0x5a, 0x20, 0xe5, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, 0x20, 0xe7, 0x03, 0x43, +0x07, 0x02, 0xe5, 0x59, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x59, 0x30, 0xe2, 0x03, 0x43, +0x07, 0x20, 0xe5, 0x59, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x59, 0x30, 0xe1, 0x03, +0x43, 0x07, 0x80, 0xe5, 0x59, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x59, 0x30, 0xe6, 0x03, +0x43, 0x06, 0x08, 0xe5, 0x5a, 0x20, 0xe4, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, +0x20, 0xe7, 0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, +0x8f, 0xf0, 0x12, 0x14, 0xb2, 0xe5, 0x5b, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, +0x12, 0x20, 0x52, 0x90, 0x00, 0x08, 0xef, 0x12, 0x14, 0x0d, 0x80, 0x0a, 0x12, 0x20, 0x53, 0x90, +0x00, 0x08, 0xe4, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x03, 0x12, 0x20, 0x52, 0x90, 0x00, 0x07, +0xef, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x14, +0x0d, 0x90, 0x00, 0x07, 0x12, 0x13, 0xce, 0x70, 0x13, 0x12, 0x20, 0x53, 0xe9, 0x24, 0x09, 0xf9, +0xe4, 0x3a, 0xfa, 0x12, 0x13, 0xb5, 0xff, 0xc3, 0x13, 0x12, 0x13, 0xfb, 0x12, 0x20, 0x94, 0x24, +0x08, 0x12, 0x20, 0x25, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x20, +0x25, 0xe0, 0xfd, 0xee, 0xed, 0x12, 0x20, 0x52, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x14, +0xb2, 0x12, 0x2f, 0x80, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, 0x90, 0xfa, +0xe2, 0xe0, 0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, +0xfa, 0xd6, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xff, 0x7e, 0x00, +0x90, 0xfa, 0xd2, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, +0x12, 0x14, 0x5b, 0xff, 0x90, 0xfa, 0xd4, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, +0x01, 0x8e, 0x56, 0x8f, 0x57, 0x74, 0x0a, 0x25, 0x57, 0xf5, 0x57, 0xe4, 0x35, 0x56, 0xf5, 0x56, +0x90, 0xfa, 0xd7, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd5, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, +0xff, 0x90, 0xfa, 0xd9, 0xf0, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0x90, 0xfa, 0xd2, 0xe0, 0x94, +0x00, 0x50, 0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, 0x60, 0x03, 0xe0, 0xff, +0x22, 0x12, 0x2a, 0x80, 0x90, 0xfa, 0xd2, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, +0xfa, 0xd6, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, +0xfa, 0xd9, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, +0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2a, 0x80, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x58, +0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7f, 0x00, 0x22, 0xaa, 0x56, 0xa9, +0x57, 0x7b, 0x01, 0x90, 0xfa, 0xd4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xd9, 0xe0, 0xf5, +0x50, 0x12, 0x26, 0x25, 0x90, 0xfa, 0xd8, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, +0xfe, 0x60, 0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x1e, 0xed, 0x24, 0x06, 0x60, 0x03, 0x02, 0x1f, +0x35, 0x78, 0x77, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, +0x74, 0x33, 0x90, 0xfa, 0x90, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xae, 0x74, 0x01, 0xf0, +0x22, 0x78, 0x78, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, +0x74, 0x43, 0x90, 0xfa, 0x92, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, +0x22, 0x90, 0xfa, 0x9c, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x1f, 0x35, 0x90, 0xff, 0xa6, 0xe0, +0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, +0x90, 0xff, 0xa6, 0x12, 0x20, 0x83, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, +0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x57, 0x90, 0xfa, +0xca, 0xe0, 0xff, 0x74, 0x34, 0x90, 0xfa, 0x94, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa6, +0xe0, 0xa3, 0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, +0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x20, 0x83, 0x90, +0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, +0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, +0x96, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, +0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, +0x06, 0xc0, 0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc8, 0xf0, 0x90, 0xff, 0x92, 0xe4, +0xf0, 0xef, 0x12, 0x15, 0x0f, 0x1f, 0xed, 0x26, 0x1f, 0xed, 0x2e, 0x1f, 0x90, 0x30, 0x1f, 0x90, +0x32, 0x1f, 0x9e, 0x38, 0x1f, 0xb0, 0x3a, 0x1f, 0xe2, 0x3e, 0x1f, 0xcd, 0x44, 0x1f, 0xc2, 0x46, +0x1f, 0xd8, 0x50, 0x1f, 0xd8, 0x52, 0x1f, 0xd8, 0x54, 0x1f, 0xd8, 0x56, 0x00, 0x00, 0x1f, 0xf2, +0x90, 0xfa, 0xc8, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x10, 0x9c, 0x80, 0x62, 0x7c, 0x00, +0x7d, 0x01, 0x7f, 0x03, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, +0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x02, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, +0x80, 0x3e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x10, 0x9c, 0x80, 0x33, 0x7c, 0x00, 0x7d, +0x01, 0x7f, 0x06, 0x12, 0x10, 0x9c, 0x80, 0x28, 0x90, 0xfa, 0xc8, 0xe0, 0xff, 0x12, 0x1e, 0x4a, +0x80, 0x1e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x10, 0x9c, 0x80, 0x13, 0x12, 0x25, 0x13, +0x80, 0x0e, 0x90, 0xfa, 0xc8, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x29, 0xda, +0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, +0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x82, 0xe6, 0xfe, 0x08, +0xe6, 0x24, 0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x78, 0x82, 0xe6, +0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, +0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a, 0x2f, 0x79, 0x52, 0x7e, 0x00, 0x7f, 0x0a, 0x02, +0x13, 0x8f, 0xff, 0x90, 0xf9, 0x6b, 0x02, 0x14, 0xfd, 0x90, 0xf9, 0x66, 0x12, 0x14, 0xfd, 0x90, +0x00, 0x04, 0x02, 0x13, 0xce, 0xe6, 0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, +0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xed, 0x12, 0x14, 0x0d, 0x8f, 0x82, 0x8e, 0x83, +0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, +0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x84, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83, 0x22, 0xa6, 0x07, +0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x22, 0x78, 0x84, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0x22, 0x78, 0x86, +0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, +0x8a, 0x83, 0xe5, 0x82, 0x22, 0x8b, 0x38, 0x8a, 0x39, 0x89, 0x3a, 0x8d, 0x3b, 0x90, 0xfa, 0xce, +0xe4, 0xf0, 0xa3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe0, +0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xcd, 0xe0, 0x65, +0x3b, 0x60, 0x46, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x21, +0x54, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x90, 0xfa, 0xd0, 0xe4, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0x12, +0x21, 0x54, 0x90, 0xfa, 0xd0, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xce, 0xcf, 0xf0, 0xa3, 0xef, +0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xce, 0xe4, +0x75, 0xf0, 0x04, 0x12, 0x14, 0x2f, 0x02, 0x20, 0xd6, 0x90, 0xfa, 0xcf, 0xe0, 0x24, 0x01, 0xff, +0x90, 0xfa, 0xce, 0xe0, 0x34, 0x00, 0xab, 0x38, 0xaa, 0x39, 0xa9, 0x3a, 0x8f, 0xf0, 0x12, 0x14, +0x93, 0x7f, 0x00, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe4, 0x75, 0xf0, +0x01, 0x12, 0x14, 0x2f, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x8f, 0x68, +0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xfb, +0xf0, 0x44, 0x02, 0xf0, 0x08, 0x12, 0x20, 0x65, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x20, 0x7c, +0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x82, 0xe6, 0xfe, 0x08, 0xe6, 0xff, +0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x68, 0x24, 0xfe, 0x44, 0x20, 0xfc, +0x4d, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, +0x82, 0x8e, 0x83, 0xa3, 0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, +0x05, 0x12, 0x20, 0x25, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x95, 0x25, 0x68, 0xf5, 0x82, +0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, +0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, +0x25, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x68, 0xf8, 0x74, 0x04, 0x46, +0xf6, 0x7f, 0x00, 0x22, 0x8b, 0x62, 0x8a, 0x63, 0x89, 0x64, 0x12, 0x2a, 0x62, 0x90, 0xfa, 0xbf, +0x12, 0x15, 0x06, 0xaa, 0x63, 0xa9, 0x64, 0x90, 0xfa, 0xc2, 0x12, 0x15, 0x06, 0x90, 0xfa, 0xc3, +0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xc2, 0x12, 0x14, 0xfd, 0xe9, 0x24, 0x01, +0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc5, 0x12, 0x15, 0x06, 0xab, 0x62, 0xaa, 0x63, 0xa9, 0x64, +0x12, 0x2a, 0x6e, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x88, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, +0xff, 0x78, 0x88, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xbf, 0x12, 0x2a, 0x43, 0xff, 0x78, +0x89, 0xf6, 0x90, 0xfa, 0xc2, 0x12, 0x2a, 0x43, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x89, 0xf6, 0x12, +0x2a, 0x40, 0x5e, 0x4f, 0xff, 0x78, 0x89, 0xf6, 0x12, 0x2a, 0x49, 0x75, 0xf0, 0x02, 0x12, 0x14, +0x2f, 0x90, 0xfa, 0xc3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0xab, 0x62, 0xaa, 0x63, 0xa9, +0x64, 0x90, 0x00, 0x04, 0x12, 0x13, 0xce, 0x30, 0xe4, 0x03, 0x12, 0x2a, 0x58, 0x78, 0x88, 0x06, +0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x22, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x90, 0xfa, +0xbe, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbd, 0xf0, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x26, +0x14, 0x70, 0x70, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x22, 0x14, 0x80, +0x62, 0x12, 0x2a, 0x79, 0x12, 0x1d, 0x5e, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0x80, 0x55, 0x90, 0xfa, +0xbe, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 0x12, +0x29, 0x85, 0x80, 0x3f, 0xe5, 0x5e, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5d, 0xfa, 0x7b, 0x01, 0xc0, +0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xfd, 0x90, +0x00, 0x08, 0x12, 0x14, 0x5b, 0xf5, 0x41, 0x85, 0xf0, 0x40, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, +0x12, 0x23, 0xee, 0x90, 0xfa, 0xbd, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 0xbe, +0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbe, 0xe0, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x02, 0x12, 0x14, 0x0d, +0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x22, 0x12, 0x0f, 0x89, 0x7f, 0x02, 0x12, 0x11, 0x9f, 0x78, 0x6d, +0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 0xb1, 0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, +0x7a, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, +0x78, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, +0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, +0xe3, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, +0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7a, +0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x78, +0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x15, +0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe3, 0xe0, 0xf5, 0xa8, 0x02, 0x10, 0x0c, 0x8b, 0x3c, +0x8a, 0x3d, 0x89, 0x3e, 0x8d, 0x3f, 0xe5, 0x3f, 0x70, 0x03, 0xaf, 0x3f, 0x22, 0x12, 0x2a, 0xa8, +0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x40, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x2e, 0xd4, 0x50, 0xf2, +0x12, 0x24, 0x7b, 0x40, 0x0b, 0x7f, 0x00, 0x22, 0x12, 0x2a, 0xc7, 0x12, 0x24, 0x7b, 0x50, 0xf8, +0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 0x3f, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, +0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 0xf5, 0x42, 0xe5, 0x3f, 0x14, 0xff, 0xe5, 0x42, 0xc3, +0x9f, 0x50, 0x2a, 0x12, 0x2e, 0xbd, 0x40, 0x03, 0xaf, 0x42, 0x22, 0xc3, 0xe5, 0x3f, 0x95, 0x42, +0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2a, 0xba, 0x05, 0x42, +0x74, 0x01, 0x25, 0x3e, 0xf5, 0x3e, 0xe4, 0x35, 0x3d, 0xf5, 0x3d, 0x80, 0xcc, 0x12, 0x2e, 0xbd, +0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xba, 0xaf, 0x3f, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x41, +0xf0, 0x02, 0x2e, 0xd4, 0x75, 0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x91, +0x02, 0x24, 0xce, 0x02, 0x2e, 0x88, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, +0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, +0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, +0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x28, +0xcb, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, +0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, +0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, +0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, +0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x36, 0x12, 0x19, 0x21, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x36, 0x24, +0x03, 0xff, 0x12, 0x2d, 0x4f, 0x12, 0x19, 0x21, 0xe4, 0xf0, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, +0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x36, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x90, 0x12, 0x19, +0x62, 0x60, 0x2c, 0x12, 0x29, 0xda, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, +0x90, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x36, 0x90, 0xfa, 0x9c, +0x12, 0x14, 0xdf, 0xe0, 0xa3, 0x30, 0xe6, 0x33, 0x12, 0x19, 0x21, 0x74, 0x04, 0xf0, 0x22, 0x75, +0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x19, 0x62, 0x60, 0x16, 0x12, 0x29, 0xda, 0xef, +0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, +0xf0, 0x22, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, +0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, +0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xfb, 0x0f, 0x12, 0x18, 0x19, 0x80, +0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x31, 0x9d, 0xf5, 0x31, 0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0xd3, +0xe5, 0x31, 0x94, 0x00, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, +0x12, 0x19, 0x3e, 0x12, 0x19, 0x92, 0x12, 0x19, 0x8c, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x1e, +0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x13, 0xce, 0xff, 0x24, 0xfc, +0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x10, 0x9c, 0x12, 0x19, +0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, +0xff, 0x12, 0x2f, 0x6a, 0x22, 0x8b, 0x4b, 0x8a, 0x4c, 0x89, 0x4d, 0x8c, 0x4e, 0x8d, 0x4f, 0xd2, +0x00, 0x12, 0x2a, 0xa8, 0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x4e, 0x90, 0xff, 0xf1, 0xf0, 0x12, +0x2e, 0xd4, 0x50, 0xf2, 0x12, 0x26, 0x9a, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xc7, 0x12, +0x26, 0x9a, 0x50, 0xf8, 0xe4, 0xf5, 0x51, 0xe5, 0x50, 0x14, 0xff, 0xe5, 0x51, 0xc3, 0x9f, 0x50, +0x17, 0x12, 0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x05, 0x51, 0x74, 0x01, 0x25, 0x4d, 0xf5, +0x4d, 0xe4, 0x35, 0x4c, 0xf5, 0x4c, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, +0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x4b, 0xaa, 0x4c, 0xa9, 0x4d, +0x12, 0x13, 0xb5, 0x90, 0xff, 0xf1, 0xf0, 0x02, 0x2e, 0xd4, 0x90, 0xff, 0xf1, 0xe5, 0x4f, 0xf0, +0x02, 0x2e, 0xd4, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, 0xfa, +0xcb, 0xe4, 0x75, 0xf0, 0x09, 0x12, 0x14, 0x2f, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, +0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x12, +0x23, 0xee, 0x90, 0xff, 0xf7, 0xe5, 0x37, 0x12, 0x26, 0xfe, 0x90, 0xff, 0xf6, 0xe5, 0x37, 0xf0, +0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x06, 0x12, 0x26, 0xfe, 0xe5, 0x37, 0x30, 0xe0, 0x07, +0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, +0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, +0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x15, 0x6b, 0xa8, 0x6b, 0xa6, 0x07, 0x30, +0x08, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x6b, 0xe6, 0xff, 0xb4, 0x03, 0x0f, +0x78, 0x82, 0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, +0x82, 0x76, 0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x86, 0x76, 0xfa, +0x08, 0x76, 0x9a, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x20, 0xb7, 0x7b, +0x01, 0x7a, 0xff, 0x79, 0x48, 0x78, 0x6e, 0x12, 0x14, 0xf4, 0xa8, 0x6b, 0xe6, 0x24, 0xfd, 0x75, +0xf0, 0x08, 0xa4, 0xff, 0xae, 0xf0, 0x78, 0x70, 0x12, 0x20, 0xb7, 0x79, 0x08, 0x78, 0x71, 0x12, +0x14, 0xf4, 0x78, 0x73, 0xef, 0x12, 0x20, 0xb7, 0x05, 0x6b, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, +0xab, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe2, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, +0x79, 0xcb, 0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7e, 0x00, 0x90, 0xfa, +0xe0, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x52, +0x09, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe0, 0xe0, 0x70, 0x04, +0xa3, 0xe0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x65, +0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe2, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x65, 0xe0, +0x54, 0xef, 0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x90, 0xff, 0x93, 0x74, 0x2a, +0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, +0xe0, 0x44, 0x90, 0xf0, 0x12, 0x27, 0x8b, 0x12, 0x15, 0x35, 0x12, 0x2d, 0xa5, 0x7e, 0x07, 0x7f, +0xd0, 0x12, 0x11, 0x68, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0x82, 0xe4, 0x78, 0x7d, 0xf6, 0x78, +0x7d, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x74, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x7d, +0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x2c, 0x5b, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe4, 0x05, 0x7f, +0x04, 0x12, 0x2c, 0x5b, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, +0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x90, 0xef, 0xf6, 0x12, 0x27, +0x19, 0x12, 0x20, 0x59, 0x30, 0xe0, 0x25, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 0x71, +0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 0xe4, +0x12, 0x14, 0x0d, 0x80, 0xe9, 0x12, 0x20, 0x2d, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x20, 0x59, 0x30, +0xe1, 0x1e, 0x12, 0x20, 0x1b, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x2f, 0x15, 0x78, 0x6e, 0x12, 0x14, +0xeb, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x14, 0x0d, 0x12, 0x20, 0x1b, 0xe0, 0x44, 0x80, 0xf0, +0x12, 0x2f, 0x80, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x03, 0x6e, 0x01, 0xff, 0x48, +0x03, 0x71, 0x01, 0xff, 0x08, 0x02, 0x6c, 0x00, 0x00, 0x44, 0xfa, 0x94, 0x00, 0x00, 0x00, 0x00, +0x44, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xae, 0x00, 0x00, 0x42, 0xfa, 0x7a, 0x00, +0x00, 0x42, 0xfa, 0x78, 0x00, 0x00, 0x42, 0xf9, 0x69, 0xff, 0xff, 0x42, 0xfa, 0x76, 0x00, 0x00, +0x43, 0xf9, 0x16, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x63, 0x20, 0x41, 0xf9, 0x64, 0x20, 0x41, 0xf9, +0x61, 0x00, 0x41, 0xf9, 0x62, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf9, 0x65, +0x00, 0x41, 0xf9, 0x15, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x19, 0x82, +0xe5, 0x31, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x31, 0x94, +0x08, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x31, 0x94, 0x08, 0xf5, 0x31, +0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0x80, 0x05, 0xaf, 0x31, 0x12, 0x19, 0x92, 0xe4, 0xfe, 0xee, +0xc3, 0x9f, 0x50, 0x19, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, +0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 0xf0, 0x0e, 0x12, 0x18, 0x19, 0x80, 0xe2, 0xef, 0x54, 0x7f, +0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 0x5f, 0x8a, 0x60, 0x89, 0x61, 0x12, 0x2a, 0x6e, 0x70, 0x05, +0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 0x5f, 0xaa, 0x60, 0xa9, 0x61, 0x12, 0x2a, 0x62, 0x90, 0xfa, +0xc5, 0x12, 0x15, 0x06, 0xe5, 0x61, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x60, 0xfa, 0x90, 0xfa, 0xbf, +0x12, 0x15, 0x06, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x78, 0x91, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, 0xff, +0x78, 0x91, 0xe6, 0xc3, 0x9f, 0x50, 0x12, 0x12, 0x2a, 0x40, 0xff, 0x12, 0x2a, 0x49, 0x12, 0x2a, +0x5c, 0x78, 0x91, 0x06, 0x12, 0x2a, 0x58, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x2f, +0x06, 0xe4, 0x93, 0xff, 0x78, 0x7a, 0xf6, 0x54, 0x0f, 0x12, 0x19, 0x07, 0xe0, 0x08, 0x76, 0x00, +0x08, 0xf6, 0x18, 0x12, 0x18, 0x42, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x7b, +0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, +0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 0x22, 0x78, 0x7b, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, +0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, +0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x03, 0x12, 0x13, 0xce, 0x54, 0xf0, 0x24, 0xa0, 0x22, +0x90, 0xfa, 0xc5, 0x12, 0x14, 0xfd, 0x02, 0x13, 0xb5, 0x90, 0xfa, 0xbf, 0x12, 0x14, 0xfd, 0xef, +0x12, 0x13, 0xfb, 0x90, 0xfa, 0xc6, 0xe4, 0x22, 0x90, 0xfa, 0xc0, 0xe4, 0x75, 0xf0, 0x01, 0x02, +0x14, 0x2f, 0x90, 0x00, 0x08, 0x12, 0x14, 0x5b, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, +0x05, 0x12, 0x13, 0xce, 0x90, 0xfa, 0xbd, 0xf0, 0x22, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x22, +0x90, 0xfa, 0xd9, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, +0xd2, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xd4, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, 0x25, 0x57, +0xf5, 0x57, 0xee, 0x35, 0x56, 0xf5, 0x56, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, +0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe2, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x3c, +0xaa, 0x3d, 0xa9, 0x3e, 0x02, 0x13, 0xfb, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x6a, +0xed, 0x70, 0x0f, 0xe5, 0x6a, 0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x2e, 0xeb, 0x7f, 0x02, 0x02, +0x2e, 0xeb, 0xaf, 0x6a, 0x12, 0x27, 0x19, 0x74, 0x74, 0x25, 0x6a, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, +0xd2, 0x09, 0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x6a, 0xb4, +0x03, 0x07, 0x7f, 0x81, 0x12, 0x2e, 0xeb, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x2e, 0xeb, 0x30, 0x09, +0x07, 0x12, 0x18, 0x9b, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x22, 0x12, 0x0f, 0x89, 0x90, +0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, +0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x2c, 0x80, +0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0d, 0x12, 0x19, 0x3e, 0x53, 0x2c, 0x7f, 0x90, +0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0x9f, +0x12, 0x19, 0x46, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, 0x8a, 0x12, 0x20, 0x9e, 0x30, 0xe1, +0x07, 0x7f, 0x13, 0x12, 0x2e, 0xa5, 0x80, 0x34, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, 0x16, +0x78, 0x8a, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 0x90, +0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x04, 0xf0, 0x78, 0x8a, +0xe6, 0xff, 0x12, 0x20, 0x59, 0xfd, 0x12, 0x2d, 0x21, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, +0x0f, 0x89, 0x78, 0x8f, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x27, 0x19, 0x90, 0xf9, 0x66, 0x12, 0x14, +0xfd, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, +0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x20, 0x4b, 0x12, 0x2f, 0x80, 0x78, +0x8f, 0xe6, 0xff, 0x12, 0x19, 0xbb, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, +0x8b, 0xef, 0xf6, 0x12, 0x2e, 0x4c, 0x12, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, +0x16, 0x78, 0x8b, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, +0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x14, 0xf0, 0xe0, 0x70, 0x02, +0xd2, 0xb3, 0x02, 0x10, 0x0c, 0x8f, 0x69, 0x12, 0x27, 0x19, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x3f, +0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, +0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0x74, +0x74, 0x25, 0x69, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f, 0x00, 0x22, 0x8f, 0x37, 0xc2, 0x08, 0x12, +0x27, 0x19, 0x12, 0x20, 0x38, 0x78, 0x84, 0x12, 0x20, 0x1d, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x20, +0x70, 0x12, 0x20, 0x21, 0xe0, 0x20, 0xe0, 0xf6, 0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, +0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0xaf, 0x37, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, +0x89, 0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x24, 0x06, 0x12, 0x20, 0x23, 0xe0, 0xfd, 0x12, 0x20, +0x53, 0x90, 0x00, 0x03, 0x12, 0x20, 0x78, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x04, +0x12, 0x14, 0x0d, 0x12, 0x2f, 0x80, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, +0xae, 0x05, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x35, +0xe4, 0x95, 0x34, 0x40, 0x02, 0xae, 0x35, 0xee, 0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, +0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x14, 0x0d, 0xaf, 0x06, 0x12, 0x2f, 0x6a, +0x22, 0x12, 0x0f, 0x89, 0x78, 0x8c, 0x12, 0x20, 0x9e, 0x30, 0xe2, 0x07, 0x7f, 0x13, 0x12, 0x2e, +0xa5, 0x80, 0x1b, 0x78, 0x8c, 0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12, +0x2e, 0xa5, 0x80, 0x0a, 0x78, 0x8c, 0xe6, 0xff, 0x12, 0x21, 0x6e, 0x12, 0x2e, 0xa5, 0x02, 0x10, +0x0c, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, +0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x74, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, +0x74, 0x95, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, +0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, +0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x80, 0xf0, 0x74, +0x74, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, 0x64, +0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, +0xc3, 0xe5, 0x31, 0x9f, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x05, 0x12, 0x25, 0x9c, 0x80, 0x03, 0x12, +0x2f, 0x76, 0x02, 0x10, 0x0c, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, +0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, +0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22, 0x12, 0x0f, 0x89, 0x78, +0x6c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, +0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x11, 0x9f, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x8e, 0x65, +0x8f, 0x66, 0xe5, 0x66, 0x15, 0x66, 0xae, 0x65, 0x70, 0x02, 0x15, 0x65, 0xd3, 0x94, 0x00, 0xee, +0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x0f, 0x62, 0x80, 0xe5, 0x22, 0x11, 0x1a, +0x2b, 0x1c, 0x23, 0x56, 0x2f, 0x5c, 0x2d, 0xcc, 0x2d, 0x7a, 0x2e, 0x6b, 0x2c, 0x8e, 0x2b, 0x66, +0x2b, 0xec, 0x2c, 0xf1, 0x2e, 0x2d, 0x1b, 0xe6, 0x2b, 0xaf, 0x28, 0x67, 0x0e, 0x12, 0x0f, 0x89, +0x78, 0x8d, 0x12, 0x20, 0x9e, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x2e, 0xa5, 0x80, 0x0a, 0x78, +0x8d, 0xe6, 0xff, 0x12, 0x2c, 0x25, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x8f, 0x67, 0x12, 0x2c, +0x25, 0xaf, 0x67, 0x12, 0x27, 0x19, 0x12, 0x20, 0x38, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x67, +0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x67, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, +0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x05, 0x12, 0x29, 0x2d, 0x80, 0x06, 0x12, +0x19, 0x7a, 0x12, 0x19, 0x82, 0x02, 0x10, 0x0c, 0x12, 0x27, 0xfb, 0x12, 0x12, 0x3b, 0x90, 0xf8, +0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x11, 0xd8, 0x12, 0x26, 0xa3, 0x12, 0x12, 0x77, +0x12, 0x10, 0xfa, 0x80, 0xe3, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0xe4, 0xf5, 0x2a, 0xf5, +0x2b, 0xef, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, 0xff, 0x12, 0x2f, 0x6a, 0x22, 0x90, 0xff, 0xf0, +0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, +0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, +0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, +0x18, 0xad, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x18, 0xf7, 0xe0, 0x54, 0xdf, 0xf0, 0x22, +0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, +0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x84, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, +0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x34, 0x30, 0x85, 0x35, 0x31, 0x90, 0xff, +0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x2f, +0x00, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, +0x38, 0x28, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0f, 0x89, 0x7f, +0x02, 0x12, 0x10, 0x18, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x12, +0x18, 0x49, 0x12, 0x29, 0x2d, 0x22, 0x12, 0x19, 0x82, 0x12, 0x19, 0x3e, 0x12, 0x19, 0x7a, 0x22, +0xc2, 0x08, 0x22, +}; + +#undef IMAGE_VERSION_NAME + +#undef IMAGE_ARRAY_NAME + diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c new file mode 100644 index 000000000000..493ab2518435 --- /dev/null +++ b/drivers/usb/serial/io_ti.c @@ -0,0 +1,2684 @@ +/* + * Edgeport USB Serial Converter driver + * + * Copyright(c) 2000-2002 Inside Out Networks, All rights reserved. + * Copyright(c) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Supports the following devices: + * EP/1 EP/2 EP/4 + * + * Version history: + * + * July 11, 2002 Removed 4 port device structure since all TI UMP + * chips have only 2 ports + * David Iacovelli (davidi@ionetworks.com) + * + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/jiffies.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/tty.h> +#include <linux/tty_driver.h> +#include <linux/tty_flip.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/serial.h> +#include <linux/ioctl.h> +#include <asm/uaccess.h> +#include <linux/usb.h> + +#ifdef CONFIG_USB_SERIAL_DEBUG + static int debug = 1; +#else + static int debug; +#endif + +#include "usb-serial.h" + +#include "io_16654.h" +#include "io_usbvend.h" +#include "io_ti.h" + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.2" +#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli" +#define DRIVER_DESC "Edgeport USB Serial Driver" + + +/* firmware image code */ +#define IMAGE_VERSION_NAME PagableOperationalCodeImageVersion +#define IMAGE_ARRAY_NAME PagableOperationalCodeImage +#define IMAGE_SIZE PagableOperationalCodeSize +#include "io_fw_down3.h" /* Define array OperationalCodeImage[] */ + +#define EPROM_PAGE_SIZE 64 + + +struct edgeport_uart_buf_desc { + __u32 count; // Number of bytes currently in buffer +}; + +/* different hardware types */ +#define HARDWARE_TYPE_930 0 +#define HARDWARE_TYPE_TIUMP 1 + +// IOCTL_PRIVATE_TI_GET_MODE Definitions +#define TI_MODE_CONFIGURING 0 // Device has not entered start device +#define TI_MODE_BOOT 1 // Staying in boot mode +#define TI_MODE_DOWNLOAD 2 // Made it to download mode +#define TI_MODE_TRANSITIONING 3 // Currently in boot mode but transitioning to download mode + + +/* Product information read from the Edgeport */ +struct product_info +{ + int TiMode; // Current TI Mode + __u8 hardware_type; // Type of hardware +} __attribute__((packed)); + + +struct edgeport_port { + __u16 uart_base; + __u16 dma_address; + __u8 shadow_msr; + __u8 shadow_mcr; + __u8 shadow_lsr; + __u8 lsr_mask; + __u32 ump_read_timeout; /* Number of miliseconds the UMP will + wait without data before completing + a read short */ + int baud_rate; + int close_pending; + int lsr_event; + struct edgeport_uart_buf_desc tx; + struct async_icount icount; + wait_queue_head_t delta_msr_wait; /* for handling sleeping while + waiting for msr change to + happen */ + struct edgeport_serial *edge_serial; + struct usb_serial_port *port; +}; + +struct edgeport_serial { + struct product_info product_info; + u8 TI_I2C_Type; // Type of I2C in UMP + u8 TiReadI2C; // Set to TRUE if we have read the I2c in Boot Mode + int num_ports_open; + struct usb_serial *serial; +}; + + +/* Devices that this driver supports */ +static struct usb_device_id edgeport_1port_id_table [] = { + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, + { } +}; + +static struct usb_device_id edgeport_2port_id_table [] = { + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) }, + { } +}; + +/* Devices that this driver supports */ +static __devinitdata struct usb_device_id id_table_combined [] = { + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) }, + { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) }, + { } +}; + +MODULE_DEVICE_TABLE (usb, id_table_combined); + + +static struct EDGE_FIRMWARE_VERSION_INFO OperationalCodeImageVersion; + +static int TIStayInBootMode = 0; +static int ignore_cpu_rev = 0; + + + +static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); + +static int TIReadVendorRequestSync (struct usb_device *dev, + __u8 request, + __u16 value, + __u16 index, + u8 *data, + int size) +{ + int status; + + status = usb_control_msg (dev, + usb_rcvctrlpipe(dev, 0), + request, + (USB_TYPE_VENDOR | + USB_RECIP_DEVICE | + USB_DIR_IN), + value, + index, + data, + size, + HZ); + if (status < 0) + return status; + if (status != size) { + dbg ("%s - wanted to write %d, but only wrote %d", + __FUNCTION__, size, status); + return -ECOMM; + } + return 0; +} + +static int TISendVendorRequestSync (struct usb_device *dev, + __u8 request, + __u16 value, + __u16 index, + u8 *data, + int size) +{ + int status; + + status = usb_control_msg (dev, + usb_sndctrlpipe(dev, 0), + request, + (USB_TYPE_VENDOR | + USB_RECIP_DEVICE | + USB_DIR_OUT), + value, + index, + data, + size, + HZ); + + if (status < 0) + return status; + if (status != size) { + dbg ("%s - wanted to write %d, but only wrote %d", + __FUNCTION__, size, status); + return -ECOMM; + } + return 0; +} + +static int TIWriteCommandSync (struct usb_device *dev, __u8 command, + __u8 moduleid, __u16 value, u8 *data, + int size) +{ + return TISendVendorRequestSync (dev, + command, // Request + value, // wValue + moduleid, // wIndex + data, // TransferBuffer + size); // TransferBufferLength + +} + + +/* clear tx/rx buffers and fifo in TI UMP */ +static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask) +{ + int port_number = port->number - port->serial->minor; + + dbg ("%s - port %d, mask %x", __FUNCTION__, port_number, mask); + + return TIWriteCommandSync (port->serial->dev, + UMPC_PURGE_PORT, + (__u8)(UMPM_UART1_PORT + port_number), + mask, + NULL, + 0); +} + +/** + * TIReadDownloadMemory - Read edgeport memory from TI chip + * @dev: usb device pointer + * @address: Device CPU address at which to read + * @length: Length of above data + * @address_type: Can read both XDATA and I2C + * @buffer: pointer to input data buffer + */ +int TIReadDownloadMemory (struct usb_device *dev, int start_address, int length, + __u8 address_type, __u8 *buffer) +{ + int status = 0; + __u8 read_length; + __u16 be_start_address; + + dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length); + + /* Read in blocks of 64 bytes + * (TI firmware can't handle more than 64 byte reads) + */ + while (length) { + if (length > 64) + read_length= 64; + else + read_length = (__u8)length; + + if (read_length > 1) { + dbg ("%s - @ %x for %d", __FUNCTION__, + start_address, read_length); + } + be_start_address = cpu_to_be16 (start_address); + status = TIReadVendorRequestSync (dev, + UMPC_MEMORY_READ, // Request + (__u16)address_type, // wValue (Address type) + be_start_address, // wIndex (Address to read) + buffer, // TransferBuffer + read_length); // TransferBufferLength + + if (status) { + dbg ("%s - ERROR %x", __FUNCTION__, status); + return status; + } + + if (read_length > 1) { + usb_serial_debug_data (__FILE__, __FUNCTION__, + read_length, buffer); + } + + /* Update pointers/length */ + start_address += read_length; + buffer += read_length; + length -= read_length; + } + + return status; +} + +int TIReadRam (struct usb_device *dev, int start_address, int length, __u8 *buffer) +{ + return TIReadDownloadMemory (dev, + start_address, + length, + DTK_ADDR_SPACE_XDATA, + buffer); +} + +/* Read edgeport memory to a given block */ +static int TIReadBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 * buffer) +{ + int status = 0; + int i; + + for (i=0; i< length; i++) { + status = TIReadVendorRequestSync (serial->serial->dev, + UMPC_MEMORY_READ, // Request + serial->TI_I2C_Type, // wValue (Address type) + (__u16)(start_address+i), // wIndex + &buffer[i], // TransferBuffer + 0x01); // TransferBufferLength + if (status) { + dbg ("%s - ERROR %x", __FUNCTION__, status); + return status; + } + } + + dbg ("%s - start_address = %x, length = %d", __FUNCTION__, start_address, length); + usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer); + + serial->TiReadI2C = 1; + + return status; +} + +/* Write given block to TI EPROM memory */ +static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer) +{ + int status = 0; + int i; + __u8 temp; + + /* Must do a read before write */ + if (!serial->TiReadI2C) { + status = TIReadBootMemory(serial, 0, 1, &temp); + if (status) + return status; + } + + for (i=0; i < length; ++i) { + status = TISendVendorRequestSync (serial->serial->dev, + UMPC_MEMORY_WRITE, // Request + buffer[i], // wValue + (__u16)(i+start_address), // wIndex + NULL, // TransferBuffer + 0); // TransferBufferLength + if (status) + return status; + } + + dbg ("%s - start_sddr = %x, length = %d", __FUNCTION__, start_address, length); + usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer); + + return status; +} + + +/* Write edgeport I2C memory to TI chip */ +static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address, int length, __u8 address_type, __u8 *buffer) +{ + int status = 0; + int write_length; + __u16 be_start_address; + + /* We can only send a maximum of 1 aligned byte page at a time */ + + /* calulate the number of bytes left in the first page */ + write_length = EPROM_PAGE_SIZE - (start_address & (EPROM_PAGE_SIZE - 1)); + + if (write_length > length) + write_length = length; + + dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __FUNCTION__, start_address, write_length); + usb_serial_debug_data (__FILE__, __FUNCTION__, write_length, buffer); + + /* Write first page */ + be_start_address = cpu_to_be16 (start_address); + status = TISendVendorRequestSync (serial->serial->dev, + UMPC_MEMORY_WRITE, // Request + (__u16)address_type, // wValue + be_start_address, // wIndex + buffer, // TransferBuffer + write_length); + if (status) { + dbg ("%s - ERROR %d", __FUNCTION__, status); + return status; + } + + length -= write_length; + start_address += write_length; + buffer += write_length; + + /* We should be aligned now -- can write max page size bytes at a time */ + while (length) { + if (length > EPROM_PAGE_SIZE) + write_length = EPROM_PAGE_SIZE; + else + write_length = length; + + dbg ("%s - Page Write Addr = %x, length = %d", __FUNCTION__, start_address, write_length); + usb_serial_debug_data (__FILE__, __FUNCTION__, write_length, buffer); + + /* Write next page */ + be_start_address = cpu_to_be16 (start_address); + status = TISendVendorRequestSync (serial->serial->dev, + UMPC_MEMORY_WRITE, // Request + (__u16)address_type, // wValue + be_start_address, // wIndex + buffer, // TransferBuffer + write_length); // TransferBufferLength + if (status) { + dbg ("%s - ERROR %d", __FUNCTION__, status); + return status; + } + + length -= write_length; + start_address += write_length; + buffer += write_length; + } + return status; +} + +/* Examine the UMP DMA registers and LSR + * + * Check the MSBit of the X and Y DMA byte count registers. + * A zero in this bit indicates that the TX DMA buffers are empty + * then check the TX Empty bit in the UART. + */ +static int TIIsTxActive (struct edgeport_port *port) +{ + int status; + struct out_endpoint_desc_block *oedb; + __u8 lsr; + int bytes_left = 0; + + oedb = kmalloc (sizeof (* oedb), GFP_KERNEL); + if (!oedb) { + err ("%s - out of memory", __FUNCTION__); + return -ENOMEM; + } + + /* Read the DMA Count Registers */ + status = TIReadRam (port->port->serial->dev, + port->dma_address, + sizeof( *oedb), + (void *)oedb); + + if (status) + goto exit_is_tx_active; + + dbg ("%s - XByteCount 0x%X", __FUNCTION__, oedb->XByteCount); + + /* and the LSR */ + status = TIReadRam (port->port->serial->dev, + port->uart_base + UMPMEM_OFFS_UART_LSR, + 1, + &lsr); + + if (status) + goto exit_is_tx_active; + dbg ("%s - LSR = 0x%X", __FUNCTION__, lsr); + + /* If either buffer has data or we are transmitting then return TRUE */ + if ((oedb->XByteCount & 0x80 ) != 0 ) + bytes_left += 64; + + if ((lsr & UMP_UART_LSR_TX_MASK ) == 0 ) + bytes_left += 1; + + /* We return Not Active if we get any kind of error */ +exit_is_tx_active: + dbg ("%s - return %d", __FUNCTION__, bytes_left ); + return bytes_left; +} + +static void TIChasePort(struct edgeport_port *port) +{ + int loops; + int last_count; + int write_size; + +restart_tx_loop: + // Base the LoopTime on the baud rate + if (port->baud_rate == 0) + port->baud_rate = 1200; + + write_size = port->tx.count; + loops = max(100, (100*write_size)/(port->baud_rate/10)); + dbg ("%s - write_size %d, baud %d loop = %d", __FUNCTION__, + write_size, port->baud_rate, loops); + + while (1) { + // Save Last count + last_count = port->tx.count; + + dbg ("%s - Tx Buffer Size = %d loops = %d", __FUNCTION__, + last_count, loops); + + /* Is the Edgeport Buffer empty? */ + if (port->tx.count == 0) + break; + + /* Block the thread for 10ms */ + wait_ms (10); + + if (last_count == port->tx.count) { + /* No activity.. count down. */ + --loops; + if (loops == 0) { + dbg ("%s - Wait for TxEmpty - TIMEOUT", + __FUNCTION__); + return; + } + } else { + /* Reset timeout value back to a minimum of 1 second */ + dbg ("%s - Wait for TxEmpty Reset Count", __FUNCTION__); + goto restart_tx_loop; + } + } + + dbg ("%s - Local Tx Buffer Empty -- Waiting for TI UMP to EMPTY X/Y and FIFO", + __FUNCTION__); + + write_size = TIIsTxActive (port); + loops = max(50, (100*write_size)/(port->baud_rate/10)); + dbg ("%s - write_size %d, baud %d loop = %d", __FUNCTION__, + write_size, port->baud_rate, loops); + + while (1) { + /* This function takes 4 ms; */ + if (!TIIsTxActive (port)) { + /* Delay a few char times */ + wait_ms (50); + dbg ("%s - Empty", __FUNCTION__); + return; + } + + --loops; + if (loops == 0) { + dbg ("%s - TIMEOUT", __FUNCTION__); + return; + } + } +} + +static int TIChooseConfiguration (struct usb_device *dev) +{ + // There may be multiple configurations on this device, in which case + // we would need to read and parse all of them to find out which one + // we want. However, we just support one config at this point, + // configuration # 1, which is Config Descriptor 0. + + dbg ("%s - Number of Interfaces = %d", __FUNCTION__, dev->config->bNumInterfaces); + dbg ("%s - MAX Power = %d", __FUNCTION__, dev->config->MaxPower*2); + + if (dev->config->bNumInterfaces != 1) { + err ("%s - bNumInterfaces is not 1, ERROR!", __FUNCTION__); + return -ENODEV; + } + + return 0; +} + +int TIReadRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer) +{ + int status; + + if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) { + status = TIReadDownloadMemory (serial->serial->dev, + start_address, + length, + serial->TI_I2C_Type, + buffer); + } else { + status = TIReadBootMemory (serial, + start_address, + length, + buffer); + } + + return status; +} + +int TIWriteRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer) +{ + if (serial->product_info.TiMode == TI_MODE_BOOT) + return TIWriteBootMemory (serial, + start_address, + length, + buffer); + + if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) + return TIWriteDownloadI2C (serial, + start_address, + length, + serial->TI_I2C_Type, + buffer); + + return -EINVAL; +} + + + +/* Read a descriptor header from I2C based on type */ +static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type, struct ti_i2c_desc *rom_desc) +{ + int start_address; + int status; + + /* Search for requested descriptor in I2C */ + start_address = 2; + do { + status = TIReadRom (serial, + start_address, + sizeof(struct ti_i2c_desc), + (__u8 *)rom_desc ); + if (status) + return 0; + + if (rom_desc->Type == desc_type) + return start_address; + + start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size; + + } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type); + + return 0; +} + +/* Validate descriptor checksum */ +static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer) +{ + __u16 i; + __u8 cs = 0; + + for (i=0; i < rom_desc->Size; i++) { + cs = (__u8)(cs + buffer[i]); + } + if (cs != rom_desc->CheckSum) { + dbg ("%s - Mismatch %x - %x", __FUNCTION__, rom_desc->CheckSum, cs); + return -EINVAL; + } + return 0; +} + +/* Make sure that the I2C image is good */ +static int TiValidateI2cImage (struct edgeport_serial *serial) +{ + int status = 0; + struct ti_i2c_desc *rom_desc; + int start_address = 2; + __u8 *buffer; + + rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); + if (!rom_desc) { + err ("%s - out of memory", __FUNCTION__); + return -ENOMEM; + } + buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL); + if (!buffer) { + err ("%s - out of memory when allocating buffer", __FUNCTION__); + kfree (rom_desc); + return -ENOMEM; + } + + // Read the first byte (Signature0) must be 0x52 + status = TIReadRom (serial, 0, 1, buffer); + if (status) + goto ExitTiValidateI2cImage; + + if (*buffer != 0x52) { + err ("%s - invalid buffer signature", __FUNCTION__); + status = -ENODEV; + goto ExitTiValidateI2cImage; + } + + do { + // Validate the I2C + status = TIReadRom (serial, + start_address, + sizeof(struct ti_i2c_desc), + (__u8 *)rom_desc); + if (status) + break; + + if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) { + status = -ENODEV; + dbg ("%s - structure too big, erroring out.", __FUNCTION__); + break; + } + + dbg ("%s Type = 0x%x", __FUNCTION__, rom_desc->Type); + + // Skip type 2 record + if ((rom_desc->Type & 0x0f) != I2C_DESC_TYPE_FIRMWARE_BASIC) { + // Read the descriptor data + status = TIReadRom(serial, + start_address+sizeof(struct ti_i2c_desc), + rom_desc->Size, + buffer); + if (status) + break; + + status = ValidChecksum(rom_desc, buffer); + if (status) + break; + } + start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size; + + } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE)); + + if ((rom_desc->Type != I2C_DESC_TYPE_ION) || (start_address > TI_MAX_I2C_SIZE)) + status = -ENODEV; + +ExitTiValidateI2cImage: + kfree (buffer); + kfree (rom_desc); + return status; +} + +static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer) +{ + int status; + int start_address; + struct ti_i2c_desc *rom_desc; + struct edge_ti_manuf_descriptor *desc; + + rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); + if (!rom_desc) { + err ("%s - out of memory", __FUNCTION__); + return -ENOMEM; + } + start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc); + + if (!start_address) { + dbg ("%s - Edge Descriptor not found in I2C", __FUNCTION__); + status = -ENODEV; + goto exit; + } + + // Read the descriptor data + status = TIReadRom (serial, + start_address+sizeof(struct ti_i2c_desc), + rom_desc->Size, + buffer); + if (status) + goto exit; + + status = ValidChecksum(rom_desc, buffer); + + desc = (struct edge_ti_manuf_descriptor *)buffer; + dbg ( "%s - IonConfig 0x%x", __FUNCTION__, desc->IonConfig ); + dbg ( "%s - Version %d", __FUNCTION__, desc->Version ); + dbg ( "%s - Cpu/Board 0x%x", __FUNCTION__, desc->CpuRev_BoardRev ); + dbg ( "%s - NumPorts %d", __FUNCTION__, desc->NumPorts ); + dbg ( "%s - NumVirtualPorts %d", __FUNCTION__, desc->NumVirtualPorts ); + dbg ( "%s - TotalPorts %d", __FUNCTION__, desc->TotalPorts ); + +exit: + kfree (rom_desc); + return status; +} + +/* Build firmware header used for firmware update */ +static int BuildI2CFirmwareHeader (__u8 *header) +{ + __u8 *buffer; + int buffer_size; + int i; + __u8 cs = 0; + struct ti_i2c_desc *i2c_header; + struct ti_i2c_image_header *img_header; + struct ti_i2c_firmware_rec *firmware_rec; + + // In order to update the I2C firmware we must change the type 2 record to type 0xF2. + // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver + // will download the latest firmware (padded to 15.5k) into the UMP ram. + // And finally when the device comes back up in download mode the driver will cause + // the new firmware to be copied from the UMP Ram to I2C and the firmware will update + // the record type from 0xf2 to 0x02. + + // Allocate a 15.5k buffer + 2 bytes for version number (Firmware Record) + buffer_size = (((1024 * 16) - 512 )+ sizeof(struct ti_i2c_firmware_rec)); + + buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!buffer) { + err ("%s - out of memory", __FUNCTION__); + return -ENOMEM; + } + + // Set entire image of 0xffs + memset (buffer, 0xff, buffer_size); + + // Copy version number into firmware record + firmware_rec = (struct ti_i2c_firmware_rec *)buffer; + + firmware_rec->Ver_Major = OperationalCodeImageVersion.MajorVersion; + firmware_rec->Ver_Minor = OperationalCodeImageVersion.MinorVersion; + + // Pointer to fw_down memory image + img_header = (struct ti_i2c_image_header *)&PagableOperationalCodeImage[0]; + + memcpy (buffer + sizeof(struct ti_i2c_firmware_rec), + &PagableOperationalCodeImage[sizeof(struct ti_i2c_image_header)], + img_header->Length); + + for (i=0; i < buffer_size; i++) { + cs = (__u8)(cs + buffer[i]); + } + + kfree (buffer); + + // Build new header + i2c_header = (struct ti_i2c_desc *)header; + firmware_rec = (struct ti_i2c_firmware_rec*)i2c_header->Data; + + i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK; + i2c_header->Size = (__u16)buffer_size; + i2c_header->CheckSum = cs; + firmware_rec->Ver_Major = OperationalCodeImageVersion.MajorVersion; + firmware_rec->Ver_Minor = OperationalCodeImageVersion.MinorVersion; + + return 0; +} + +/* Try to figure out what type of I2c we have */ +static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial) +{ + int status; + __u8 data; + + // Try to read type 2 + status = TIReadVendorRequestSync (serial->serial->dev, + UMPC_MEMORY_READ, // Request + DTK_ADDR_SPACE_I2C_TYPE_II, // wValue (Address type) + 0, // wIndex + &data, // TransferBuffer + 0x01); // TransferBufferLength + if (status) + dbg ("%s - read 2 status error = %d", __FUNCTION__, status); + else + dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data); + if ((!status) && data == 0x52) { + dbg ("%s - ROM_TYPE_II", __FUNCTION__); + serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; + return 0; + } + + // Try to read type 3 + status = TIReadVendorRequestSync (serial->serial->dev, + UMPC_MEMORY_READ, // Request + DTK_ADDR_SPACE_I2C_TYPE_III, // wValue (Address type) + 0, // wIndex + &data, // TransferBuffer + 0x01); // TransferBufferLength + if (status) + dbg ("%s - read 3 status error = %d", __FUNCTION__, status); + else + dbg ("%s - read 2 data = 0x%x", __FUNCTION__, data); + if ((!status) && data == 0x52) { + dbg ("%s - ROM_TYPE_III", __FUNCTION__); + serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III; + return 0; + } + + dbg ("%s - Unknown", __FUNCTION__); + serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; + return -ENODEV; +} + +static int TISendBulkTransferSync (struct usb_serial *serial, void *buffer, int length, int *num_sent) +{ + int status; + + status = usb_bulk_msg (serial->dev, + usb_sndbulkpipe(serial->dev, + serial->port[0].bulk_out_endpointAddress), + buffer, + length, + num_sent, + HZ); + return status; +} + +/* Download given firmware image to the device (IN BOOT MODE) */ +static int TIDownloadCodeImage (struct edgeport_serial *serial, __u8 *image, int image_length) +{ + int status = 0; + int pos; + int transfer; + int done; + + // Transfer firmware image + for (pos = 0; pos < image_length; ) { + // Read the next buffer from file + transfer = image_length - pos; + if (transfer > EDGE_FW_BULK_MAX_PACKET_SIZE) + transfer = EDGE_FW_BULK_MAX_PACKET_SIZE; + + // Transfer data + status = TISendBulkTransferSync (serial->serial, &image[pos], transfer, &done); + if (status) + break; + // Advance buffer pointer + pos += done; + } + + return status; +} + +// FIXME!!! +static int TIConfigureBootDevice (struct usb_device *dev) +{ + return 0; +} + +/** + * DownloadTIFirmware - Download run-time operating firmware to the TI5052 + * + * This routine downloads the main operating code into the TI5052, using the + * boot code already burned into E2PROM or ROM. + */ +static int TIDownloadFirmware (struct edgeport_serial *serial) +{ + int status = 0; + int start_address; + struct edge_ti_manuf_descriptor *ti_manuf_desc; + struct usb_interface_descriptor *interface; + int download_cur_ver; + int download_new_ver; + + /* This routine is entered by both the BOOT mode and the Download mode + * We can determine which code is running by the reading the config + * descriptor and if we have only one bulk pipe it is in boot mode + */ + serial->product_info.hardware_type = HARDWARE_TYPE_TIUMP; + + /* Default to type 2 i2c */ + serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; + + status = TIChooseConfiguration (serial->serial->dev); + if (status) + return status; + + interface = serial->serial->dev->config->interface->altsetting; + if (!interface) { + err ("%s - no interface set, error!", __FUNCTION__); + return -ENODEV; + } + + // Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING + // if we have more than one endpoint we are definitely in download mode + if (interface->bNumEndpoints > 1) + serial->product_info.TiMode = TI_MODE_DOWNLOAD; + else + // Otherwise we will remain in configuring mode + serial->product_info.TiMode = TI_MODE_CONFIGURING; + + // Save Download Version Number + OperationalCodeImageVersion.MajorVersion = PagableOperationalCodeImageVersion.MajorVersion; + OperationalCodeImageVersion.MinorVersion = PagableOperationalCodeImageVersion.MinorVersion; + OperationalCodeImageVersion.BuildNumber = PagableOperationalCodeImageVersion.BuildNumber; + + /********************************************************************/ + /* Download Mode */ + /********************************************************************/ + if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) { + struct ti_i2c_desc *rom_desc; + + dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN DOWNLOAD MODE>>>>>>>>>>", __FUNCTION__); + + status = TiValidateI2cImage (serial); + if (status) { + dbg ("%s - <<<<<<<<<<<<<<<DOWNLOAD MODE -- BAD I2C >>>>>>>>>>", + __FUNCTION__); + return status; + } + + /* Validate Hardware version number + * Read Manufacturing Descriptor from TI Based Edgeport + */ + ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL); + if (!ti_manuf_desc) { + err ("%s - out of memory.", __FUNCTION__); + return -ENOMEM; + } + status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc); + if (status) { + kfree (ti_manuf_desc); + return status; + } + + // Check version number of ION descriptor + if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) { + dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__, + TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev)); + kfree (ti_manuf_desc); + return -EINVAL; + } + + rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL); + if (!rom_desc) { + err ("%s - out of memory.", __FUNCTION__); + kfree (ti_manuf_desc); + return -ENOMEM; + } + + // Search for type 2 record (firmware record) + if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc)) != 0) { + struct ti_i2c_firmware_rec *firmware_version; + __u8 record; + + dbg ("%s - Found Type FIRMWARE (Type 2) record", __FUNCTION__); + + firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL); + if (!firmware_version) { + err ("%s - out of memory.", __FUNCTION__); + kfree (rom_desc); + kfree (ti_manuf_desc); + return -ENOMEM; + } + + // Validate version number + // Read the descriptor data + status = TIReadRom (serial, + start_address+sizeof(struct ti_i2c_desc), + sizeof(struct ti_i2c_firmware_rec), + (__u8 *)firmware_version); + if (status) { + kfree (firmware_version); + kfree (rom_desc); + kfree (ti_manuf_desc); + return status; + } + + // Check version number of download with current version in I2c + download_cur_ver = (firmware_version->Ver_Major << 8) + + (firmware_version->Ver_Minor); + download_new_ver = (OperationalCodeImageVersion.MajorVersion << 8) + + (OperationalCodeImageVersion.MinorVersion); + + dbg ("%s - >>>Firmware Versions Device %d.%d Driver %d.%d", + __FUNCTION__, + firmware_version->Ver_Major, + firmware_version->Ver_Minor, + OperationalCodeImageVersion.MajorVersion, + OperationalCodeImageVersion.MinorVersion); + + // Check if we have an old version in the I2C and update if necessary + if (download_cur_ver != download_new_ver) { + dbg ("%s - Update I2C Download from %d.%d to %d.%d", + __FUNCTION__, + firmware_version->Ver_Major, + firmware_version->Ver_Minor, + OperationalCodeImageVersion.MajorVersion, + OperationalCodeImageVersion.MinorVersion); + + // In order to update the I2C firmware we must change the type 2 record to type 0xF2. + // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver + // will download the latest firmware (padded to 15.5k) into the UMP ram. + // And finally when the device comes back up in download mode the driver will cause + // the new firmware to be copied from the UMP Ram to I2C and the firmware will update + // the record type from 0xf2 to 0x02. + + record = I2C_DESC_TYPE_FIRMWARE_BLANK; + + // Change the I2C Firmware record type to 0xf2 to trigger an update + status = TIWriteRom (serial, + start_address, + sizeof(record), + &record); + if (status) { + kfree (firmware_version); + kfree (rom_desc); + kfree (ti_manuf_desc); + return status; + } + + // verify the write -- must do this in order for write to + // complete before we do the hardware reset + status = TIReadRom (serial, + start_address, + sizeof(record), + &record); + + if (status) { + kfree (firmware_version); + kfree (rom_desc); + kfree (ti_manuf_desc); + return status; + } + + if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) { + err ("%s - error resetting device", __FUNCTION__); + kfree (firmware_version); + kfree (rom_desc); + kfree (ti_manuf_desc); + return -ENODEV; + } + + dbg ("%s - HARDWARE RESET", __FUNCTION__); + + // Reset UMP -- Back to BOOT MODE + status = TISendVendorRequestSync (serial->serial->dev, + UMPC_HARDWARE_RESET, // Request + 0, // wValue + 0, // wIndex + NULL, // TransferBuffer + 0); // TransferBufferLength + + dbg ( "%s - HARDWARE RESET return %d", __FUNCTION__, status); + + /* return an error on purpose. */ + return -ENODEV; + } + } + // Search for type 0xF2 record (firmware blank record) + else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) { + #define HEADER_SIZE (sizeof(struct ti_i2c_desc) + sizeof(struct ti_i2c_firmware_rec)) + __u8 *header; + __u8 *vheader; + + header = kmalloc (HEADER_SIZE, GFP_KERNEL); + if (!header) { + err ("%s - out of memory.", __FUNCTION__); + kfree (rom_desc); + kfree (ti_manuf_desc); + return -ENOMEM; + } + + vheader = kmalloc (HEADER_SIZE, GFP_KERNEL); + if (!vheader) { + err ("%s - out of memory.", __FUNCTION__); + kfree (header); + kfree (rom_desc); + kfree (ti_manuf_desc); + return -ENOMEM; + } + + dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __FUNCTION__); + + // In order to update the I2C firmware we must change the type 2 record to type 0xF2. + // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver + // will download the latest firmware (padded to 15.5k) into the UMP ram. + // And finally when the device comes back up in download mode the driver will cause + // the new firmware to be copied from the UMP Ram to I2C and the firmware will update + // the record type from 0xf2 to 0x02. + status = BuildI2CFirmwareHeader(header); + if (status) { + kfree (vheader); + kfree (header); + kfree (rom_desc); + kfree (ti_manuf_desc); + return status; + } + + // Update I2C with type 0xf2 record with correct size and checksum + status = TIWriteRom (serial, + start_address, + HEADER_SIZE, + header); + if (status) { + kfree (vheader); + kfree (header); + kfree (rom_desc); + kfree (ti_manuf_desc); + return status; + } + + // verify the write -- must do this in order for write to + // complete before we do the hardware reset + status = TIReadRom (serial, + start_address, + HEADER_SIZE, + vheader); + + if (status) { + dbg ("%s - can't read header back", __FUNCTION__); + kfree (vheader); + kfree (header); + kfree (rom_desc); + kfree (ti_manuf_desc); + return status; + } + if (memcmp(vheader, header, HEADER_SIZE)) { + dbg ("%s - write download record failed", __FUNCTION__); + kfree (vheader); + kfree (header); + kfree (rom_desc); + kfree (ti_manuf_desc); + return status; + } + + kfree (vheader); + kfree (header); + + dbg ("%s - Start firmware update", __FUNCTION__); + + // Tell firmware to copy download image into I2C + status = TISendVendorRequestSync (serial->serial->dev, + UMPC_COPY_DNLD_TO_I2C, // Request + 0, // wValue + 0, // wIndex + NULL, // TransferBuffer + 0); // TransferBufferLength + + dbg ("%s - Update complete 0x%x", __FUNCTION__, status); + if (status) { + dbg ("%s - UMPC_COPY_DNLD_TO_I2C failed", __FUNCTION__); + kfree (rom_desc); + kfree (ti_manuf_desc); + return status; + } + } + + // The device is running the download code + kfree (rom_desc); + kfree (ti_manuf_desc); + return 0; + } + + /********************************************************************/ + /* Boot Mode */ + /********************************************************************/ + dbg ("%s - <<<<<<<<<<<<<<<RUNNING IN BOOT MODE>>>>>>>>>>>>>>>", + __FUNCTION__); + + // Configure the TI device so we can use the BULK pipes for download + status = TIConfigureBootDevice (serial->serial->dev); + if (status) + return status; + + if (serial->serial->dev->descriptor.idVendor != USB_VENDOR_ID_ION) { + dbg ("%s - VID = 0x%x", __FUNCTION__, + serial->serial->dev->descriptor.idVendor); + serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; + goto StayInBootMode; + } + + // We have an ION device (I2c Must be programmed) + // Determine I2C image type + if (TIGetI2cTypeInBootMode(serial)) { + goto StayInBootMode; + } + + // Registry variable set? + if (TIStayInBootMode) { + dbg ("%s - TIStayInBootMode", __FUNCTION__); + goto StayInBootMode; + } + + // Check for ION Vendor ID and that the I2C is valid + if (!TiValidateI2cImage(serial)) { + struct ti_i2c_image_header *header; + int i; + __u8 cs = 0; + __u8 *buffer; + int buffer_size; + + /* Validate Hardware version number + * Read Manufacturing Descriptor from TI Based Edgeport + */ + ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL); + if (!ti_manuf_desc) { + err ("%s - out of memory.", __FUNCTION__); + return -ENOMEM; + } + status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc); + if (status) { + kfree (ti_manuf_desc); + goto StayInBootMode; + } + + // Check for version 2 + if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) { + dbg ("%s - Wrong CPU Rev %d (Must be 2)", __FUNCTION__, + TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev)); + kfree (ti_manuf_desc); + goto StayInBootMode; + } + + kfree (ti_manuf_desc); + + // In order to update the I2C firmware we must change the type 2 record to type 0xF2. + // This will force the UMP to come up in Boot Mode. Then while in boot mode, the driver + // will download the latest firmware (padded to 15.5k) into the UMP ram. + // And finally when the device comes back up in download mode the driver will cause + // the new firmware to be copied from the UMP Ram to I2C and the firmware will update + // the record type from 0xf2 to 0x02. + + /* + * Do we really have to copy the whole firmware image, + * or could we do this in place! + */ + + // Allocate a 15.5k buffer + 3 byte header + buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header)); + buffer = kmalloc (buffer_size, GFP_KERNEL); + if (!buffer) { + err ("%s - out of memory", __FUNCTION__); + return -ENOMEM; + } + + // Initialize the buffer to 0xff (pad the buffer) + memset (buffer, 0xff, buffer_size); + + memcpy (buffer, &PagableOperationalCodeImage[0], PagableOperationalCodeSize); + + for(i = sizeof(struct ti_i2c_image_header); i < buffer_size; i++) { + cs = (__u8)(cs + buffer[i]); + } + + header = (struct ti_i2c_image_header *)buffer; + + // update length and checksum after padding + header->Length = (__u16)(buffer_size - sizeof(struct ti_i2c_image_header)); + header->CheckSum = cs; + + // Download the operational code + dbg ("%s - Downloading operational code image (TI UMP)", __FUNCTION__); + status = TIDownloadCodeImage (serial, buffer, buffer_size); + + kfree (buffer); + + if (status) { + dbg ("%s - Error downloading operational code image", __FUNCTION__); + return status; + } + + // Device will reboot + serial->product_info.TiMode = TI_MODE_TRANSITIONING; + + dbg ("%s - Download successful -- Device rebooting...", __FUNCTION__); + + /* return an error on purpose */ + return -ENODEV; + } + +StayInBootMode: + // Eprom is invalid or blank stay in boot mode + dbg ("%s - <<<<<<<<<<<<<<<STAYING IN BOOT MODE>>>>>>>>>>>>", __FUNCTION__); + serial->product_info.TiMode = TI_MODE_BOOT; + + return 0; +} + + +static int TISetDtr (struct edgeport_port *port) +{ + int port_number = port->port->number - port->port->serial->minor; + + dbg ("%s", __FUNCTION__); + port->shadow_mcr |= MCR_DTR; + + return TIWriteCommandSync (port->port->serial->dev, + UMPC_SET_CLR_DTR, + (__u8)(UMPM_UART1_PORT + port_number), + 1, /* set */ + NULL, + 0); +} + +static int TIClearDtr (struct edgeport_port *port) +{ + int port_number = port->port->number - port->port->serial->minor; + + dbg ("%s", __FUNCTION__); + port->shadow_mcr &= ~MCR_DTR; + + return TIWriteCommandSync (port->port->serial->dev, + UMPC_SET_CLR_DTR, + (__u8)(UMPM_UART1_PORT + port_number), + 0, /* clear */ + NULL, + 0); +} + +static int TISetRts (struct edgeport_port *port) +{ + int port_number = port->port->number - port->port->serial->minor; + + dbg ("%s", __FUNCTION__); + port->shadow_mcr |= MCR_RTS; + + return TIWriteCommandSync (port->port->serial->dev, + UMPC_SET_CLR_RTS, + (__u8)(UMPM_UART1_PORT + port_number), + 1, /* set */ + NULL, + 0); +} + +static int TIClearRts (struct edgeport_port *port) +{ + int port_number = port->port->number - port->port->serial->minor; + + dbg ("%s", __FUNCTION__); + port->shadow_mcr &= ~MCR_RTS; + + return TIWriteCommandSync (port->port->serial->dev, + UMPC_SET_CLR_RTS, + (__u8)(UMPM_UART1_PORT + port_number), + 0, /* clear */ + NULL, + 0); +} + +static int TISetLoopBack (struct edgeport_port *port) +{ + int port_number = port->port->number - port->port->serial->minor; + + dbg ("%s", __FUNCTION__); + + return TIWriteCommandSync (port->port->serial->dev, + UMPC_SET_CLR_LOOPBACK, + (__u8)(UMPM_UART1_PORT + port_number), + 1, /* set */ + NULL, + 0); +} + +static int TIClearLoopBack (struct edgeport_port *port) +{ + int port_number = port->port->number - port->port->serial->minor; + + dbg ("%s", __FUNCTION__); + + return TIWriteCommandSync (port->port->serial->dev, + UMPC_SET_CLR_LOOPBACK, + (__u8)(UMPM_UART1_PORT + port_number), + 0, /* clear */ + NULL, + 0); +} + +static int TISetBreak (struct edgeport_port *port) +{ + int port_number = port->port->number - port->port->serial->minor; + + dbg ("%s", __FUNCTION__); + + return TIWriteCommandSync (port->port->serial->dev, + UMPC_SET_CLR_BREAK, + (__u8)(UMPM_UART1_PORT + port_number), + 1, /* set */ + NULL, + 0); +} + +static int TIClearBreak (struct edgeport_port *port) +{ + int port_number = port->port->number - port->port->serial->minor; + + dbg ("%s", __FUNCTION__); + + return TIWriteCommandSync (port->port->serial->dev, + UMPC_SET_CLR_BREAK, + (__u8)(UMPM_UART1_PORT + port_number), + 0, /* clear */ + NULL, + 0); +} + +static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr) +{ + int status = 0; + + dbg ("%s - %x", __FUNCTION__, mcr); + + if (mcr & MCR_DTR) + status = TISetDtr (port); + else + status = TIClearDtr (port); + + if (status) + return status; + + if (mcr & MCR_RTS) + status = TISetRts (port); + else + status = TIClearRts (port); + + if (status) + return status; + + if (mcr & MCR_LOOPBACK) + status = TISetLoopBack (port); + else + status = TIClearLoopBack (port); + + return status; +} + + + +/* Convert TI LSR to standard UART flags */ +static __u8 MapLineStatus (__u8 ti_lsr) +{ + __u8 lsr = 0; + +#define MAP_FLAG(flagUmp, flagUart) \ + if (ti_lsr & flagUmp) lsr |= flagUart; + + MAP_FLAG(UMP_UART_LSR_OV_MASK, LSR_OVER_ERR) /* overrun */ + MAP_FLAG(UMP_UART_LSR_PE_MASK, LSR_PAR_ERR) /* parity error */ + MAP_FLAG(UMP_UART_LSR_FE_MASK, LSR_FRM_ERR) /* framing error */ + MAP_FLAG(UMP_UART_LSR_BR_MASK, LSR_BREAK) /* break detected */ + MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL) /* receive data available */ + MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY) /* transmit holding register empty */ + +#undef MAP_FLAG + + return lsr; +} + +static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr) +{ + struct async_icount *icount; + + dbg ("%s - %02x", __FUNCTION__, msr); + + if (msr & (MSR_DELTA_CTS | MSR_DELTA_DSR | MSR_DELTA_RI | MSR_DELTA_CD)) { + icount = &edge_port->icount; + + /* update input line counters */ + if (msr & MSR_DELTA_CTS) + icount->cts++; + if (msr & MSR_DELTA_DSR) + icount->dsr++; + if (msr & MSR_DELTA_CD) + icount->dcd++; + if (msr & MSR_DELTA_RI) + icount->rng++; + wake_up_interruptible (&edge_port->delta_msr_wait); + } + + /* Save the new modem status */ + edge_port->shadow_msr = msr & 0xf0; + + return; +} + +static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 lsr, __u8 data) +{ + struct async_icount *icount; + __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); + + dbg ("%s - %02x", __FUNCTION__, new_lsr); + + edge_port->shadow_lsr = lsr; + + if (new_lsr & LSR_BREAK) { + /* + * Parity and Framing errors only count if they + * occur exclusive of a break being received. + */ + new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); + } + + /* Place LSR data byte into Rx buffer */ + if (lsr_data && edge_port->port->tty) { + tty_insert_flip_char(edge_port->port->tty, data, 0); + tty_flip_buffer_push(edge_port->port->tty); + } + + /* update input line counters */ + icount = &edge_port->icount; + if (new_lsr & LSR_BREAK) + icount->brk++; + if (new_lsr & LSR_OVER_ERR) + icount->overrun++; + if (new_lsr & LSR_PAR_ERR) + icount->parity++; + if (new_lsr & LSR_FRM_ERR) + icount->frame++; +} + + +static void edge_interrupt_callback (struct urb *urb) +{ + struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; + struct usb_serial_port *port; + struct edgeport_port *edge_port; + unsigned char *data = urb->transfer_buffer; + int length = urb->actual_length; + int port_number; + int function; + __u8 lsr; + __u8 msr; + + dbg("%s", __FUNCTION__); + + if (serial_paranoia_check (edge_serial->serial, __FUNCTION__)) { + return; + } + + if (urb->status) { + dbg(__FUNCTION__" - nonzero control read status received: %d", urb->status); + return; + } + + if (!length) { + dbg ("%s - no data in urb", __FUNCTION__); + return; + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, length, data); + + if (length != 2) { + dbg ("%s - expecting packet of size 2, got %d", __FUNCTION__, length); + return; + } + + port_number = TIUMP_GET_PORT_FROM_CODE (data[0]); + function = TIUMP_GET_FUNC_FROM_CODE (data[0]); + dbg ("%s - port_number %d, function %d, info 0x%x", + __FUNCTION__, port_number, function, data[1]); + port = &edge_serial->serial->port[port_number]; + if (port_paranoia_check (port, __FUNCTION__)) { + dbg ("%s - change found for port that is not present", + __FUNCTION__); + return; + } + edge_port = port->private; + if (!edge_port) { + dbg ("%s - edge_port not found", __FUNCTION__); + return; + } + switch (function) { + case TIUMP_INTERRUPT_CODE_LSR: + lsr = MapLineStatus(data[1]); + if (lsr & UMP_UART_LSR_DATA_MASK) { + /* Save the LSR event for bulk read completion routine */ + dbg ("%s - LSR Event Port %u LSR Status = %02x", + __FUNCTION__, port_number, lsr); + edge_port->lsr_event = 1; + edge_port->lsr_mask = lsr; + } else { + dbg ("%s - ===== Port %d LSR Status = %02x ======", + __FUNCTION__, port_number, lsr); + handle_new_lsr (edge_port, 0, lsr, 0); + } + break; + + case TIUMP_INTERRUPT_CODE_MSR: // MSR + /* Copy MSR from UMP */ + msr = data[1]; + dbg ("%s - ===== Port %u MSR Status = %02x ======\n", + __FUNCTION__, port_number, msr); + handle_new_msr (edge_port, msr); + break; + + default: + err ("%s - Unknown Interrupt code from UMP %x\n", + __FUNCTION__, data[1]); + break; + + } +} + +static void edge_bulk_in_callback (struct urb *urb) +{ + struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; + unsigned char *data = urb->transfer_buffer; + struct tty_struct *tty; + int status; + int i; + int port_number; + + dbg("%s", __FUNCTION__); + + if (port_paranoia_check (edge_port->port, __FUNCTION__)) + return; + + if (urb->status) { + dbg ("%s - nonzero read bulk status received: %d", + __FUNCTION__, urb->status); + + if (urb->status == -EPIPE) { + /* clear any problem that might have happened on this pipe */ + usb_clear_halt (edge_port->port->serial->dev, urb->pipe); + goto exit; + } + return; + } + + port_number = edge_port->port->number - edge_port->port->serial->minor; + + if (edge_port->lsr_event) { + edge_port->lsr_event = 0; + dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======", + __FUNCTION__, port_number, edge_port->lsr_mask, *data); + handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data); + /* Adjust buffer length/pointer */ + --urb->actual_length; + ++data; + } + + tty = edge_port->port->tty; + if (tty && urb->actual_length) { + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + + if (edge_port->close_pending) { + dbg ("%s - close is pending, dropping data on the floor.", __FUNCTION__); + } else { + for (i = 0; i < urb->actual_length ; ++i) { + /* if we insert more than TTY_FLIPBUF_SIZE characters, + * we drop them. */ + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + /* this doesn't actually push the data through unless + * tty->low_latency is set */ + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } + edge_port->icount.rx += urb->actual_length; + } + +exit: + /* continue always trying to read */ + urb->dev = edge_port->port->serial->dev; + status = usb_submit_urb (urb, GFP_ATOMIC); + if (status) + err ("%s - usb_submit_urb failed with result %d", + __FUNCTION__, status); +} + +static void edge_bulk_out_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + struct tty_struct *tty; + + dbg ("%s - port %d", __FUNCTION__, port->number); + + if (!serial) { + dbg ("%s - bad serial pointer, exiting", __FUNCTION__); + return; + } + + if (urb->status) { + dbg ("%s - nonzero write bulk status received: %d", + __FUNCTION__, urb->status); + + if (urb->status == -EPIPE) { + /* clear any problem that might have happened on this pipe */ + usb_clear_halt (serial->dev, urb->pipe); + } + return; + } + + tty = port->tty; + if (tty) { + /* let the tty driver wakeup if it has a special write_wakeup function */ + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { + (tty->ldisc.write_wakeup)(tty); + } + + /* tell the tty driver that something has changed */ + wake_up_interruptible(&tty->write_wait); + } +} + +static int edge_open (struct usb_serial_port *port, struct file * filp) +{ + struct edgeport_port *edge_port = (struct edgeport_port *)port->private; + struct edgeport_serial *edge_serial; + struct usb_device *dev; + struct urb *urb; + int port_number; + int status; + u16 open_settings; + u8 transaction_timeout; + + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (edge_port == NULL) + return -ENODEV; + + /* force low_latency on so that our tty_push actually forces the data through, + otherwise it is scheduled, and with high data rates (like with OHCI) data + can get lost. */ + if (port->tty) + port->tty->low_latency = 1; + + port_number = port->number - port->serial->minor; + switch (port_number) { + case 0: + edge_port->uart_base = UMPMEM_BASE_UART1; + edge_port->dma_address = UMPD_OEDB1_ADDRESS; + break; + case 1: + edge_port->uart_base = UMPMEM_BASE_UART2; + edge_port->dma_address = UMPD_OEDB2_ADDRESS; + break; + default: + err ("Unknown port number!!!"); + return -ENODEV; + } + + dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x", + __FUNCTION__, port_number, edge_port->uart_base, edge_port->dma_address); + + dev = port->serial->dev; + + memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount)); + init_waitqueue_head (&edge_port->delta_msr_wait); + + /* turn off loopback */ + status = TIClearLoopBack (edge_port); + if (status) + return status; + + /* set up the port settings */ + edge_set_termios (port, NULL); + + /* open up the port */ + + /* milliseconds to timeout for DMA transfer */ + transaction_timeout = 2; + + edge_port->ump_read_timeout = max (20, ((transaction_timeout * 3) / 2) ); + + // milliseconds to timeout for DMA transfer + open_settings = (u8)(UMP_DMA_MODE_CONTINOUS | + UMP_PIPE_TRANS_TIMEOUT_ENA | + (transaction_timeout << 2)); + + dbg ("%s - Sending UMPC_OPEN_PORT", __FUNCTION__); + + /* Tell TI to open and start the port */ + status = TIWriteCommandSync (dev, + UMPC_OPEN_PORT, + (u8)(UMPM_UART1_PORT + port_number), + open_settings, + NULL, + 0); + if (status) + return status; + + /* Start the DMA? */ + status = TIWriteCommandSync (dev, + UMPC_START_PORT, + (u8)(UMPM_UART1_PORT + port_number), + 0, + NULL, + 0); + if (status) + return status; + + /* Clear TX and RX buffers in UMP */ + status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN); + if (status) + return status; + + /* Read Initial MSR */ + status = TIReadVendorRequestSync (dev, + UMPC_READ_MSR, // Request + 0, // wValue + (__u16)(UMPM_UART1_PORT + port_number), // wIndex (Address) + &edge_port->shadow_msr, // TransferBuffer + 1); // TransferBufferLength + if (status) + return status; + + dbg ("ShadowMSR 0x%X", edge_port->shadow_msr); + + edge_serial = edge_port->edge_serial; + if (edge_serial->num_ports_open == 0) { + /* we are the first port to be opened, let's post the interrupt urb */ + urb = edge_serial->serial->port[0].interrupt_in_urb; + if (!urb) { + err ("%s - no interrupt urb present, exiting", __FUNCTION__); + return -EINVAL; + } + urb->complete = edge_interrupt_callback; + urb->context = edge_serial; + urb->dev = dev; + status = usb_submit_urb (urb, GFP_KERNEL); + if (status) { + err ("%s - usb_submit_urb failed with value %d", __FUNCTION__, status); + return status; + } + } + + /* + * reset the data toggle on the bulk endpoints to work around bug in + * host controllers where things get out of sync some times + */ + usb_clear_halt (dev, port->write_urb->pipe); + usb_clear_halt (dev, port->read_urb->pipe); + + /* start up our bulk read urb */ + urb = port->read_urb; + if (!urb) { + err ("%s - no read urb present, exiting", __FUNCTION__); + return -EINVAL; + } + urb->complete = edge_bulk_in_callback; + urb->context = edge_port; + urb->dev = dev; + status = usb_submit_urb (urb, GFP_KERNEL); + if (status) { + err ("%s - read bulk usb_submit_urb failed with value %d", __FUNCTION__, status); + return status; + } + + ++edge_serial->num_ports_open; + + dbg("%s - exited", __FUNCTION__); + + return 0; +} + +static void edge_close (struct usb_serial_port *port, struct file * filp) +{ + struct usb_serial *serial; + struct edgeport_serial *edge_serial; + struct edgeport_port *edge_port; + int port_number; + int status; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); + + serial = get_usb_serial (port, __FUNCTION__); + if (!serial) + return; + + edge_serial = (struct edgeport_serial *)serial->private; + edge_port = (struct edgeport_port *)port->private; + if ((edge_serial == NULL) || (edge_port == NULL)) + return; + + if (serial->dev) { + /* The bulkreadcompletion routine will check + * this flag and dump add read data */ + edge_port->close_pending = 1; + + /* chase the port close */ + TIChasePort (edge_port); + + usb_unlink_urb (port->read_urb); + + /* assuming we can still talk to the device, + * send a close port command to it */ + dbg("%s - send umpc_close_port", __FUNCTION__); + port_number = port->number - port->serial->minor; + status = TIWriteCommandSync (port->serial->dev, + UMPC_CLOSE_PORT, + (__u8)(UMPM_UART1_PORT + port_number), + 0, + NULL, + 0); + --edge_port->edge_serial->num_ports_open; + if (edge_port->edge_serial->num_ports_open <= 0) { + /* last port is now closed, let's shut down our interrupt urb */ + usb_unlink_urb (serial->port[0].interrupt_in_urb); + edge_port->edge_serial->num_ports_open = 0; + } + edge_port->close_pending = 0; + } + + dbg(__FUNCTION__" exited"); +} + +static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count) +{ + struct usb_serial *serial = port->serial; + struct edgeport_port *edge_port = port->private; + int result; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (count == 0) { + dbg("%s - write request of 0 bytes", __FUNCTION__); + return 0; + } + + if (edge_port == NULL) + return -ENODEV; + if (edge_port->close_pending == 1) + return -ENODEV; + + if (port->write_urb->status == -EINPROGRESS) { + dbg ("%s - already writing", __FUNCTION__); + return 0; + } + + count = min (count, port->bulk_out_size); + + if (from_user) { + if (copy_from_user(port->write_urb->transfer_buffer, data, count)) + return -EFAULT; + } else { + memcpy (port->write_urb->transfer_buffer, data, count); + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer); + + /* set up our urb */ + usb_fill_bulk_urb (port->write_urb, serial->dev, + usb_sndbulkpipe (serial->dev, + port->bulk_out_endpointAddress), + port->write_urb->transfer_buffer, count, + edge_bulk_out_callback, + port); + + /* send the data out the bulk port */ + result = usb_submit_urb(port->write_urb, GFP_ATOMIC); + if (result) + err(__FUNCTION__ " - failed submitting write urb, error %d", result); + else + result = count; + + if (result > 0) + edge_port->icount.tx += count; + + return result; +} + +static int edge_write_room (struct usb_serial_port *port) +{ + struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); + int room = 0; + + dbg(__FUNCTION__); + + if (edge_port == NULL) + return -ENODEV; + if (edge_port->close_pending == 1) + return -ENODEV; + + dbg(__FUNCTION__" - port %d", port->number); + + if (port->write_urb->status != -EINPROGRESS) + room = port->bulk_out_size; + + dbg(__FUNCTION__ " - returns %d", room); + return room; +} + +static int edge_chars_in_buffer (struct usb_serial_port *port) +{ + struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); + int chars = 0; + + dbg(__FUNCTION__); + + if (edge_port == NULL) + return -ENODEV; + if (edge_port->close_pending == 1) + return -ENODEV; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (port->write_urb->status == -EINPROGRESS) + chars = port->write_urb->transfer_buffer_length; + + dbg ("%s - returns %d", __FUNCTION__, chars); + return chars; +} + +static void edge_throttle (struct usb_serial_port *port) +{ + struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); + struct tty_struct *tty; + int status; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (edge_port == NULL) + return; + + tty = port->tty; + if (!tty) { + dbg ("%s - no tty available", __FUNCTION__); + return; + } + /* if we are implementing XON/XOFF, send the stop character */ + if (I_IXOFF(tty)) { + unsigned char stop_char = STOP_CHAR(tty); + status = edge_write (port, 0, &stop_char, 1); + if (status <= 0) { + return; + } + } + + /* if we are implementing RTS/CTS, toggle that line */ + if (tty->termios->c_cflag & CRTSCTS) { + status = TIClearRts (edge_port); + } + + usb_unlink_urb (port->read_urb); +} + +static void edge_unthrottle (struct usb_serial_port *port) +{ + struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); + struct tty_struct *tty; + int status; + + dbg(__FUNCTION__" - port %d", port->number); + + if (edge_port == NULL) + return; + + tty = port->tty; + if (!tty) { + dbg ("%s - no tty available", __FUNCTION__); + return; + } + + /* if we are implementing XON/XOFF, send the start character */ + if (I_IXOFF(tty)) { + unsigned char start_char = START_CHAR(tty); + status = edge_write (port, 0, &start_char, 1); + if (status <= 0) { + return; + } + } + + /* if we are implementing RTS/CTS, toggle that line */ + if (tty->termios->c_cflag & CRTSCTS) { + status = TISetRts (edge_port); + } + + port->read_urb->dev = port->serial->dev; + status = usb_submit_urb (port->read_urb, GFP_ATOMIC); + if (status) { + err ("%s - usb_submit_urb failed with value %d", __FUNCTION__, status); + } +} + + +static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) +{ + struct ump_uart_config *config; + struct tty_struct *tty; + int baud; + int round; + unsigned cflag; + int status; + int port_number = edge_port->port->number - edge_port->port->serial->minor; + + dbg("%s - port %d", __FUNCTION__, edge_port->port->number); + + tty = edge_port->port->tty; + if ((!tty) || + (!tty->termios)) { + dbg("%s - no tty structures", __FUNCTION__); + return; + } + + config = kmalloc (sizeof (*config), GFP_KERNEL); + if (!config) { + err ("%s - out of memory", __FUNCTION__); + return; + } + + cflag = tty->termios->c_cflag; + + config->wFlags = 0; + + /* These flags must be set */ + config->wFlags |= UMP_MASK_UART_FLAGS_RECEIVE_MS_INT; + config->wFlags |= UMP_MASK_UART_FLAGS_AUTO_START_ON_ERR; + config->bUartMode = 0; + + switch (cflag & CSIZE) { + case CS5: + config->bDataBits = UMP_UART_CHAR5BITS; + dbg ("%s - data bits = 5", __FUNCTION__); + break; + case CS6: + config->bDataBits = UMP_UART_CHAR6BITS; + dbg ("%s - data bits = 6", __FUNCTION__); + break; + case CS7: + config->bDataBits = UMP_UART_CHAR7BITS; + dbg ("%s - data bits = 7", __FUNCTION__); + break; + default: + case CS8: + config->bDataBits = UMP_UART_CHAR8BITS; + dbg ("%s - data bits = 8", __FUNCTION__); + break; + } + + if (cflag & PARENB) { + if (cflag & PARODD) { + config->wFlags |= UMP_MASK_UART_FLAGS_PARITY; + config->bParity = UMP_UART_ODDPARITY; + dbg(__FUNCTION__" - parity = odd"); + } else { + config->wFlags |= UMP_MASK_UART_FLAGS_PARITY; + config->bParity = UMP_UART_EVENPARITY; + dbg(__FUNCTION__" - parity = even"); + } + } else { + config->bParity = UMP_UART_NOPARITY; + dbg(__FUNCTION__" - parity = none"); + } + + if (cflag & CSTOPB) { + config->bStopBits = UMP_UART_STOPBIT2; + dbg(__FUNCTION__" - stop bits = 2"); + } else { + config->bStopBits = UMP_UART_STOPBIT1; + dbg(__FUNCTION__" - stop bits = 1"); + } + + /* figure out the flow control settings */ + if (cflag & CRTSCTS) { + config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW; + config->wFlags |= UMP_MASK_UART_FLAGS_RTS_FLOW; + dbg(__FUNCTION__" - RTS/CTS is enabled"); + } else { + dbg(__FUNCTION__" - RTS/CTS is disabled"); + } + + /* if we are implementing XON/XOFF, set the start and stop character in the device */ + if (I_IXOFF(tty) || I_IXON(tty)) { + config->cXon = START_CHAR(tty); + config->cXoff = STOP_CHAR(tty); + + /* if we are implementing INBOUND XON/XOFF */ + if (I_IXOFF(tty)) { + config->wFlags |= UMP_MASK_UART_FLAGS_IN_X; + dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", + __FUNCTION__, config->cXon, config->cXoff); + } else { + dbg ("%s - INBOUND XON/XOFF is disabled", __FUNCTION__); + } + + /* if we are implementing OUTBOUND XON/XOFF */ + if (I_IXON(tty)) { + config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X; + dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", + __FUNCTION__, config->cXon, config->cXoff); + } else { + dbg ("%s - OUTBOUND XON/XOFF is disabled", __FUNCTION__); + } + } + + /* Round the baud rate */ + baud = tty_get_baud_rate(tty); + if (!baud) { + /* pick a default, any default... */ + baud = 9600; + } + config->wBaudRate = (__u16)(461550L / baud); + round = 4615500L / baud; + if ((round - (config->wBaudRate * 10)) >= 5) + config->wBaudRate++; + + dbg ("%s - baud rate = %d, wBaudRate = %d", __FUNCTION__, baud, config->wBaudRate); + + dbg ("wBaudRate: %d", (int)(461550L / config->wBaudRate)); + dbg ("wFlags: 0x%x", config->wFlags); + dbg ("bDataBits: %d", config->bDataBits); + dbg ("bParity: %d", config->bParity); + dbg ("bStopBits: %d", config->bStopBits); + dbg ("cXon: %d", config->cXon); + dbg ("cXoff: %d", config->cXoff); + dbg ("bUartMode: %d", config->bUartMode); + + /* move the word values into big endian mode */ + cpu_to_be16s (&config->wFlags); + cpu_to_be16s (&config->wBaudRate); + + status = TIWriteCommandSync (edge_port->port->serial->dev, + UMPC_SET_CONFIG, + (__u8)(UMPM_UART1_PORT + port_number), + 0, + (__u8 *)config, + sizeof(*config)); + if (status) { + dbg ("%s - error %d when trying to write config to device", + __FUNCTION__, status); + } + + kfree (config); + + return; +} + +static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) +{ + struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); + struct tty_struct *tty = port->tty; + unsigned int cflag; + + if (!port->tty || !port->tty->termios) { + dbg ("%s - no tty or termios", __FUNCTION__); + return; + } + + cflag = tty->termios->c_cflag; + /* check that they really want us to change something */ + if (old_termios) { + if ((cflag == old_termios->c_cflag) && + (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { + dbg ("%s - nothing to change", __FUNCTION__); + return; + } + } + + dbg("%s - clfag %08x iflag %08x", __FUNCTION__, + tty->termios->c_cflag, + RELEVANT_IFLAG(tty->termios->c_iflag)); + if (old_termios) { + dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, + old_termios->c_cflag, + RELEVANT_IFLAG(old_termios->c_iflag)); + } + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (edge_port == NULL) + return; + + /* change the port settings to the new ones specified */ + change_port_settings (edge_port, old_termios); + + return; +} + +static int set_modem_info (struct edgeport_port *edge_port, unsigned int cmd, unsigned int *value) +{ + unsigned int mcr = edge_port->shadow_mcr; + unsigned int arg; + + if (copy_from_user(&arg, value, sizeof(int))) + return -EFAULT; + + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + mcr |= MCR_RTS; + if (arg & TIOCM_DTR) + mcr |= MCR_RTS; + if (arg & TIOCM_LOOP) + mcr |= MCR_LOOPBACK; + break; + + case TIOCMBIC: + if (arg & TIOCM_RTS) + mcr &= ~MCR_RTS; + if (arg & TIOCM_DTR) + mcr &= ~MCR_RTS; + if (arg & TIOCM_LOOP) + mcr &= ~MCR_LOOPBACK; + break; + + case TIOCMSET: + /* turn off the RTS and DTR and LOOPBACK + * and then only turn on what was asked to */ + mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK); + mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0); + mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0); + mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0); + break; + } + + edge_port->shadow_mcr = mcr; + + TIRestoreMCR (edge_port, mcr); + + return 0; +} + +static int get_modem_info (struct edgeport_port *edge_port, unsigned int *value) +{ + unsigned int result = 0; + unsigned int msr = edge_port->shadow_msr; + unsigned int mcr = edge_port->shadow_mcr; + + result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */ + | ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ + | ((msr & MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ + | ((msr & MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */ + | ((msr & MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ + | ((msr & MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ + + + dbg(__FUNCTION__" -- %x", result); + + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + return 0; +} + +static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct * retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + + memset(&tmp, 0, sizeof(tmp)); + + tmp.type = PORT_16550A; + tmp.line = edge_port->port->serial->minor; + tmp.port = edge_port->port->number; + tmp.irq = 0; + tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; + tmp.xmit_fifo_size = edge_port->port->bulk_out_size; + tmp.baud_base = 9600; + tmp.close_delay = 5*HZ; + tmp.closing_wait = 30*HZ; +// tmp.custom_divisor = state->custom_divisor; +// tmp.hub6 = state->hub6; +// tmp.io_type = state->io_type; + + + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); + struct async_icount cnow; + struct async_icount cprev; + + dbg(__FUNCTION__" - port %d, cmd = 0x%x", port->number, cmd); + + switch (cmd) { + case TIOCINQ: + dbg(__FUNCTION__" (%d) TIOCINQ", port->number); +// return get_number_bytes_avail(edge_port, (unsigned int *) arg); + break; + + case TIOCSERGETLSR: + dbg(__FUNCTION__" (%d) TIOCSERGETLSR", port->number); +// return get_lsr_info(edge_port, (unsigned int *) arg); + break; + + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + dbg(__FUNCTION__" (%d) TIOCMSET/TIOCMBIC/TIOCMSET", port->number); + return set_modem_info(edge_port, cmd, (unsigned int *) arg); + break; + + case TIOCMGET: + dbg(__FUNCTION__" (%d) TIOCMGET", port->number); + return get_modem_info(edge_port, (unsigned int *) arg); + break; + + case TIOCGSERIAL: + dbg(__FUNCTION__" (%d) TIOCGSERIAL", port->number); + return get_serial_info(edge_port, (struct serial_struct *) arg); + break; + + case TIOCSSERIAL: + dbg(__FUNCTION__" (%d) TIOCSSERIAL", port->number); + break; + + case TIOCMIWAIT: + dbg(__FUNCTION__" (%d) TIOCMIWAIT", port->number); + cprev = edge_port->icount; + while (1) { + interruptible_sleep_on(&edge_port->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + cnow = edge_port->icount; + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + return 0; + } + cprev = cnow; + } + /* not reached */ + break; + + case TIOCGICOUNT: + dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, + port->number, edge_port->icount.rx, edge_port->icount.tx); + if (copy_to_user((void *)arg, &edge_port->icount, sizeof(edge_port->icount))) + return -EFAULT; + return 0; + } + + return -ENOIOCTLCMD; +} + +static void edge_break (struct usb_serial_port *port, int break_state) +{ + struct edgeport_port *edge_port = (struct edgeport_port *)(port->private); + int status; + + dbg ("%s - state = %d", __FUNCTION__, break_state); + + /* chase the port close */ + TIChasePort (edge_port); + + if (break_state == -1) { + status = TISetBreak (edge_port); + } else { + status = TIClearBreak (edge_port); + } + if (status) { + dbg ("%s - error %d sending break set/clear command.", + __FUNCTION__, status); + } +} + +static int edge_startup (struct usb_serial *serial) +{ + struct edgeport_serial *edge_serial; + struct edgeport_port *edge_port; + struct usb_device *dev; + int status; + int i; + + dev = serial->dev; + + /* create our private serial structure */ + edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL); + if (edge_serial == NULL) { + err(__FUNCTION__" - Out of memory"); + return -ENOMEM; + } + memset (edge_serial, 0, sizeof(struct edgeport_serial)); + edge_serial->serial = serial; + serial->private = edge_serial; + + status = TIDownloadFirmware (edge_serial); + if (status) { + kfree (edge_serial); + return status; + } + + /* set up our port private structures */ + for (i = 0; i < serial->num_ports; ++i) { + edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); + if (edge_port == NULL) { + err(__FUNCTION__" - Out of memory"); + return -ENOMEM; + } + memset (edge_port, 0, sizeof(struct edgeport_port)); + edge_port->port = &serial->port[i]; + edge_port->edge_serial = edge_serial; + serial->port[i].private = edge_port; + } + + return 0; +} + +static void edge_shutdown (struct usb_serial *serial) +{ + int i; + + dbg (__FUNCTION__); + + for (i=0; i < serial->num_ports; ++i) { + kfree (serial->port[i].private); + serial->port[i].private = NULL; + } + kfree (serial->private); + serial->private = NULL; +} + + +static struct usb_serial_device_type edgeport_1port_device = { + owner: THIS_MODULE, + name: "Edgeport TI 1 port adapter", + id_table: edgeport_1port_id_table, + num_interrupt_in: 1, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: edge_open, + close: edge_close, + throttle: edge_throttle, + unthrottle: edge_unthrottle, + attach: edge_startup, + shutdown: edge_shutdown, + ioctl: edge_ioctl, + set_termios: edge_set_termios, + write: edge_write, + write_room: edge_write_room, + chars_in_buffer: edge_chars_in_buffer, + break_ctl: edge_break, +}; + +static struct usb_serial_device_type edgeport_2port_device = { + owner: THIS_MODULE, + name: "Edgeport TI 2 port adapter", + id_table: edgeport_2port_id_table, + num_interrupt_in: 1, + num_bulk_in: 2, + num_bulk_out: 2, + num_ports: 2, + open: edge_open, + close: edge_close, + throttle: edge_throttle, + unthrottle: edge_unthrottle, + attach: edge_startup, + shutdown: edge_shutdown, + ioctl: edge_ioctl, + set_termios: edge_set_termios, + write: edge_write, + write_room: edge_write_room, + chars_in_buffer: edge_chars_in_buffer, + break_ctl: edge_break, +}; + + +static int __init edgeport_init(void) +{ + usb_serial_register (&edgeport_1port_device); + usb_serial_register (&edgeport_2port_device); + info(DRIVER_DESC " " DRIVER_VERSION); + return 0; +} + +static void __exit edgeport_exit (void) +{ + usb_serial_deregister (&edgeport_1port_device); + usb_serial_deregister (&edgeport_2port_device); +} + +module_init(edgeport_init); +module_exit(edgeport_exit); + +/* Module information */ +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + +MODULE_PARM(ignore_cpu_rev, "i"); +MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device"); + diff --git a/drivers/usb/serial/io_ti.h b/drivers/usb/serial/io_ti.h new file mode 100644 index 000000000000..82a06c8b444c --- /dev/null +++ b/drivers/usb/serial/io_ti.h @@ -0,0 +1,180 @@ +/***************************************************************************** + * + * Copyright (c) 1997-2002 Inside Out Networks, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * + * Feb-16-2001 DMI Added I2C structure definitions + * May-29-2002 gkh Ported to Linux + * + * + ******************************************************************************/ + +#ifndef _IO_TI_H_ +#define _IO_TI_H_ + +/* Address Space */ +#define DTK_ADDR_SPACE_XDATA 0x03 /* Addr is placed in XDATA space */ +#define DTK_ADDR_SPACE_I2C_TYPE_II 0x82 /* Addr is placed in I2C area */ +#define DTK_ADDR_SPACE_I2C_TYPE_III 0x83 /* Addr is placed in I2C area */ + +// UART Defines +#define UMPMEM_BASE_UART1 0xFFA0 /* UMP UART1 base address */ +#define UMPMEM_BASE_UART2 0xFFB0 /* UMP UART2 base address */ +#define UMPMEM_OFFS_UART_LSR 0x05 /* UMP UART LSR register offset */ + +/* Bits per character */ +#define UMP_UART_CHAR5BITS 0x00 +#define UMP_UART_CHAR6BITS 0x01 +#define UMP_UART_CHAR7BITS 0x02 +#define UMP_UART_CHAR8BITS 0x03 + +/* Parity */ +#define UMP_UART_NOPARITY 0x00 +#define UMP_UART_ODDPARITY 0x01 +#define UMP_UART_EVENPARITY 0x02 +#define UMP_UART_MARKPARITY 0x03 +#define UMP_UART_SPACEPARITY 0x04 + +/* Stop bits */ +#define UMP_UART_STOPBIT1 0x00 +#define UMP_UART_STOPBIT15 0x01 +#define UMP_UART_STOPBIT2 0x02 + +/* Line status register masks */ +#define UMP_UART_LSR_OV_MASK 0x01 +#define UMP_UART_LSR_PE_MASK 0x02 +#define UMP_UART_LSR_FE_MASK 0x04 +#define UMP_UART_LSR_BR_MASK 0x08 +#define UMP_UART_LSR_ER_MASK 0x0F +#define UMP_UART_LSR_RX_MASK 0x10 +#define UMP_UART_LSR_TX_MASK 0x20 + +#define UMP_UART_LSR_DATA_MASK ( LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK ) + +/* Port Settings Constants) */ +#define UMP_MASK_UART_FLAGS_RTS_FLOW 0x0001 +#define UMP_MASK_UART_FLAGS_RTS_DISABLE 0x0002 +#define UMP_MASK_UART_FLAGS_PARITY 0x0008 +#define UMP_MASK_UART_FLAGS_OUT_X_DSR_FLOW 0x0010 +#define UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW 0x0020 +#define UMP_MASK_UART_FLAGS_OUT_X 0x0040 +#define UMP_MASK_UART_FLAGS_OUT_XA 0x0080 +#define UMP_MASK_UART_FLAGS_IN_X 0x0100 +#define UMP_MASK_UART_FLAGS_DTR_FLOW 0x0800 +#define UMP_MASK_UART_FLAGS_DTR_DISABLE 0x1000 +#define UMP_MASK_UART_FLAGS_RECEIVE_MS_INT 0x2000 +#define UMP_MASK_UART_FLAGS_AUTO_START_ON_ERR 0x4000 + +#define UMP_DMA_MODE_CONTINOUS 0x01 +#define UMP_PIPE_TRANS_TIMEOUT_ENA 0x80 +#define UMP_PIPE_TRANSFER_MODE_MASK 0x03 +#define UMP_PIPE_TRANS_TIMEOUT_MASK 0x7C + +/* Purge port Direction Mask Bits */ +#define UMP_PORT_DIR_OUT 0x01 +#define UMP_PORT_DIR_IN 0x02 + +// Address of Port 0 +#define UMPM_UART1_PORT 0x03 + +// Commands +#define UMPC_SET_CONFIG 0x05 +#define UMPC_OPEN_PORT 0x06 +#define UMPC_CLOSE_PORT 0x07 +#define UMPC_START_PORT 0x08 +#define UMPC_STOP_PORT 0x09 +#define UMPC_TEST_PORT 0x0A +#define UMPC_PURGE_PORT 0x0B + +#define UMPC_COMPLETE_READ 0x80 // Force the Firmware to complete the current Read +#define UMPC_HARDWARE_RESET 0x81 // Force UMP back into BOOT Mode +#define UMPC_COPY_DNLD_TO_I2C 0x82 // Copy current download image to type 0xf2 record in 16k I2C + // firmware will change 0xff record to type 2 record when complete + + // Special function register commands + // wIndex is register address + // wValue is MSB/LSB mask/data +#define UMPC_WRITE_SFR 0x83 // Write SFR Register + + // wIndex is register address +#define UMPC_READ_SFR 0x84 // Read SRF Register + + // Set or Clear DTR (wValue bit 0 Set/Clear) wIndex ModuleID (port) +#define UMPC_SET_CLR_DTR 0x85 + + // Set or Clear RTS (wValue bit 0 Set/Clear) wIndex ModuleID (port) +#define UMPC_SET_CLR_RTS 0x86 + + // Set or Clear LOOPBACK (wValue bit 0 Set/Clear) wIndex ModuleID (port) +#define UMPC_SET_CLR_LOOPBACK 0x87 + + // Set or Clear BREAK (wValue bit 0 Set/Clear) wIndex ModuleID (port) +#define UMPC_SET_CLR_BREAK 0x88 + + // Read MSR wIndex ModuleID (port) +#define UMPC_READ_MSR 0x89 + + /* Toolkit commands */ + /* Read-write group */ +#define UMPC_MEMORY_READ 0x92 +#define UMPC_MEMORY_WRITE 0x93 + +/* + * UMP DMA Definitions + */ +#define UMPD_OEDB1_ADDRESS 0xFF08 +#define UMPD_OEDB2_ADDRESS 0xFF10 + +struct out_endpoint_desc_block +{ + __u8 Configuration; + __u8 XBufAddr; + __u8 XByteCount; + __u8 Unused1; + __u8 Unused2; + __u8 YBufAddr; + __u8 YByteCount; + __u8 BufferSize; +} __attribute__((packed)); + + +/* + * TYPE DEFINITIONS + * Structures for Firmware commands + */ +struct ump_uart_config /* UART settings */ +{ + __u16 wBaudRate; /* Baud rate */ + __u16 wFlags; /* Bitmap mask of flags */ + __u8 bDataBits; /* 5..8 - data bits per character */ + __u8 bParity; /* Parity settings */ + __u8 bStopBits; /* Stop bits settings */ + char cXon; /* XON character */ + char cXoff; /* XOFF character */ + __u8 bUartMode; /* Will be updated when a user */ + /* interface is defined */ +} __attribute__((packed)); + + +/* + * TYPE DEFINITIONS + * Structures for USB interrupts + */ +struct ump_interrupt /* Interrupt packet structure */ +{ + __u8 bICode; /* Interrupt code (interrupt num) */ + __u8 bIInfo; /* Interrupt information */ +} __attribute__((packed)); + + +#define TIUMP_GET_PORT_FROM_CODE(c) (((c) >> 4) - 3) +#define TIUMP_GET_FUNC_FROM_CODE(c) ((c) & 0x0f) +#define TIUMP_INTERRUPT_CODE_LSR 0x03 +#define TIUMP_INTERRUPT_CODE_MSR 0x04 + +#endif diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h index 068066e821e8..37fe6744a92c 100644 --- a/drivers/usb/serial/io_usbvend.h +++ b/drivers/usb/serial/io_usbvend.h @@ -106,11 +106,23 @@ #define ION_DEVICE_ID_BB_EDGEPORT_4_DIN 0x011 // Edgeport/4 RS232 with Apple DIN connector #define ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU 0x012 // Half of an Edgeport/16 (the kind with 2 EP/8s) #define ION_DEVICE_ID_BB_EDGEPORT_8I 0x014 // Edgeport/8 RS422 (single-CPU) -// These IDs are used by the Edgeport.exe program for uninstalling. -// -#define EDGEPORT_DEVICE_IDS {0x001, 0x003, 0x004, 0x005, 0x006, 0x007, 0x00B, \ - 0x00C, 0x00D, 0x00E, 0x00F, 0x010, 0x011, 0x012, \ - 0x013, 0x014 } + + +/* Edgeport TI based devices */ +#define ION_DEVICE_ID_TI_EDGEPORT_4 0x0201 /* Edgeport/4 RS232 */ +#define ION_DEVICE_ID_TI_EDGEPORT_2 0x0205 /* Edgeport/2 RS232 */ +#define ION_DEVICE_ID_TI_EDGEPORT_4I 0x0206 /* Edgeport/4i RS422 */ +#define ION_DEVICE_ID_TI_EDGEPORT_2I 0x0207 /* Edgeport/2i RS422/RS485 */ +#define ION_DEVICE_ID_TI_EDGEPORT_421 0x020C /* Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port) */ +#define ION_DEVICE_ID_TI_EDGEPORT_21 0x020D /* Edgeport/21 2 RS232 + Parallel (lucent on a different hub port) */ +#define ION_DEVICE_ID_TI_EDGEPORT_1 0x0215 /* Edgeport/1 RS232 */ +#define ION_DEVICE_ID_TI_EDGEPORT_42 0x0217 /* Edgeport/42 4 hub 2 RS232 */ +#define ION_DEVICE_ID_TI_EDGEPORT_22 0x021A /* Edgeport/22 Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 */ + +#define ION_DEVICE_ID_TI_EDGEPORT_421_BOOT 0x0240 /* Edgeport/421 in boot mode */ +#define ION_DEVICE_ID_TI_EDGEPORT_421_DOWN 0x0241 /* Edgeport/421 in download mode first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */ +#define ION_DEVICE_ID_TI_EDGEPORT_21_BOOT 0x0242 /* Edgeport/21 in boot mode */ +#define ION_DEVICE_ID_TI_EDGEPORT_21_DOWN 0x0243 /*Edgeport/42 in download mode: first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */ #define MAKE_USB_PRODUCT_ID( OemId, DeviceId ) \ @@ -217,7 +229,7 @@ // descriptor format, so that they may be separately retrieved, // if necessary, with a minimum of work on the 930. This also // requires them to be in UNICODE format, which, for English at -// least, simply means extending each UCHAR into a USHORT. +// least, simply means extending each __u8 into a __u16. // 3. For all fields, 00 means 'uninitialized'. // 4. All unused areas should be set to 00 for future expansion. // @@ -384,5 +396,92 @@ struct edge_boot_descriptor { #define BOOT_CAP_RESET_CMD 0x0001 // If set, boot correctly supports ION_RESET_DEVICE -#endif // if !defined() + +/************************************************************************ + T I U M P D E F I N I T I O N S + ***********************************************************************/ + +//************************************************************************ +// TI I2C Format Definitions +//************************************************************************ +#define I2C_DESC_TYPE_INFO_BASIC 1 +#define I2C_DESC_TYPE_FIRMWARE_BASIC 2 +#define I2C_DESC_TYPE_DEVICE 3 +#define I2C_DESC_TYPE_CONFIG 4 +#define I2C_DESC_TYPE_STRING 5 +#define I2C_DESC_TYPE_FIRMWARE_BLANK 0xf2 + +#define I2C_DESC_TYPE_MAX 5 +// 3410 may define types 6, 7 for other firmware downloads + +// Special section defined by ION +#define I2C_DESC_TYPE_ION 0 // Not defined by TI + + +struct ti_i2c_desc +{ + __u8 Type; // Type of descriptor + __u16 Size; // Size of data only not including header + __u8 CheckSum; // Checksum (8 bit sum of data only) + __u8 Data[0]; // Data starts here +}__attribute__((packed)); + +struct ti_i2c_firmware_rec +{ + __u8 Ver_Major; // Firmware Major version number + __u8 Ver_Minor; // Firmware Minor version number + __u8 Data[0]; // Download starts here +}__attribute__((packed)); + + +// Structure of header of download image in fw_down.h +struct ti_i2c_image_header +{ + __u16 Length; + __u8 CheckSum; +}__attribute__((packed)); + +struct ti_basic_descriptor +{ + __u8 Power; // Self powered + // bit 7: 1 - power switching supported + // 0 - power switching not supported + // + // bit 0: 1 - self powered + // 0 - bus powered + // + // + __u16 HubVid; // VID HUB + __u16 HubPid; // PID HUB + __u16 DevPid; // PID Edgeport + __u8 HubTime; // Time for power on to power good + __u8 HubCurrent; // HUB Current = 100ma +} __attribute__((packed)); + + +#define TI_GET_CPU_REVISION(x) (__u8)((((x)>>4)&0x0f)) +#define TI_GET_BOARD_REVISION(x) (__u8)(((x)&0x0f)) + +#define TI_I2C_SIZE_MASK 0x1f // 5 bits +#define TI_GET_I2C_SIZE(x) ((((x) & TI_I2C_SIZE_MASK)+1)*256) + +#define TI_MAX_I2C_SIZE ( 16 * 1024 ) + +/* TI USB 5052 definitions */ +struct edge_ti_manuf_descriptor +{ + __u8 IonConfig; // Config byte for ION manufacturing use + __u8 IonConfig2; // Expansion + __u8 Version; // Verqsion + __u8 CpuRev_BoardRev; // CPU revision level (0xF0) and Board Rev Level (0x0F) + __u8 NumPorts; // Number of ports for this UMP + __u8 NumVirtualPorts; // Number of Virtual ports + __u8 HubConfig1; // Used to configure the Hub + __u8 HubConfig2; // Used to configure the Hub + __u8 TotalPorts; // Total Number of Com Ports for the entire device (All UMPs) + __u8 Reserved; +}__attribute__((packed)); + + +#endif // if !defined() diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c index ae7f1f3da7a5..c232a4ec3010 100644 --- a/drivers/usb/serial/usbserial.c +++ b/drivers/usb/serial/usbserial.c @@ -15,6 +15,11 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (06/05/2002) gkh + * moved location of startup() call in serial_probe() until after all + * of the port information and endpoints are initialized. This makes + * things easier for some drivers. + * * (04/10/2002) gkh * added serial_read_proc function which creates a * /proc/tty/driver/usb-serial file. @@ -341,7 +346,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.5" +#define DRIVER_VERSION "v1.6" #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/" #define DRIVER_DESC "USB Serial Driver core" diff --git a/drivers/usb/storage/Config.help b/drivers/usb/storage/Config.help index 4acef81f9879..81131aef0bce 100644 --- a/drivers/usb/storage/Config.help +++ b/drivers/usb/storage/Config.help @@ -1,6 +1,9 @@ CONFIG_USB_STORAGE Say Y here if you want to connect USB mass storage devices to your - computer's USB port. + computer's USB port. This is the driver you need for USB floppy drives, + USB hard disks, USB tape drives and USB CD-ROMs, along with + similar devices. This driver may also be used for some cameras and + card readers. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -44,3 +47,11 @@ CONFIG_USB_STORAGE_SDDR09 CONFIG_USB_STORAGE_SDDR55 Say Y here to include additional code to support the Sandisk SDDR-55 SmartMedia reader in the USB Mass Storage driver. + +CONFIG_USB_STORAGE_HP8200e + Say Y here to include additional code to support Hewlett-Packard + 8200e/8210e/8230e CD-Writer Plus drives. + +CONFIG_USB_STORAGE_JUMPSHOT + Say Y here to include additional code to support the Lexar Jumpshot + USB CompactFlash reader. diff --git a/drivers/usb/storage/Config.in b/drivers/usb/storage/Config.in index 7f630fb6d53d..6b67604160ca 100644 --- a/drivers/usb/storage/Config.in +++ b/drivers/usb/storage/Config.in @@ -6,11 +6,11 @@ if [ "$CONFIG_SCSI" = "n" ]; then fi dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI dep_mbool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG $CONFIG_USB_STORAGE - dep_mbool ' Datafab Compact Flash Reader support' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL + dep_mbool ' Datafab Compact Flash Reader support (EXPERIMENTAL)' CONFIG_USB_STORAGE_DATAFAB $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL dep_mbool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM $CONFIG_USB_STORAGE dep_mbool ' ISD-200 USB/ATA Bridge support' CONFIG_USB_STORAGE_ISD200 $CONFIG_USB_STORAGE dep_mbool ' Microtech CompactFlash/SmartMedia support' CONFIG_USB_STORAGE_DPCM $CONFIG_USB_STORAGE - dep_mbool ' HP CD-Writer 82xx support' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL - dep_mbool ' SanDisk SDDR-09 (and other SmartMedia) support' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL - dep_mbool ' SanDisk SDDR-55 SmartMedia support' CONFIG_USB_STORAGE_SDDR55 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL - dep_mbool ' Lexar Jumpshot Compact Flash Reader' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL + dep_mbool ' HP CD-Writer 82xx support (EXPERIMENTAL)' CONFIG_USB_STORAGE_HP8200e $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL + dep_mbool ' SanDisk SDDR-09 (and other SmartMedia) support (EXPERIMENTAL)' CONFIG_USB_STORAGE_SDDR09 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL + dep_mbool ' SanDisk SDDR-55 SmartMedia support (EXPERIMENTAL)' CONFIG_USB_STORAGE_SDDR55 $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL + dep_mbool ' Lexar Jumpshot Compact Flash Reader (EXPERIMENTAL)' CONFIG_USB_STORAGE_JUMPSHOT $CONFIG_USB_STORAGE $CONFIG_EXPERIMENTAL diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index c0bdea0c4e6e..e68801addae4 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -182,46 +182,46 @@ static struct us_unusual_dev us_unusual_dev_list[] = { # include "unusual_devs.h" # undef UNUSUAL_DEV /* Control/Bulk transport for all SubClass values */ - { useProtocol: US_SC_RBC, - useTransport: US_PR_CB}, - { useProtocol: US_SC_8020, - useTransport: US_PR_CB}, - { useProtocol: US_SC_QIC, - useTransport: US_PR_CB}, - { useProtocol: US_SC_UFI, - useTransport: US_PR_CB}, - { useProtocol: US_SC_8070, - useTransport: US_PR_CB}, - { useProtocol: US_SC_SCSI, - useTransport: US_PR_CB}, + { .useProtocol = US_SC_RBC, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_8020, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_QIC, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_UFI, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_8070, + .useTransport = US_PR_CB}, + { .useProtocol = US_SC_SCSI, + .useTransport = US_PR_CB}, /* Control/Bulk/Interrupt transport for all SubClass values */ - { useProtocol: US_SC_RBC, - useTransport: US_PR_CBI}, - { useProtocol: US_SC_8020, - useTransport: US_PR_CBI}, - { useProtocol: US_SC_QIC, - useTransport: US_PR_CBI}, - { useProtocol: US_SC_UFI, - useTransport: US_PR_CBI}, - { useProtocol: US_SC_8070, - useTransport: US_PR_CBI}, - { useProtocol: US_SC_SCSI, - useTransport: US_PR_CBI}, + { .useProtocol = US_SC_RBC, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_8020, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_QIC, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_UFI, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_8070, + .useTransport = US_PR_CBI}, + { .useProtocol = US_SC_SCSI, + .useTransport = US_PR_CBI}, /* Bulk-only transport for all SubClass values */ - { useProtocol: US_SC_RBC, - useTransport: US_PR_BULK}, - { useProtocol: US_SC_8020, - useTransport: US_PR_BULK}, - { useProtocol: US_SC_QIC, - useTransport: US_PR_BULK}, - { useProtocol: US_SC_UFI, - useTransport: US_PR_BULK}, - { useProtocol: US_SC_8070, - useTransport: US_PR_BULK}, - { useProtocol: US_SC_SCSI, - useTransport: US_PR_BULK}, + { .useProtocol = US_SC_RBC, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_8020, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_QIC, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_UFI, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_8070, + .useTransport = US_PR_BULK}, + { .useProtocol = US_SC_SCSI, + .useTransport = US_PR_BULK}, /* Terminating entry */ { 0 } |
