hscx.c revision 672c3fd9069e5a138f9d4afc9aeb5aa34aacce32
1/* $Id: hscx.c,v 1.24.2.4 2004/01/24 20:47:23 keil Exp $ 2 * 3 * HSCX specific routines 4 * 5 * Author Karsten Keil 6 * Copyright by Karsten Keil <keil@isdn4linux.de> 7 * 8 * This software may be used and distributed according to the terms 9 * of the GNU General Public License, incorporated herein by reference. 10 * 11 */ 12 13#include <linux/init.h> 14#include "hisax.h" 15#include "hscx.h" 16#include "isac.h" 17#include "isdnl1.h" 18#include <linux/interrupt.h> 19 20static char *HSCXVer[] = 21{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", 22 "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"}; 23 24int 25HscxVersion(struct IsdnCardState *cs, char *s) 26{ 27 int verA, verB; 28 29 verA = cs->BC_Read_Reg(cs, 0, HSCX_VSTR) & 0xf; 30 verB = cs->BC_Read_Reg(cs, 1, HSCX_VSTR) & 0xf; 31 printk(KERN_INFO "%s HSCX version A: %s B: %s\n", s, 32 HSCXVer[verA], HSCXVer[verB]); 33 if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf)) 34 return (1); 35 else 36 return (0); 37} 38 39void 40modehscx(struct BCState *bcs, int mode, int bc) 41{ 42 struct IsdnCardState *cs = bcs->cs; 43 int hscx = bcs->hw.hscx.hscx; 44 45 if (cs->debug & L1_DEB_HSCX) 46 debugl1(cs, "hscx %c mode %d ichan %d", 47 'A' + hscx, mode, bc); 48 bcs->mode = mode; 49 bcs->channel = bc; 50 cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF); 51 cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF); 52 cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF); 53 cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0); 54 cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0); 55 cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, 56 test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85); 57 cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30); 58 cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7); 59 cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7); 60 61 /* Switch IOM 1 SSI */ 62 if (test_bit(HW_IOM1, &cs->HW_Flags) && (hscx == 0)) 63 bc = 1 - bc; 64 65 if (bc == 0) { 66 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 67 test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0); 68 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 69 test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0); 70 } else { 71 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1); 72 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1); 73 } 74 switch (mode) { 75 case (L1_MODE_NULL): 76 cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f); 77 cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f); 78 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84); 79 break; 80 case (L1_MODE_TRANS): 81 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4); 82 break; 83 case (L1_MODE_HDLC): 84 cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, 85 test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d); 86 cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c); 87 break; 88 } 89 if (mode) 90 cs->BC_Write_Reg(cs, hscx, HSCX_CMDR, 0x41); 91 cs->BC_Write_Reg(cs, hscx, HSCX_ISTA, 0x00); 92} 93 94void 95hscx_l2l1(struct PStack *st, int pr, void *arg) 96{ 97 struct BCState *bcs = st->l1.bcs; 98 u_long flags; 99 struct sk_buff *skb = arg; 100 101 switch (pr) { 102 case (PH_DATA | REQUEST): 103 spin_lock_irqsave(&bcs->cs->lock, flags); 104 if (bcs->tx_skb) { 105 skb_queue_tail(&bcs->squeue, skb); 106 } else { 107 bcs->tx_skb = skb; 108 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); 109 bcs->hw.hscx.count = 0; 110 bcs->cs->BC_Send_Data(bcs); 111 } 112 spin_unlock_irqrestore(&bcs->cs->lock, flags); 113 break; 114 case (PH_PULL | INDICATION): 115 spin_lock_irqsave(&bcs->cs->lock, flags); 116 if (bcs->tx_skb) { 117 printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n"); 118 } else { 119 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); 120 bcs->tx_skb = skb; 121 bcs->hw.hscx.count = 0; 122 bcs->cs->BC_Send_Data(bcs); 123 } 124 spin_unlock_irqrestore(&bcs->cs->lock, flags); 125 break; 126 case (PH_PULL | REQUEST): 127 if (!bcs->tx_skb) { 128 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 129 st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); 130 } else 131 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 132 break; 133 case (PH_ACTIVATE | REQUEST): 134 spin_lock_irqsave(&bcs->cs->lock, flags); 135 test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); 136 modehscx(bcs, st->l1.mode, st->l1.bc); 137 spin_unlock_irqrestore(&bcs->cs->lock, flags); 138 l1_msg_b(st, pr, arg); 139 break; 140 case (PH_DEACTIVATE | REQUEST): 141 l1_msg_b(st, pr, arg); 142 break; 143 case (PH_DEACTIVATE | CONFIRM): 144 spin_lock_irqsave(&bcs->cs->lock, flags); 145 test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); 146 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); 147 modehscx(bcs, 0, st->l1.bc); 148 spin_unlock_irqrestore(&bcs->cs->lock, flags); 149 st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); 150 break; 151 } 152} 153 154static void 155close_hscxstate(struct BCState *bcs) 156{ 157 modehscx(bcs, 0, bcs->channel); 158 if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { 159 if (bcs->hw.hscx.rcvbuf) { 160 kfree(bcs->hw.hscx.rcvbuf); 161 bcs->hw.hscx.rcvbuf = NULL; 162 } 163 if (bcs->blog) { 164 kfree(bcs->blog); 165 bcs->blog = NULL; 166 } 167 skb_queue_purge(&bcs->rqueue); 168 skb_queue_purge(&bcs->squeue); 169 if (bcs->tx_skb) { 170 dev_kfree_skb_any(bcs->tx_skb); 171 bcs->tx_skb = NULL; 172 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); 173 } 174 } 175} 176 177int 178open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs) 179{ 180 if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { 181 if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { 182 printk(KERN_WARNING 183 "HiSax: No memory for hscx.rcvbuf\n"); 184 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); 185 return (1); 186 } 187 if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { 188 printk(KERN_WARNING 189 "HiSax: No memory for bcs->blog\n"); 190 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); 191 kfree(bcs->hw.hscx.rcvbuf); 192 bcs->hw.hscx.rcvbuf = NULL; 193 return (2); 194 } 195 skb_queue_head_init(&bcs->rqueue); 196 skb_queue_head_init(&bcs->squeue); 197 } 198 bcs->tx_skb = NULL; 199 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); 200 bcs->event = 0; 201 bcs->hw.hscx.rcvidx = 0; 202 bcs->tx_cnt = 0; 203 return (0); 204} 205 206static int 207setstack_hscx(struct PStack *st, struct BCState *bcs) 208{ 209 bcs->channel = st->l1.bc; 210 if (open_hscxstate(st->l1.hardware, bcs)) 211 return (-1); 212 st->l1.bcs = bcs; 213 st->l2.l2l1 = hscx_l2l1; 214 setstack_manager(st); 215 bcs->st = st; 216 setstack_l1_B(st); 217 return (0); 218} 219 220void 221clear_pending_hscx_ints(struct IsdnCardState *cs) 222{ 223 int val, eval; 224 225 val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA); 226 debugl1(cs, "HSCX B ISTA %x", val); 227 if (val & 0x01) { 228 eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR); 229 debugl1(cs, "HSCX B EXIR %x", eval); 230 } 231 if (val & 0x02) { 232 eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR); 233 debugl1(cs, "HSCX A EXIR %x", eval); 234 } 235 val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA); 236 debugl1(cs, "HSCX A ISTA %x", val); 237 val = cs->BC_Read_Reg(cs, 1, HSCX_STAR); 238 debugl1(cs, "HSCX B STAR %x", val); 239 val = cs->BC_Read_Reg(cs, 0, HSCX_STAR); 240 debugl1(cs, "HSCX A STAR %x", val); 241 /* disable all IRQ */ 242 cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF); 243 cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF); 244} 245 246void 247inithscx(struct IsdnCardState *cs) 248{ 249 cs->bcs[0].BC_SetStack = setstack_hscx; 250 cs->bcs[1].BC_SetStack = setstack_hscx; 251 cs->bcs[0].BC_Close = close_hscxstate; 252 cs->bcs[1].BC_Close = close_hscxstate; 253 cs->bcs[0].hw.hscx.hscx = 0; 254 cs->bcs[1].hw.hscx.hscx = 1; 255 cs->bcs[0].hw.hscx.tsaxr0 = 0x2f; 256 cs->bcs[0].hw.hscx.tsaxr1 = 3; 257 cs->bcs[1].hw.hscx.tsaxr0 = 0x2f; 258 cs->bcs[1].hw.hscx.tsaxr1 = 3; 259 modehscx(cs->bcs, 0, 0); 260 modehscx(cs->bcs + 1, 0, 0); 261} 262 263void 264inithscxisac(struct IsdnCardState *cs, int part) 265{ 266 if (part & 1) { 267 clear_pending_isac_ints(cs); 268 clear_pending_hscx_ints(cs); 269 initisac(cs); 270 inithscx(cs); 271 } 272 if (part & 2) { 273 /* Reenable all IRQ */ 274 cs->writeisac(cs, ISAC_MASK, 0); 275 cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0); 276 cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0); 277 /* RESET Receiver and Transmitter */ 278 cs->writeisac(cs, ISAC_CMDR, 0x41); 279 } 280} 281