aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/hp_sdc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/serio/hp_sdc.c')
-rw-r--r--drivers/input/serio/hp_sdc.c427
1 files changed, 241 insertions, 186 deletions
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index b57370dc4e3d..6af199805ffc 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -34,27 +34,27 @@
34 * 34 *
35 * Driver theory of operation: 35 * Driver theory of operation:
36 * 36 *
37 * hp_sdc_put does all writing to the SDC. ISR can run on a different 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 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. 39 * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly.
40 * 40 *
41 * All data coming back from the SDC is sent via interrupt and can be read 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. 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 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, 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, 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 46 * keeping outbound throughput flowing at the 6500KBps that the HIL is
47 * capable of is more than can be done at HZ=100. 47 * capable of is more than can be done at HZ=100.
48 * 48 *
49 * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf 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 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 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 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. 53 * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
54 * 54 *
55 * The i8042 write index and the values in the 4-byte input buffer 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, 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 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. 58 * do not need to be locked since they are only ever accessed by hp_sdc_put.
59 * 59 *
60 * A timer task schedules the tasklet once per second just to make 60 * A timer task schedules the tasklet once per second just to make
@@ -100,39 +100,46 @@ EXPORT_SYMBOL(hp_sdc_release_timer_irq);
100EXPORT_SYMBOL(hp_sdc_release_hil_irq); 100EXPORT_SYMBOL(hp_sdc_release_hil_irq);
101EXPORT_SYMBOL(hp_sdc_release_cooked_irq); 101EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
102 102
103EXPORT_SYMBOL(__hp_sdc_enqueue_transaction);
103EXPORT_SYMBOL(hp_sdc_enqueue_transaction); 104EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
104EXPORT_SYMBOL(hp_sdc_dequeue_transaction); 105EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
105 106
106static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */ 107static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */
107 108
108/*************** primitives for use in any context *********************/ 109/*************** primitives for use in any context *********************/
109static inline uint8_t hp_sdc_status_in8 (void) { 110static inline uint8_t hp_sdc_status_in8(void)
111{
110 uint8_t status; 112 uint8_t status;
111 unsigned long flags; 113 unsigned long flags;
112 114
113 write_lock_irqsave(&hp_sdc.ibf_lock, flags); 115 write_lock_irqsave(&hp_sdc.ibf_lock, flags);
114 status = sdc_readb(hp_sdc.status_io); 116 status = sdc_readb(hp_sdc.status_io);
115 if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0; 117 if (!(status & HP_SDC_STATUS_IBF))
118 hp_sdc.ibf = 0;
116 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); 119 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
117 120
118 return status; 121 return status;
119} 122}
120 123
121static inline uint8_t hp_sdc_data_in8 (void) { 124static inline uint8_t hp_sdc_data_in8(void)
122 return sdc_readb(hp_sdc.data_io); 125{
126 return sdc_readb(hp_sdc.data_io);
123} 127}
124 128
125static inline void hp_sdc_status_out8 (uint8_t val) { 129static inline void hp_sdc_status_out8(uint8_t val)
130{
126 unsigned long flags; 131 unsigned long flags;
127 132
128 write_lock_irqsave(&hp_sdc.ibf_lock, flags); 133 write_lock_irqsave(&hp_sdc.ibf_lock, flags);
129 hp_sdc.ibf = 1; 134 hp_sdc.ibf = 1;
130 if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff; 135 if ((val & 0xf0) == 0xe0)
136 hp_sdc.wi = 0xff;
131 sdc_writeb(val, hp_sdc.status_io); 137 sdc_writeb(val, hp_sdc.status_io);
132 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); 138 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
133} 139}
134 140
135static inline void hp_sdc_data_out8 (uint8_t val) { 141static inline void hp_sdc_data_out8(uint8_t val)
142{
136 unsigned long flags; 143 unsigned long flags;
137 144
138 write_lock_irqsave(&hp_sdc.ibf_lock, flags); 145 write_lock_irqsave(&hp_sdc.ibf_lock, flags);
@@ -141,11 +148,12 @@ static inline void hp_sdc_data_out8 (uint8_t val) {
141 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); 148 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
142} 149}
143 150
144/* Care must be taken to only invoke hp_sdc_spin_ibf when 151/* Care must be taken to only invoke hp_sdc_spin_ibf when
145 * absolutely needed, or in rarely invoked subroutines. 152 * absolutely needed, or in rarely invoked subroutines.
146 * Not only does it waste CPU cycles, it also wastes bus cycles. 153 * Not only does it waste CPU cycles, it also wastes bus cycles.
147 */ 154 */
148static inline void hp_sdc_spin_ibf(void) { 155static inline void hp_sdc_spin_ibf(void)
156{
149 unsigned long flags; 157 unsigned long flags;
150 rwlock_t *lock; 158 rwlock_t *lock;
151 159
@@ -158,19 +166,21 @@ static inline void hp_sdc_spin_ibf(void) {
158 } 166 }
159 read_unlock(lock); 167 read_unlock(lock);
160 write_lock(lock); 168 write_lock(lock);
161 while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {}; 169 while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF)
170 { }
162 hp_sdc.ibf = 0; 171 hp_sdc.ibf = 0;
163 write_unlock_irqrestore(lock, flags); 172 write_unlock_irqrestore(lock, flags);
164} 173}
165 174
166 175
167/************************ Interrupt context functions ************************/ 176/************************ Interrupt context functions ************************/
168static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) { 177static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data)
178{
169 hp_sdc_transaction *curr; 179 hp_sdc_transaction *curr;
170 180
171 read_lock(&hp_sdc.rtq_lock); 181 read_lock(&hp_sdc.rtq_lock);
172 if (hp_sdc.rcurr < 0) { 182 if (hp_sdc.rcurr < 0) {
173 read_unlock(&hp_sdc.rtq_lock); 183 read_unlock(&hp_sdc.rtq_lock);
174 return; 184 return;
175 } 185 }
176 curr = hp_sdc.tq[hp_sdc.rcurr]; 186 curr = hp_sdc.tq[hp_sdc.rcurr];
@@ -183,25 +193,27 @@ static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
183 193
184 if (hp_sdc.rqty <= 0) { 194 if (hp_sdc.rqty <= 0) {
185 /* All data has been gathered. */ 195 /* All data has been gathered. */
186 if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) { 196 if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE)
187 if (curr->act.semaphore) up(curr->act.semaphore); 197 if (curr->act.semaphore)
188 } 198 up(curr->act.semaphore);
189 if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) { 199
200 if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK)
190 if (curr->act.irqhook) 201 if (curr->act.irqhook)
191 curr->act.irqhook(irq, dev_id, status, data); 202 curr->act.irqhook(irq, dev_id, status, data);
192 } 203
193 curr->actidx = curr->idx; 204 curr->actidx = curr->idx;
194 curr->idx++; 205 curr->idx++;
195 /* Return control of this transaction */ 206 /* Return control of this transaction */
196 write_lock(&hp_sdc.rtq_lock); 207 write_lock(&hp_sdc.rtq_lock);
197 hp_sdc.rcurr = -1; 208 hp_sdc.rcurr = -1;
198 hp_sdc.rqty = 0; 209 hp_sdc.rqty = 0;
199 write_unlock(&hp_sdc.rtq_lock); 210 write_unlock(&hp_sdc.rtq_lock);
200 tasklet_schedule(&hp_sdc.task); 211 tasklet_schedule(&hp_sdc.task);
201 } 212 }
202} 213}
203 214
204static irqreturn_t hp_sdc_isr(int irq, void *dev_id) { 215static irqreturn_t hp_sdc_isr(int irq, void *dev_id)
216{
205 uint8_t status, data; 217 uint8_t status, data;
206 218
207 status = hp_sdc_status_in8(); 219 status = hp_sdc_status_in8();
@@ -209,67 +221,74 @@ static irqreturn_t hp_sdc_isr(int irq, void *dev_id) {
209 data = hp_sdc_data_in8(); 221 data = hp_sdc_data_in8();
210 222
211 /* For now we are ignoring these until we get the SDC to behave. */ 223 /* For now we are ignoring these until we get the SDC to behave. */
212 if (((status & 0xf1) == 0x51) && data == 0x82) { 224 if (((status & 0xf1) == 0x51) && data == 0x82)
213 return IRQ_HANDLED; 225 return IRQ_HANDLED;
214 }
215 226
216 switch(status & HP_SDC_STATUS_IRQMASK) { 227 switch (status & HP_SDC_STATUS_IRQMASK) {
217 case 0: /* This case is not documented. */ 228 case 0: /* This case is not documented. */
218 break; 229 break;
219 case HP_SDC_STATUS_USERTIMER: 230
220 case HP_SDC_STATUS_PERIODIC: 231 case HP_SDC_STATUS_USERTIMER:
221 case HP_SDC_STATUS_TIMER: 232 case HP_SDC_STATUS_PERIODIC:
233 case HP_SDC_STATUS_TIMER:
222 read_lock(&hp_sdc.hook_lock); 234 read_lock(&hp_sdc.hook_lock);
223 if (hp_sdc.timer != NULL) 235 if (hp_sdc.timer != NULL)
224 hp_sdc.timer(irq, dev_id, status, data); 236 hp_sdc.timer(irq, dev_id, status, data);
225 read_unlock(&hp_sdc.hook_lock); 237 read_unlock(&hp_sdc.hook_lock);
226 break; 238 break;
227 case HP_SDC_STATUS_REG: 239
240 case HP_SDC_STATUS_REG:
228 hp_sdc_take(irq, dev_id, status, data); 241 hp_sdc_take(irq, dev_id, status, data);
229 break; 242 break;
230 case HP_SDC_STATUS_HILCMD: 243
231 case HP_SDC_STATUS_HILDATA: 244 case HP_SDC_STATUS_HILCMD:
245 case HP_SDC_STATUS_HILDATA:
232 read_lock(&hp_sdc.hook_lock); 246 read_lock(&hp_sdc.hook_lock);
233 if (hp_sdc.hil != NULL) 247 if (hp_sdc.hil != NULL)
234 hp_sdc.hil(irq, dev_id, status, data); 248 hp_sdc.hil(irq, dev_id, status, data);
235 read_unlock(&hp_sdc.hook_lock); 249 read_unlock(&hp_sdc.hook_lock);
236 break; 250 break;
237 case HP_SDC_STATUS_PUP: 251
252 case HP_SDC_STATUS_PUP:
238 read_lock(&hp_sdc.hook_lock); 253 read_lock(&hp_sdc.hook_lock);
239 if (hp_sdc.pup != NULL) 254 if (hp_sdc.pup != NULL)
240 hp_sdc.pup(irq, dev_id, status, data); 255 hp_sdc.pup(irq, dev_id, status, data);
241 else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n"); 256 else
257 printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
242 read_unlock(&hp_sdc.hook_lock); 258 read_unlock(&hp_sdc.hook_lock);
243 break; 259 break;
244 default: 260
261 default:
245 read_lock(&hp_sdc.hook_lock); 262 read_lock(&hp_sdc.hook_lock);
246 if (hp_sdc.cooked != NULL) 263 if (hp_sdc.cooked != NULL)
247 hp_sdc.cooked(irq, dev_id, status, data); 264 hp_sdc.cooked(irq, dev_id, status, data);
248 read_unlock(&hp_sdc.hook_lock); 265 read_unlock(&hp_sdc.hook_lock);
249 break; 266 break;
250 } 267 }
268
251 return IRQ_HANDLED; 269 return IRQ_HANDLED;
252} 270}
253 271
254 272
255static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) { 273static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id)
274{
256 int status; 275 int status;
257 276
258 status = hp_sdc_status_in8(); 277 status = hp_sdc_status_in8();
259 printk(KERN_WARNING PREFIX "NMI !\n"); 278 printk(KERN_WARNING PREFIX "NMI !\n");
260 279
261#if 0 280#if 0
262 if (status & HP_SDC_NMISTATUS_FHS) { 281 if (status & HP_SDC_NMISTATUS_FHS) {
263 read_lock(&hp_sdc.hook_lock); 282 read_lock(&hp_sdc.hook_lock);
264 if (hp_sdc.timer != NULL) 283 if (hp_sdc.timer != NULL)
265 hp_sdc.timer(irq, dev_id, status, 0); 284 hp_sdc.timer(irq, dev_id, status, 0);
266 read_unlock(&hp_sdc.hook_lock); 285 read_unlock(&hp_sdc.hook_lock);
267 } 286 } else {
268 else {
269 /* TODO: pass this on to the HIL handler, or do SAK here? */ 287 /* TODO: pass this on to the HIL handler, or do SAK here? */
270 printk(KERN_WARNING PREFIX "HIL NMI\n"); 288 printk(KERN_WARNING PREFIX "HIL NMI\n");
271 } 289 }
272#endif 290#endif
291
273 return IRQ_HANDLED; 292 return IRQ_HANDLED;
274} 293}
275 294
@@ -278,13 +297,17 @@ static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) {
278 297
279unsigned long hp_sdc_put(void); 298unsigned long hp_sdc_put(void);
280 299
281static void hp_sdc_tasklet(unsigned long foo) { 300static void hp_sdc_tasklet(unsigned long foo)
282 301{
283 write_lock_irq(&hp_sdc.rtq_lock); 302 write_lock_irq(&hp_sdc.rtq_lock);
303
284 if (hp_sdc.rcurr >= 0) { 304 if (hp_sdc.rcurr >= 0) {
285 struct timeval tv; 305 struct timeval tv;
306
286 do_gettimeofday(&tv); 307 do_gettimeofday(&tv);
287 if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000; 308 if (tv.tv_sec > hp_sdc.rtv.tv_sec)
309 tv.tv_usec += USEC_PER_SEC;
310
288 if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) { 311 if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
289 hp_sdc_transaction *curr; 312 hp_sdc_transaction *curr;
290 uint8_t tmp; 313 uint8_t tmp;
@@ -300,27 +323,29 @@ static void hp_sdc_tasklet(unsigned long foo) {
300 hp_sdc.rqty = 0; 323 hp_sdc.rqty = 0;
301 tmp = curr->seq[curr->actidx]; 324 tmp = curr->seq[curr->actidx];
302 curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD; 325 curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
303 if(tmp & HP_SDC_ACT_SEMAPHORE) { 326 if (tmp & HP_SDC_ACT_SEMAPHORE)
304 if (curr->act.semaphore) 327 if (curr->act.semaphore)
305 up(curr->act.semaphore); 328 up(curr->act.semaphore);
306 } 329
307 if(tmp & HP_SDC_ACT_CALLBACK) { 330 if (tmp & HP_SDC_ACT_CALLBACK) {
308 /* Note this means that irqhooks may be called 331 /* Note this means that irqhooks may be called
309 * in tasklet/bh context. 332 * in tasklet/bh context.
310 */ 333 */
311 if (curr->act.irqhook) 334 if (curr->act.irqhook)
312 curr->act.irqhook(0, NULL, 0, 0); 335 curr->act.irqhook(0, NULL, 0, 0);
313 } 336 }
337
314 curr->actidx = curr->idx; 338 curr->actidx = curr->idx;
315 curr->idx++; 339 curr->idx++;
316 hp_sdc.rcurr = -1; 340 hp_sdc.rcurr = -1;
317 } 341 }
318 } 342 }
319 write_unlock_irq(&hp_sdc.rtq_lock); 343 write_unlock_irq(&hp_sdc.rtq_lock);
320 hp_sdc_put(); 344 hp_sdc_put();
321} 345}
322 346
323unsigned long hp_sdc_put(void) { 347unsigned long hp_sdc_put(void)
348{
324 hp_sdc_transaction *curr; 349 hp_sdc_transaction *curr;
325 uint8_t act; 350 uint8_t act;
326 int idx, curridx; 351 int idx, curridx;
@@ -333,19 +358,24 @@ unsigned long hp_sdc_put(void) {
333 requires output, so we skip to the administrativa. */ 358 requires output, so we skip to the administrativa. */
334 if (hp_sdc.ibf) { 359 if (hp_sdc.ibf) {
335 hp_sdc_status_in8(); 360 hp_sdc_status_in8();
336 if (hp_sdc.ibf) goto finish; 361 if (hp_sdc.ibf)
362 goto finish;
337 } 363 }
338 364
339 anew: 365 anew:
340 /* See if we are in the middle of a sequence. */ 366 /* See if we are in the middle of a sequence. */
341 if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0; 367 if (hp_sdc.wcurr < 0)
368 hp_sdc.wcurr = 0;
342 read_lock_irq(&hp_sdc.rtq_lock); 369 read_lock_irq(&hp_sdc.rtq_lock);
343 if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++; 370 if (hp_sdc.rcurr == hp_sdc.wcurr)
371 hp_sdc.wcurr++;
344 read_unlock_irq(&hp_sdc.rtq_lock); 372 read_unlock_irq(&hp_sdc.rtq_lock);
345 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; 373 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
374 hp_sdc.wcurr = 0;
346 curridx = hp_sdc.wcurr; 375 curridx = hp_sdc.wcurr;
347 376
348 if (hp_sdc.tq[curridx] != NULL) goto start; 377 if (hp_sdc.tq[curridx] != NULL)
378 goto start;
349 379
350 while (++curridx != hp_sdc.wcurr) { 380 while (++curridx != hp_sdc.wcurr) {
351 if (curridx >= HP_SDC_QUEUE_LEN) { 381 if (curridx >= HP_SDC_QUEUE_LEN) {
@@ -358,7 +388,8 @@ unsigned long hp_sdc_put(void) {
358 continue; 388 continue;
359 } 389 }
360 read_unlock_irq(&hp_sdc.rtq_lock); 390 read_unlock_irq(&hp_sdc.rtq_lock);
361 if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */ 391 if (hp_sdc.tq[curridx] != NULL)
392 break; /* Found one. */
362 } 393 }
363 if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */ 394 if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
364 curridx = -1; 395 curridx = -1;
@@ -374,7 +405,8 @@ unsigned long hp_sdc_put(void) {
374 goto finish; 405 goto finish;
375 } 406 }
376 407
377 if (hp_sdc.wcurr == -1) goto done; 408 if (hp_sdc.wcurr == -1)
409 goto done;
378 410
379 curr = hp_sdc.tq[curridx]; 411 curr = hp_sdc.tq[curridx];
380 idx = curr->actidx; 412 idx = curr->actidx;
@@ -383,20 +415,23 @@ unsigned long hp_sdc_put(void) {
383 hp_sdc.tq[curridx] = NULL; 415 hp_sdc.tq[curridx] = NULL;
384 /* Interleave outbound data between the transactions. */ 416 /* Interleave outbound data between the transactions. */
385 hp_sdc.wcurr++; 417 hp_sdc.wcurr++;
386 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; 418 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
387 goto finish; 419 hp_sdc.wcurr = 0;
420 goto finish;
388 } 421 }
389 422
390 act = curr->seq[idx]; 423 act = curr->seq[idx];
391 idx++; 424 idx++;
392 425
393 if (curr->idx >= curr->endidx) { 426 if (curr->idx >= curr->endidx) {
394 if (act & HP_SDC_ACT_DEALLOC) kfree(curr); 427 if (act & HP_SDC_ACT_DEALLOC)
428 kfree(curr);
395 hp_sdc.tq[curridx] = NULL; 429 hp_sdc.tq[curridx] = NULL;
396 /* Interleave outbound data between the transactions. */ 430 /* Interleave outbound data between the transactions. */
397 hp_sdc.wcurr++; 431 hp_sdc.wcurr++;
398 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; 432 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
399 goto finish; 433 hp_sdc.wcurr = 0;
434 goto finish;
400 } 435 }
401 436
402 while (act & HP_SDC_ACT_PRECMD) { 437 while (act & HP_SDC_ACT_PRECMD) {
@@ -409,9 +444,10 @@ unsigned long hp_sdc_put(void) {
409 curr->idx++; 444 curr->idx++;
410 /* act finished? */ 445 /* act finished? */
411 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD) 446 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
412 goto actdone; 447 goto actdone;
413 /* skip quantity field if data-out sequence follows. */ 448 /* skip quantity field if data-out sequence follows. */
414 if (act & HP_SDC_ACT_DATAOUT) curr->idx++; 449 if (act & HP_SDC_ACT_DATAOUT)
450 curr->idx++;
415 goto finish; 451 goto finish;
416 } 452 }
417 if (act & HP_SDC_ACT_DATAOUT) { 453 if (act & HP_SDC_ACT_DATAOUT) {
@@ -423,15 +459,15 @@ unsigned long hp_sdc_put(void) {
423 hp_sdc_data_out8(curr->seq[curr->idx]); 459 hp_sdc_data_out8(curr->seq[curr->idx]);
424 curr->idx++; 460 curr->idx++;
425 /* act finished? */ 461 /* act finished? */
426 if ((curr->idx - idx >= qty) && 462 if (curr->idx - idx >= qty &&
427 ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)) 463 (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT)
428 goto actdone; 464 goto actdone;
429 goto finish; 465 goto finish;
430 } 466 }
431 idx += qty; 467 idx += qty;
432 act &= ~HP_SDC_ACT_DATAOUT; 468 act &= ~HP_SDC_ACT_DATAOUT;
433 } 469 } else
434 else while (act & HP_SDC_ACT_DATAREG) { 470 while (act & HP_SDC_ACT_DATAREG) {
435 int mask; 471 int mask;
436 uint8_t w7[4]; 472 uint8_t w7[4];
437 473
@@ -445,26 +481,30 @@ unsigned long hp_sdc_put(void) {
445 act &= ~HP_SDC_ACT_DATAREG; 481 act &= ~HP_SDC_ACT_DATAREG;
446 break; 482 break;
447 } 483 }
448 484
449 w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0]; 485 w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
450 w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1]; 486 w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
451 w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2]; 487 w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
452 w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3]; 488 w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
453 489
454 if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 || 490 if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
455 w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) { 491 w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) {
456 int i = 0; 492 int i = 0;
457 493
458 /* Need to point the write index register */ 494 /* Need to point the write index register */
459 while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; 495 while (i < 4 && w7[i] == hp_sdc.r7[i])
496 i++;
497
460 if (i < 4) { 498 if (i < 4) {
461 hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i); 499 hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
462 hp_sdc.wi = 0x70 + i; 500 hp_sdc.wi = 0x70 + i;
463 goto finish; 501 goto finish;
464 } 502 }
503
465 idx++; 504 idx++;
466 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG) 505 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
467 goto actdone; 506 goto actdone;
507
468 curr->idx = idx; 508 curr->idx = idx;
469 act &= ~HP_SDC_ACT_DATAREG; 509 act &= ~HP_SDC_ACT_DATAREG;
470 break; 510 break;
@@ -476,12 +516,13 @@ unsigned long hp_sdc_put(void) {
476 { 516 {
477 int i = 0; 517 int i = 0;
478 518
479 while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++; 519 while ((i < 4) && w7[i] == hp_sdc.r7[i])
520 i++;
480 if (i >= 4) { 521 if (i >= 4) {
481 curr->idx = idx + 1; 522 curr->idx = idx + 1;
482 if ((act & HP_SDC_ACT_DURING) == 523 if ((act & HP_SDC_ACT_DURING) ==
483 HP_SDC_ACT_DATAREG) 524 HP_SDC_ACT_DATAREG)
484 goto actdone; 525 goto actdone;
485 } 526 }
486 } 527 }
487 goto finish; 528 goto finish;
@@ -497,7 +538,7 @@ unsigned long hp_sdc_put(void) {
497 538
498 539
499 if (act & HP_SDC_ACT_POSTCMD) { 540 if (act & HP_SDC_ACT_POSTCMD) {
500 uint8_t postcmd; 541 uint8_t postcmd;
501 542
502 /* curr->idx should == idx at this point. */ 543 /* curr->idx should == idx at this point. */
503 postcmd = curr->seq[idx]; 544 postcmd = curr->seq[idx];
@@ -505,12 +546,12 @@ unsigned long hp_sdc_put(void) {
505 if (act & HP_SDC_ACT_DATAIN) { 546 if (act & HP_SDC_ACT_DATAIN) {
506 547
507 /* Start a new read */ 548 /* Start a new read */
508 hp_sdc.rqty = curr->seq[curr->idx]; 549 hp_sdc.rqty = curr->seq[curr->idx];
509 do_gettimeofday(&hp_sdc.rtv); 550 do_gettimeofday(&hp_sdc.rtv);
510 curr->idx++; 551 curr->idx++;
511 /* Still need to lock here in case of spurious irq. */ 552 /* Still need to lock here in case of spurious irq. */
512 write_lock_irq(&hp_sdc.rtq_lock); 553 write_lock_irq(&hp_sdc.rtq_lock);
513 hp_sdc.rcurr = curridx; 554 hp_sdc.rcurr = curridx;
514 write_unlock_irq(&hp_sdc.rtq_lock); 555 write_unlock_irq(&hp_sdc.rtq_lock);
515 hp_sdc_status_out8(postcmd); 556 hp_sdc_status_out8(postcmd);
516 goto finish; 557 goto finish;
@@ -519,75 +560,86 @@ unsigned long hp_sdc_put(void) {
519 goto actdone; 560 goto actdone;
520 } 561 }
521 562
522actdone: 563 actdone:
523 if (act & HP_SDC_ACT_SEMAPHORE) { 564 if (act & HP_SDC_ACT_SEMAPHORE)
524 up(curr->act.semaphore); 565 up(curr->act.semaphore);
525 } 566 else if (act & HP_SDC_ACT_CALLBACK)
526 else if (act & HP_SDC_ACT_CALLBACK) {
527 curr->act.irqhook(0,NULL,0,0); 567 curr->act.irqhook(0,NULL,0,0);
528 } 568
529 if (curr->idx >= curr->endidx) { /* This transaction is over. */ 569 if (curr->idx >= curr->endidx) { /* This transaction is over. */
530 if (act & HP_SDC_ACT_DEALLOC) kfree(curr); 570 if (act & HP_SDC_ACT_DEALLOC)
571 kfree(curr);
531 hp_sdc.tq[curridx] = NULL; 572 hp_sdc.tq[curridx] = NULL;
532 } 573 } else {
533 else {
534 curr->actidx = idx + 1; 574 curr->actidx = idx + 1;
535 curr->idx = idx + 2; 575 curr->idx = idx + 2;
536 } 576 }
537 /* Interleave outbound data between the transactions. */ 577 /* Interleave outbound data between the transactions. */
538 hp_sdc.wcurr++; 578 hp_sdc.wcurr++;
539 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0; 579 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN)
580 hp_sdc.wcurr = 0;
540 581
541 finish: 582 finish:
542 /* If by some quirk IBF has cleared and our ISR has run to 583 /* If by some quirk IBF has cleared and our ISR has run to
543 see that that has happened, do it all again. */ 584 see that that has happened, do it all again. */
544 if (!hp_sdc.ibf && limit++ < 20) goto anew; 585 if (!hp_sdc.ibf && limit++ < 20)
586 goto anew;
545 587
546 done: 588 done:
547 if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task); 589 if (hp_sdc.wcurr >= 0)
590 tasklet_schedule(&hp_sdc.task);
548 write_unlock(&hp_sdc.lock); 591 write_unlock(&hp_sdc.lock);
592
549 return 0; 593 return 0;
550} 594}
551 595
552/******* Functions called in either user or kernel context ****/ 596/******* Functions called in either user or kernel context ****/
553int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) { 597int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this)
554 unsigned long flags; 598{
555 int i; 599 int i;
556 600
557 if (this == NULL) { 601 if (this == NULL) {
558 tasklet_schedule(&hp_sdc.task); 602 BUG();
559 return -EINVAL; 603 return -EINVAL;
560 }; 604 }
561
562 write_lock_irqsave(&hp_sdc.lock, flags);
563 605
564 /* Can't have same transaction on queue twice */ 606 /* Can't have same transaction on queue twice */
565 for (i=0; i < HP_SDC_QUEUE_LEN; i++) 607 for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
566 if (hp_sdc.tq[i] == this) goto fail; 608 if (hp_sdc.tq[i] == this)
609 goto fail;
567 610
568 this->actidx = 0; 611 this->actidx = 0;
569 this->idx = 1; 612 this->idx = 1;
570 613
571 /* Search for empty slot */ 614 /* Search for empty slot */
572 for (i=0; i < HP_SDC_QUEUE_LEN; i++) { 615 for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
573 if (hp_sdc.tq[i] == NULL) { 616 if (hp_sdc.tq[i] == NULL) {
574 hp_sdc.tq[i] = this; 617 hp_sdc.tq[i] = this;
575 write_unlock_irqrestore(&hp_sdc.lock, flags);
576 tasklet_schedule(&hp_sdc.task); 618 tasklet_schedule(&hp_sdc.task);
577 return 0; 619 return 0;
578 } 620 }
579 } 621
580 write_unlock_irqrestore(&hp_sdc.lock, flags);
581 printk(KERN_WARNING PREFIX "No free slot to add transaction.\n"); 622 printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
582 return -EBUSY; 623 return -EBUSY;
583 624
584 fail: 625 fail:
585 write_unlock_irqrestore(&hp_sdc.lock,flags);
586 printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n"); 626 printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
587 return -EINVAL; 627 return -EINVAL;
588} 628}
589 629
590int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) { 630int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
631 unsigned long flags;
632 int ret;
633
634 write_lock_irqsave(&hp_sdc.lock, flags);
635 ret = __hp_sdc_enqueue_transaction(this);
636 write_unlock_irqrestore(&hp_sdc.lock,flags);
637
638 return ret;
639}
640
641int hp_sdc_dequeue_transaction(hp_sdc_transaction *this)
642{
591 unsigned long flags; 643 unsigned long flags;
592 int i; 644 int i;
593 645
@@ -595,8 +647,9 @@ int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
595 647
596 /* TODO: don't remove it if it's not done. */ 648 /* TODO: don't remove it if it's not done. */
597 649
598 for (i=0; i < HP_SDC_QUEUE_LEN; i++) 650 for (i = 0; i < HP_SDC_QUEUE_LEN; i++)
599 if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL; 651 if (hp_sdc.tq[i] == this)
652 hp_sdc.tq[i] = NULL;
600 653
601 write_unlock_irqrestore(&hp_sdc.lock, flags); 654 write_unlock_irqrestore(&hp_sdc.lock, flags);
602 return 0; 655 return 0;
@@ -605,11 +658,11 @@ int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
605 658
606 659
607/********************** User context functions **************************/ 660/********************** User context functions **************************/
608int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) { 661int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback)
609 662{
610 if (callback == NULL || hp_sdc.dev == NULL) { 663 if (callback == NULL || hp_sdc.dev == NULL)
611 return -EINVAL; 664 return -EINVAL;
612 } 665
613 write_lock_irq(&hp_sdc.hook_lock); 666 write_lock_irq(&hp_sdc.hook_lock);
614 if (hp_sdc.timer != NULL) { 667 if (hp_sdc.timer != NULL) {
615 write_unlock_irq(&hp_sdc.hook_lock); 668 write_unlock_irq(&hp_sdc.hook_lock);
@@ -629,11 +682,11 @@ int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
629 return 0; 682 return 0;
630} 683}
631 684
632int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) { 685int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback)
633 686{
634 if (callback == NULL || hp_sdc.dev == NULL) { 687 if (callback == NULL || hp_sdc.dev == NULL)
635 return -EINVAL; 688 return -EINVAL;
636 } 689
637 write_lock_irq(&hp_sdc.hook_lock); 690 write_lock_irq(&hp_sdc.hook_lock);
638 if (hp_sdc.hil != NULL) { 691 if (hp_sdc.hil != NULL) {
639 write_unlock_irq(&hp_sdc.hook_lock); 692 write_unlock_irq(&hp_sdc.hook_lock);
@@ -650,11 +703,11 @@ int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
650 return 0; 703 return 0;
651} 704}
652 705
653int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) { 706int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback)
654 707{
655 if (callback == NULL || hp_sdc.dev == NULL) { 708 if (callback == NULL || hp_sdc.dev == NULL)
656 return -EINVAL; 709 return -EINVAL;
657 } 710
658 write_lock_irq(&hp_sdc.hook_lock); 711 write_lock_irq(&hp_sdc.hook_lock);
659 if (hp_sdc.cooked != NULL) { 712 if (hp_sdc.cooked != NULL) {
660 write_unlock_irq(&hp_sdc.hook_lock); 713 write_unlock_irq(&hp_sdc.hook_lock);
@@ -672,9 +725,8 @@ int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
672 return 0; 725 return 0;
673} 726}
674 727
675int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) { 728int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback)
676 729{
677
678 write_lock_irq(&hp_sdc.hook_lock); 730 write_lock_irq(&hp_sdc.hook_lock);
679 if ((callback != hp_sdc.timer) || 731 if ((callback != hp_sdc.timer) ||
680 (hp_sdc.timer == NULL)) { 732 (hp_sdc.timer == NULL)) {
@@ -694,8 +746,8 @@ int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
694 return 0; 746 return 0;
695} 747}
696 748
697int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) { 749int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback)
698 750{
699 write_lock_irq(&hp_sdc.hook_lock); 751 write_lock_irq(&hp_sdc.hook_lock);
700 if ((callback != hp_sdc.hil) || 752 if ((callback != hp_sdc.hil) ||
701 (hp_sdc.hil == NULL)) { 753 (hp_sdc.hil == NULL)) {
@@ -715,8 +767,8 @@ int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
715 return 0; 767 return 0;
716} 768}
717 769
718int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) { 770int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback)
719 771{
720 write_lock_irq(&hp_sdc.hook_lock); 772 write_lock_irq(&hp_sdc.hook_lock);
721 if ((callback != hp_sdc.cooked) || 773 if ((callback != hp_sdc.cooked) ||
722 (hp_sdc.cooked == NULL)) { 774 (hp_sdc.cooked == NULL)) {
@@ -738,7 +790,8 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
738 790
739/************************* Keepalive timer task *********************/ 791/************************* Keepalive timer task *********************/
740 792
741void hp_sdc_kicker (unsigned long data) { 793void hp_sdc_kicker (unsigned long data)
794{
742 tasklet_schedule(&hp_sdc.task); 795 tasklet_schedule(&hp_sdc.task);
743 /* Re-insert the periodic task. */ 796 /* Re-insert the periodic task. */
744 mod_timer(&hp_sdc.kicker, jiffies + HZ); 797 mod_timer(&hp_sdc.kicker, jiffies + HZ);
@@ -748,12 +801,12 @@ void hp_sdc_kicker (unsigned long data) {
748 801
749#if defined(__hppa__) 802#if defined(__hppa__)
750 803
751static struct parisc_device_id hp_sdc_tbl[] = { 804static const struct parisc_device_id hp_sdc_tbl[] = {
752 { 805 {
753 .hw_type = HPHW_FIO, 806 .hw_type = HPHW_FIO,
754 .hversion_rev = HVERSION_REV_ANY_ID, 807 .hversion_rev = HVERSION_REV_ANY_ID,
755 .hversion = HVERSION_ANY_ID, 808 .hversion = HVERSION_ANY_ID,
756 .sversion = 0x73, 809 .sversion = 0x73,
757 }, 810 },
758 { 0, } 811 { 0, }
759}; 812};
@@ -772,16 +825,15 @@ static struct parisc_driver hp_sdc_driver = {
772 825
773static int __init hp_sdc_init(void) 826static int __init hp_sdc_init(void)
774{ 827{
775 int i;
776 char *errstr; 828 char *errstr;
777 hp_sdc_transaction t_sync; 829 hp_sdc_transaction t_sync;
778 uint8_t ts_sync[6]; 830 uint8_t ts_sync[6];
779 struct semaphore s_sync; 831 struct semaphore s_sync;
780 832
781 rwlock_init(&hp_sdc.lock); 833 rwlock_init(&hp_sdc.lock);
782 rwlock_init(&hp_sdc.ibf_lock); 834 rwlock_init(&hp_sdc.ibf_lock);
783 rwlock_init(&hp_sdc.rtq_lock); 835 rwlock_init(&hp_sdc.rtq_lock);
784 rwlock_init(&hp_sdc.hook_lock); 836 rwlock_init(&hp_sdc.hook_lock);
785 837
786 hp_sdc.timer = NULL; 838 hp_sdc.timer = NULL;
787 hp_sdc.hil = NULL; 839 hp_sdc.hil = NULL;
@@ -796,7 +848,8 @@ static int __init hp_sdc_init(void)
796 hp_sdc.r7[3] = 0xff; 848 hp_sdc.r7[3] = 0xff;
797 hp_sdc.ibf = 1; 849 hp_sdc.ibf = 1;
798 850
799 for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL; 851 memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq));
852
800 hp_sdc.wcurr = -1; 853 hp_sdc.wcurr = -1;
801 hp_sdc.rcurr = -1; 854 hp_sdc.rcurr = -1;
802 hp_sdc.rqty = 0; 855 hp_sdc.rqty = 0;
@@ -804,27 +857,32 @@ static int __init hp_sdc_init(void)
804 hp_sdc.dev_err = -ENODEV; 857 hp_sdc.dev_err = -ENODEV;
805 858
806 errstr = "IO not found for"; 859 errstr = "IO not found for";
807 if (!hp_sdc.base_io) goto err0; 860 if (!hp_sdc.base_io)
861 goto err0;
808 862
809 errstr = "IRQ not found for"; 863 errstr = "IRQ not found for";
810 if (!hp_sdc.irq) goto err0; 864 if (!hp_sdc.irq)
865 goto err0;
811 866
812 hp_sdc.dev_err = -EBUSY; 867 hp_sdc.dev_err = -EBUSY;
813 868
814#if defined(__hppa__) 869#if defined(__hppa__)
815 errstr = "IO not available for"; 870 errstr = "IO not available for";
816 if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0; 871 if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name))
817#endif 872 goto err0;
873#endif
818 874
819 errstr = "IRQ not available for"; 875 errstr = "IRQ not available for";
820 if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC", 876 if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
821 (void *) hp_sdc.base_io)) goto err1; 877 "HP SDC", &hp_sdc))
878 goto err1;
822 879
823 errstr = "NMI not available for"; 880 errstr = "NMI not available for";
824 if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", 881 if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED,
825 (void *) hp_sdc.base_io)) goto err2; 882 "HP SDC NMI", &hp_sdc))
883 goto err2;
826 884
827 printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", 885 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); 886 (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
829 887
830 hp_sdc_status_in8(); 888 hp_sdc_status_in8();
@@ -854,13 +912,14 @@ static int __init hp_sdc_init(void)
854 hp_sdc.dev_err = 0; 912 hp_sdc.dev_err = 0;
855 return 0; 913 return 0;
856 err2: 914 err2:
857 free_irq(hp_sdc.irq, NULL); 915 free_irq(hp_sdc.irq, &hp_sdc);
858 err1: 916 err1:
859 release_region(hp_sdc.data_io, 2); 917 release_region(hp_sdc.data_io, 2);
860 err0: 918 err0:
861 printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", 919 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); 920 errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
863 hp_sdc.dev = NULL; 921 hp_sdc.dev = NULL;
922
864 return hp_sdc.dev_err; 923 return hp_sdc.dev_err;
865} 924}
866 925
@@ -868,8 +927,10 @@ static int __init hp_sdc_init(void)
868 927
869static int __init hp_sdc_init_hppa(struct parisc_device *d) 928static int __init hp_sdc_init_hppa(struct parisc_device *d)
870{ 929{
871 if (!d) return 1; 930 if (!d)
872 if (hp_sdc.dev != NULL) return 1; /* We only expect one SDC */ 931 return 1;
932 if (hp_sdc.dev != NULL)
933 return 1; /* We only expect one SDC */
873 934
874 hp_sdc.dev = d; 935 hp_sdc.dev = d;
875 hp_sdc.irq = d->irq; 936 hp_sdc.irq = d->irq;
@@ -898,18 +959,16 @@ static void hp_sdc_exit(void)
898 /* Wait until we know this has been processed by the i8042 */ 959 /* Wait until we know this has been processed by the i8042 */
899 hp_sdc_spin_ibf(); 960 hp_sdc_spin_ibf();
900 961
901 free_irq(hp_sdc.nmi, NULL); 962 free_irq(hp_sdc.nmi, &hp_sdc);
902 free_irq(hp_sdc.irq, NULL); 963 free_irq(hp_sdc.irq, &hp_sdc);
903 write_unlock_irq(&hp_sdc.lock); 964 write_unlock_irq(&hp_sdc.lock);
904 965
905 del_timer(&hp_sdc.kicker); 966 del_timer(&hp_sdc.kicker);
906 967
907 tasklet_kill(&hp_sdc.task); 968 tasklet_kill(&hp_sdc.task);
908 969
909/* release_region(hp_sdc.data_io, 2); */
910
911#if defined(__hppa__) 970#if defined(__hppa__)
912 if (unregister_parisc_driver(&hp_sdc_driver)) 971 if (unregister_parisc_driver(&hp_sdc_driver))
913 printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); 972 printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
914#endif 973#endif
915} 974}
@@ -923,7 +982,7 @@ static int __init hp_sdc_register(void)
923 mm_segment_t fs; 982 mm_segment_t fs;
924 unsigned char i; 983 unsigned char i;
925#endif 984#endif
926 985
927 hp_sdc.dev = NULL; 986 hp_sdc.dev = NULL;
928 hp_sdc.dev_err = 0; 987 hp_sdc.dev_err = 0;
929#if defined(__hppa__) 988#if defined(__hppa__)
@@ -960,8 +1019,8 @@ static int __init hp_sdc_register(void)
960 tq_init.seq = tq_init_seq; 1019 tq_init.seq = tq_init_seq;
961 tq_init.act.semaphore = &tq_init_sem; 1020 tq_init.act.semaphore = &tq_init_sem;
962 1021
963 tq_init_seq[0] = 1022 tq_init_seq[0] =
964 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; 1023 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
965 tq_init_seq[1] = HP_SDC_CMD_READ_KCC; 1024 tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
966 tq_init_seq[2] = 1; 1025 tq_init_seq[2] = 1;
967 tq_init_seq[3] = 0; 1026 tq_init_seq[3] = 0;
@@ -979,13 +1038,13 @@ static int __init hp_sdc_register(void)
979 } 1038 }
980 hp_sdc.r11 = tq_init_seq[4]; 1039 hp_sdc.r11 = tq_init_seq[4];
981 if (hp_sdc.r11 & HP_SDC_CFG_NEW) { 1040 if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
982 char *str; 1041 const char *str;
983 printk(KERN_INFO PREFIX "New style SDC\n"); 1042 printk(KERN_INFO PREFIX "New style SDC\n");
984 tq_init_seq[1] = HP_SDC_CMD_READ_XTD; 1043 tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
985 tq_init.actidx = 0; 1044 tq_init.actidx = 0;
986 tq_init.idx = 1; 1045 tq_init.idx = 1;
987 down(&tq_init_sem); 1046 down(&tq_init_sem);
988 hp_sdc_enqueue_transaction(&tq_init); 1047 hp_sdc_enqueue_transaction(&tq_init);
989 down(&tq_init_sem); 1048 down(&tq_init_sem);
990 up(&tq_init_sem); 1049 up(&tq_init_sem);
991 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { 1050 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
@@ -995,15 +1054,13 @@ static int __init hp_sdc_register(void)
995 hp_sdc.r7e = tq_init_seq[4]; 1054 hp_sdc.r7e = tq_init_seq[4];
996 HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str) 1055 HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
997 printk(KERN_INFO PREFIX "Revision: %s\n", str); 1056 printk(KERN_INFO PREFIX "Revision: %s\n", str);
998 if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) { 1057 if (hp_sdc.r7e & HP_SDC_XTD_BEEPER)
999 printk(KERN_INFO PREFIX "TI SN76494 beeper present\n"); 1058 printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
1000 } 1059 if (hp_sdc.r7e & HP_SDC_XTD_BBRTC)
1001 if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) {
1002 printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n"); 1060 printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
1003 }
1004 printk(KERN_INFO PREFIX "Spunking the self test register to force PUP " 1061 printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
1005 "on next firmware reset.\n"); 1062 "on next firmware reset.\n");
1006 tq_init_seq[0] = HP_SDC_ACT_PRECMD | 1063 tq_init_seq[0] = HP_SDC_ACT_PRECMD |
1007 HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; 1064 HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
1008 tq_init_seq[1] = HP_SDC_CMD_SET_STR; 1065 tq_init_seq[1] = HP_SDC_CMD_SET_STR;
1009 tq_init_seq[2] = 1; 1066 tq_init_seq[2] = 1;
@@ -1012,14 +1069,12 @@ static int __init hp_sdc_register(void)
1012 tq_init.idx = 1; 1069 tq_init.idx = 1;
1013 tq_init.endidx = 4; 1070 tq_init.endidx = 4;
1014 down(&tq_init_sem); 1071 down(&tq_init_sem);
1015 hp_sdc_enqueue_transaction(&tq_init); 1072 hp_sdc_enqueue_transaction(&tq_init);
1016 down(&tq_init_sem); 1073 down(&tq_init_sem);
1017 up(&tq_init_sem); 1074 up(&tq_init_sem);
1018 } 1075 } else
1019 else { 1076 printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
1020 printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
1021 (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087"); 1077 (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
1022 }
1023 1078
1024 return 0; 1079 return 0;
1025} 1080}
@@ -1027,13 +1082,13 @@ static int __init hp_sdc_register(void)
1027module_init(hp_sdc_register); 1082module_init(hp_sdc_register);
1028module_exit(hp_sdc_exit); 1083module_exit(hp_sdc_exit);
1029 1084
1030/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64) 1085/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64)
1031 * cycles cycles-adj time 1086 * cycles cycles-adj time
1032 * between two consecutive mfctl(16)'s: 4 n/a 63ns 1087 * between two consecutive mfctl(16)'s: 4 n/a 63ns
1033 * hp_sdc_spin_ibf when idle: 119 115 1.7us 1088 * hp_sdc_spin_ibf when idle: 119 115 1.7us
1034 * gsc_writeb status register: 83 79 1.2us 1089 * gsc_writeb status register: 83 79 1.2us
1035 * IBF to clear after sending SET_IM: 6204 6006 93us 1090 * IBF to clear after sending SET_IM: 6204 6006 93us
1036 * IBF to clear after sending LOAD_RT: 4467 4352 68us 1091 * IBF to clear after sending LOAD_RT: 4467 4352 68us
1037 * IBF to clear after sending two LOAD_RTs: 18974 18859 295us 1092 * IBF to clear after sending two LOAD_RTs: 18974 18859 295us
1038 * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us 1093 * 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 1094 * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms