linux/drivers/parport/parport_amiga.c
<<
>>
Prefs
   1/* Low-level parallel port routines for the Amiga built-in port
   2 *
   3 * Author: Joerg Dorchain <joerg@dorchain.net>
   4 *
   5 * This is a complete rewrite of the code, but based heaviy upon the old
   6 * lp_intern. code.
   7 *
   8 * The built-in Amiga parallel port provides one port at a fixed address
   9 * with 8 bidirectional data lines (D0 - D7) and 3 bidirectional status
  10 * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically
  11 * in hardware when the data register is accessed), and 1 input control line
  12 * /ACK, able to cause an interrupt, but both not directly settable by
  13 * software.
  14 */
  15
  16#include <linux/module.h>
  17#include <linux/init.h>
  18#include <linux/parport.h>
  19#include <linux/ioport.h>
  20#include <linux/interrupt.h>
  21#include <asm/setup.h>
  22#include <asm/amigahw.h>
  23#include <asm/irq.h>
  24#include <asm/io.h>
  25#include <asm/amigaints.h>
  26
  27#undef DEBUG
  28#ifdef DEBUG
  29#define DPRINTK printk
  30#else
  31#define DPRINTK(x...)   do { } while (0)
  32#endif
  33
  34static struct parport *this_port = NULL;
  35
  36static void amiga_write_data(struct parport *p, unsigned char data)
  37{
  38        DPRINTK(KERN_DEBUG "write_data %c\n",data);
  39        /* Triggers also /STROBE. This behavior cannot be changed */
  40        ciaa.prb = data;
  41        mb();
  42}
  43
  44static unsigned char amiga_read_data(struct parport *p)
  45{
  46        /* Triggers also /STROBE. This behavior cannot be changed */
  47        return ciaa.prb;
  48}
  49
  50#if 0
  51static unsigned char control_pc_to_amiga(unsigned char control)
  52{
  53        unsigned char ret = 0;
  54
  55        if (control & PARPORT_CONTROL_SELECT) /* XXX: What is SELECP? */
  56                ;
  57        if (control & PARPORT_CONTROL_INIT) /* INITP */
  58                /* reset connected to cpu reset pin */;
  59        if (control & PARPORT_CONTROL_AUTOFD) /* AUTOLF */
  60                /* Not connected */;
  61        if (control & PARPORT_CONTROL_STROBE) /* Strobe */
  62                /* Handled only directly by hardware */;
  63        return ret;
  64}
  65#endif
  66
  67static unsigned char control_amiga_to_pc(unsigned char control)
  68{
  69        return PARPORT_CONTROL_SELECT |
  70              PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE;
  71        /* fake value: interrupt enable, select in, no reset,
  72        no autolf, no strobe - seems to be closest the wiring diagram */
  73}
  74
  75static void amiga_write_control(struct parport *p, unsigned char control)
  76{
  77        DPRINTK(KERN_DEBUG "write_control %02x\n",control);
  78        /* No implementation possible */
  79}
  80        
  81static unsigned char amiga_read_control( struct parport *p)
  82{
  83        DPRINTK(KERN_DEBUG "read_control \n");
  84        return control_amiga_to_pc(0);
  85}
  86
  87static unsigned char amiga_frob_control( struct parport *p, unsigned char mask, unsigned char val)
  88{
  89        unsigned char old;
  90
  91        DPRINTK(KERN_DEBUG "frob_control mask %02x, value %02x\n",mask,val);
  92        old = amiga_read_control(p);
  93        amiga_write_control(p, (old & ~mask) ^ val);
  94        return old;
  95}
  96
  97#if 0 /* currently unused */
  98static unsigned char status_pc_to_amiga(unsigned char status)
  99{
 100        unsigned char ret = 1;
 101
 102        if (status & PARPORT_STATUS_BUSY) /* Busy */
 103                ret &= ~1;
 104        if (status & PARPORT_STATUS_ACK) /* Ack */
 105                /* handled in hardware */;
 106        if (status & PARPORT_STATUS_PAPEROUT) /* PaperOut */
 107                ret |= 2;
 108        if (status & PARPORT_STATUS_SELECT) /* select */
 109                ret |= 4;
 110        if (status & PARPORT_STATUS_ERROR) /* error */
 111                /* not connected */;
 112        return ret;
 113}
 114#endif
 115
 116static unsigned char status_amiga_to_pc(unsigned char status)
 117{
 118        unsigned char ret = PARPORT_STATUS_BUSY | PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR;
 119
 120        if (status & 1) /* Busy */
 121                ret &= ~PARPORT_STATUS_BUSY;
 122        if (status & 2) /* PaperOut */
 123                ret |= PARPORT_STATUS_PAPEROUT;
 124        if (status & 4) /* Selected */
 125                ret |= PARPORT_STATUS_SELECT;
 126        /* the rest is not connected or handled autonomously in hardware */
 127
 128        return ret;
 129}
 130
 131static unsigned char amiga_read_status(struct parport *p)
 132{
 133        unsigned char status;
 134
 135        status = status_amiga_to_pc(ciab.pra & 7);
 136        DPRINTK(KERN_DEBUG "read_status %02x\n", status);
 137        return status;
 138}
 139
 140static void amiga_enable_irq(struct parport *p)
 141{
 142        enable_irq(IRQ_AMIGA_CIAA_FLG);
 143}
 144
 145static void amiga_disable_irq(struct parport *p)
 146{
 147        disable_irq(IRQ_AMIGA_CIAA_FLG);
 148}
 149
 150static void amiga_data_forward(struct parport *p)
 151{
 152        DPRINTK(KERN_DEBUG "forward\n");
 153        ciaa.ddrb = 0xff; /* all pins output */
 154        mb();
 155}
 156
 157static void amiga_data_reverse(struct parport *p)
 158{
 159        DPRINTK(KERN_DEBUG "reverse\n");
 160        ciaa.ddrb = 0; /* all pins input */
 161        mb();
 162}
 163
 164static void amiga_init_state(struct pardevice *dev, struct parport_state *s)
 165{
 166        s->u.amiga.data = 0;
 167        s->u.amiga.datadir = 255;
 168        s->u.amiga.status = 0;
 169        s->u.amiga.statusdir = 0;
 170}
 171
 172static void amiga_save_state(struct parport *p, struct parport_state *s)
 173{
 174        mb();
 175        s->u.amiga.data = ciaa.prb;
 176        s->u.amiga.datadir = ciaa.ddrb;
 177        s->u.amiga.status = ciab.pra & 7;
 178        s->u.amiga.statusdir = ciab.ddra & 7;
 179        mb();
 180}
 181
 182static void amiga_restore_state(struct parport *p, struct parport_state *s)
 183{
 184        mb();
 185        ciaa.prb = s->u.amiga.data;
 186        ciaa.ddrb = s->u.amiga.datadir;
 187        ciab.pra |= (ciab.pra & 0xf8) | s->u.amiga.status;
 188        ciab.ddra |= (ciab.ddra & 0xf8) | s->u.amiga.statusdir;
 189        mb();
 190}
 191
 192static struct parport_operations pp_amiga_ops = {
 193        .write_data     = amiga_write_data,
 194        .read_data      = amiga_read_data,
 195
 196        .write_control  = amiga_write_control,
 197        .read_control   = amiga_read_control,
 198        .frob_control   = amiga_frob_control,
 199
 200        .read_status    = amiga_read_status,
 201
 202        .enable_irq     = amiga_enable_irq,
 203        .disable_irq    = amiga_disable_irq,
 204
 205        .data_forward   = amiga_data_forward,
 206        .data_reverse   = amiga_data_reverse,
 207
 208        .init_state     = amiga_init_state,
 209        .save_state     = amiga_save_state,
 210        .restore_state  = amiga_restore_state,
 211
 212        .epp_write_data = parport_ieee1284_epp_write_data,
 213        .epp_read_data  = parport_ieee1284_epp_read_data,
 214        .epp_write_addr = parport_ieee1284_epp_write_addr,
 215        .epp_read_addr  = parport_ieee1284_epp_read_addr,
 216
 217        .ecp_write_data = parport_ieee1284_ecp_write_data,
 218        .ecp_read_data  = parport_ieee1284_ecp_read_data,
 219        .ecp_write_addr = parport_ieee1284_ecp_write_addr,
 220
 221        .compat_write_data      = parport_ieee1284_write_compat,
 222        .nibble_read_data       = parport_ieee1284_read_nibble,
 223        .byte_read_data         = parport_ieee1284_read_byte,
 224
 225        .owner          = THIS_MODULE,
 226};
 227
 228/* ----------- Initialisation code --------------------------------- */
 229
 230static int __init parport_amiga_init(void)
 231{
 232        struct parport *p;
 233        int err;
 234
 235        if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_PARALLEL))
 236                return -ENODEV;
 237
 238        err = -EBUSY;
 239        if (!request_mem_region(CIAA_PHYSADDR-1+0x100, 0x100, "parallel"))
 240                goto out_mem;
 241
 242        ciaa.ddrb = 0xff;
 243        ciab.ddra &= 0xf8;
 244        mb();
 245
 246        p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG,
 247                                   PARPORT_DMA_NONE, &pp_amiga_ops);
 248        if (!p)
 249                goto out_port;
 250
 251        err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name, p);
 252        if (err)
 253                goto out_irq;
 254
 255        this_port = p;
 256        printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
 257        /* XXX: set operating mode */
 258        parport_announce_port(p);
 259
 260        return 0;
 261
 262out_irq:
 263        parport_put_port(p);
 264out_port:
 265        release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
 266out_mem:
 267        return err;
 268}
 269
 270static void __exit parport_amiga_exit(void)
 271{
 272        parport_remove_port(this_port);
 273        if (this_port->irq != PARPORT_IRQ_NONE)
 274                free_irq(IRQ_AMIGA_CIAA_FLG, this_port);
 275        parport_put_port(this_port);
 276        release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
 277}
 278
 279
 280MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
 281MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port");
 282MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port");
 283MODULE_LICENSE("GPL");
 284
 285module_init(parport_amiga_init)
 286module_exit(parport_amiga_exit)
 287