cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hp_sdc.c (29035B)


      1/*
      2 * HP i8042-based System Device Controller driver.
      3 *
      4 * Copyright (c) 2001 Brian S. Julin
      5 * All rights reserved.
      6 *
      7 * Redistribution and use in source and binary forms, with or without
      8 * modification, are permitted provided that the following conditions
      9 * are met:
     10 * 1. Redistributions of source code must retain the above copyright
     11 *    notice, this list of conditions, and the following disclaimer,
     12 *    without modification.
     13 * 2. The name of the author may not be used to endorse or promote products
     14 *    derived from this software without specific prior written permission.
     15 *
     16 * Alternatively, this software may be distributed under the terms of the
     17 * GNU General Public License ("GPL").
     18 *
     19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
     23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28 *
     29 * References:
     30 * System Device Controller Microprocessor Firmware Theory of Operation
     31 *      for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
     32 * Helge Deller's original hilkbd.c port for PA-RISC.
     33 *
     34 *
     35 * Driver theory of operation:
     36 *
     37 * hp_sdc_put does all writing to the SDC.  ISR can run on a different
     38 * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time
     39 * (it cannot really benefit from SMP anyway.)  A tasket fit this perfectly.
     40 *
     41 * All data coming back from the SDC is sent via interrupt and can be read
     42 * fully in the ISR, so there are no latency/throughput problems there.
     43 * The problem is with output, due to the slow clock speed of the SDC
     44 * compared to the CPU.  This should not be too horrible most of the time,
     45 * but if used with HIL devices that support the multibyte transfer command,
     46 * keeping outbound throughput flowing at the 6500KBps that the HIL is
     47 * capable of is more than can be done at HZ=100.
     48 *
     49 * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf
     50 * is set to 0 when the IBF flag in the status register has cleared.  ISR
     51 * may do this, and may also access the parts of queued transactions related
     52 * to reading data back from the SDC, but otherwise will not touch the
     53 * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
     54 *
     55 * The i8042 write index and the values in the 4-byte input buffer
     56 * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
     57 * to minimize the amount of IO needed to the SDC.  However these values
     58 * do not need to be locked since they are only ever accessed by hp_sdc_put.
     59 *
     60 * A timer task schedules the tasklet once per second just to make
     61 * sure it doesn't freeze up and to allow for bad reads to time out.
     62 */
     63
     64#include <linux/hp_sdc.h>
     65#include <linux/errno.h>
     66#include <linux/init.h>
     67#include <linux/module.h>
     68#include <linux/ioport.h>
     69#include <linux/time.h>
     70#include <linux/semaphore.h>
     71#include <linux/slab.h>
     72#include <linux/hil.h>
     73#include <asm/io.h>
     74
     75/* Machine-specific abstraction */
     76
     77#if defined(__hppa__)
     78# include <asm/parisc-device.h>
     79# define sdc_readb(p)		gsc_readb(p)
     80# define sdc_writeb(v,p)	gsc_writeb((v),(p))
     81#elif defined(__mc68000__)
     82#include <linux/uaccess.h>
     83# define sdc_readb(p)		in_8(p)
     84# define sdc_writeb(v,p)	out_8((p),(v))
     85#else
     86# error "HIL is not supported on this platform"
     87#endif
     88
     89#define PREFIX "HP SDC: "
     90
     91MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
     92MODULE_DESCRIPTION("HP i8042-based SDC Driver");
     93MODULE_LICENSE("Dual BSD/GPL");
     94
     95EXPORT_SYMBOL(hp_sdc_request_timer_irq);
     96EXPORT_SYMBOL(hp_sdc_request_hil_irq);
     97EXPORT_SYMBOL(hp_sdc_request_cooked_irq);
     98
     99EXPORT_SYMBOL(hp_sdc_release_timer_irq);
    100EXPORT_SYMBOL(hp_sdc_release_hil_irq);
    101EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
    102
    103EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
    104EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
    105EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
    106
    107static bool hp_sdc_disabled;
    108module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0);
    109MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver.");
    110
    111static hp_i8042_sdc	hp_sdc;	/* All driver state is kept in here. */
    112
    113/*************** primitives for use in any context *********************/
    114static inline uint8_t hp_sdc_status_in8(void)
    115{
    116	uint8_t status;
    117	unsigned long flags;
    118
    119	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
    120	status = sdc_readb(hp_sdc.status_io);
    121	if (!(status & HP_SDC_STATUS_IBF))
    122		hp_sdc.ibf = 0;
    123	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
    124
    125	return status;
    126}
    127
    128static inline uint8_t hp_sdc_data_in8(void)
    129{
    130	return sdc_readb(hp_sdc.data_io);
    131}
    132
    133static inline void hp_sdc_status_out8(uint8_t val)
    134{
    135	unsigned long flags;
    136
    137	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
    138	hp_sdc.ibf = 1;
    139	if ((val & 0xf0) == 0xe0)
    140		hp_sdc.wi = 0xff;
    141	sdc_writeb(val, hp_sdc.status_io);
    142	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
    143}
    144
    145static inline void hp_sdc_data_out8(uint8_t val)
    146{
    147	unsigned long flags;
    148
    149	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
    150	hp_sdc.ibf = 1;
    151	sdc_writeb(val, hp_sdc.data_io);
    152	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
    153}
    154
    155/*	Care must be taken to only invoke hp_sdc_spin_ibf when
    156 *	absolutely needed, or in rarely invoked subroutines.
    157 *	Not only does it waste CPU cycles, it also wastes bus cycles.
    158 */
    159static inline void hp_sdc_spin_ibf(void)
    160{
    161	unsigned long flags;
    162	rwlock_t *lock;
    163
    164	lock = &hp_sdc.ibf_lock;
    165
    166	read_lock_irqsave(lock, flags);
    167	if (!hp_sdc.ibf) {
    168		read_unlock_irqrestore(lock, flags);
    169		return;
    170	}
    171	read_unlock(lock);
    172	write_lock(lock);
    173	while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF)
    174		{ }
    175	hp_sdc.ibf = 0;
    176	write_unlock_irqrestore(lock, flags);
    177}
    178
    179
    180/************************ Interrupt context functions ************************/
    181static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data)
    182{
    183	hp_sdc_transaction *curr;
    184
    185	read_lock(&hp_sdc.rtq_lock);
    186	if (hp_sdc.rcurr < 0) {
    187		read_unlock(&hp_sdc.rtq_lock);
    188		return;
    189	}
    190	curr = hp_sdc.tq[hp_sdc.rcurr];
    191	read_unlock(&hp_sdc.rtq_lock);
    192
    193	curr->seq[curr->idx++] = status;
    194	curr->seq[curr->idx++] = data;
    195	hp_sdc.rqty -= 2;
    196	hp_sdc.rtime = ktime_get();
    197
    198	if (hp_sdc.rqty <= 0) {
    199		/* All data has been gathered. */
    200		if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE)
    201			if (curr->act.semaphore)
    202				up(curr->act.semaphore);
    203
    204		if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK)
    205			if (curr->act.irqhook)
    206				curr->act.irqhook(irq, dev_id, status, data);
    207
    208		curr->actidx = curr->idx;
    209		curr->idx++;
    210		/* Return control of this transaction */
    211		write_lock(&hp_sdc.rtq_lock);
    212		hp_sdc.rcurr = -1;
    213		hp_sdc.rqty = 0;
    214		write_unlock(&hp_sdc.rtq_lock);
    215		tasklet_schedule(&hp_sdc.task);
    216	}
    217}
    218
    219static irqreturn_t hp_sdc_isr(int irq, void *dev_id)
    220{
    221	uint8_t status, data;
    222
    223	status = hp_sdc_status_in8();
    224	/* Read data unconditionally to advance i8042. */
    225	data =   hp_sdc_data_in8();
    226
    227	/* For now we are ignoring these until we get the SDC to behave. */
    228	if (((status & 0xf1) == 0x51) && data == 0x82)
    229		return IRQ_HANDLED;
    230
    231	switch (status & HP_SDC_STATUS_IRQMASK) {
    232	case 0: /* This case is not documented. */
    233		break;
    234
    235	case HP_SDC_STATUS_USERTIMER:
    236	case HP_SDC_STATUS_PERIODIC:
    237	case HP_SDC_STATUS_TIMER:
    238		read_lock(&hp_sdc.hook_lock);
    239		if (hp_sdc.timer != NULL)
    240			hp_sdc.timer(irq, dev_id, status, data);
    241		read_unlock(&hp_sdc.hook_lock);
    242		break;
    243
    244	case HP_SDC_STATUS_REG:
    245		hp_sdc_take(irq, dev_id, status, data);
    246		break;
    247
    248	case HP_SDC_STATUS_HILCMD:
    249	case HP_SDC_STATUS_HILDATA:
    250		read_lock(&hp_sdc.hook_lock);
    251		if (hp_sdc.hil != NULL)
    252			hp_sdc.hil(irq, dev_id, status, data);
    253		read_unlock(&hp_sdc.hook_lock);
    254		break;
    255
    256	case HP_SDC_STATUS_PUP:
    257		read_lock(&hp_sdc.hook_lock);
    258		if (hp_sdc.pup != NULL)
    259			hp_sdc.pup(irq, dev_id, status, data);
    260		else
    261			printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
    262		read_unlock(&hp_sdc.hook_lock);
    263		break;
    264
    265	default:
    266		read_lock(&hp_sdc.hook_lock);
    267		if (hp_sdc.cooked != NULL)
    268			hp_sdc.cooked(irq, dev_id, status, data);
    269		read_unlock(&hp_sdc.hook_lock);
    270		break;
    271	}
    272
    273	return IRQ_HANDLED;
    274}
    275
    276
    277static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id)
    278{
    279	int status;
    280
    281	status = hp_sdc_status_in8();
    282	printk(KERN_WARNING PREFIX "NMI !\n");
    283
    284#if 0
    285	if (status & HP_SDC_NMISTATUS_FHS) {
    286		read_lock(&hp_sdc.hook_lock);
    287		if (hp_sdc.timer != NULL)
    288			hp_sdc.timer(irq, dev_id, status, 0);
    289		read_unlock(&hp_sdc.hook_lock);
    290	} else {
    291		/* TODO: pass this on to the HIL handler, or do SAK here? */
    292		printk(KERN_WARNING PREFIX "HIL NMI\n");
    293	}
    294#endif
    295
    296	return IRQ_HANDLED;
    297}
    298
    299
    300/***************** Kernel (tasklet) context functions ****************/
    301
    302unsigned long hp_sdc_put(void);
    303
    304static void hp_sdc_tasklet(unsigned long foo)
    305{
    306	write_lock_irq(&hp_sdc.rtq_lock);
    307
    308	if (hp_sdc.rcurr >= 0) {
    309		ktime_t now = ktime_get();
    310
    311		if (ktime_after(now, ktime_add_us(hp_sdc.rtime,
    312						  HP_SDC_MAX_REG_DELAY))) {
    313			hp_sdc_transaction *curr;
    314			uint8_t tmp;
    315
    316			curr = hp_sdc.tq[hp_sdc.rcurr];
    317			/* If this turns out to be a normal failure mode
    318			 * we'll need to figure out a way to communicate
    319			 * it back to the application. and be less verbose.
    320			 */
    321			printk(KERN_WARNING PREFIX "read timeout (%lldus)!\n",
    322			       ktime_us_delta(now, hp_sdc.rtime));
    323			curr->idx += hp_sdc.rqty;
    324			hp_sdc.rqty = 0;
    325			tmp = curr->seq[curr->actidx];
    326			curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
    327			if (tmp & HP_SDC_ACT_SEMAPHORE)
    328				if (curr->act.semaphore)
    329					up(curr->act.semaphore);
    330
    331			if (tmp & HP_SDC_ACT_CALLBACK) {
    332				/* Note this means that irqhooks may be called
    333				 * in tasklet/bh context.
    334				 */
    335				if (curr->act.irqhook)
    336					curr->act.irqhook(0, NULL, 0, 0);
    337			}
    338
    339			curr->actidx = curr->idx;
    340			curr->idx++;
    341			hp_sdc.rcurr = -1;
    342		}
    343	}
    344	write_unlock_irq(&hp_sdc.rtq_lock);
    345	hp_sdc_put();
    346}
    347
    348unsigned long hp_sdc_put(void)
    349{
    350	hp_sdc_transaction *curr;
    351	uint8_t act;
    352	int idx, curridx;
    353
    354	int limit = 0;
    355
    356	write_lock(&hp_sdc.lock);
    357
    358	/* If i8042 buffers are full, we cannot do anything that
    359	   requires output, so we skip to the administrativa. */
    360	if (hp_sdc.ibf) {
    361		hp_sdc_status_in8();
    362		if (hp_sdc.ibf)
    363			goto finish;
    364	}
    365
    366 anew:
    367	/* See if we are in the middle of a sequence. */
    368	if (hp_sdc.wcurr < 0)
    369		hp_sdc.wcurr = 0;
    370	read_lock_irq(&hp_sdc.rtq_lock);
    371	if (hp_sdc.rcurr == hp_sdc.wcurr)
    372		hp_sdc.wcurr++;
    373	read_unlock_irq(&hp_sdc.rtq_lock);
    374	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
    375		hp_sdc.wcurr = 0;
    376	curridx = hp_sdc.wcurr;
    377
    378	if (hp_sdc.tq[curridx] != NULL)
    379		goto start;
    380
    381	while (++curridx != hp_sdc.wcurr) {
    382		if (curridx >= HP_SDC_QUEUE_LEN) {
    383			curridx = -1; /* Wrap to top */
    384			continue;
    385		}
    386		read_lock_irq(&hp_sdc.rtq_lock);
    387		if (hp_sdc.rcurr == curridx) {
    388			read_unlock_irq(&hp_sdc.rtq_lock);
    389			continue;
    390		}
    391		read_unlock_irq(&hp_sdc.rtq_lock);
    392		if (hp_sdc.tq[curridx] != NULL)
    393			break; /* Found one. */
    394	}
    395	if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
    396		curridx = -1;
    397	}
    398	hp_sdc.wcurr = curridx;
    399
    400 start:
    401
    402	/* Check to see if the interrupt mask needs to be set. */
    403	if (hp_sdc.set_im) {
    404		hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM);
    405		hp_sdc.set_im = 0;
    406		goto finish;
    407	}
    408
    409	if (hp_sdc.wcurr == -1)
    410		goto done;
    411
    412	curr = hp_sdc.tq[curridx];
    413	idx = curr->actidx;
    414
    415	if (curr->actidx >= curr->endidx) {
    416		hp_sdc.tq[curridx] = NULL;
    417		/* Interleave outbound data between the transactions. */
    418		hp_sdc.wcurr++;
    419		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
    420			hp_sdc.wcurr = 0;
    421		goto finish;
    422	}
    423
    424	act = curr->seq[idx];
    425	idx++;
    426
    427	if (curr->idx >= curr->endidx) {
    428		if (act & HP_SDC_ACT_DEALLOC)
    429			kfree(curr);
    430		hp_sdc.tq[curridx] = NULL;
    431		/* Interleave outbound data between the transactions. */
    432		hp_sdc.wcurr++;
    433		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
    434			hp_sdc.wcurr = 0;
    435		goto finish;
    436	}
    437
    438	while (act & HP_SDC_ACT_PRECMD) {
    439		if (curr->idx != idx) {
    440			idx++;
    441			act &= ~HP_SDC_ACT_PRECMD;
    442			break;
    443		}
    444		hp_sdc_status_out8(curr->seq[idx]);
    445		curr->idx++;
    446		/* act finished? */
    447		if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
    448			goto actdone;
    449		/* skip quantity field if data-out sequence follows. */
    450		if (act & HP_SDC_ACT_DATAOUT)
    451			curr->idx++;
    452		goto finish;
    453	}
    454	if (act & HP_SDC_ACT_DATAOUT) {
    455		int qty;
    456
    457		qty = curr->seq[idx];
    458		idx++;
    459		if (curr->idx - idx < qty) {
    460			hp_sdc_data_out8(curr->seq[curr->idx]);
    461			curr->idx++;
    462			/* act finished? */
    463			if (curr->idx - idx >= qty &&
    464			    (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)
    465				goto actdone;
    466			goto finish;
    467		}
    468		idx += qty;
    469		act &= ~HP_SDC_ACT_DATAOUT;
    470	} else
    471	    while (act & HP_SDC_ACT_DATAREG) {
    472		int mask;
    473		uint8_t w7[4];
    474
    475		mask = curr->seq[idx];
    476		if (idx != curr->idx) {
    477			idx++;
    478			idx += !!(mask & 1);
    479			idx += !!(mask & 2);
    480			idx += !!(mask & 4);
    481			idx += !!(mask & 8);
    482			act &= ~HP_SDC_ACT_DATAREG;
    483			break;
    484		}
    485
    486		w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
    487		w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
    488		w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
    489		w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
    490
    491		if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
    492		    w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) {
    493			int i = 0;
    494
    495			/* Need to point the write index register */
    496			while (i < 4 && w7[i] == hp_sdc.r7[i])
    497				i++;
    498
    499			if (i < 4) {
    500				hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
    501				hp_sdc.wi = 0x70 + i;
    502				goto finish;
    503			}
    504
    505			idx++;
    506			if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
    507				goto actdone;
    508
    509			curr->idx = idx;
    510			act &= ~HP_SDC_ACT_DATAREG;
    511			break;
    512		}
    513
    514		hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]);
    515		hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70];
    516		hp_sdc.wi++; /* write index register autoincrements */
    517		{
    518			int i = 0;
    519
    520			while ((i < 4) && w7[i] == hp_sdc.r7[i])
    521				i++;
    522			if (i >= 4) {
    523				curr->idx = idx + 1;
    524				if ((act & HP_SDC_ACT_DURING) ==
    525				    HP_SDC_ACT_DATAREG)
    526					goto actdone;
    527			}
    528		}
    529		goto finish;
    530	}
    531	/* We don't go any further in the command if there is a pending read,
    532	   because we don't want interleaved results. */
    533	read_lock_irq(&hp_sdc.rtq_lock);
    534	if (hp_sdc.rcurr >= 0) {
    535		read_unlock_irq(&hp_sdc.rtq_lock);
    536		goto finish;
    537	}
    538	read_unlock_irq(&hp_sdc.rtq_lock);
    539
    540
    541	if (act & HP_SDC_ACT_POSTCMD) {
    542		uint8_t postcmd;
    543
    544		/* curr->idx should == idx at this point. */
    545		postcmd = curr->seq[idx];
    546		curr->idx++;
    547		if (act & HP_SDC_ACT_DATAIN) {
    548
    549			/* Start a new read */
    550			hp_sdc.rqty = curr->seq[curr->idx];
    551			hp_sdc.rtime = ktime_get();
    552			curr->idx++;
    553			/* Still need to lock here in case of spurious irq. */
    554			write_lock_irq(&hp_sdc.rtq_lock);
    555			hp_sdc.rcurr = curridx;
    556			write_unlock_irq(&hp_sdc.rtq_lock);
    557			hp_sdc_status_out8(postcmd);
    558			goto finish;
    559		}
    560		hp_sdc_status_out8(postcmd);
    561		goto actdone;
    562	}
    563
    564 actdone:
    565	if (act & HP_SDC_ACT_SEMAPHORE)
    566		up(curr->act.semaphore);
    567	else if (act & HP_SDC_ACT_CALLBACK)
    568		curr->act.irqhook(0,NULL,0,0);
    569
    570	if (curr->idx >= curr->endidx) { /* This transaction is over. */
    571		if (act & HP_SDC_ACT_DEALLOC)
    572			kfree(curr);
    573		hp_sdc.tq[curridx] = NULL;
    574	} else {
    575		curr->actidx = idx + 1;
    576		curr->idx = idx + 2;
    577	}
    578	/* Interleave outbound data between the transactions. */
    579	hp_sdc.wcurr++;
    580	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
    581		hp_sdc.wcurr = 0;
    582
    583 finish:
    584	/* If by some quirk IBF has cleared and our ISR has run to
    585	   see that that has happened, do it all again. */
    586	if (!hp_sdc.ibf && limit++ < 20)
    587		goto anew;
    588
    589 done:
    590	if (hp_sdc.wcurr >= 0)
    591		tasklet_schedule(&hp_sdc.task);
    592	write_unlock(&hp_sdc.lock);
    593
    594	return 0;
    595}
    596
    597/******* Functions called in either user or kernel context ****/
    598int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this)
    599{
    600	int i;
    601
    602	if (this == NULL) {
    603		BUG();
    604		return -EINVAL;
    605	}
    606
    607	/* Can't have same transaction on queue twice */
    608	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
    609		if (hp_sdc.tq[i] == this)
    610			goto fail;
    611
    612	this->actidx = 0;
    613	this->idx = 1;
    614
    615	/* Search for empty slot */
    616	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
    617		if (hp_sdc.tq[i] == NULL) {
    618			hp_sdc.tq[i] = this;
    619			tasklet_schedule(&hp_sdc.task);
    620			return 0;
    621		}
    622
    623	printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
    624	return -EBUSY;
    625
    626 fail:
    627	printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
    628	return -EINVAL;
    629}
    630
    631int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
    632	unsigned long flags;
    633	int ret;
    634
    635	write_lock_irqsave(&hp_sdc.lock, flags);
    636	ret = __hp_sdc_enqueue_transaction(this);
    637	write_unlock_irqrestore(&hp_sdc.lock,flags);
    638
    639	return ret;
    640}
    641
    642int hp_sdc_dequeue_transaction(hp_sdc_transaction *this)
    643{
    644	unsigned long flags;
    645	int i;
    646
    647	write_lock_irqsave(&hp_sdc.lock, flags);
    648
    649	/* TODO: don't remove it if it's not done. */
    650
    651	for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
    652		if (hp_sdc.tq[i] == this)
    653			hp_sdc.tq[i] = NULL;
    654
    655	write_unlock_irqrestore(&hp_sdc.lock, flags);
    656	return 0;
    657}
    658
    659
    660
    661/********************** User context functions **************************/
    662int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback)
    663{
    664	if (callback == NULL || hp_sdc.dev == NULL)
    665		return -EINVAL;
    666
    667	write_lock_irq(&hp_sdc.hook_lock);
    668	if (hp_sdc.timer != NULL) {
    669		write_unlock_irq(&hp_sdc.hook_lock);
    670		return -EBUSY;
    671	}
    672
    673	hp_sdc.timer = callback;
    674	/* Enable interrupts from the timers */
    675	hp_sdc.im &= ~HP_SDC_IM_FH;
    676        hp_sdc.im &= ~HP_SDC_IM_PT;
    677	hp_sdc.im &= ~HP_SDC_IM_TIMERS;
    678	hp_sdc.set_im = 1;
    679	write_unlock_irq(&hp_sdc.hook_lock);
    680
    681	tasklet_schedule(&hp_sdc.task);
    682
    683	return 0;
    684}
    685
    686int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback)
    687{
    688	if (callback == NULL || hp_sdc.dev == NULL)
    689		return -EINVAL;
    690
    691	write_lock_irq(&hp_sdc.hook_lock);
    692	if (hp_sdc.hil != NULL) {
    693		write_unlock_irq(&hp_sdc.hook_lock);
    694		return -EBUSY;
    695	}
    696
    697	hp_sdc.hil = callback;
    698	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
    699	hp_sdc.set_im = 1;
    700	write_unlock_irq(&hp_sdc.hook_lock);
    701
    702	tasklet_schedule(&hp_sdc.task);
    703
    704	return 0;
    705}
    706
    707int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback)
    708{
    709	if (callback == NULL || hp_sdc.dev == NULL)
    710		return -EINVAL;
    711
    712	write_lock_irq(&hp_sdc.hook_lock);
    713	if (hp_sdc.cooked != NULL) {
    714		write_unlock_irq(&hp_sdc.hook_lock);
    715		return -EBUSY;
    716	}
    717
    718	/* Enable interrupts from the HIL MLC */
    719	hp_sdc.cooked = callback;
    720	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
    721	hp_sdc.set_im = 1;
    722	write_unlock_irq(&hp_sdc.hook_lock);
    723
    724	tasklet_schedule(&hp_sdc.task);
    725
    726	return 0;
    727}
    728
    729int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback)
    730{
    731	write_lock_irq(&hp_sdc.hook_lock);
    732	if ((callback != hp_sdc.timer) ||
    733	    (hp_sdc.timer == NULL)) {
    734		write_unlock_irq(&hp_sdc.hook_lock);
    735		return -EINVAL;
    736	}
    737
    738	/* Disable interrupts from the timers */
    739	hp_sdc.timer = NULL;
    740	hp_sdc.im |= HP_SDC_IM_TIMERS;
    741	hp_sdc.im |= HP_SDC_IM_FH;
    742	hp_sdc.im |= HP_SDC_IM_PT;
    743	hp_sdc.set_im = 1;
    744	write_unlock_irq(&hp_sdc.hook_lock);
    745	tasklet_schedule(&hp_sdc.task);
    746
    747	return 0;
    748}
    749
    750int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback)
    751{
    752	write_lock_irq(&hp_sdc.hook_lock);
    753	if ((callback != hp_sdc.hil) ||
    754	    (hp_sdc.hil == NULL)) {
    755		write_unlock_irq(&hp_sdc.hook_lock);
    756		return -EINVAL;
    757	}
    758
    759	hp_sdc.hil = NULL;
    760	/* Disable interrupts from HIL only if there is no cooked driver. */
    761	if(hp_sdc.cooked == NULL) {
    762		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
    763		hp_sdc.set_im = 1;
    764	}
    765	write_unlock_irq(&hp_sdc.hook_lock);
    766	tasklet_schedule(&hp_sdc.task);
    767
    768	return 0;
    769}
    770
    771int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
    772{
    773	write_lock_irq(&hp_sdc.hook_lock);
    774	if ((callback != hp_sdc.cooked) ||
    775	    (hp_sdc.cooked == NULL)) {
    776		write_unlock_irq(&hp_sdc.hook_lock);
    777		return -EINVAL;
    778	}
    779
    780	hp_sdc.cooked = NULL;
    781	/* Disable interrupts from HIL only if there is no raw HIL driver. */
    782	if(hp_sdc.hil == NULL) {
    783		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
    784		hp_sdc.set_im = 1;
    785	}
    786	write_unlock_irq(&hp_sdc.hook_lock);
    787	tasklet_schedule(&hp_sdc.task);
    788
    789	return 0;
    790}
    791
    792/************************* Keepalive timer task *********************/
    793
    794static void hp_sdc_kicker(struct timer_list *unused)
    795{
    796	tasklet_schedule(&hp_sdc.task);
    797	/* Re-insert the periodic task. */
    798	mod_timer(&hp_sdc.kicker, jiffies + HZ);
    799}
    800
    801/************************** Module Initialization ***************************/
    802
    803#if defined(__hppa__)
    804
    805static const struct parisc_device_id hp_sdc_tbl[] __initconst = {
    806	{
    807		.hw_type =	HPHW_FIO,
    808		.hversion_rev =	HVERSION_REV_ANY_ID,
    809		.hversion =	HVERSION_ANY_ID,
    810		.sversion =	0x73,
    811	 },
    812	{ 0, }
    813};
    814
    815MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
    816
    817static int __init hp_sdc_init_hppa(struct parisc_device *d);
    818static struct delayed_work moduleloader_work;
    819
    820static struct parisc_driver hp_sdc_driver __refdata = {
    821	.name =		"hp_sdc",
    822	.id_table =	hp_sdc_tbl,
    823	.probe =	hp_sdc_init_hppa,
    824};
    825
    826#endif /* __hppa__ */
    827
    828static int __init hp_sdc_init(void)
    829{
    830	char *errstr;
    831	hp_sdc_transaction t_sync;
    832	uint8_t ts_sync[6];
    833	struct semaphore s_sync;
    834
    835	rwlock_init(&hp_sdc.lock);
    836	rwlock_init(&hp_sdc.ibf_lock);
    837	rwlock_init(&hp_sdc.rtq_lock);
    838	rwlock_init(&hp_sdc.hook_lock);
    839
    840	hp_sdc.timer		= NULL;
    841	hp_sdc.hil		= NULL;
    842	hp_sdc.pup		= NULL;
    843	hp_sdc.cooked		= NULL;
    844	hp_sdc.im		= HP_SDC_IM_MASK;  /* Mask maskable irqs */
    845	hp_sdc.set_im		= 1;
    846	hp_sdc.wi		= 0xff;
    847	hp_sdc.r7[0]		= 0xff;
    848	hp_sdc.r7[1]		= 0xff;
    849	hp_sdc.r7[2]		= 0xff;
    850	hp_sdc.r7[3]		= 0xff;
    851	hp_sdc.ibf		= 1;
    852
    853	memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq));
    854
    855	hp_sdc.wcurr		= -1;
    856        hp_sdc.rcurr		= -1;
    857	hp_sdc.rqty		= 0;
    858
    859	hp_sdc.dev_err = -ENODEV;
    860
    861	errstr = "IO not found for";
    862	if (!hp_sdc.base_io)
    863		goto err0;
    864
    865	errstr = "IRQ not found for";
    866	if (!hp_sdc.irq)
    867		goto err0;
    868
    869	hp_sdc.dev_err = -EBUSY;
    870
    871#if defined(__hppa__)
    872	errstr = "IO not available for";
    873        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name))
    874		goto err0;
    875#endif
    876
    877	errstr = "IRQ not available for";
    878	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED,
    879			"HP SDC", &hp_sdc))
    880		goto err1;
    881
    882	errstr = "NMI not available for";
    883	if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED,
    884			"HP SDC NMI", &hp_sdc))
    885		goto err2;
    886
    887	pr_info(PREFIX "HP SDC at 0x%08lx, IRQ %d (NMI IRQ %d)\n",
    888	       hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
    889
    890	hp_sdc_status_in8();
    891	hp_sdc_data_in8();
    892
    893	tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0);
    894
    895	/* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */
    896	t_sync.actidx	= 0;
    897	t_sync.idx	= 1;
    898	t_sync.endidx	= 6;
    899	t_sync.seq	= ts_sync;
    900	ts_sync[0]	= HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE;
    901	ts_sync[1]	= 0x0f;
    902	ts_sync[2] = ts_sync[3]	= ts_sync[4] = ts_sync[5] = 0;
    903	t_sync.act.semaphore = &s_sync;
    904	sema_init(&s_sync, 0);
    905	hp_sdc_enqueue_transaction(&t_sync);
    906	down(&s_sync); /* Wait for t_sync to complete */
    907
    908	/* Create the keepalive task */
    909	timer_setup(&hp_sdc.kicker, hp_sdc_kicker, 0);
    910	hp_sdc.kicker.expires = jiffies + HZ;
    911	add_timer(&hp_sdc.kicker);
    912
    913	hp_sdc.dev_err = 0;
    914	return 0;
    915 err2:
    916	free_irq(hp_sdc.irq, &hp_sdc);
    917 err1:
    918	release_region(hp_sdc.data_io, 2);
    919 err0:
    920	printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n",
    921		errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
    922	hp_sdc.dev = NULL;
    923
    924	return hp_sdc.dev_err;
    925}
    926
    927#if defined(__hppa__)
    928
    929static void request_module_delayed(struct work_struct *work)
    930{
    931	request_module("hp_sdc_mlc");
    932}
    933
    934static int __init hp_sdc_init_hppa(struct parisc_device *d)
    935{
    936	int ret;
    937
    938	if (!d)
    939		return 1;
    940	if (hp_sdc.dev != NULL)
    941		return 1;	/* We only expect one SDC */
    942
    943	hp_sdc.dev		= d;
    944	hp_sdc.irq		= d->irq;
    945	hp_sdc.nmi		= d->aux_irq;
    946	hp_sdc.base_io		= d->hpa.start;
    947	hp_sdc.data_io		= d->hpa.start + 0x800;
    948	hp_sdc.status_io	= d->hpa.start + 0x801;
    949
    950	INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed);
    951
    952	ret = hp_sdc_init();
    953	/* after successful initialization give SDC some time to settle
    954	 * and then load the hp_sdc_mlc upper layer driver */
    955	if (!ret)
    956		schedule_delayed_work(&moduleloader_work,
    957			msecs_to_jiffies(2000));
    958
    959	return ret;
    960}
    961
    962#endif /* __hppa__ */
    963
    964static void hp_sdc_exit(void)
    965{
    966	/* do nothing if we don't have a SDC */
    967	if (!hp_sdc.dev)
    968		return;
    969
    970	write_lock_irq(&hp_sdc.lock);
    971
    972	/* Turn off all maskable "sub-function" irq's. */
    973	hp_sdc_spin_ibf();
    974	sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io);
    975
    976	/* Wait until we know this has been processed by the i8042 */
    977	hp_sdc_spin_ibf();
    978
    979	free_irq(hp_sdc.nmi, &hp_sdc);
    980	free_irq(hp_sdc.irq, &hp_sdc);
    981	write_unlock_irq(&hp_sdc.lock);
    982
    983	del_timer_sync(&hp_sdc.kicker);
    984
    985	tasklet_kill(&hp_sdc.task);
    986
    987#if defined(__hppa__)
    988	cancel_delayed_work_sync(&moduleloader_work);
    989	if (unregister_parisc_driver(&hp_sdc_driver))
    990		printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
    991#endif
    992}
    993
    994static int __init hp_sdc_register(void)
    995{
    996	hp_sdc_transaction tq_init;
    997	uint8_t tq_init_seq[5];
    998	struct semaphore tq_init_sem;
    999#if defined(__mc68000__)
   1000	unsigned char i;
   1001#endif
   1002
   1003	if (hp_sdc_disabled) {
   1004		printk(KERN_WARNING PREFIX "HP SDC driver disabled by no_hpsdc=1.\n");
   1005		return -ENODEV;
   1006	}
   1007
   1008	hp_sdc.dev = NULL;
   1009	hp_sdc.dev_err = 0;
   1010#if defined(__hppa__)
   1011	if (register_parisc_driver(&hp_sdc_driver)) {
   1012		printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n");
   1013		return -ENODEV;
   1014	}
   1015#elif defined(__mc68000__)
   1016	if (!MACH_IS_HP300)
   1017	    return -ENODEV;
   1018
   1019	hp_sdc.irq	 = 1;
   1020	hp_sdc.nmi	 = 7;
   1021	hp_sdc.base_io	 = (unsigned long) 0xf0428000;
   1022	hp_sdc.data_io	 = (unsigned long) hp_sdc.base_io + 1;
   1023	hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
   1024	if (!copy_from_kernel_nofault(&i, (unsigned char *)hp_sdc.data_io, 1))
   1025		hp_sdc.dev = (void *)1;
   1026	hp_sdc.dev_err   = hp_sdc_init();
   1027#endif
   1028	if (hp_sdc.dev == NULL) {
   1029		printk(KERN_WARNING PREFIX "No SDC found.\n");
   1030		return hp_sdc.dev_err;
   1031	}
   1032
   1033	sema_init(&tq_init_sem, 0);
   1034
   1035	tq_init.actidx		= 0;
   1036	tq_init.idx		= 1;
   1037	tq_init.endidx		= 5;
   1038	tq_init.seq		= tq_init_seq;
   1039	tq_init.act.semaphore	= &tq_init_sem;
   1040
   1041	tq_init_seq[0] =
   1042		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
   1043	tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
   1044	tq_init_seq[2] = 1;
   1045	tq_init_seq[3] = 0;
   1046	tq_init_seq[4] = 0;
   1047
   1048	hp_sdc_enqueue_transaction(&tq_init);
   1049
   1050	down(&tq_init_sem);
   1051	up(&tq_init_sem);
   1052
   1053	if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
   1054		printk(KERN_WARNING PREFIX "Error reading config byte.\n");
   1055		hp_sdc_exit();
   1056		return -ENODEV;
   1057	}
   1058	hp_sdc.r11 = tq_init_seq[4];
   1059	if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
   1060		const char *str;
   1061		printk(KERN_INFO PREFIX "New style SDC\n");
   1062		tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
   1063		tq_init.actidx		= 0;
   1064		tq_init.idx		= 1;
   1065		down(&tq_init_sem);
   1066		hp_sdc_enqueue_transaction(&tq_init);
   1067		down(&tq_init_sem);
   1068		up(&tq_init_sem);
   1069		if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
   1070			printk(KERN_WARNING PREFIX "Error reading extended config byte.\n");
   1071			return -ENODEV;
   1072		}
   1073		hp_sdc.r7e = tq_init_seq[4];
   1074		HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
   1075		printk(KERN_INFO PREFIX "Revision: %s\n", str);
   1076		if (hp_sdc.r7e & HP_SDC_XTD_BEEPER)
   1077			printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
   1078		if (hp_sdc.r7e & HP_SDC_XTD_BBRTC)
   1079			printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
   1080		printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
   1081		       "on next firmware reset.\n");
   1082		tq_init_seq[0] = HP_SDC_ACT_PRECMD |
   1083			HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
   1084		tq_init_seq[1] = HP_SDC_CMD_SET_STR;
   1085		tq_init_seq[2] = 1;
   1086		tq_init_seq[3] = 0;
   1087		tq_init.actidx		= 0;
   1088		tq_init.idx		= 1;
   1089		tq_init.endidx		= 4;
   1090		down(&tq_init_sem);
   1091		hp_sdc_enqueue_transaction(&tq_init);
   1092		down(&tq_init_sem);
   1093		up(&tq_init_sem);
   1094	} else
   1095		printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
   1096		       (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
   1097
   1098        return 0;
   1099}
   1100
   1101module_init(hp_sdc_register);
   1102module_exit(hp_sdc_exit);
   1103
   1104/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64)
   1105 *                                              cycles cycles-adj    time
   1106 * between two consecutive mfctl(16)'s:              4        n/a    63ns
   1107 * hp_sdc_spin_ibf when idle:                      119        115   1.7us
   1108 * gsc_writeb status register:                      83         79   1.2us
   1109 * IBF to clear after sending SET_IM:             6204       6006    93us
   1110 * IBF to clear after sending LOAD_RT:            4467       4352    68us
   1111 * IBF to clear after sending two LOAD_RTs:      18974      18859   295us
   1112 * READ_T1, read status/data, IRQ, call handler: 35564        n/a   556us
   1113 * cmd to ~IBF READ_T1 2nd time right after:   5158403        n/a    81ms
   1114 * between IRQ received and ~IBF for above:    2578877        n/a    40ms
   1115 *
   1116 * Performance stats after a run of this module configuring HIL and
   1117 * receiving a few mouse events:
   1118 *
   1119 * status in8  282508 cycles 7128 calls
   1120 * status out8   8404 cycles  341 calls
   1121 * data out8     1734 cycles   78 calls
   1122 * isr         174324 cycles  617 calls (includes take)
   1123 * take          1241 cycles    2 calls
   1124 * put        1411504 cycles 6937 calls
   1125 * task       1655209 cycles 6937 calls (includes put)
   1126 *
   1127 */