diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
commit | c7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch) | |
tree | 3682407a599b8f9f03fc096298134cafba1c9b2f /drivers/misc/parport_pc.c | |
parent | 1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff) |
o Merge with Linux 2.1.116.
o New Newport console code.
o New G364 console code.
Diffstat (limited to 'drivers/misc/parport_pc.c')
-rw-r--r-- | drivers/misc/parport_pc.c | 140 |
1 files changed, 98 insertions, 42 deletions
diff --git a/drivers/misc/parport_pc.c b/drivers/misc/parport_pc.c index 7396e2e11..334f9a1d2 100644 --- a/drivers/misc/parport_pc.c +++ b/drivers/misc/parport_pc.c @@ -3,7 +3,8 @@ * Authors: Phil Blundell <Philip.Blundell@pobox.com> * Tim Waugh <tim@cyberelk.demon.co.uk> * Jose Renau <renau@acm.org> - * David Campbell <campbell@tirian.che.curtin.edu.au> + * David Campbell <campbell@torque.net> + * Andrea Arcangeli <arcangeli@mbox.queen.it> * * based on work by Grant Guenther <grant@torque.net> and Phil Blundell. */ @@ -19,8 +20,8 @@ * * In addition, there are some optional registers: * - * base+3 EPP command - * base+4 EPP + * base+3 EPP address + * base+4 EPP data * base+0x400 ECP config A * base+0x401 ECP config B * base+0x402 ECP control @@ -59,12 +60,30 @@ static void parport_pc_null_intr_func(int irq, void *dev_id, struct pt_regs *reg void parport_pc_write_epp(struct parport *p, unsigned char d) { - outb(d, p->base+EPPREG); + outb(d, p->base+EPPDATA); } unsigned char parport_pc_read_epp(struct parport *p) { - return inb(p->base+EPPREG); + return inb(p->base+EPPDATA); +} + +void parport_pc_write_epp_addr(struct parport *p, unsigned char d) +{ + outb(d, p->base+EPPADDR); +} + +unsigned char parport_pc_read_epp_addr(struct parport *p) +{ + return inb(p->base+EPPADDR); +} + +int parport_pc_check_epp_timeout(struct parport *p) +{ + if (!(inb(p->base+STATUS) & 1)) + return 0; + parport_pc_epp_clear_timeout(p); + return 1; } unsigned char parport_pc_read_configb(struct parport *p) @@ -171,23 +190,31 @@ int parport_pc_claim_resources(struct parport *p) return 0; } +void parport_pc_init_state(struct parport_state *s) +{ + s->u.pc.ctr = 0xc; + s->u.pc.ecr = 0x0; +} + void parport_pc_save_state(struct parport *p, struct parport_state *s) { s->u.pc.ctr = parport_pc_read_control(p); - s->u.pc.ecr = parport_pc_read_econtrol(p); + if (p->modes & PARPORT_MODE_PCECR) + s->u.pc.ecr = parport_pc_read_econtrol(p); } void parport_pc_restore_state(struct parport *p, struct parport_state *s) { parport_pc_write_control(p, s->u.pc.ctr); - parport_pc_write_econtrol(p, s->u.pc.ecr); + if (p->modes & PARPORT_MODE_PCECR) + parport_pc_write_econtrol(p, s->u.pc.ecr); } size_t parport_pc_epp_read_block(struct parport *p, void *buf, size_t length) { size_t got = 0; for (; got < length; got++) { - *((char*)buf)++ = inb (p->base+EPPREG); + *((char*)buf)++ = inb (p->base+EPPDATA); if (inb (p->base+STATUS) & 0x01) break; } @@ -198,7 +225,7 @@ size_t parport_pc_epp_write_block(struct parport *p, void *buf, size_t length) { size_t written = 0; for (; written < length; written++) { - outb (*((char*)buf)++, p->base+EPPREG); + outb (*((char*)buf)++, p->base+EPPDATA); if (inb (p->base+STATUS) & 0x01) break; } @@ -234,6 +261,16 @@ void parport_pc_dec_use_count(void) #endif } +static void parport_pc_fill_inode(struct inode *inode, int fill) +{ +#ifdef MODULE + if (fill) + MOD_INC_USE_COUNT; + else + MOD_DEC_USE_COUNT; +#endif +} + struct parport_operations parport_pc_ops = { parport_pc_write_data, @@ -258,12 +295,19 @@ struct parport_operations parport_pc_ops = parport_pc_release_resources, parport_pc_claim_resources, + parport_pc_write_epp, + parport_pc_read_epp, + parport_pc_write_epp_addr, + parport_pc_read_epp_addr, + parport_pc_check_epp_timeout, + parport_pc_epp_write_block, parport_pc_epp_read_block, parport_pc_ecp_write_block, parport_pc_ecp_read_block, + parport_pc_init_state, parport_pc_save_state, parport_pc_restore_state, @@ -272,7 +316,8 @@ struct parport_operations parport_pc_ops = parport_pc_examine_irq, parport_pc_inc_use_count, - parport_pc_dec_use_count + parport_pc_dec_use_count, + parport_pc_fill_inode }; /* --- Mode detection ------------------------------------- */ @@ -280,7 +325,7 @@ struct parport_operations parport_pc_ops = /* * Clear TIMEOUT BIT in EPP MODE */ -static int epp_clear_timeout(struct parport *pb) +int parport_pc_epp_clear_timeout(struct parport *pb) { unsigned char r; @@ -303,8 +348,15 @@ static int epp_clear_timeout(struct parport *pb) */ static int parport_SPP_supported(struct parport *pb) { + /* + * first clear an eventually pending EPP timeout + * I (sailer@ife.ee.ethz.ch) have an SMSC chipset + * that does not even respond to SPP cycles if an EPP + * timeout is pending + */ + parport_pc_epp_clear_timeout(pb); + /* Do a simple read-write test to make sure the port exists. */ - parport_pc_write_econtrol(pb, 0xc); parport_pc_write_control(pb, 0xc); parport_pc_write_data(pb, 0xaa); if (parport_pc_read_data(pb) != 0xaa) return 0; @@ -362,12 +414,13 @@ static int parport_ECR_present(struct parport *pb) static int parport_ECP_supported(struct parport *pb) { int i; - unsigned char oecr = parport_pc_read_econtrol(pb); + unsigned char oecr; /* If there is no ECR, we have no hope of supporting ECP. */ if (!(pb->modes & PARPORT_MODE_PCECR)) return 0; + oecr = parport_pc_read_econtrol(pb); /* * Using LGS chipset it uses ECR register, but * it doesn't support ECP or FIFO MODE @@ -396,18 +449,18 @@ static int parport_ECP_supported(struct parport *pb) static int parport_EPP_supported(struct parport *pb) { /* If EPP timeout bit clear then EPP available */ - if (!epp_clear_timeout(pb)) + if (!parport_pc_epp_clear_timeout(pb)) return 0; /* No way to clear timeout */ parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x20); parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x10); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); parport_pc_read_epp(pb); udelay(30); /* Wait for possible EPP timeout */ if (parport_pc_read_status(pb) & 0x01) { - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); return PARPORT_MODE_PCEPP; } @@ -417,11 +470,12 @@ static int parport_EPP_supported(struct parport *pb) static int parport_ECPEPP_supported(struct parport *pb) { int mode; - unsigned char oecr = parport_pc_read_econtrol(pb); + unsigned char oecr; if (!(pb->modes & PARPORT_MODE_PCECR)) return 0; - + + oecr = parport_pc_read_econtrol(pb); /* Search for SMC style EPP+ECP mode */ parport_pc_write_econtrol(pb, 0x80); @@ -454,7 +508,7 @@ static int parport_PS2_supported(struct parport *pb) int ok = 0; unsigned char octr = parport_pc_read_control(pb); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); parport_pc_write_control(pb, octr | 0x20); /* try to tri-state the buffer */ @@ -472,11 +526,12 @@ static int parport_PS2_supported(struct parport *pb) static int parport_ECPPS2_supported(struct parport *pb) { int mode; - unsigned char oecr = parport_pc_read_econtrol(pb); + unsigned char oecr; if (!(pb->modes & PARPORT_MODE_PCECR)) return 0; - + + oecr = parport_pc_read_econtrol(pb); parport_pc_write_econtrol(pb, 0x20); mode = parport_PS2_supported(pb); @@ -536,22 +591,25 @@ static int irq_probe_EPP(struct parport *pb) { int irqs; unsigned char octr = parport_pc_read_control(pb); - unsigned char oecr = parport_pc_read_econtrol(pb); + unsigned char oecr; #ifndef ADVANCED_DETECT return PARPORT_IRQ_NONE; #endif - + + if (pb->modes & PARPORT_MODE_PCECR) + oecr = parport_pc_read_econtrol(pb); + sti(); irqs = probe_irq_on(); if (pb->modes & PARPORT_MODE_PCECR) parport_pc_frob_econtrol (pb, 0x10, 0x10); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); parport_pc_frob_control (pb, 0x20, 0x20); parport_pc_frob_control (pb, 0x10, 0x10); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); /* Device isn't expecting an EPP read * and generates an IRQ. @@ -560,7 +618,8 @@ static int irq_probe_EPP(struct parport *pb) udelay(20); pb->irq = probe_irq_off (irqs); - parport_pc_write_econtrol(pb, oecr); + if (pb->modes & PARPORT_MODE_PCECR) + parport_pc_write_econtrol(pb, oecr); parport_pc_write_control(pb, octr); if (pb->irq <= 0) @@ -573,12 +632,14 @@ static int irq_probe_SPP(struct parport *pb) { int irqs; unsigned char octr = parport_pc_read_control(pb); - unsigned char oecr = parport_pc_read_econtrol(pb); + unsigned char oecr; #ifndef ADVANCED_DETECT return PARPORT_IRQ_NONE; #endif + if (pb->modes & PARPORT_MODE_PCECR) + oecr = parport_pc_read_econtrol(pb); probe_irq_off(probe_irq_on()); /* Clear any interrupts */ irqs = probe_irq_on(); @@ -602,7 +663,8 @@ static int irq_probe_SPP(struct parport *pb) if (pb->irq <= 0) pb->irq = PARPORT_IRQ_NONE; /* No interrupt detected */ - parport_pc_write_econtrol(pb, oecr); + if (pb->modes & PARPORT_MODE_PCECR) + parport_pc_write_econtrol(pb, oecr); parport_pc_write_control(pb, octr); return pb->irq; } @@ -616,8 +678,6 @@ static int irq_probe_SPP(struct parport *pb) */ static int parport_irq_probe(struct parport *pb) { - unsigned char oecr = parport_pc_read_econtrol (pb); - if (pb->modes & PARPORT_MODE_PCECR) { pb->irq = programmable_irq_support(pb); if (pb->irq != PARPORT_IRQ_NONE) @@ -628,23 +688,20 @@ static int parport_irq_probe(struct parport *pb) pb->irq = irq_probe_ECP(pb); if (pb->irq == PARPORT_IRQ_NONE && - (pb->modes & PARPORT_MODE_PCECPEPP)) { + (pb->modes & PARPORT_MODE_PCECPEPP)) pb->irq = irq_probe_EPP(pb); - parport_pc_write_econtrol(pb, oecr); - } - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_PCEPP)) pb->irq = irq_probe_EPP(pb); - epp_clear_timeout(pb); + parport_pc_epp_clear_timeout(pb); if (pb->irq == PARPORT_IRQ_NONE) pb->irq = irq_probe_SPP(pb); out: - parport_pc_write_econtrol (pb, oecr); return pb->irq; } @@ -708,7 +765,11 @@ static int probe_one_port(unsigned long int base, int irq, int dma) p->flags |= PARPORT_FLAG_COMA; /* Done probing. Now put the port into a sensible start-up state. */ - parport_pc_write_econtrol(p, 0xc); + if (p->modes & PARPORT_MODE_PCECR) + /* + * Put the ECP detected port in the more SPP like mode. + */ + parport_pc_write_econtrol(p, 0x0); parport_pc_write_control(p, 0xc); parport_pc_write_data(p, 0); @@ -733,11 +794,6 @@ int parport_pc_init(int *io, int *irq, int *dma) count += probe_one_port(0x278, irq[0], dma[0]); } - /* Give any attached devices a chance to gather their thoughts */ - current->state = TASK_INTERRUPTIBLE; - current->timeout = jiffies + 75; - schedule (); - return count; } |