Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * HP Human Interface Loop Master Link Controller driver.
0003  *
0004  * Copyright (c) 2001 Brian S. Julin
0005  * All rights reserved.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions, and the following disclaimer,
0012  *    without modification.
0013  * 2. The name of the author may not be used to endorse or promote products
0014  *    derived from this software without specific prior written permission.
0015  *
0016  * Alternatively, this software may be distributed under the terms of the
0017  * GNU General Public License ("GPL").
0018  *
0019  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0020  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0022  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
0023  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0024  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0025  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0026  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0027  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0028  *
0029  * References:
0030  * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
0031  *
0032  */
0033 
0034 #include <linux/hil.h>
0035 #include <linux/time.h>
0036 #include <linux/interrupt.h>
0037 #include <linux/semaphore.h>
0038 #include <linux/serio.h>
0039 #include <linux/list.h>
0040 
0041 typedef struct hil_mlc hil_mlc;
0042 
0043 /* The HIL has a complicated state engine.
0044  * We define the structure of nodes in the state engine here.
0045  */
0046 enum hilse_act {
0047     /* HILSE_OUT prepares to receive input if the next node
0048      * is an IN or EXPECT, and then sends the given packet.
0049      */
0050     HILSE_OUT = 0,
0051 
0052     /* HILSE_CTS checks if the loop is busy. */
0053     HILSE_CTS,
0054 
0055     /* HILSE_OUT_LAST sends the given command packet to 
0056      * the last configured/running device on the loop.
0057      */
0058     HILSE_OUT_LAST,
0059 
0060     /* HILSE_OUT_DISC sends the given command packet to
0061      * the next device past the last configured/running one.
0062      */
0063     HILSE_OUT_DISC,
0064 
0065     /* HILSE_FUNC runs a callback function with given arguments.
0066      * a positive return value causes the "ugly" branch to be taken.
0067      */
0068     HILSE_FUNC,
0069 
0070     /* HILSE_IN simply expects any non-errored packet to arrive 
0071      * within arg usecs.
0072      */
0073     HILSE_IN        = 0x100,
0074 
0075     /* HILSE_EXPECT expects a particular packet to arrive 
0076      * within arg usecs, any other packet is considered an error.
0077      */
0078     HILSE_EXPECT,
0079 
0080     /* HILSE_EXPECT_LAST as above but dev field should be last 
0081      * discovered/operational device.
0082      */
0083     HILSE_EXPECT_LAST,
0084 
0085     /* HILSE_EXPECT_LAST as above but dev field should be first 
0086      * undiscovered/inoperational device.
0087      */
0088     HILSE_EXPECT_DISC
0089 };
0090 
0091 typedef int (hilse_func) (hil_mlc *mlc, int arg);
0092 struct hilse_node {
0093     enum hilse_act      act;    /* How to process this node         */
0094     union {
0095         hilse_func  *func;  /* Function to call if HILSE_FUNC   */
0096         hil_packet  packet; /* Packet to send or to compare     */
0097     } object;
0098     int         arg;    /* Timeout in usec or parm for func */
0099     int         good;   /* Node to jump to on success       */
0100     int         bad;    /* Node to jump to on error         */
0101     int         ugly;   /* Node to jump to on timeout       */
0102 };
0103 
0104 /* Methods for back-end drivers, e.g. hp_sdc_mlc */
0105 typedef int (hil_mlc_cts) (hil_mlc *mlc);
0106 typedef int (hil_mlc_out) (hil_mlc *mlc);
0107 typedef int (hil_mlc_in)  (hil_mlc *mlc, suseconds_t timeout);
0108 
0109 struct hil_mlc_devinfo {
0110     uint8_t idd[16];    /* Device ID Byte and Describe Record */
0111     uint8_t rsc[16];    /* Security Code Header and Record */
0112     uint8_t exd[16];    /* Extended Describe Record */
0113     uint8_t rnm[16];    /* Device name as returned by RNM command */
0114 };
0115 
0116 struct hil_mlc_serio_map {
0117     hil_mlc *mlc;
0118     int di_revmap;
0119     int didx;
0120 };
0121 
0122 /* How many (possibly old/detached) devices the we try to keep track of */
0123 #define HIL_MLC_DEVMEM 16
0124 
0125 struct hil_mlc {
0126     struct list_head    list;   /* hil_mlc is organized as linked list */
0127 
0128     rwlock_t        lock;
0129 
0130     void *priv; /* Data specific to a particular type of MLC */
0131 
0132     int             seidx;  /* Current node in state engine */
0133     int         istarted, ostarted;
0134 
0135     hil_mlc_cts     *cts;
0136     struct semaphore    csem;   /* Raised when loop idle */
0137 
0138     hil_mlc_out     *out;
0139     struct semaphore    osem;   /* Raised when outpacket dispatched */
0140     hil_packet      opacket;
0141 
0142     hil_mlc_in      *in;
0143     struct semaphore    isem;   /* Raised when a packet arrives */
0144     hil_packet      ipacket[16];
0145     hil_packet      imatch;
0146     int         icount;
0147     unsigned long       instart;
0148     unsigned long       intimeout;
0149 
0150     int         ddi;    /* Last operational device id */
0151     int         lcv;    /* LCV to throttle loops */
0152     time64_t        lcv_time; /* Time loop was started */
0153 
0154     int         di_map[7]; /* Maps below items to live devs */
0155     struct hil_mlc_devinfo  di[HIL_MLC_DEVMEM];
0156     struct serio        *serio[HIL_MLC_DEVMEM];
0157     struct hil_mlc_serio_map serio_map[HIL_MLC_DEVMEM];
0158     hil_packet      serio_opacket[HIL_MLC_DEVMEM];
0159     int         serio_oidx[HIL_MLC_DEVMEM];
0160     struct hil_mlc_devinfo  di_scratch; /* Temporary area */
0161 
0162     int         opercnt;
0163 
0164     struct tasklet_struct   *tasklet;
0165 };
0166 
0167 int hil_mlc_register(hil_mlc *mlc);
0168 int hil_mlc_unregister(hil_mlc *mlc);