65 #include <linux/errno.h>
67 #include <linux/module.h>
69 #include <linux/time.h>
71 #include <linux/slab.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))
86 # error "HIL is not supported on this platform"
89 #define PREFIX "HP SDC: "
107 static bool hp_sdc_disabled;
114 static inline uint8_t hp_sdc_status_in8(
void)
128 static inline uint8_t hp_sdc_data_in8(
void)
130 return sdc_readb(hp_sdc.
data_io);
133 static inline void hp_sdc_status_out8(
uint8_t val)
139 if ((val & 0xf0) == 0xe0)
145 static inline void hp_sdc_data_out8(
uint8_t val)
151 sdc_writeb(val, hp_sdc.
data_io);
159 static inline void hp_sdc_spin_ibf(
void)
186 if (hp_sdc.
rcurr < 0) {
190 curr = hp_sdc.
tq[hp_sdc.
rcurr];
198 if (hp_sdc.
rqty <= 0) {
215 tasklet_schedule(&hp_sdc.
task);
219 static irqreturn_t hp_sdc_isr(
int irq,
void *dev_id)
223 status = hp_sdc_status_in8();
225 data = hp_sdc_data_in8();
228 if (((status & 0xf1) == 0x51) && data == 0x82)
240 hp_sdc.
timer(irq, dev_id, status, data);
245 hp_sdc_take(irq, dev_id, status, data);
252 hp_sdc.
hil(irq, dev_id, status, data);
259 hp_sdc.
pup(irq, dev_id, status, data);
268 hp_sdc.
cooked(irq, dev_id, status, data);
277 static irqreturn_t hp_sdc_nmisr(
int irq,
void *dev_id)
281 status = hp_sdc_status_in8();
288 hp_sdc.
timer(irq, dev_id, status, 0);
304 static void hp_sdc_tasklet(
unsigned long foo)
308 if (hp_sdc.
rcurr >= 0) {
312 if (tv.tv_sec > hp_sdc.
rtv.tv_sec)
319 curr = hp_sdc.
tq[hp_sdc.
rcurr];
325 (
int)(tv.tv_usec - hp_sdc.
rtv.tv_usec));
371 if (hp_sdc.
wcurr < 0)
379 curridx = hp_sdc.
wcurr;
381 if (hp_sdc.
tq[curridx] !=
NULL)
384 while (++curridx != hp_sdc.
wcurr) {
390 if (hp_sdc.
rcurr == curridx) {
395 if (hp_sdc.
tq[curridx] !=
NULL)
398 if (curridx == hp_sdc.
wcurr) {
401 hp_sdc.
wcurr = curridx;
412 if (hp_sdc.
wcurr == -1)
415 curr = hp_sdc.
tq[curridx];
419 hp_sdc.
tq[curridx] =
NULL;
433 hp_sdc.
tq[curridx] =
NULL;
442 if (curr->
idx != idx) {
444 act &= ~HP_SDC_ACT_PRECMD;
447 hp_sdc_status_out8(curr->
seq[idx]);
462 if (curr->
idx - idx < qty) {
463 hp_sdc_data_out8(curr->
seq[curr->
idx]);
466 if (curr->
idx - idx >= qty &&
472 act &= ~HP_SDC_ACT_DATAOUT;
479 if (idx != curr->
idx) {
485 act &= ~HP_SDC_ACT_DATAREG;
489 w7[0] = (mask & 1) ? curr->
seq[++idx] : hp_sdc.
r7[0];
490 w7[1] = (mask & 2) ? curr->
seq[++
idx] : hp_sdc.
r7[1];
491 w7[2] = (mask & 4) ? curr->
seq[++idx] : hp_sdc.
r7[2];
492 w7[3] = (mask & 8) ? curr->
seq[++
idx] : hp_sdc.
r7[3];
494 if (hp_sdc.
wi > 0x73 || hp_sdc.
wi < 0x70 ||
495 w7[hp_sdc.
wi - 0x70] == hp_sdc.
r7[hp_sdc.
wi - 0x70]) {
499 while (i < 4 && w7[i] == hp_sdc.
r7[i])
504 hp_sdc.
wi = 0x70 +
i;
513 act &= ~HP_SDC_ACT_DATAREG;
517 hp_sdc_data_out8(w7[hp_sdc.
wi - 0x70]);
518 hp_sdc.
r7[hp_sdc.
wi - 0x70] = w7[hp_sdc.
wi - 0x70];
523 while ((i < 4) && w7[i] == hp_sdc.
r7[i])
537 if (hp_sdc.
rcurr >= 0) {
558 hp_sdc.
rcurr = curridx;
560 hp_sdc_status_out8(postcmd);
563 hp_sdc_status_out8(postcmd);
568 if (act & HP_SDC_ACT_SEMAPHORE)
576 hp_sdc.
tq[curridx] =
NULL;
589 if (!hp_sdc.
ibf && limit++ < 20)
593 if (hp_sdc.
wcurr >= 0)
594 tasklet_schedule(&hp_sdc.
task);
612 if (hp_sdc.
tq[i] ==
this)
620 if (hp_sdc.
tq[i] ==
NULL) {
622 tasklet_schedule(&hp_sdc.
task);
655 if (hp_sdc.
tq[i] ==
this)
667 if (callback ==
NULL || hp_sdc.dev ==
NULL)
684 tasklet_schedule(&hp_sdc.
task);
691 if (callback ==
NULL || hp_sdc.dev ==
NULL)
705 tasklet_schedule(&hp_sdc.
task);
712 if (callback ==
NULL || hp_sdc.dev ==
NULL)
727 tasklet_schedule(&hp_sdc.
task);
735 if ((callback != hp_sdc.
timer) ||
748 tasklet_schedule(&hp_sdc.
task);
756 if ((callback != hp_sdc.
hil) ||
769 tasklet_schedule(&hp_sdc.
task);
777 if ((callback != hp_sdc.
cooked) ||
790 tasklet_schedule(&hp_sdc.
task);
797 static void hp_sdc_kicker(
unsigned long data)
799 tasklet_schedule(&hp_sdc.
task);
806 #if defined(__hppa__)
825 .id_table = hp_sdc_tbl,
826 .probe = hp_sdc_init_hppa,
831 static int __init hp_sdc_init(
void)
864 errstr =
"IO not found for";
868 errstr =
"IRQ not found for";
874 #if defined(__hppa__)
875 errstr =
"IO not available for";
880 errstr =
"IRQ not available for";
885 errstr =
"NMI not available for";
887 "HP SDC NMI", &hp_sdc))
902 t_sync.
seq = ts_sync;
905 ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0;
907 sema_init(&s_sync, 0);
914 hp_sdc.
kicker.function = &hp_sdc_kicker;
931 #if defined(__hppa__)
935 request_module(
"hp_sdc_mlc");
944 if (hp_sdc.dev !=
NULL)
968 static void hp_sdc_exit(
void)
991 #if defined(__hppa__)
998 static int __init hp_sdc_register(
void)
1003 #if defined(__mc68000__)
1008 if (hp_sdc_disabled) {
1015 #if defined(__hppa__)
1020 #elif defined(__mc68000__)
1032 hp_sdc.dev = (
void *)1;
1034 hp_sdc.
dev_err = hp_sdc_init();
1036 if (hp_sdc.dev ==
NULL) {
1041 sema_init(&tq_init_sem, 0);
1046 tq_init.
seq = tq_init_seq;
1066 hp_sdc.
r11 = tq_init_seq[4];
1077 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
1081 hp_sdc.
r7e = tq_init_seq[4];