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