1 /* $Id: avm_a1p.c,v 2.9.2.5 2004/01/24 20:47:19 keil Exp $
 
   3  * low level stuff for the following AVM cards:
 
   6  * FRITZ!Card PCMCIA 2.0
 
   9  * Copyright    by Carsten Paeth     <calle@calle.de>
 
  11  * This software may be used and distributed according to the terms
 
  12  * of the GNU General Public License, incorporated herein by reference.
 
  16 #include <linux/init.h>
 
  22 /* register offsets */
 
  23 #define ADDRREG_OFFSET          0x02
 
  24 #define DATAREG_OFFSET          0x03
 
  25 #define ASL0_OFFSET             0x04
 
  26 #define ASL1_OFFSET             0x05
 
  27 #define MODREG_OFFSET           0x06
 
  28 #define VERREG_OFFSET           0x07
 
  31 #define ISAC_FIFO_OFFSET        0x00
 
  32 #define ISAC_REG_OFFSET         0x20
 
  33 #define HSCX_CH_DIFF            0x40
 
  34 #define HSCX_FIFO_OFFSET        0x80
 
  35 #define HSCX_REG_OFFSET         0xa0
 
  38 #define  ASL0_R_TIMER           0x10 /* active low */
 
  39 #define  ASL0_R_ISAC            0x20 /* active low */
 
  40 #define  ASL0_R_HSCX            0x40 /* active low */
 
  41 #define  ASL0_R_TESTBIT         0x80
 
  42 #define  ASL0_R_IRQPENDING      (ASL0_R_ISAC|ASL0_R_HSCX|ASL0_R_TIMER)
 
  45 #define  ASL0_W_RESET           0x01
 
  46 #define  ASL0_W_TDISABLE        0x02
 
  47 #define  ASL0_W_TRESET          0x04
 
  48 #define  ASL0_W_IRQENABLE       0x08
 
  49 #define  ASL0_W_TESTBIT         0x80
 
  52 #define  ASL1_W_LED0            0x10
 
  53 #define  ASL1_W_LED1            0x20
 
  54 #define  ASL1_W_ENABLE_S0       0xC0
 
  56 #define byteout(addr,val) outb(val,addr)
 
  57 #define bytein(addr) inb(addr)
 
  59 static const char *avm_revision = "$Revision: 2.9.2.5 $";
 
  62 ReadISAC(struct IsdnCardState *cs, u_char offset)
 
  67         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
 
  68         ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
 
  73 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
 
  76         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
 
  77         byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
 
  81 ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 
  83         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
 
  84         insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
 
  88 WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
 
  90         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
 
  91         outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
 
  95 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 
 100         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
 
 101                         HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
 
 102         ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
 
 107 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
 
 110         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
 
 111                         HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
 
 112         byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
 
 116 ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
 
 118         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
 
 119                         HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
 
 120         insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
 
 124 WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
 
 126         byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
 
 127                         HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
 
 128         outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
 
 132  * fast interrupt HSCX stuff goes here
 
 135 #define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
 
 136 #define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
 
 137 #define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) 
 
 138 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
 
 140 #include "hscx_irq.c"
 
 143 avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 
 145         struct IsdnCardState *cs = dev_id;
 
 149         spin_lock_irqsave(&cs->lock, flags);
 
 150         while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) {
 
 151                 if (cs->debug & L1_DEB_INTSTAT)
 
 152                         debugl1(cs, "avm IntStatus %x", sval);
 
 153                 if (sval & ASL0_R_HSCX) {
 
 154                         val = ReadHSCX(cs, 1, HSCX_ISTA);
 
 156                                 hscx_int_main(cs, val);
 
 158                 if (sval & ASL0_R_ISAC) {
 
 159                         val = ReadISAC(cs, ISAC_ISTA);
 
 161                                 isac_interrupt(cs, val);
 
 164         WriteHSCX(cs, 0, HSCX_MASK, 0xff);
 
 165         WriteHSCX(cs, 1, HSCX_MASK, 0xff);
 
 166         WriteISAC(cs, ISAC_MASK, 0xff);
 
 167         WriteISAC(cs, ISAC_MASK, 0x00);
 
 168         WriteHSCX(cs, 0, HSCX_MASK, 0x00);
 
 169         WriteHSCX(cs, 1, HSCX_MASK, 0x00);
 
 170         spin_unlock_irqrestore(&cs->lock, flags);
 
 175 AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 
 181                         spin_lock_irqsave(&cs->lock, flags);
 
 182                         byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
 
 184                         byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
 
 186                         byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
 
 187                         spin_unlock_irqrestore(&cs->lock, flags);
 
 191                         /* free_irq is done in HiSax_closecard(). */
 
 192                         /* free_irq(cs->irq, cs); */
 
 196                         spin_lock_irqsave(&cs->lock, flags);
 
 197                         byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
 
 198                         clear_pending_isac_ints(cs);
 
 199                         clear_pending_hscx_ints(cs);
 
 202                         spin_unlock_irqrestore(&cs->lock, flags);
 
 206                         /* we really don't need it for the PCMCIA Version */
 
 210                         /* all card drivers ignore others, so we do the same */
 
 217 setup_avm_a1_pcmcia(struct IsdnCard *card)
 
 220         struct IsdnCardState *cs = card->cs;
 
 224         strcpy(tmp, avm_revision);
 
 225         printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
 
 227         if (cs->typ != ISDN_CTYPE_A1_PCMCIA)
 
 230         cs->hw.avm.cfg_reg = card->para[1];
 
 231         cs->irq = card->para[0];
 
 234         byteout(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
 
 235         byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
 
 237         byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
 
 239         byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
 
 241         byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, ASL0_W_TDISABLE|ASL0_W_TRESET);
 
 243         model = bytein(cs->hw.avm.cfg_reg+MODREG_OFFSET);
 
 244         vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
 
 246         printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
 
 247                                 cs->hw.avm.cfg_reg, cs->irq, model, vers);
 
 250         cs->readisac = &ReadISAC;
 
 251         cs->writeisac = &WriteISAC;
 
 252         cs->readisacfifo = &ReadISACfifo;
 
 253         cs->writeisacfifo = &WriteISACfifo;
 
 254         cs->BC_Read_Reg = &ReadHSCX;
 
 255         cs->BC_Write_Reg = &WriteHSCX;
 
 256         cs->BC_Send_Data = &hscx_fill_fifo;
 
 257         cs->cardmsg = &AVM_card_msg;
 
 258         cs->irq_flags = SA_SHIRQ;
 
 259         cs->irq_func = &avm_a1p_interrupt;
 
 261         ISACVersion(cs, "AVM A1 PCMCIA:");
 
 262         if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
 
 264                        "AVM A1 PCMCIA: wrong HSCX versions check IO address\n");