linux/drivers/parport/parport_atari.c
<<
>>
Prefs
   1/* Low-level parallel port routines for the Atari builtin port
   2 *
   3 * Author: Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
   4 *
   5 * Based on parport_amiga.c.
   6 *
   7 * The built-in Atari parallel port provides one port at a fixed address
   8 * with 8 output data lines (D0 - D7), 1 output control line (STROBE)
   9 * and 1 input status line (BUSY) able to cause an interrupt.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/init.h>
  14#include <linux/parport.h>
  15#include <linux/interrupt.h>
  16#include <asm/setup.h>
  17#include <asm/atarihw.h>
  18#include <asm/irq.h>
  19#include <asm/atariints.h>
  20
  21static struct parport *this_port = NULL;
  22
  23static unsigned char
  24parport_atari_read_data(struct parport *p)
  25{
  26        unsigned long flags;
  27        unsigned char data;
  28
  29        local_irq_save(flags);
  30        sound_ym.rd_data_reg_sel = 15;
  31        data = sound_ym.rd_data_reg_sel;
  32        local_irq_restore(flags);
  33        return data;
  34}
  35
  36static void
  37parport_atari_write_data(struct parport *p, unsigned char data)
  38{
  39        unsigned long flags;
  40
  41        local_irq_save(flags);
  42        sound_ym.rd_data_reg_sel = 15;
  43        sound_ym.wd_data = data;
  44        local_irq_restore(flags);
  45}
  46
  47static unsigned char
  48parport_atari_read_control(struct parport *p)
  49{
  50        unsigned long flags;
  51        unsigned char control = 0;
  52
  53        local_irq_save(flags);
  54        sound_ym.rd_data_reg_sel = 14;
  55        if (!(sound_ym.rd_data_reg_sel & (1 << 5)))
  56                control = PARPORT_CONTROL_STROBE;
  57        local_irq_restore(flags);
  58        return control;
  59}
  60
  61static void
  62parport_atari_write_control(struct parport *p, unsigned char control)
  63{
  64        unsigned long flags;
  65
  66        local_irq_save(flags);
  67        sound_ym.rd_data_reg_sel = 14;
  68        if (control & PARPORT_CONTROL_STROBE)
  69                sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~(1 << 5);
  70        else
  71                sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
  72        local_irq_restore(flags);
  73}
  74
  75static unsigned char
  76parport_atari_frob_control(struct parport *p, unsigned char mask,
  77                           unsigned char val)
  78{
  79        unsigned char old = parport_atari_read_control(p);
  80        parport_atari_write_control(p, (old & ~mask) ^ val);
  81        return old;
  82}
  83
  84static unsigned char
  85parport_atari_read_status(struct parport *p)
  86{
  87        return ((st_mfp.par_dt_reg & 1 ? 0 : PARPORT_STATUS_BUSY) |
  88                PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR);
  89}
  90
  91static void
  92parport_atari_init_state(struct pardevice *d, struct parport_state *s)
  93{
  94}
  95
  96static void
  97parport_atari_save_state(struct parport *p, struct parport_state *s)
  98{
  99}
 100
 101static void
 102parport_atari_restore_state(struct parport *p, struct parport_state *s)
 103{
 104}
 105
 106static void
 107parport_atari_enable_irq(struct parport *p)
 108{
 109        enable_irq(IRQ_MFP_BUSY);
 110}
 111
 112static void
 113parport_atari_disable_irq(struct parport *p)
 114{
 115        disable_irq(IRQ_MFP_BUSY);
 116}
 117
 118static void
 119parport_atari_data_forward(struct parport *p)
 120{
 121        unsigned long flags;
 122
 123        local_irq_save(flags);
 124        /* Soundchip port B as output. */
 125        sound_ym.rd_data_reg_sel = 7;
 126        sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x40;
 127        local_irq_restore(flags);
 128}
 129
 130static void
 131parport_atari_data_reverse(struct parport *p)
 132{
 133}
 134
 135static struct parport_operations parport_atari_ops = {
 136        .write_data     = parport_atari_write_data,
 137        .read_data      = parport_atari_read_data,
 138
 139        .write_control  = parport_atari_write_control,
 140        .read_control   = parport_atari_read_control,
 141        .frob_control   = parport_atari_frob_control,
 142
 143        .read_status    = parport_atari_read_status,
 144
 145        .enable_irq     = parport_atari_enable_irq,
 146        .disable_irq    = parport_atari_disable_irq,
 147
 148        .data_forward   = parport_atari_data_forward,
 149        .data_reverse   = parport_atari_data_reverse,
 150
 151        .init_state     = parport_atari_init_state,
 152        .save_state     = parport_atari_save_state,
 153        .restore_state  = parport_atari_restore_state,
 154
 155        .epp_write_data = parport_ieee1284_epp_write_data,
 156        .epp_read_data  = parport_ieee1284_epp_read_data,
 157        .epp_write_addr = parport_ieee1284_epp_write_addr,
 158        .epp_read_addr  = parport_ieee1284_epp_read_addr,
 159
 160        .ecp_write_data = parport_ieee1284_ecp_write_data,
 161        .ecp_read_data  = parport_ieee1284_ecp_read_data,
 162        .ecp_write_addr = parport_ieee1284_ecp_write_addr,
 163
 164        .compat_write_data      = parport_ieee1284_write_compat,
 165        .nibble_read_data       = parport_ieee1284_read_nibble,
 166        .byte_read_data         = parport_ieee1284_read_byte,
 167
 168        .owner          = THIS_MODULE,
 169};
 170
 171
 172static int __init parport_atari_init(void)
 173{
 174        struct parport *p;
 175        unsigned long flags;
 176
 177        if (MACH_IS_ATARI) {
 178                local_irq_save(flags);
 179                /* Soundchip port A/B as output. */
 180                sound_ym.rd_data_reg_sel = 7;
 181                sound_ym.wd_data = (sound_ym.rd_data_reg_sel & 0x3f) | 0xc0;
 182                /* STROBE high. */
 183                sound_ym.rd_data_reg_sel = 14;
 184                sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
 185                local_irq_restore(flags);
 186                /* MFP port I0 as input. */
 187                st_mfp.data_dir &= ~1;
 188                /* MFP port I0 interrupt on high->low edge. */
 189                st_mfp.active_edge &= ~1;
 190                p = parport_register_port((unsigned long)&sound_ym.wd_data,
 191                                          IRQ_MFP_BUSY, PARPORT_DMA_NONE,
 192                                          &parport_atari_ops);
 193                if (!p)
 194                        return -ENODEV;
 195                if (request_irq(IRQ_MFP_BUSY, parport_irq_handler,
 196                                IRQ_TYPE_SLOW, p->name, p)) {
 197                        parport_put_port (p);
 198                        return -ENODEV;
 199                }
 200
 201                this_port = p;
 202                printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
 203                parport_announce_port (p);
 204
 205                return 0;
 206        }
 207        return -ENODEV;
 208}
 209
 210static void __exit parport_atari_exit(void)
 211{
 212        parport_remove_port(this_port);
 213        if (this_port->irq != PARPORT_IRQ_NONE)
 214                free_irq(IRQ_MFP_BUSY, this_port);
 215        parport_put_port(this_port);
 216}
 217
 218MODULE_AUTHOR("Andreas Schwab");
 219MODULE_DESCRIPTION("Parport Driver for Atari builtin Port");
 220MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port");
 221MODULE_LICENSE("GPL");
 222
 223module_init(parport_atari_init)
 224module_exit(parport_atari_exit)
 225