xref: /linux/drivers/input/serio/hp_sdc.c (revision c537b994505099b7197e7d3125b942ecbcc51eb6)
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/slab.h>
71 #include <linux/hil.h>
72 #include <asm/io.h>
73 #include <asm/system.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 <asm/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 
91 MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
92 MODULE_DESCRIPTION("HP i8042-based SDC Driver");
93 MODULE_LICENSE("Dual BSD/GPL");
94 
95 EXPORT_SYMBOL(hp_sdc_request_timer_irq);
96 EXPORT_SYMBOL(hp_sdc_request_hil_irq);
97 EXPORT_SYMBOL(hp_sdc_request_cooked_irq);
98 
99 EXPORT_SYMBOL(hp_sdc_release_timer_irq);
100 EXPORT_SYMBOL(hp_sdc_release_hil_irq);
101 EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
102 
103 EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
104 EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
105 
106 static hp_i8042_sdc	hp_sdc;	/* All driver state is kept in here. */
107 
108 /*************** primitives for use in any context *********************/
109 static inline uint8_t hp_sdc_status_in8 (void) {
110 	uint8_t status;
111 	unsigned long flags;
112 
113 	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
114 	status = sdc_readb(hp_sdc.status_io);
115 	if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0;
116 	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
117 
118 	return status;
119 }
120 
121 static inline uint8_t hp_sdc_data_in8 (void) {
122 	return sdc_readb(hp_sdc.data_io);
123 }
124 
125 static inline void hp_sdc_status_out8 (uint8_t val) {
126 	unsigned long flags;
127 
128 	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
129 	hp_sdc.ibf = 1;
130 	if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff;
131 	sdc_writeb(val, hp_sdc.status_io);
132 	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
133 }
134 
135 static inline void hp_sdc_data_out8 (uint8_t val) {
136 	unsigned long flags;
137 
138 	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
139 	hp_sdc.ibf = 1;
140 	sdc_writeb(val, hp_sdc.data_io);
141 	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
142 }
143 
144 /*	Care must be taken to only invoke hp_sdc_spin_ibf when
145  *	absolutely needed, or in rarely invoked subroutines.
146  *	Not only does it waste CPU cycles, it also wastes bus cycles.
147  */
148 static inline void hp_sdc_spin_ibf(void) {
149 	unsigned long flags;
150 	rwlock_t *lock;
151 
152 	lock = &hp_sdc.ibf_lock;
153 
154 	read_lock_irqsave(lock, flags);
155 	if (!hp_sdc.ibf) {
156 		read_unlock_irqrestore(lock, flags);
157 		return;
158 	}
159 	read_unlock(lock);
160 	write_lock(lock);
161 	while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {};
162 	hp_sdc.ibf = 0;
163 	write_unlock_irqrestore(lock, flags);
164 }
165 
166 
167 /************************ Interrupt context functions ************************/
168 static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
169 	hp_sdc_transaction *curr;
170 
171 	read_lock(&hp_sdc.rtq_lock);
172 	if (hp_sdc.rcurr < 0) {
173 	  	read_unlock(&hp_sdc.rtq_lock);
174 		return;
175 	}
176 	curr = hp_sdc.tq[hp_sdc.rcurr];
177 	read_unlock(&hp_sdc.rtq_lock);
178 
179 	curr->seq[curr->idx++] = status;
180 	curr->seq[curr->idx++] = data;
181 	hp_sdc.rqty -= 2;
182 	do_gettimeofday(&hp_sdc.rtv);
183 
184 	if (hp_sdc.rqty <= 0) {
185 		/* All data has been gathered. */
186 		if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) {
187 			if (curr->act.semaphore) up(curr->act.semaphore);
188 		}
189 		if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) {
190 			if (curr->act.irqhook)
191 				curr->act.irqhook(irq, dev_id, status, data);
192 		}
193 		curr->actidx = curr->idx;
194 		curr->idx++;
195 		/* Return control of this transaction */
196 		write_lock(&hp_sdc.rtq_lock);
197 		hp_sdc.rcurr = -1;
198 		hp_sdc.rqty = 0;
199 		write_unlock(&hp_sdc.rtq_lock);
200 		tasklet_schedule(&hp_sdc.task);
201 	}
202 }
203 
204 static irqreturn_t hp_sdc_isr(int irq, void *dev_id) {
205 	uint8_t status, data;
206 
207 	status = hp_sdc_status_in8();
208 	/* Read data unconditionally to advance i8042. */
209 	data =   hp_sdc_data_in8();
210 
211 	/* For now we are ignoring these until we get the SDC to behave. */
212 	if (((status & 0xf1) == 0x51) && data == 0x82) {
213 	  return IRQ_HANDLED;
214 	}
215 
216 	switch(status & HP_SDC_STATUS_IRQMASK) {
217 	      case 0: /* This case is not documented. */
218 		break;
219 	      case HP_SDC_STATUS_USERTIMER:
220 	      case HP_SDC_STATUS_PERIODIC:
221 	      case HP_SDC_STATUS_TIMER:
222 		read_lock(&hp_sdc.hook_lock);
223 	      	if (hp_sdc.timer != NULL)
224 			hp_sdc.timer(irq, dev_id, status, data);
225 		read_unlock(&hp_sdc.hook_lock);
226 		break;
227 	      case HP_SDC_STATUS_REG:
228 		hp_sdc_take(irq, dev_id, status, data);
229 		break;
230 	      case HP_SDC_STATUS_HILCMD:
231 	      case HP_SDC_STATUS_HILDATA:
232 		read_lock(&hp_sdc.hook_lock);
233 		if (hp_sdc.hil != NULL)
234 			hp_sdc.hil(irq, dev_id, status, data);
235 		read_unlock(&hp_sdc.hook_lock);
236 		break;
237 	      case HP_SDC_STATUS_PUP:
238 		read_lock(&hp_sdc.hook_lock);
239 		if (hp_sdc.pup != NULL)
240 			hp_sdc.pup(irq, dev_id, status, data);
241 		else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
242 		read_unlock(&hp_sdc.hook_lock);
243 		break;
244 	      default:
245 		read_lock(&hp_sdc.hook_lock);
246 		if (hp_sdc.cooked != NULL)
247 			hp_sdc.cooked(irq, dev_id, status, data);
248 		read_unlock(&hp_sdc.hook_lock);
249 		break;
250 	}
251 	return IRQ_HANDLED;
252 }
253 
254 
255 static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) {
256 	int status;
257 
258 	status = hp_sdc_status_in8();
259 	printk(KERN_WARNING PREFIX "NMI !\n");
260 
261 #if 0
262 	if (status & HP_SDC_NMISTATUS_FHS) {
263 		read_lock(&hp_sdc.hook_lock);
264 	      	if (hp_sdc.timer != NULL)
265 			hp_sdc.timer(irq, dev_id, status, 0);
266 		read_unlock(&hp_sdc.hook_lock);
267 	}
268 	else {
269 		/* TODO: pass this on to the HIL handler, or do SAK here? */
270 		printk(KERN_WARNING PREFIX "HIL NMI\n");
271 	}
272 #endif
273 	return IRQ_HANDLED;
274 }
275 
276 
277 /***************** Kernel (tasklet) context functions ****************/
278 
279 unsigned long hp_sdc_put(void);
280 
281 static void hp_sdc_tasklet(unsigned long foo) {
282 
283 	write_lock_irq(&hp_sdc.rtq_lock);
284 	if (hp_sdc.rcurr >= 0) {
285 		struct timeval tv;
286 		do_gettimeofday(&tv);
287 		if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000;
288 		if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
289 			hp_sdc_transaction *curr;
290 			uint8_t tmp;
291 
292 			curr = hp_sdc.tq[hp_sdc.rcurr];
293 			/* If this turns out to be a normal failure mode
294 			 * we'll need to figure out a way to communicate
295 			 * it back to the application. and be less verbose.
296 			 */
297 			printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
298 			       tv.tv_usec - hp_sdc.rtv.tv_usec);
299 			curr->idx += hp_sdc.rqty;
300 			hp_sdc.rqty = 0;
301 			tmp = curr->seq[curr->actidx];
302 			curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
303 			if(tmp & HP_SDC_ACT_SEMAPHORE) {
304 				if (curr->act.semaphore)
305 					up(curr->act.semaphore);
306 			}
307 			if(tmp & HP_SDC_ACT_CALLBACK) {
308 				/* Note this means that irqhooks may be called
309 				 * in tasklet/bh context.
310 				 */
311 				if (curr->act.irqhook)
312 					curr->act.irqhook(0, NULL, 0, 0);
313 			}
314 			curr->actidx = curr->idx;
315 			curr->idx++;
316 			hp_sdc.rcurr = -1;
317 		}
318 	}
319 	write_unlock_irq(&hp_sdc.rtq_lock);
320 	hp_sdc_put();
321 }
322 
323 unsigned long hp_sdc_put(void) {
324 	hp_sdc_transaction *curr;
325 	uint8_t act;
326 	int idx, curridx;
327 
328 	int limit = 0;
329 
330 	write_lock(&hp_sdc.lock);
331 
332 	/* If i8042 buffers are full, we cannot do anything that
333 	   requires output, so we skip to the administrativa. */
334 	if (hp_sdc.ibf) {
335 		hp_sdc_status_in8();
336 		if (hp_sdc.ibf) goto finish;
337 	}
338 
339  anew:
340 	/* See if we are in the middle of a sequence. */
341 	if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0;
342 	read_lock_irq(&hp_sdc.rtq_lock);
343 	if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++;
344 	read_unlock_irq(&hp_sdc.rtq_lock);
345 	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
346 	curridx = hp_sdc.wcurr;
347 
348 	if (hp_sdc.tq[curridx] != NULL) goto start;
349 
350 	while (++curridx != hp_sdc.wcurr) {
351 		if (curridx >= HP_SDC_QUEUE_LEN) {
352 			curridx = -1; /* Wrap to top */
353 			continue;
354 		}
355 		read_lock_irq(&hp_sdc.rtq_lock);
356 		if (hp_sdc.rcurr == curridx) {
357 			read_unlock_irq(&hp_sdc.rtq_lock);
358 			continue;
359 		}
360 		read_unlock_irq(&hp_sdc.rtq_lock);
361 		if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */
362 	}
363 	if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
364 		curridx = -1;
365 	}
366 	hp_sdc.wcurr = curridx;
367 
368  start:
369 
370 	/* Check to see if the interrupt mask needs to be set. */
371 	if (hp_sdc.set_im) {
372 		hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM);
373 		hp_sdc.set_im = 0;
374 		goto finish;
375 	}
376 
377 	if (hp_sdc.wcurr == -1) goto done;
378 
379 	curr = hp_sdc.tq[curridx];
380 	idx = curr->actidx;
381 
382 	if (curr->actidx >= curr->endidx) {
383 		hp_sdc.tq[curridx] = NULL;
384 		/* Interleave outbound data between the transactions. */
385 		hp_sdc.wcurr++;
386 		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
387 		goto finish;
388 	}
389 
390 	act = curr->seq[idx];
391 	idx++;
392 
393 	if (curr->idx >= curr->endidx) {
394 		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
395 		hp_sdc.tq[curridx] = NULL;
396 		/* Interleave outbound data between the transactions. */
397 		hp_sdc.wcurr++;
398 		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
399 		goto finish;
400 	}
401 
402 	while (act & HP_SDC_ACT_PRECMD) {
403 		if (curr->idx != idx) {
404 			idx++;
405 			act &= ~HP_SDC_ACT_PRECMD;
406 			break;
407 		}
408 		hp_sdc_status_out8(curr->seq[idx]);
409 		curr->idx++;
410 		/* act finished? */
411 		if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
412 		  goto actdone;
413 		/* skip quantity field if data-out sequence follows. */
414 		if (act & HP_SDC_ACT_DATAOUT) curr->idx++;
415 		goto finish;
416 	}
417 	if (act & HP_SDC_ACT_DATAOUT) {
418 		int qty;
419 
420 		qty = curr->seq[idx];
421 		idx++;
422 		if (curr->idx - idx < qty) {
423 			hp_sdc_data_out8(curr->seq[curr->idx]);
424 			curr->idx++;
425 			/* act finished? */
426 			if ((curr->idx - idx >= qty) &&
427 			    ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT))
428 				goto actdone;
429 			goto finish;
430 		}
431 		idx += qty;
432 		act &= ~HP_SDC_ACT_DATAOUT;
433 	}
434 	else while (act & HP_SDC_ACT_DATAREG) {
435 		int mask;
436 		uint8_t w7[4];
437 
438 		mask = curr->seq[idx];
439 		if (idx != curr->idx) {
440 			idx++;
441 			idx += !!(mask & 1);
442 			idx += !!(mask & 2);
443 			idx += !!(mask & 4);
444 			idx += !!(mask & 8);
445 			act &= ~HP_SDC_ACT_DATAREG;
446 			break;
447 		}
448 
449 		w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
450 		w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
451 		w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
452 		w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
453 
454 		if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
455 		        w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) {
456 			int i = 0;
457 
458 			/* Need to point the write index register */
459 			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
460 			if (i < 4) {
461 				hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
462 				hp_sdc.wi = 0x70 + i;
463 				goto finish;
464 			}
465 			idx++;
466 			if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
467 				goto actdone;
468 			curr->idx = idx;
469 			act &= ~HP_SDC_ACT_DATAREG;
470 			break;
471 		}
472 
473 		hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]);
474 		hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70];
475 		hp_sdc.wi++; /* write index register autoincrements */
476 		{
477 			int i = 0;
478 
479 			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
480 			if (i >= 4) {
481 				curr->idx = idx + 1;
482 				if ((act & HP_SDC_ACT_DURING) ==
483 				    HP_SDC_ACT_DATAREG)
484 				        goto actdone;
485 			}
486 		}
487 		goto finish;
488 	}
489 	/* We don't go any further in the command if there is a pending read,
490 	   because we don't want interleaved results. */
491 	read_lock_irq(&hp_sdc.rtq_lock);
492 	if (hp_sdc.rcurr >= 0) {
493 		read_unlock_irq(&hp_sdc.rtq_lock);
494 		goto finish;
495 	}
496 	read_unlock_irq(&hp_sdc.rtq_lock);
497 
498 
499 	if (act & HP_SDC_ACT_POSTCMD) {
500 	  	uint8_t postcmd;
501 
502 		/* curr->idx should == idx at this point. */
503 		postcmd = curr->seq[idx];
504 		curr->idx++;
505 		if (act & HP_SDC_ACT_DATAIN) {
506 
507 			/* Start a new read */
508 	  		hp_sdc.rqty = curr->seq[curr->idx];
509 			do_gettimeofday(&hp_sdc.rtv);
510 			curr->idx++;
511 			/* Still need to lock here in case of spurious irq. */
512 			write_lock_irq(&hp_sdc.rtq_lock);
513 			hp_sdc.rcurr = curridx;
514 			write_unlock_irq(&hp_sdc.rtq_lock);
515 			hp_sdc_status_out8(postcmd);
516 			goto finish;
517 		}
518 		hp_sdc_status_out8(postcmd);
519 		goto actdone;
520 	}
521 
522 actdone:
523 	if (act & HP_SDC_ACT_SEMAPHORE) {
524 		up(curr->act.semaphore);
525 	}
526 	else if (act & HP_SDC_ACT_CALLBACK) {
527 		curr->act.irqhook(0,NULL,0,0);
528 	}
529 	if (curr->idx >= curr->endidx) { /* This transaction is over. */
530 		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
531 		hp_sdc.tq[curridx] = NULL;
532 	}
533 	else {
534 		curr->actidx = idx + 1;
535 		curr->idx = idx + 2;
536 	}
537 	/* Interleave outbound data between the transactions. */
538 	hp_sdc.wcurr++;
539 	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
540 
541  finish:
542 	/* If by some quirk IBF has cleared and our ISR has run to
543 	   see that that has happened, do it all again. */
544 	if (!hp_sdc.ibf && limit++ < 20) goto anew;
545 
546  done:
547 	if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task);
548 	write_unlock(&hp_sdc.lock);
549 	return 0;
550 }
551 
552 /******* Functions called in either user or kernel context ****/
553 int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
554 	unsigned long flags;
555 	int i;
556 
557 	if (this == NULL) {
558 		tasklet_schedule(&hp_sdc.task);
559 		return -EINVAL;
560 	};
561 
562 	write_lock_irqsave(&hp_sdc.lock, flags);
563 
564 	/* Can't have same transaction on queue twice */
565 	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
566 		if (hp_sdc.tq[i] == this) goto fail;
567 
568 	this->actidx = 0;
569 	this->idx = 1;
570 
571 	/* Search for empty slot */
572 	for (i=0; i < HP_SDC_QUEUE_LEN; i++) {
573 		if (hp_sdc.tq[i] == NULL) {
574 			hp_sdc.tq[i] = this;
575 			write_unlock_irqrestore(&hp_sdc.lock, flags);
576 			tasklet_schedule(&hp_sdc.task);
577 			return 0;
578 		}
579 	}
580 	write_unlock_irqrestore(&hp_sdc.lock, flags);
581 	printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
582 	return -EBUSY;
583 
584  fail:
585 	write_unlock_irqrestore(&hp_sdc.lock,flags);
586 	printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
587 	return -EINVAL;
588 }
589 
590 int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
591 	unsigned long flags;
592 	int i;
593 
594 	write_lock_irqsave(&hp_sdc.lock, flags);
595 
596 	/* TODO: don't remove it if it's not done. */
597 
598 	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
599 		if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL;
600 
601 	write_unlock_irqrestore(&hp_sdc.lock, flags);
602 	return 0;
603 }
604 
605 
606 
607 /********************** User context functions **************************/
608 int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
609 
610 	if (callback == NULL || hp_sdc.dev == NULL) {
611 		return -EINVAL;
612 	}
613 	write_lock_irq(&hp_sdc.hook_lock);
614 	if (hp_sdc.timer != NULL) {
615 		write_unlock_irq(&hp_sdc.hook_lock);
616 		return -EBUSY;
617 	}
618 
619 	hp_sdc.timer = callback;
620 	/* Enable interrupts from the timers */
621 	hp_sdc.im &= ~HP_SDC_IM_FH;
622         hp_sdc.im &= ~HP_SDC_IM_PT;
623 	hp_sdc.im &= ~HP_SDC_IM_TIMERS;
624 	hp_sdc.set_im = 1;
625 	write_unlock_irq(&hp_sdc.hook_lock);
626 
627 	tasklet_schedule(&hp_sdc.task);
628 
629 	return 0;
630 }
631 
632 int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
633 
634 	if (callback == NULL || hp_sdc.dev == NULL) {
635 		return -EINVAL;
636 	}
637 	write_lock_irq(&hp_sdc.hook_lock);
638 	if (hp_sdc.hil != NULL) {
639 		write_unlock_irq(&hp_sdc.hook_lock);
640 		return -EBUSY;
641 	}
642 
643 	hp_sdc.hil = callback;
644 	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
645 	hp_sdc.set_im = 1;
646 	write_unlock_irq(&hp_sdc.hook_lock);
647 
648 	tasklet_schedule(&hp_sdc.task);
649 
650 	return 0;
651 }
652 
653 int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
654 
655 	if (callback == NULL || hp_sdc.dev == NULL) {
656 		return -EINVAL;
657 	}
658 	write_lock_irq(&hp_sdc.hook_lock);
659 	if (hp_sdc.cooked != NULL) {
660 		write_unlock_irq(&hp_sdc.hook_lock);
661 		return -EBUSY;
662 	}
663 
664 	/* Enable interrupts from the HIL MLC */
665 	hp_sdc.cooked = callback;
666 	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
667 	hp_sdc.set_im = 1;
668 	write_unlock_irq(&hp_sdc.hook_lock);
669 
670 	tasklet_schedule(&hp_sdc.task);
671 
672 	return 0;
673 }
674 
675 int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
676 
677 
678 	write_lock_irq(&hp_sdc.hook_lock);
679 	if ((callback != hp_sdc.timer) ||
680 	    (hp_sdc.timer == NULL)) {
681 		write_unlock_irq(&hp_sdc.hook_lock);
682 		return -EINVAL;
683 	}
684 
685 	/* Disable interrupts from the timers */
686 	hp_sdc.timer = NULL;
687 	hp_sdc.im |= HP_SDC_IM_TIMERS;
688 	hp_sdc.im |= HP_SDC_IM_FH;
689 	hp_sdc.im |= HP_SDC_IM_PT;
690 	hp_sdc.set_im = 1;
691 	write_unlock_irq(&hp_sdc.hook_lock);
692 	tasklet_schedule(&hp_sdc.task);
693 
694 	return 0;
695 }
696 
697 int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
698 
699 	write_lock_irq(&hp_sdc.hook_lock);
700 	if ((callback != hp_sdc.hil) ||
701 	    (hp_sdc.hil == NULL)) {
702 		write_unlock_irq(&hp_sdc.hook_lock);
703 		return -EINVAL;
704 	}
705 
706 	hp_sdc.hil = NULL;
707 	/* Disable interrupts from HIL only if there is no cooked driver. */
708 	if(hp_sdc.cooked == NULL) {
709 		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
710 		hp_sdc.set_im = 1;
711 	}
712 	write_unlock_irq(&hp_sdc.hook_lock);
713 	tasklet_schedule(&hp_sdc.task);
714 
715 	return 0;
716 }
717 
718 int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
719 
720 	write_lock_irq(&hp_sdc.hook_lock);
721 	if ((callback != hp_sdc.cooked) ||
722 	    (hp_sdc.cooked == NULL)) {
723 		write_unlock_irq(&hp_sdc.hook_lock);
724 		return -EINVAL;
725 	}
726 
727 	hp_sdc.cooked = NULL;
728 	/* Disable interrupts from HIL only if there is no raw HIL driver. */
729 	if(hp_sdc.hil == NULL) {
730 		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
731 		hp_sdc.set_im = 1;
732 	}
733 	write_unlock_irq(&hp_sdc.hook_lock);
734 	tasklet_schedule(&hp_sdc.task);
735 
736 	return 0;
737 }
738 
739 /************************* Keepalive timer task *********************/
740 
741 void hp_sdc_kicker (unsigned long data) {
742 	tasklet_schedule(&hp_sdc.task);
743 	/* Re-insert the periodic task. */
744 	mod_timer(&hp_sdc.kicker, jiffies + HZ);
745 }
746 
747 /************************** Module Initialization ***************************/
748 
749 #if defined(__hppa__)
750 
751 static struct parisc_device_id hp_sdc_tbl[] = {
752 	{
753 		.hw_type =	HPHW_FIO,
754 		.hversion_rev =	HVERSION_REV_ANY_ID,
755 		.hversion =	HVERSION_ANY_ID,
756 		.sversion =	0x73,
757 	 },
758 	{ 0, }
759 };
760 
761 MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
762 
763 static int __init hp_sdc_init_hppa(struct parisc_device *d);
764 
765 static struct parisc_driver hp_sdc_driver = {
766 	.name =		"hp_sdc",
767 	.id_table =	hp_sdc_tbl,
768 	.probe =	hp_sdc_init_hppa,
769 };
770 
771 #endif /* __hppa__ */
772 
773 static int __init hp_sdc_init(void)
774 {
775 	int i;
776 	char *errstr;
777 	hp_sdc_transaction t_sync;
778 	uint8_t ts_sync[6];
779 	struct semaphore s_sync;
780 
781   	rwlock_init(&hp_sdc.lock);
782   	rwlock_init(&hp_sdc.ibf_lock);
783   	rwlock_init(&hp_sdc.rtq_lock);
784   	rwlock_init(&hp_sdc.hook_lock);
785 
786 	hp_sdc.timer		= NULL;
787 	hp_sdc.hil		= NULL;
788 	hp_sdc.pup		= NULL;
789 	hp_sdc.cooked		= NULL;
790 	hp_sdc.im		= HP_SDC_IM_MASK;  /* Mask maskable irqs */
791 	hp_sdc.set_im		= 1;
792 	hp_sdc.wi		= 0xff;
793 	hp_sdc.r7[0]		= 0xff;
794 	hp_sdc.r7[1]		= 0xff;
795 	hp_sdc.r7[2]		= 0xff;
796 	hp_sdc.r7[3]		= 0xff;
797 	hp_sdc.ibf		= 1;
798 
799 	for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL;
800 	hp_sdc.wcurr		= -1;
801         hp_sdc.rcurr		= -1;
802 	hp_sdc.rqty		= 0;
803 
804 	hp_sdc.dev_err = -ENODEV;
805 
806 	errstr = "IO not found for";
807 	if (!hp_sdc.base_io) goto err0;
808 
809 	errstr = "IRQ not found for";
810 	if (!hp_sdc.irq) goto err0;
811 
812 	hp_sdc.dev_err = -EBUSY;
813 
814 #if defined(__hppa__)
815 	errstr = "IO not available for";
816         if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0;
817 #endif
818 
819 	errstr = "IRQ not available for";
820         if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC",
821 		       (void *) hp_sdc.base_io)) goto err1;
822 
823 	errstr = "NMI not available for";
824 	if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI",
825 			(void *) hp_sdc.base_io)) goto err2;
826 
827 	printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n",
828 	       (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
829 
830 	hp_sdc_status_in8();
831 	hp_sdc_data_in8();
832 
833 	tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0);
834 
835 	/* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */
836 	t_sync.actidx	= 0;
837 	t_sync.idx	= 1;
838 	t_sync.endidx	= 6;
839 	t_sync.seq	= ts_sync;
840 	ts_sync[0]	= HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE;
841 	ts_sync[1]	= 0x0f;
842 	ts_sync[2] = ts_sync[3]	= ts_sync[4] = ts_sync[5] = 0;
843 	t_sync.act.semaphore = &s_sync;
844 	init_MUTEX_LOCKED(&s_sync);
845 	hp_sdc_enqueue_transaction(&t_sync);
846 	down(&s_sync); /* Wait for t_sync to complete */
847 
848 	/* Create the keepalive task */
849 	init_timer(&hp_sdc.kicker);
850 	hp_sdc.kicker.expires = jiffies + HZ;
851 	hp_sdc.kicker.function = &hp_sdc_kicker;
852 	add_timer(&hp_sdc.kicker);
853 
854 	hp_sdc.dev_err = 0;
855 	return 0;
856  err2:
857 	free_irq(hp_sdc.irq, NULL);
858  err1:
859 	release_region(hp_sdc.data_io, 2);
860  err0:
861 	printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n",
862 		errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
863 	hp_sdc.dev = NULL;
864 	return hp_sdc.dev_err;
865 }
866 
867 #if defined(__hppa__)
868 
869 static int __init hp_sdc_init_hppa(struct parisc_device *d)
870 {
871 	if (!d) return 1;
872 	if (hp_sdc.dev != NULL) return 1;	/* We only expect one SDC */
873 
874 	hp_sdc.dev		= d;
875 	hp_sdc.irq		= d->irq;
876 	hp_sdc.nmi		= d->aux_irq;
877 	hp_sdc.base_io		= d->hpa.start;
878 	hp_sdc.data_io		= d->hpa.start + 0x800;
879 	hp_sdc.status_io	= d->hpa.start + 0x801;
880 
881 	return hp_sdc_init();
882 }
883 
884 #endif /* __hppa__ */
885 
886 #if !defined(__mc68000__) /* Link error on m68k! */
887 static void __exit hp_sdc_exit(void)
888 #else
889 static void hp_sdc_exit(void)
890 #endif
891 {
892 	write_lock_irq(&hp_sdc.lock);
893 
894 	/* Turn off all maskable "sub-function" irq's. */
895 	hp_sdc_spin_ibf();
896 	sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io);
897 
898 	/* Wait until we know this has been processed by the i8042 */
899 	hp_sdc_spin_ibf();
900 
901 	free_irq(hp_sdc.nmi, NULL);
902 	free_irq(hp_sdc.irq, NULL);
903 	write_unlock_irq(&hp_sdc.lock);
904 
905 	del_timer(&hp_sdc.kicker);
906 
907 	tasklet_kill(&hp_sdc.task);
908 
909 /*        release_region(hp_sdc.data_io, 2); */
910 
911 #if defined(__hppa__)
912 	if (unregister_parisc_driver(&hp_sdc_driver))
913 		printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
914 #endif
915 }
916 
917 static int __init hp_sdc_register(void)
918 {
919 	hp_sdc_transaction tq_init;
920 	uint8_t tq_init_seq[5];
921 	struct semaphore tq_init_sem;
922 #if defined(__mc68000__)
923 	mm_segment_t fs;
924 	unsigned char i;
925 #endif
926 
927 	hp_sdc.dev = NULL;
928 	hp_sdc.dev_err = 0;
929 #if defined(__hppa__)
930 	if (register_parisc_driver(&hp_sdc_driver)) {
931 		printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n");
932 		return -ENODEV;
933 	}
934 #elif defined(__mc68000__)
935 	if (!MACH_IS_HP300)
936 	    return -ENODEV;
937 
938 	hp_sdc.irq	 = 1;
939 	hp_sdc.nmi	 = 7;
940 	hp_sdc.base_io	 = (unsigned long) 0xf0428000;
941 	hp_sdc.data_io	 = (unsigned long) hp_sdc.base_io + 1;
942 	hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
943 	fs = get_fs();
944 	set_fs(KERNEL_DS);
945 	if (!get_user(i, (unsigned char *)hp_sdc.data_io))
946 		hp_sdc.dev = (void *)1;
947 	set_fs(fs);
948 	hp_sdc.dev_err   = hp_sdc_init();
949 #endif
950 	if (hp_sdc.dev == NULL) {
951 		printk(KERN_WARNING PREFIX "No SDC found.\n");
952 		return hp_sdc.dev_err;
953 	}
954 
955 	init_MUTEX_LOCKED(&tq_init_sem);
956 
957 	tq_init.actidx		= 0;
958 	tq_init.idx		= 1;
959 	tq_init.endidx		= 5;
960 	tq_init.seq		= tq_init_seq;
961 	tq_init.act.semaphore	= &tq_init_sem;
962 
963 	tq_init_seq[0] =
964 	  HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
965 	tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
966 	tq_init_seq[2] = 1;
967 	tq_init_seq[3] = 0;
968 	tq_init_seq[4] = 0;
969 
970 	hp_sdc_enqueue_transaction(&tq_init);
971 
972 	down(&tq_init_sem);
973 	up(&tq_init_sem);
974 
975 	if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
976 		printk(KERN_WARNING PREFIX "Error reading config byte.\n");
977 		hp_sdc_exit();
978 		return -ENODEV;
979 	}
980 	hp_sdc.r11 = tq_init_seq[4];
981 	if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
982 		char *str;
983 		printk(KERN_INFO PREFIX "New style SDC\n");
984 		tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
985 		tq_init.actidx		= 0;
986 		tq_init.idx		= 1;
987 		down(&tq_init_sem);
988 		hp_sdc_enqueue_transaction(&tq_init);
989 		down(&tq_init_sem);
990 		up(&tq_init_sem);
991 		if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
992 			printk(KERN_WARNING PREFIX "Error reading extended config byte.\n");
993 			return -ENODEV;
994 		}
995 		hp_sdc.r7e = tq_init_seq[4];
996 		HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
997 		printk(KERN_INFO PREFIX "Revision: %s\n", str);
998 		if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) {
999 			printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
1000 		}
1001 		if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) {
1002 			printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
1003 		}
1004 		printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
1005 		       "on next firmware reset.\n");
1006 		tq_init_seq[0] = HP_SDC_ACT_PRECMD |
1007 			HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
1008 		tq_init_seq[1] = HP_SDC_CMD_SET_STR;
1009 		tq_init_seq[2] = 1;
1010 		tq_init_seq[3] = 0;
1011 		tq_init.actidx		= 0;
1012 		tq_init.idx		= 1;
1013 		tq_init.endidx		= 4;
1014 		down(&tq_init_sem);
1015 		hp_sdc_enqueue_transaction(&tq_init);
1016 		down(&tq_init_sem);
1017 		up(&tq_init_sem);
1018 	}
1019 	else {
1020 		printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
1021 		       (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
1022 	}
1023 
1024         return 0;
1025 }
1026 
1027 module_init(hp_sdc_register);
1028 module_exit(hp_sdc_exit);
1029 
1030 /* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64)
1031  *                                              cycles cycles-adj    time
1032  * between two consecutive mfctl(16)'s:              4        n/a    63ns
1033  * hp_sdc_spin_ibf when idle:                      119        115   1.7us
1034  * gsc_writeb status register:                      83         79   1.2us
1035  * IBF to clear after sending SET_IM:             6204       6006    93us
1036  * IBF to clear after sending LOAD_RT:            4467       4352    68us
1037  * IBF to clear after sending two LOAD_RTs:      18974      18859   295us
1038  * READ_T1, read status/data, IRQ, call handler: 35564        n/a   556us
1039  * cmd to ~IBF READ_T1 2nd time right after:   5158403        n/a    81ms
1040  * between IRQ received and ~IBF for above:    2578877        n/a    40ms
1041  *
1042  * Performance stats after a run of this module configuring HIL and
1043  * receiving a few mouse events:
1044  *
1045  * status in8  282508 cycles 7128 calls
1046  * status out8   8404 cycles  341 calls
1047  * data out8     1734 cycles   78 calls
1048  * isr         174324 cycles  617 calls (includes take)
1049  * take          1241 cycles    2 calls
1050  * put        1411504 cycles 6937 calls
1051  * task       1655209 cycles 6937 calls (includes put)
1052  *
1053  */
1054