| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 1 | /* | 
|  | 2 | * hfcmulti.c  low level driver for hfc-4s/hfc-8s/hfc-e1 based cards | 
|  | 3 | * | 
|  | 4 | * Author	Andreas Eversberg (jolly@eversberg.eu) | 
|  | 5 | * ported to mqueue mechanism: | 
|  | 6 | *		Peter Sprenger (sprengermoving-bytes.de) | 
|  | 7 | * | 
|  | 8 | * inspired by existing hfc-pci driver: | 
|  | 9 | * Copyright 1999  by Werner Cornelius (werner@isdn-development.de) | 
|  | 10 | * Copyright 2008  by Karsten Keil (kkeil@suse.de) | 
|  | 11 | * Copyright 2008  by Andreas Eversberg (jolly@eversberg.eu) | 
|  | 12 | * | 
|  | 13 | * This program is free software; you can redistribute it and/or modify | 
|  | 14 | * it under the terms of the GNU General Public License as published by | 
|  | 15 | * the Free Software Foundation; either version 2, or (at your option) | 
|  | 16 | * any later version. | 
|  | 17 | * | 
|  | 18 | * This program is distributed in the hope that it will be useful, | 
|  | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 21 | * GNU General Public License for more details. | 
|  | 22 | * | 
|  | 23 | * You should have received a copy of the GNU General Public License | 
|  | 24 | * along with this program; if not, write to the Free Software | 
|  | 25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
|  | 26 | * | 
|  | 27 | * | 
|  | 28 | * Thanks to Cologne Chip AG for this great controller! | 
|  | 29 | */ | 
|  | 30 |  | 
|  | 31 | /* | 
|  | 32 | * module parameters: | 
|  | 33 | * type: | 
|  | 34 | *	By default (0), the card is automatically detected. | 
|  | 35 | *	Or use the following combinations: | 
|  | 36 | *	Bit 0-7   = 0x00001 = HFC-E1 (1 port) | 
|  | 37 | * or	Bit 0-7   = 0x00004 = HFC-4S (4 ports) | 
|  | 38 | * or	Bit 0-7   = 0x00008 = HFC-8S (8 ports) | 
|  | 39 | *	Bit 8     = 0x00100 = uLaw (instead of aLaw) | 
|  | 40 | *	Bit 9     = 0x00200 = Disable DTMF detect on all B-channels via hardware | 
|  | 41 | *	Bit 10    = spare | 
|  | 42 | *	Bit 11    = 0x00800 = Force PCM bus into slave mode. (otherwhise auto) | 
|  | 43 | * or   Bit 12    = 0x01000 = Force PCM bus into master mode. (otherwhise auto) | 
|  | 44 | *	Bit 13	  = spare | 
|  | 45 | *	Bit 14    = 0x04000 = Use external ram (128K) | 
|  | 46 | *	Bit 15    = 0x08000 = Use external ram (512K) | 
|  | 47 | *	Bit 16    = 0x10000 = Use 64 timeslots instead of 32 | 
|  | 48 | * or	Bit 17    = 0x20000 = Use 128 timeslots instead of anything else | 
|  | 49 | *	Bit 18    = spare | 
|  | 50 | *	Bit 19    = 0x80000 = Send the Watchdog a Signal (Dual E1 with Watchdog) | 
|  | 51 | * (all other bits are reserved and shall be 0) | 
|  | 52 | *	example: 0x20204 one HFC-4S with dtmf detection and 128 timeslots on PCM | 
|  | 53 | *		 bus (PCM master) | 
|  | 54 | * | 
|  | 55 | * port: (optional or required for all ports on all installed cards) | 
|  | 56 | *	HFC-4S/HFC-8S only bits: | 
|  | 57 | *	Bit 0	  = 0x001 = Use master clock for this S/T interface | 
|  | 58 | *			    (ony once per chip). | 
|  | 59 | *	Bit 1     = 0x002 = transmitter line setup (non capacitive mode) | 
|  | 60 | *			    Don't use this unless you know what you are doing! | 
|  | 61 | *	Bit 2     = 0x004 = Disable E-channel. (No E-channel processing) | 
|  | 62 | *	example: 0x0001,0x0000,0x0000,0x0000 one HFC-4S with master clock | 
|  | 63 | *		 received from port 1 | 
|  | 64 | * | 
|  | 65 | *	HFC-E1 only bits: | 
|  | 66 | *	Bit 0     = 0x0001 = interface: 0=copper, 1=optical | 
|  | 67 | *	Bit 1     = 0x0002 = reserved (later for 32 B-channels transparent mode) | 
|  | 68 | *	Bit 2     = 0x0004 = Report LOS | 
|  | 69 | *	Bit 3     = 0x0008 = Report AIS | 
|  | 70 | *	Bit 4     = 0x0010 = Report SLIP | 
|  | 71 | *	Bit 5     = 0x0020 = Report RDI | 
|  | 72 | *	Bit 8     = 0x0100 = Turn off CRC-4 Multiframe Mode, use double frame | 
|  | 73 | *			     mode instead. | 
|  | 74 | *	Bit 9	  = 0x0200 = Force get clock from interface, even in NT mode. | 
|  | 75 | * or	Bit 10	  = 0x0400 = Force put clock to interface, even in TE mode. | 
|  | 76 | *	Bit 11    = 0x0800 = Use direct RX clock for PCM sync rather than PLL. | 
|  | 77 | *			     (E1 only) | 
|  | 78 | *	Bit 12-13 = 0xX000 = elastic jitter buffer (1-3), Set both bits to 0 | 
|  | 79 | *			     for default. | 
|  | 80 | * (all other bits are reserved and shall be 0) | 
|  | 81 | * | 
|  | 82 | * debug: | 
|  | 83 | *	NOTE: only one debug value must be given for all cards | 
|  | 84 | *	enable debugging (see hfc_multi.h for debug options) | 
|  | 85 | * | 
|  | 86 | * poll: | 
|  | 87 | *	NOTE: only one poll value must be given for all cards | 
|  | 88 | *	Give the number of samples for each fifo process. | 
|  | 89 | *	By default 128 is used. Decrease to reduce delay, increase to | 
|  | 90 | *	reduce cpu load. If unsure, don't mess with it! | 
|  | 91 | *	Valid is 8, 16, 32, 64, 128, 256. | 
|  | 92 | * | 
|  | 93 | * pcm: | 
|  | 94 | *	NOTE: only one pcm value must be given for every card. | 
|  | 95 | *	The PCM bus id tells the mISDNdsp module about the connected PCM bus. | 
|  | 96 | *	By default (0), the PCM bus id is 100 for the card that is PCM master. | 
|  | 97 | *	If multiple cards are PCM master (because they are not interconnected), | 
|  | 98 | *	each card with PCM master will have increasing PCM id. | 
|  | 99 | *	All PCM busses with the same ID are expected to be connected and have | 
|  | 100 | *	common time slots slots. | 
|  | 101 | *	Only one chip of the PCM bus must be master, the others slave. | 
|  | 102 | *	-1 means no support of PCM bus not even. | 
|  | 103 | *	Omit this value, if all cards are interconnected or none is connected. | 
|  | 104 | *	If unsure, don't give this parameter. | 
|  | 105 | * | 
|  | 106 | * dslot: | 
|  | 107 | *	NOTE: only one poll value must be given for every card. | 
|  | 108 | *	Also this value must be given for non-E1 cards. If omitted, the E1 | 
|  | 109 | *	card has D-channel on time slot 16, which is default. | 
|  | 110 | *	If 1..15 or 17..31, an alternate time slot is used for D-channel. | 
|  | 111 | *	In this case, the application must be able to handle this. | 
|  | 112 | *	If -1 is given, the D-channel is disabled and all 31 slots can be used | 
|  | 113 | *	for B-channel. (only for specific applications) | 
|  | 114 | *	If you don't know how to use it, you don't need it! | 
|  | 115 | * | 
|  | 116 | * iomode: | 
|  | 117 | *	NOTE: only one mode value must be given for every card. | 
|  | 118 | *	-> See hfc_multi.h for HFC_IO_MODE_* values | 
|  | 119 | *	By default, the IO mode is pci memory IO (MEMIO). | 
|  | 120 | *	Some cards requre specific IO mode, so it cannot be changed. | 
|  | 121 | *	It may be usefull to set IO mode to register io (REGIO) to solve | 
|  | 122 | *	PCI bridge problems. | 
|  | 123 | *	If unsure, don't give this parameter. | 
|  | 124 | * | 
|  | 125 | * clockdelay_nt: | 
|  | 126 | *	NOTE: only one clockdelay_nt value must be given once for all cards. | 
|  | 127 | *	Give the value of the clock control register (A_ST_CLK_DLY) | 
|  | 128 | *	of the S/T interfaces in NT mode. | 
|  | 129 | *	This register is needed for the TBR3 certification, so don't change it. | 
|  | 130 | * | 
|  | 131 | * clockdelay_te: | 
|  | 132 | *	NOTE: only one clockdelay_te value must be given once | 
|  | 133 | *	Give the value of the clock control register (A_ST_CLK_DLY) | 
|  | 134 | *	of the S/T interfaces in TE mode. | 
|  | 135 | *	This register is needed for the TBR3 certification, so don't change it. | 
|  | 136 | */ | 
|  | 137 |  | 
|  | 138 | /* | 
|  | 139 | * debug register access (never use this, it will flood your system log) | 
|  | 140 | * #define HFC_REGISTER_DEBUG | 
|  | 141 | */ | 
|  | 142 |  | 
| Karsten Keil | 31981db | 2008-08-02 16:40:37 +0200 | [diff] [blame] | 143 | static const char *hfcmulti_revision = "2.02"; | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 144 |  | 
|  | 145 | #include <linux/module.h> | 
|  | 146 | #include <linux/pci.h> | 
|  | 147 | #include <linux/delay.h> | 
|  | 148 | #include <linux/mISDNhw.h> | 
|  | 149 | #include <linux/mISDNdsp.h> | 
|  | 150 |  | 
|  | 151 | /* | 
|  | 152 | #define IRQCOUNT_DEBUG | 
|  | 153 | #define IRQ_DEBUG | 
|  | 154 | */ | 
|  | 155 |  | 
|  | 156 | #include "hfc_multi.h" | 
|  | 157 | #ifdef ECHOPREP | 
|  | 158 | #include "gaintab.h" | 
|  | 159 | #endif | 
|  | 160 |  | 
|  | 161 | #define	MAX_CARDS	8 | 
|  | 162 | #define	MAX_PORTS	(8 * MAX_CARDS) | 
|  | 163 |  | 
|  | 164 | static LIST_HEAD(HFClist); | 
|  | 165 | static spinlock_t HFClock; /* global hfc list lock */ | 
|  | 166 |  | 
|  | 167 | static void ph_state_change(struct dchannel *); | 
|  | 168 | static void (*hfc_interrupt)(void); | 
|  | 169 | static void (*register_interrupt)(void); | 
|  | 170 | static int (*unregister_interrupt)(void); | 
|  | 171 | static int interrupt_registered; | 
|  | 172 |  | 
|  | 173 | static struct hfc_multi *syncmaster; | 
|  | 174 | int plxsd_master; /* if we have a master card (yet) */ | 
|  | 175 | static spinlock_t plx_lock; /* may not acquire other lock inside */ | 
|  | 176 | EXPORT_SYMBOL(plx_lock); | 
|  | 177 |  | 
|  | 178 | #define	TYP_E1		1 | 
|  | 179 | #define	TYP_4S		4 | 
|  | 180 | #define TYP_8S		8 | 
|  | 181 |  | 
|  | 182 | static int poll_timer = 6;	/* default = 128 samples = 16ms */ | 
|  | 183 | /* number of POLL_TIMER interrupts for G2 timeout (ca 1s) */ | 
|  | 184 | static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30  }; | 
|  | 185 | #define	CLKDEL_TE	0x0f	/* CLKDEL in TE mode */ | 
|  | 186 | #define	CLKDEL_NT	0x6c	/* CLKDEL in NT mode | 
|  | 187 | (0x60 MUST be included!) */ | 
|  | 188 | static u_char silence =	0xff;	/* silence by LAW */ | 
|  | 189 |  | 
|  | 190 | #define	DIP_4S	0x1		/* DIP Switches for Beronet 1S/2S/4S cards */ | 
|  | 191 | #define	DIP_8S	0x2		/* DIP Switches for Beronet 8S+ cards */ | 
|  | 192 | #define	DIP_E1	0x3		/* DIP Switches for Beronet E1 cards */ | 
|  | 193 |  | 
|  | 194 | /* | 
|  | 195 | * module stuff | 
|  | 196 | */ | 
|  | 197 |  | 
|  | 198 | static uint	type[MAX_CARDS]; | 
|  | 199 | static uint	pcm[MAX_CARDS]; | 
|  | 200 | static uint	dslot[MAX_CARDS]; | 
|  | 201 | static uint	iomode[MAX_CARDS]; | 
|  | 202 | static uint	port[MAX_PORTS]; | 
|  | 203 | static uint	debug; | 
|  | 204 | static uint	poll; | 
|  | 205 | static uint	timer; | 
|  | 206 | static uint	clockdelay_te = CLKDEL_TE; | 
|  | 207 | static uint	clockdelay_nt = CLKDEL_NT; | 
|  | 208 |  | 
|  | 209 | static int	HFC_cnt, Port_cnt, PCM_cnt = 99; | 
|  | 210 |  | 
|  | 211 | MODULE_AUTHOR("Andreas Eversberg"); | 
|  | 212 | MODULE_LICENSE("GPL"); | 
|  | 213 | module_param(debug, uint, S_IRUGO | S_IWUSR); | 
|  | 214 | module_param(poll, uint, S_IRUGO | S_IWUSR); | 
|  | 215 | module_param(timer, uint, S_IRUGO | S_IWUSR); | 
|  | 216 | module_param(clockdelay_te, uint, S_IRUGO | S_IWUSR); | 
|  | 217 | module_param(clockdelay_nt, uint, S_IRUGO | S_IWUSR); | 
|  | 218 | module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR); | 
|  | 219 | module_param_array(pcm, uint, NULL, S_IRUGO | S_IWUSR); | 
|  | 220 | module_param_array(dslot, uint, NULL, S_IRUGO | S_IWUSR); | 
|  | 221 | module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR); | 
|  | 222 | module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR); | 
|  | 223 |  | 
|  | 224 | #ifdef HFC_REGISTER_DEBUG | 
|  | 225 | #define HFC_outb(hc, reg, val) \ | 
|  | 226 | (hc->HFC_outb(hc, reg, val, __func__, __LINE__)) | 
|  | 227 | #define HFC_outb_nodebug(hc, reg, val) \ | 
|  | 228 | (hc->HFC_outb_nodebug(hc, reg, val, __func__, __LINE__)) | 
|  | 229 | #define HFC_inb(hc, reg) \ | 
|  | 230 | (hc->HFC_inb(hc, reg, __func__, __LINE__)) | 
|  | 231 | #define HFC_inb_nodebug(hc, reg) \ | 
|  | 232 | (hc->HFC_inb_nodebug(hc, reg, __func__, __LINE__)) | 
|  | 233 | #define HFC_inw(hc, reg) \ | 
|  | 234 | (hc->HFC_inw(hc, reg, __func__, __LINE__)) | 
|  | 235 | #define HFC_inw_nodebug(hc, reg) \ | 
|  | 236 | (hc->HFC_inw_nodebug(hc, reg, __func__, __LINE__)) | 
|  | 237 | #define HFC_wait(hc) \ | 
|  | 238 | (hc->HFC_wait(hc, __func__, __LINE__)) | 
|  | 239 | #define HFC_wait_nodebug(hc) \ | 
|  | 240 | (hc->HFC_wait_nodebug(hc, __func__, __LINE__)) | 
|  | 241 | #else | 
|  | 242 | #define HFC_outb(hc, reg, val)		(hc->HFC_outb(hc, reg, val)) | 
|  | 243 | #define HFC_outb_nodebug(hc, reg, val)	(hc->HFC_outb_nodebug(hc, reg, val)) | 
|  | 244 | #define HFC_inb(hc, reg)		(hc->HFC_inb(hc, reg)) | 
|  | 245 | #define HFC_inb_nodebug(hc, reg)	(hc->HFC_inb_nodebug(hc, reg)) | 
|  | 246 | #define HFC_inw(hc, reg)		(hc->HFC_inw(hc, reg)) | 
|  | 247 | #define HFC_inw_nodebug(hc, reg)	(hc->HFC_inw_nodebug(hc, reg)) | 
|  | 248 | #define HFC_wait(hc)			(hc->HFC_wait(hc)) | 
|  | 249 | #define HFC_wait_nodebug(hc)		(hc->HFC_wait_nodebug(hc)) | 
|  | 250 | #endif | 
|  | 251 |  | 
|  | 252 | /* HFC_IO_MODE_PCIMEM */ | 
|  | 253 | static void | 
|  | 254 | #ifdef HFC_REGISTER_DEBUG | 
|  | 255 | HFC_outb_pcimem(struct hfc_multi *hc, u_char reg, u_char val, | 
|  | 256 | const char *function, int line) | 
|  | 257 | #else | 
|  | 258 | HFC_outb_pcimem(struct hfc_multi *hc, u_char reg, u_char val) | 
|  | 259 | #endif | 
|  | 260 | { | 
|  | 261 | writeb(val, (hc->pci_membase)+reg); | 
|  | 262 | } | 
|  | 263 | static u_char | 
|  | 264 | #ifdef HFC_REGISTER_DEBUG | 
|  | 265 | HFC_inb_pcimem(struct hfc_multi *hc, u_char reg, const char *function, int line) | 
|  | 266 | #else | 
|  | 267 | HFC_inb_pcimem(struct hfc_multi *hc, u_char reg) | 
|  | 268 | #endif | 
|  | 269 | { | 
|  | 270 | return readb((hc->pci_membase)+reg); | 
|  | 271 | } | 
|  | 272 | static u_short | 
|  | 273 | #ifdef HFC_REGISTER_DEBUG | 
|  | 274 | HFC_inw_pcimem(struct hfc_multi *hc, u_char reg, const char *function, int line) | 
|  | 275 | #else | 
|  | 276 | HFC_inw_pcimem(struct hfc_multi *hc, u_char reg) | 
|  | 277 | #endif | 
|  | 278 | { | 
|  | 279 | return readw((hc->pci_membase)+reg); | 
|  | 280 | } | 
|  | 281 | static void | 
|  | 282 | #ifdef HFC_REGISTER_DEBUG | 
|  | 283 | HFC_wait_pcimem(struct hfc_multi *hc, const char *function, int line) | 
|  | 284 | #else | 
|  | 285 | HFC_wait_pcimem(struct hfc_multi *hc) | 
|  | 286 | #endif | 
|  | 287 | { | 
|  | 288 | while (readb((hc->pci_membase)+R_STATUS) & V_BUSY); | 
|  | 289 | } | 
|  | 290 |  | 
|  | 291 | /* HFC_IO_MODE_REGIO */ | 
|  | 292 | static void | 
|  | 293 | #ifdef HFC_REGISTER_DEBUG | 
|  | 294 | HFC_outb_regio(struct hfc_multi *hc, u_char reg, u_char val, | 
|  | 295 | const char *function, int line) | 
|  | 296 | #else | 
|  | 297 | HFC_outb_regio(struct hfc_multi *hc, u_char reg, u_char val) | 
|  | 298 | #endif | 
|  | 299 | { | 
|  | 300 | outb(reg, (hc->pci_iobase)+4); | 
|  | 301 | outb(val, hc->pci_iobase); | 
|  | 302 | } | 
|  | 303 | static u_char | 
|  | 304 | #ifdef HFC_REGISTER_DEBUG | 
|  | 305 | HFC_inb_regio(struct hfc_multi *hc, u_char reg, const char *function, int line) | 
|  | 306 | #else | 
|  | 307 | HFC_inb_regio(struct hfc_multi *hc, u_char reg) | 
|  | 308 | #endif | 
|  | 309 | { | 
|  | 310 | outb(reg, (hc->pci_iobase)+4); | 
|  | 311 | return inb(hc->pci_iobase); | 
|  | 312 | } | 
|  | 313 | static u_short | 
|  | 314 | #ifdef HFC_REGISTER_DEBUG | 
|  | 315 | HFC_inw_regio(struct hfc_multi *hc, u_char reg, const char *function, int line) | 
|  | 316 | #else | 
|  | 317 | HFC_inw_regio(struct hfc_multi *hc, u_char reg) | 
|  | 318 | #endif | 
|  | 319 | { | 
|  | 320 | outb(reg, (hc->pci_iobase)+4); | 
|  | 321 | return inw(hc->pci_iobase); | 
|  | 322 | } | 
|  | 323 | static void | 
|  | 324 | #ifdef HFC_REGISTER_DEBUG | 
|  | 325 | HFC_wait_regio(struct hfc_multi *hc, const char *function, int line) | 
|  | 326 | #else | 
|  | 327 | HFC_wait_regio(struct hfc_multi *hc) | 
|  | 328 | #endif | 
|  | 329 | { | 
|  | 330 | outb(R_STATUS, (hc->pci_iobase)+4); | 
|  | 331 | while (inb(hc->pci_iobase) & V_BUSY); | 
|  | 332 | } | 
|  | 333 |  | 
|  | 334 | #ifdef HFC_REGISTER_DEBUG | 
|  | 335 | static void | 
|  | 336 | HFC_outb_debug(struct hfc_multi *hc, u_char reg, u_char val, | 
|  | 337 | const char *function, int line) | 
|  | 338 | { | 
|  | 339 | char regname[256] = "", bits[9] = "xxxxxxxx"; | 
|  | 340 | int i; | 
|  | 341 |  | 
|  | 342 | i = -1; | 
|  | 343 | while (hfc_register_names[++i].name) { | 
|  | 344 | if (hfc_register_names[i].reg == reg) | 
|  | 345 | strcat(regname, hfc_register_names[i].name); | 
|  | 346 | } | 
|  | 347 | if (regname[0] == '\0') | 
|  | 348 | strcpy(regname, "register"); | 
|  | 349 |  | 
|  | 350 | bits[7] = '0'+(!!(val&1)); | 
|  | 351 | bits[6] = '0'+(!!(val&2)); | 
|  | 352 | bits[5] = '0'+(!!(val&4)); | 
|  | 353 | bits[4] = '0'+(!!(val&8)); | 
|  | 354 | bits[3] = '0'+(!!(val&16)); | 
|  | 355 | bits[2] = '0'+(!!(val&32)); | 
|  | 356 | bits[1] = '0'+(!!(val&64)); | 
|  | 357 | bits[0] = '0'+(!!(val&128)); | 
|  | 358 | printk(KERN_DEBUG | 
|  | 359 | "HFC_outb(chip %d, %02x=%s, 0x%02x=%s); in %s() line %d\n", | 
|  | 360 | hc->id, reg, regname, val, bits, function, line); | 
|  | 361 | HFC_outb_nodebug(hc, reg, val); | 
|  | 362 | } | 
|  | 363 | static u_char | 
|  | 364 | HFC_inb_debug(struct hfc_multi *hc, u_char reg, const char *function, int line) | 
|  | 365 | { | 
|  | 366 | char regname[256] = "", bits[9] = "xxxxxxxx"; | 
|  | 367 | u_char val = HFC_inb_nodebug(hc, reg); | 
|  | 368 | int i; | 
|  | 369 |  | 
|  | 370 | i = 0; | 
|  | 371 | while (hfc_register_names[i++].name) | 
|  | 372 | ; | 
|  | 373 | while (hfc_register_names[++i].name) { | 
|  | 374 | if (hfc_register_names[i].reg == reg) | 
|  | 375 | strcat(regname, hfc_register_names[i].name); | 
|  | 376 | } | 
|  | 377 | if (regname[0] == '\0') | 
|  | 378 | strcpy(regname, "register"); | 
|  | 379 |  | 
|  | 380 | bits[7] = '0'+(!!(val&1)); | 
|  | 381 | bits[6] = '0'+(!!(val&2)); | 
|  | 382 | bits[5] = '0'+(!!(val&4)); | 
|  | 383 | bits[4] = '0'+(!!(val&8)); | 
|  | 384 | bits[3] = '0'+(!!(val&16)); | 
|  | 385 | bits[2] = '0'+(!!(val&32)); | 
|  | 386 | bits[1] = '0'+(!!(val&64)); | 
|  | 387 | bits[0] = '0'+(!!(val&128)); | 
|  | 388 | printk(KERN_DEBUG | 
|  | 389 | "HFC_inb(chip %d, %02x=%s) = 0x%02x=%s; in %s() line %d\n", | 
|  | 390 | hc->id, reg, regname, val, bits, function, line); | 
|  | 391 | return val; | 
|  | 392 | } | 
|  | 393 | static u_short | 
|  | 394 | HFC_inw_debug(struct hfc_multi *hc, u_char reg, const char *function, int line) | 
|  | 395 | { | 
|  | 396 | char regname[256] = ""; | 
|  | 397 | u_short val = HFC_inw_nodebug(hc, reg); | 
|  | 398 | int i; | 
|  | 399 |  | 
|  | 400 | i = 0; | 
|  | 401 | while (hfc_register_names[i++].name) | 
|  | 402 | ; | 
|  | 403 | while (hfc_register_names[++i].name) { | 
|  | 404 | if (hfc_register_names[i].reg == reg) | 
|  | 405 | strcat(regname, hfc_register_names[i].name); | 
|  | 406 | } | 
|  | 407 | if (regname[0] == '\0') | 
|  | 408 | strcpy(regname, "register"); | 
|  | 409 |  | 
|  | 410 | printk(KERN_DEBUG | 
|  | 411 | "HFC_inw(chip %d, %02x=%s) = 0x%04x; in %s() line %d\n", | 
|  | 412 | hc->id, reg, regname, val, function, line); | 
|  | 413 | return val; | 
|  | 414 | } | 
|  | 415 | static void | 
|  | 416 | HFC_wait_debug(struct hfc_multi *hc, const char *function, int line) | 
|  | 417 | { | 
|  | 418 | printk(KERN_DEBUG "HFC_wait(chip %d); in %s() line %d\n", | 
|  | 419 | hc->id, function, line); | 
|  | 420 | HFC_wait_nodebug(hc); | 
|  | 421 | } | 
|  | 422 | #endif | 
|  | 423 |  | 
|  | 424 | /* write fifo data (REGIO) */ | 
|  | 425 | void | 
|  | 426 | write_fifo_regio(struct hfc_multi *hc, u_char *data, int len) | 
|  | 427 | { | 
|  | 428 | outb(A_FIFO_DATA0, (hc->pci_iobase)+4); | 
|  | 429 | while (len>>2) { | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 430 | outl(cpu_to_le32(*(u32 *)data), hc->pci_iobase); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 431 | data += 4; | 
|  | 432 | len -= 4; | 
|  | 433 | } | 
|  | 434 | while (len>>1) { | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 435 | outw(cpu_to_le16(*(u16 *)data), hc->pci_iobase); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 436 | data += 2; | 
|  | 437 | len -= 2; | 
|  | 438 | } | 
|  | 439 | while (len) { | 
|  | 440 | outb(*data, hc->pci_iobase); | 
|  | 441 | data++; | 
|  | 442 | len--; | 
|  | 443 | } | 
|  | 444 | } | 
|  | 445 | /* write fifo data (PCIMEM) */ | 
|  | 446 | void | 
|  | 447 | write_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) | 
|  | 448 | { | 
|  | 449 | while (len>>2) { | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 450 | writel(cpu_to_le32(*(u32 *)data), | 
|  | 451 | hc->pci_membase + A_FIFO_DATA0); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 452 | data += 4; | 
|  | 453 | len -= 4; | 
|  | 454 | } | 
|  | 455 | while (len>>1) { | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 456 | writew(cpu_to_le16(*(u16 *)data), | 
|  | 457 | hc->pci_membase + A_FIFO_DATA0); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 458 | data += 2; | 
|  | 459 | len -= 2; | 
|  | 460 | } | 
|  | 461 | while (len) { | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 462 | writeb(*data, hc->pci_membase + A_FIFO_DATA0); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 463 | data++; | 
|  | 464 | len--; | 
|  | 465 | } | 
|  | 466 | } | 
|  | 467 | /* read fifo data (REGIO) */ | 
|  | 468 | void | 
|  | 469 | read_fifo_regio(struct hfc_multi *hc, u_char *data, int len) | 
|  | 470 | { | 
|  | 471 | outb(A_FIFO_DATA0, (hc->pci_iobase)+4); | 
|  | 472 | while (len>>2) { | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 473 | *(u32 *)data = le32_to_cpu(inl(hc->pci_iobase)); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 474 | data += 4; | 
|  | 475 | len -= 4; | 
|  | 476 | } | 
|  | 477 | while (len>>1) { | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 478 | *(u16 *)data = le16_to_cpu(inw(hc->pci_iobase)); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 479 | data += 2; | 
|  | 480 | len -= 2; | 
|  | 481 | } | 
|  | 482 | while (len) { | 
|  | 483 | *data = inb(hc->pci_iobase); | 
|  | 484 | data++; | 
|  | 485 | len--; | 
|  | 486 | } | 
|  | 487 | } | 
|  | 488 |  | 
|  | 489 | /* read fifo data (PCIMEM) */ | 
|  | 490 | void | 
|  | 491 | read_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) | 
|  | 492 | { | 
|  | 493 | while (len>>2) { | 
|  | 494 | *(u32 *)data = | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 495 | le32_to_cpu(readl(hc->pci_membase + A_FIFO_DATA0)); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 496 | data += 4; | 
|  | 497 | len -= 4; | 
|  | 498 | } | 
|  | 499 | while (len>>1) { | 
|  | 500 | *(u16 *)data = | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 501 | le16_to_cpu(readw(hc->pci_membase + A_FIFO_DATA0)); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 502 | data += 2; | 
|  | 503 | len -= 2; | 
|  | 504 | } | 
|  | 505 | while (len) { | 
| Karsten Keil | b3e0aee | 2008-08-02 16:35:53 +0200 | [diff] [blame] | 506 | *data = readb(hc->pci_membase + A_FIFO_DATA0); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 507 | data++; | 
|  | 508 | len--; | 
|  | 509 | } | 
|  | 510 | } | 
|  | 511 |  | 
|  | 512 |  | 
|  | 513 | static void | 
|  | 514 | enable_hwirq(struct hfc_multi *hc) | 
|  | 515 | { | 
|  | 516 | hc->hw.r_irq_ctrl |= V_GLOB_IRQ_EN; | 
|  | 517 | HFC_outb(hc, R_IRQ_CTRL, hc->hw.r_irq_ctrl); | 
|  | 518 | } | 
|  | 519 |  | 
|  | 520 | static void | 
|  | 521 | disable_hwirq(struct hfc_multi *hc) | 
|  | 522 | { | 
|  | 523 | hc->hw.r_irq_ctrl &= ~((u_char)V_GLOB_IRQ_EN); | 
|  | 524 | HFC_outb(hc, R_IRQ_CTRL, hc->hw.r_irq_ctrl); | 
|  | 525 | } | 
|  | 526 |  | 
|  | 527 | #define	NUM_EC 2 | 
|  | 528 | #define	MAX_TDM_CHAN 32 | 
|  | 529 |  | 
|  | 530 |  | 
|  | 531 | inline void | 
|  | 532 | enablepcibridge(struct hfc_multi *c) | 
|  | 533 | { | 
|  | 534 | HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x3); /* was _io before */ | 
|  | 535 | } | 
|  | 536 |  | 
|  | 537 | inline void | 
|  | 538 | disablepcibridge(struct hfc_multi *c) | 
|  | 539 | { | 
|  | 540 | HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x2); /* was _io before */ | 
|  | 541 | } | 
|  | 542 |  | 
|  | 543 | inline unsigned char | 
|  | 544 | readpcibridge(struct hfc_multi *hc, unsigned char address) | 
|  | 545 | { | 
|  | 546 | unsigned short cipv; | 
|  | 547 | unsigned char data; | 
|  | 548 |  | 
|  | 549 | if (!hc->pci_iobase) | 
|  | 550 | return 0; | 
|  | 551 |  | 
|  | 552 | /* slow down a PCI read access by 1 PCI clock cycle */ | 
|  | 553 | HFC_outb(hc, R_CTRL, 0x4); /*was _io before*/ | 
|  | 554 |  | 
|  | 555 | if (address == 0) | 
|  | 556 | cipv = 0x4000; | 
|  | 557 | else | 
|  | 558 | cipv = 0x5800; | 
|  | 559 |  | 
|  | 560 | /* select local bridge port address by writing to CIP port */ | 
|  | 561 | /* data = HFC_inb(c, cipv); * was _io before */ | 
|  | 562 | outw(cipv, hc->pci_iobase + 4); | 
|  | 563 | data = inb(hc->pci_iobase); | 
|  | 564 |  | 
|  | 565 | /* restore R_CTRL for normal PCI read cycle speed */ | 
|  | 566 | HFC_outb(hc, R_CTRL, 0x0); /* was _io before */ | 
|  | 567 |  | 
|  | 568 | return data; | 
|  | 569 | } | 
|  | 570 |  | 
|  | 571 | inline void | 
|  | 572 | writepcibridge(struct hfc_multi *hc, unsigned char address, unsigned char data) | 
|  | 573 | { | 
|  | 574 | unsigned short cipv; | 
|  | 575 | unsigned int datav; | 
|  | 576 |  | 
|  | 577 | if (!hc->pci_iobase) | 
|  | 578 | return; | 
|  | 579 |  | 
|  | 580 | if (address == 0) | 
|  | 581 | cipv = 0x4000; | 
|  | 582 | else | 
|  | 583 | cipv = 0x5800; | 
|  | 584 |  | 
|  | 585 | /* select local bridge port address by writing to CIP port */ | 
|  | 586 | outw(cipv, hc->pci_iobase + 4); | 
|  | 587 | /* define a 32 bit dword with 4 identical bytes for write sequence */ | 
|  | 588 | datav = data | ((__u32) data << 8) | ((__u32) data << 16) | | 
|  | 589 | ((__u32) data << 24); | 
|  | 590 |  | 
|  | 591 | /* | 
|  | 592 | * write this 32 bit dword to the bridge data port | 
|  | 593 | * this will initiate a write sequence of up to 4 writes to the same | 
|  | 594 | * address on the local bus interface the number of write accesses | 
|  | 595 | * is undefined but >=1 and depends on the next PCI transaction | 
|  | 596 | * during write sequence on the local bus | 
|  | 597 | */ | 
|  | 598 | outl(datav, hc->pci_iobase); | 
|  | 599 | } | 
|  | 600 |  | 
|  | 601 | inline void | 
|  | 602 | cpld_set_reg(struct hfc_multi *hc, unsigned char reg) | 
|  | 603 | { | 
|  | 604 | /* Do data pin read low byte */ | 
|  | 605 | HFC_outb(hc, R_GPIO_OUT1, reg); | 
|  | 606 | } | 
|  | 607 |  | 
|  | 608 | inline void | 
|  | 609 | cpld_write_reg(struct hfc_multi *hc, unsigned char reg, unsigned char val) | 
|  | 610 | { | 
|  | 611 | cpld_set_reg(hc, reg); | 
|  | 612 |  | 
|  | 613 | enablepcibridge(hc); | 
|  | 614 | writepcibridge(hc, 1, val); | 
|  | 615 | disablepcibridge(hc); | 
|  | 616 |  | 
|  | 617 | return; | 
|  | 618 | } | 
|  | 619 |  | 
|  | 620 | inline unsigned char | 
|  | 621 | cpld_read_reg(struct hfc_multi *hc, unsigned char reg) | 
|  | 622 | { | 
|  | 623 | unsigned char bytein; | 
|  | 624 |  | 
|  | 625 | cpld_set_reg(hc, reg); | 
|  | 626 |  | 
|  | 627 | /* Do data pin read low byte */ | 
|  | 628 | HFC_outb(hc, R_GPIO_OUT1, reg); | 
|  | 629 |  | 
|  | 630 | enablepcibridge(hc); | 
|  | 631 | bytein = readpcibridge(hc, 1); | 
|  | 632 | disablepcibridge(hc); | 
|  | 633 |  | 
|  | 634 | return bytein; | 
|  | 635 | } | 
|  | 636 |  | 
|  | 637 | inline void | 
|  | 638 | vpm_write_address(struct hfc_multi *hc, unsigned short addr) | 
|  | 639 | { | 
|  | 640 | cpld_write_reg(hc, 0, 0xff & addr); | 
|  | 641 | cpld_write_reg(hc, 1, 0x01 & (addr >> 8)); | 
|  | 642 | } | 
|  | 643 |  | 
|  | 644 | inline unsigned short | 
|  | 645 | vpm_read_address(struct hfc_multi *c) | 
|  | 646 | { | 
|  | 647 | unsigned short addr; | 
|  | 648 | unsigned short highbit; | 
|  | 649 |  | 
|  | 650 | addr = cpld_read_reg(c, 0); | 
|  | 651 | highbit = cpld_read_reg(c, 1); | 
|  | 652 |  | 
|  | 653 | addr = addr | (highbit << 8); | 
|  | 654 |  | 
|  | 655 | return addr & 0x1ff; | 
|  | 656 | } | 
|  | 657 |  | 
|  | 658 | inline unsigned char | 
|  | 659 | vpm_in(struct hfc_multi *c, int which, unsigned short addr) | 
|  | 660 | { | 
|  | 661 | unsigned char res; | 
|  | 662 |  | 
|  | 663 | vpm_write_address(c, addr); | 
|  | 664 |  | 
|  | 665 | if (!which) | 
|  | 666 | cpld_set_reg(c, 2); | 
|  | 667 | else | 
|  | 668 | cpld_set_reg(c, 3); | 
|  | 669 |  | 
|  | 670 | enablepcibridge(c); | 
|  | 671 | res = readpcibridge(c, 1); | 
|  | 672 | disablepcibridge(c); | 
|  | 673 |  | 
|  | 674 | cpld_set_reg(c, 0); | 
|  | 675 |  | 
|  | 676 | return res; | 
|  | 677 | } | 
|  | 678 |  | 
|  | 679 | inline void | 
|  | 680 | vpm_out(struct hfc_multi *c, int which, unsigned short addr, | 
|  | 681 | unsigned char data) | 
|  | 682 | { | 
|  | 683 | vpm_write_address(c, addr); | 
|  | 684 |  | 
|  | 685 | enablepcibridge(c); | 
|  | 686 |  | 
|  | 687 | if (!which) | 
|  | 688 | cpld_set_reg(c, 2); | 
|  | 689 | else | 
|  | 690 | cpld_set_reg(c, 3); | 
|  | 691 |  | 
|  | 692 | writepcibridge(c, 1, data); | 
|  | 693 |  | 
|  | 694 | cpld_set_reg(c, 0); | 
|  | 695 |  | 
|  | 696 | disablepcibridge(c); | 
|  | 697 |  | 
|  | 698 | { | 
|  | 699 | unsigned char regin; | 
|  | 700 | regin = vpm_in(c, which, addr); | 
|  | 701 | if (regin != data) | 
|  | 702 | printk(KERN_DEBUG "Wrote 0x%x to register 0x%x but got back " | 
|  | 703 | "0x%x\n", data, addr, regin); | 
|  | 704 | } | 
|  | 705 |  | 
|  | 706 | } | 
|  | 707 |  | 
|  | 708 |  | 
|  | 709 | void | 
|  | 710 | vpm_init(struct hfc_multi *wc) | 
|  | 711 | { | 
|  | 712 | unsigned char reg; | 
|  | 713 | unsigned int mask; | 
|  | 714 | unsigned int i, x, y; | 
|  | 715 | unsigned int ver; | 
|  | 716 |  | 
|  | 717 | for (x = 0; x < NUM_EC; x++) { | 
|  | 718 | /* Setup GPIO's */ | 
|  | 719 | if (!x) { | 
|  | 720 | ver = vpm_in(wc, x, 0x1a0); | 
|  | 721 | printk(KERN_DEBUG "VPM: Chip %d: ver %02x\n", x, ver); | 
|  | 722 | } | 
|  | 723 |  | 
|  | 724 | for (y = 0; y < 4; y++) { | 
|  | 725 | vpm_out(wc, x, 0x1a8 + y, 0x00); /* GPIO out */ | 
|  | 726 | vpm_out(wc, x, 0x1ac + y, 0x00); /* GPIO dir */ | 
|  | 727 | vpm_out(wc, x, 0x1b0 + y, 0x00); /* GPIO sel */ | 
|  | 728 | } | 
|  | 729 |  | 
|  | 730 | /* Setup TDM path - sets fsync and tdm_clk as inputs */ | 
|  | 731 | reg = vpm_in(wc, x, 0x1a3); /* misc_con */ | 
|  | 732 | vpm_out(wc, x, 0x1a3, reg & ~2); | 
|  | 733 |  | 
|  | 734 | /* Setup Echo length (256 taps) */ | 
|  | 735 | vpm_out(wc, x, 0x022, 1); | 
|  | 736 | vpm_out(wc, x, 0x023, 0xff); | 
|  | 737 |  | 
|  | 738 | /* Setup timeslots */ | 
|  | 739 | vpm_out(wc, x, 0x02f, 0x00); | 
|  | 740 | mask = 0x02020202 << (x * 4); | 
|  | 741 |  | 
|  | 742 | /* Setup the tdm channel masks for all chips */ | 
|  | 743 | for (i = 0; i < 4; i++) | 
|  | 744 | vpm_out(wc, x, 0x33 - i, (mask >> (i << 3)) & 0xff); | 
|  | 745 |  | 
|  | 746 | /* Setup convergence rate */ | 
|  | 747 | printk(KERN_DEBUG "VPM: A-law mode\n"); | 
|  | 748 | reg = 0x00 | 0x10 | 0x01; | 
|  | 749 | vpm_out(wc, x, 0x20, reg); | 
|  | 750 | printk(KERN_DEBUG "VPM reg 0x20 is %x\n", reg); | 
|  | 751 | /*vpm_out(wc, x, 0x20, (0x00 | 0x08 | 0x20 | 0x10)); */ | 
|  | 752 |  | 
|  | 753 | vpm_out(wc, x, 0x24, 0x02); | 
|  | 754 | reg = vpm_in(wc, x, 0x24); | 
|  | 755 | printk(KERN_DEBUG "NLP Thresh is set to %d (0x%x)\n", reg, reg); | 
|  | 756 |  | 
|  | 757 | /* Initialize echo cans */ | 
|  | 758 | for (i = 0; i < MAX_TDM_CHAN; i++) { | 
|  | 759 | if (mask & (0x00000001 << i)) | 
|  | 760 | vpm_out(wc, x, i, 0x00); | 
|  | 761 | } | 
|  | 762 |  | 
|  | 763 | /* | 
|  | 764 | * ARM arch at least disallows a udelay of | 
|  | 765 | * more than 2ms... it gives a fake "__bad_udelay" | 
|  | 766 | * reference at link-time. | 
|  | 767 | * long delays in kernel code are pretty sucky anyway | 
|  | 768 | * for now work around it using 5 x 2ms instead of 1 x 10ms | 
|  | 769 | */ | 
|  | 770 |  | 
|  | 771 | udelay(2000); | 
|  | 772 | udelay(2000); | 
|  | 773 | udelay(2000); | 
|  | 774 | udelay(2000); | 
|  | 775 | udelay(2000); | 
|  | 776 |  | 
|  | 777 | /* Put in bypass mode */ | 
|  | 778 | for (i = 0; i < MAX_TDM_CHAN; i++) { | 
|  | 779 | if (mask & (0x00000001 << i)) | 
|  | 780 | vpm_out(wc, x, i, 0x01); | 
|  | 781 | } | 
|  | 782 |  | 
|  | 783 | /* Enable bypass */ | 
|  | 784 | for (i = 0; i < MAX_TDM_CHAN; i++) { | 
|  | 785 | if (mask & (0x00000001 << i)) | 
|  | 786 | vpm_out(wc, x, 0x78 + i, 0x01); | 
|  | 787 | } | 
|  | 788 |  | 
|  | 789 | } | 
|  | 790 | } | 
|  | 791 |  | 
|  | 792 | void | 
|  | 793 | vpm_check(struct hfc_multi *hctmp) | 
|  | 794 | { | 
|  | 795 | unsigned char gpi2; | 
|  | 796 |  | 
|  | 797 | gpi2 = HFC_inb(hctmp, R_GPI_IN2); | 
|  | 798 |  | 
|  | 799 | if ((gpi2 & 0x3) != 0x3) | 
|  | 800 | printk(KERN_DEBUG "Got interrupt 0x%x from VPM!\n", gpi2); | 
|  | 801 | } | 
|  | 802 |  | 
|  | 803 |  | 
|  | 804 | /* | 
|  | 805 | * Interface to enable/disable the HW Echocan | 
|  | 806 | * | 
|  | 807 | * these functions are called within a spin_lock_irqsave on | 
|  | 808 | * the channel instance lock, so we are not disturbed by irqs | 
|  | 809 | * | 
|  | 810 | * we can later easily change the interface to make  other | 
|  | 811 | * things configurable, for now we configure the taps | 
|  | 812 | * | 
|  | 813 | */ | 
|  | 814 |  | 
|  | 815 | void | 
|  | 816 | vpm_echocan_on(struct hfc_multi *hc, int ch, int taps) | 
|  | 817 | { | 
|  | 818 | unsigned int timeslot; | 
|  | 819 | unsigned int unit; | 
|  | 820 | struct bchannel *bch = hc->chan[ch].bch; | 
|  | 821 | #ifdef TXADJ | 
|  | 822 | int txadj = -4; | 
|  | 823 | struct sk_buff *skb; | 
|  | 824 | #endif | 
|  | 825 | if (hc->chan[ch].protocol != ISDN_P_B_RAW) | 
|  | 826 | return; | 
|  | 827 |  | 
|  | 828 | if (!bch) | 
|  | 829 | return; | 
|  | 830 |  | 
|  | 831 | #ifdef TXADJ | 
|  | 832 | skb = _alloc_mISDN_skb(PH_CONTROL_IND, HFC_VOL_CHANGE_TX, | 
|  | 833 | sizeof(int), &txadj, GFP_ATOMIC); | 
|  | 834 | if (skb) | 
|  | 835 | recv_Bchannel_skb(bch, skb); | 
|  | 836 | #endif | 
|  | 837 |  | 
|  | 838 | timeslot = ((ch/4)*8) + ((ch%4)*4) + 1; | 
|  | 839 | unit = ch % 4; | 
|  | 840 |  | 
|  | 841 | printk(KERN_NOTICE "vpm_echocan_on called taps [%d] on timeslot %d\n", | 
|  | 842 | taps, timeslot); | 
|  | 843 |  | 
|  | 844 | vpm_out(hc, unit, timeslot, 0x7e); | 
|  | 845 | } | 
|  | 846 |  | 
|  | 847 | void | 
|  | 848 | vpm_echocan_off(struct hfc_multi *hc, int ch) | 
|  | 849 | { | 
|  | 850 | unsigned int timeslot; | 
|  | 851 | unsigned int unit; | 
|  | 852 | struct bchannel *bch = hc->chan[ch].bch; | 
|  | 853 | #ifdef TXADJ | 
|  | 854 | int txadj = 0; | 
|  | 855 | struct sk_buff *skb; | 
|  | 856 | #endif | 
|  | 857 |  | 
|  | 858 | if (hc->chan[ch].protocol != ISDN_P_B_RAW) | 
|  | 859 | return; | 
|  | 860 |  | 
|  | 861 | if (!bch) | 
|  | 862 | return; | 
|  | 863 |  | 
|  | 864 | #ifdef TXADJ | 
|  | 865 | skb = _alloc_mISDN_skb(PH_CONTROL_IND, HFC_VOL_CHANGE_TX, | 
|  | 866 | sizeof(int), &txadj, GFP_ATOMIC); | 
|  | 867 | if (skb) | 
|  | 868 | recv_Bchannel_skb(bch, skb); | 
|  | 869 | #endif | 
|  | 870 |  | 
|  | 871 | timeslot = ((ch/4)*8) + ((ch%4)*4) + 1; | 
|  | 872 | unit = ch % 4; | 
|  | 873 |  | 
|  | 874 | printk(KERN_NOTICE "vpm_echocan_off called on timeslot %d\n", | 
|  | 875 | timeslot); | 
|  | 876 | /* FILLME */ | 
|  | 877 | vpm_out(hc, unit, timeslot, 0x01); | 
|  | 878 | } | 
|  | 879 |  | 
|  | 880 |  | 
|  | 881 | /* | 
|  | 882 | * Speech Design resync feature | 
|  | 883 | * NOTE: This is called sometimes outside interrupt handler. | 
|  | 884 | * We must lock irqsave, so no other interrupt (other card) will occurr! | 
|  | 885 | * Also multiple interrupts may nest, so must lock each access (lists, card)! | 
|  | 886 | */ | 
|  | 887 | static inline void | 
|  | 888 | hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) | 
|  | 889 | { | 
|  | 890 | struct hfc_multi *hc, *next, *pcmmaster = 0; | 
|  | 891 | u_int *plx_acc_32, pv; | 
|  | 892 | u_long flags; | 
|  | 893 |  | 
|  | 894 | spin_lock_irqsave(&HFClock, flags); | 
|  | 895 | spin_lock(&plx_lock); /* must be locked inside other locks */ | 
|  | 896 |  | 
|  | 897 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 898 | printk(KERN_DEBUG "%s: RESYNC(syncmaster=0x%p)\n", | 
|  | 899 | __func__, syncmaster); | 
|  | 900 |  | 
|  | 901 | /* select new master */ | 
|  | 902 | if (newmaster) { | 
|  | 903 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 904 | printk(KERN_DEBUG "using provided controller\n"); | 
|  | 905 | } else { | 
|  | 906 | list_for_each_entry_safe(hc, next, &HFClist, list) { | 
|  | 907 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 908 | if (hc->syncronized) { | 
|  | 909 | newmaster = hc; | 
|  | 910 | break; | 
|  | 911 | } | 
|  | 912 | } | 
|  | 913 | } | 
|  | 914 | } | 
|  | 915 |  | 
|  | 916 | /* Disable sync of all cards */ | 
|  | 917 | list_for_each_entry_safe(hc, next, &HFClist, list) { | 
|  | 918 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 919 | plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); | 
|  | 920 | pv = readl(plx_acc_32); | 
|  | 921 | pv &= ~PLX_SYNC_O_EN; | 
|  | 922 | writel(pv, plx_acc_32); | 
|  | 923 | if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)) { | 
|  | 924 | pcmmaster = hc; | 
|  | 925 | if (hc->type == 1) { | 
|  | 926 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 927 | printk(KERN_DEBUG | 
|  | 928 | "Schedule SYNC_I\n"); | 
|  | 929 | hc->e1_resync |= 1; /* get SYNC_I */ | 
|  | 930 | } | 
|  | 931 | } | 
|  | 932 | } | 
|  | 933 | } | 
|  | 934 |  | 
|  | 935 | if (newmaster) { | 
|  | 936 | hc = newmaster; | 
|  | 937 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 938 | printk(KERN_DEBUG "id=%d (0x%p) = syncronized with " | 
|  | 939 | "interface.\n", hc->id, hc); | 
|  | 940 | /* Enable new sync master */ | 
|  | 941 | plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); | 
|  | 942 | pv = readl(plx_acc_32); | 
|  | 943 | pv |= PLX_SYNC_O_EN; | 
|  | 944 | writel(pv, plx_acc_32); | 
|  | 945 | /* switch to jatt PLL, if not disabled by RX_SYNC */ | 
|  | 946 | if (hc->type == 1 && !test_bit(HFC_CHIP_RX_SYNC, &hc->chip)) { | 
|  | 947 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 948 | printk(KERN_DEBUG "Schedule jatt PLL\n"); | 
|  | 949 | hc->e1_resync |= 2; /* switch to jatt */ | 
|  | 950 | } | 
|  | 951 | } else { | 
|  | 952 | if (pcmmaster) { | 
|  | 953 | hc = pcmmaster; | 
|  | 954 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 955 | printk(KERN_DEBUG | 
|  | 956 | "id=%d (0x%p) = PCM master syncronized " | 
|  | 957 | "with QUARTZ\n", hc->id, hc); | 
|  | 958 | if (hc->type == 1) { | 
|  | 959 | /* Use the crystal clock for the PCM | 
|  | 960 | master card */ | 
|  | 961 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 962 | printk(KERN_DEBUG | 
|  | 963 | "Schedule QUARTZ for HFC-E1\n"); | 
|  | 964 | hc->e1_resync |= 4; /* switch quartz */ | 
|  | 965 | } else { | 
|  | 966 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 967 | printk(KERN_DEBUG | 
|  | 968 | "QUARTZ is automatically " | 
|  | 969 | "enabled by HFC-%dS\n", hc->type); | 
|  | 970 | } | 
|  | 971 | plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); | 
|  | 972 | pv = readl(plx_acc_32); | 
|  | 973 | pv |= PLX_SYNC_O_EN; | 
|  | 974 | writel(pv, plx_acc_32); | 
|  | 975 | } else | 
|  | 976 | if (!rm) | 
|  | 977 | printk(KERN_ERR "%s no pcm master, this MUST " | 
|  | 978 | "not happen!\n", __func__); | 
|  | 979 | } | 
|  | 980 | syncmaster = newmaster; | 
|  | 981 |  | 
|  | 982 | spin_unlock(&plx_lock); | 
|  | 983 | spin_unlock_irqrestore(&HFClock, flags); | 
|  | 984 | } | 
|  | 985 |  | 
|  | 986 | /* This must be called AND hc must be locked irqsave!!! */ | 
|  | 987 | inline void | 
|  | 988 | plxsd_checksync(struct hfc_multi *hc, int rm) | 
|  | 989 | { | 
|  | 990 | if (hc->syncronized) { | 
|  | 991 | if (syncmaster == NULL) { | 
|  | 992 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 993 | printk(KERN_WARNING "%s: GOT sync on card %d" | 
|  | 994 | " (id=%d)\n", __func__, hc->id + 1, | 
|  | 995 | hc->id); | 
|  | 996 | hfcmulti_resync(hc, hc, rm); | 
|  | 997 | } | 
|  | 998 | } else { | 
|  | 999 | if (syncmaster == hc) { | 
|  | 1000 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 1001 | printk(KERN_WARNING "%s: LOST sync on card %d" | 
|  | 1002 | " (id=%d)\n", __func__, hc->id + 1, | 
|  | 1003 | hc->id); | 
|  | 1004 | hfcmulti_resync(hc, NULL, rm); | 
|  | 1005 | } | 
|  | 1006 | } | 
|  | 1007 | } | 
|  | 1008 |  | 
|  | 1009 |  | 
|  | 1010 | /* | 
|  | 1011 | * free hardware resources used by driver | 
|  | 1012 | */ | 
|  | 1013 | static void | 
|  | 1014 | release_io_hfcmulti(struct hfc_multi *hc) | 
|  | 1015 | { | 
|  | 1016 | u_int	*plx_acc_32, pv; | 
|  | 1017 | u_long	plx_flags; | 
|  | 1018 |  | 
|  | 1019 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1020 | printk(KERN_DEBUG "%s: entered\n", __func__); | 
|  | 1021 |  | 
|  | 1022 | /* soft reset also masks all interrupts */ | 
|  | 1023 | hc->hw.r_cirm |= V_SRES; | 
|  | 1024 | HFC_outb(hc, R_CIRM, hc->hw.r_cirm); | 
|  | 1025 | udelay(1000); | 
|  | 1026 | hc->hw.r_cirm &= ~V_SRES; | 
|  | 1027 | HFC_outb(hc, R_CIRM, hc->hw.r_cirm); | 
|  | 1028 | udelay(1000); /* instead of 'wait' that may cause locking */ | 
|  | 1029 |  | 
|  | 1030 | /* release Speech Design card, if PLX was initialized */ | 
|  | 1031 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip) && hc->plx_membase) { | 
|  | 1032 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 1033 | printk(KERN_DEBUG "%s: release PLXSD card %d\n", | 
|  | 1034 | __func__, hc->id + 1); | 
|  | 1035 | spin_lock_irqsave(&plx_lock, plx_flags); | 
|  | 1036 | plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); | 
|  | 1037 | writel(PLX_GPIOC_INIT, plx_acc_32); | 
|  | 1038 | pv = readl(plx_acc_32); | 
|  | 1039 | /* Termination off */ | 
|  | 1040 | pv &= ~PLX_TERM_ON; | 
|  | 1041 | /* Disconnect the PCM */ | 
|  | 1042 | pv |= PLX_SLAVE_EN_N; | 
|  | 1043 | pv &= ~PLX_MASTER_EN; | 
|  | 1044 | pv &= ~PLX_SYNC_O_EN; | 
|  | 1045 | /* Put the DSP in Reset */ | 
|  | 1046 | pv &= ~PLX_DSP_RES_N; | 
|  | 1047 | writel(pv, plx_acc_32); | 
|  | 1048 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1049 | printk(KERN_WARNING "%s: PCM off: PLX_GPIO=%x\n", | 
|  | 1050 | __func__, pv); | 
|  | 1051 | spin_unlock_irqrestore(&plx_lock, plx_flags); | 
|  | 1052 | } | 
|  | 1053 |  | 
|  | 1054 | /* disable memory mapped ports / io ports */ | 
|  | 1055 | test_and_clear_bit(HFC_CHIP_PLXSD, &hc->chip); /* prevent resync */ | 
|  | 1056 | pci_write_config_word(hc->pci_dev, PCI_COMMAND, 0); | 
|  | 1057 | if (hc->pci_membase) | 
|  | 1058 | iounmap((void *)hc->pci_membase); | 
|  | 1059 | if (hc->plx_membase) | 
|  | 1060 | iounmap((void *)hc->plx_membase); | 
|  | 1061 | if (hc->pci_iobase) | 
|  | 1062 | release_region(hc->pci_iobase, 8); | 
|  | 1063 |  | 
|  | 1064 | if (hc->pci_dev) { | 
|  | 1065 | pci_disable_device(hc->pci_dev); | 
|  | 1066 | pci_set_drvdata(hc->pci_dev, NULL); | 
|  | 1067 | } | 
|  | 1068 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1069 | printk(KERN_DEBUG "%s: done\n", __func__); | 
|  | 1070 | } | 
|  | 1071 |  | 
|  | 1072 | /* | 
|  | 1073 | * function called to reset the HFC chip. A complete software reset of chip | 
|  | 1074 | * and fifos is done. All configuration of the chip is done. | 
|  | 1075 | */ | 
|  | 1076 |  | 
|  | 1077 | static int | 
|  | 1078 | init_chip(struct hfc_multi *hc) | 
|  | 1079 | { | 
|  | 1080 | u_long			flags, val, val2 = 0, rev; | 
|  | 1081 | int			i, err = 0; | 
|  | 1082 | u_char			r_conf_en, rval; | 
|  | 1083 | u_int			*plx_acc_32, pv; | 
|  | 1084 | u_long			plx_flags, hfc_flags; | 
|  | 1085 | int			plx_count; | 
|  | 1086 | struct hfc_multi	*pos, *next, *plx_last_hc; | 
|  | 1087 |  | 
|  | 1088 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 1089 | /* reset all registers */ | 
|  | 1090 | memset(&hc->hw, 0, sizeof(struct hfcm_hw)); | 
|  | 1091 |  | 
|  | 1092 | /* revision check */ | 
|  | 1093 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1094 | printk(KERN_DEBUG "%s: entered\n", __func__); | 
|  | 1095 | val = HFC_inb(hc, R_CHIP_ID)>>4; | 
|  | 1096 | if (val != 0x8 && val != 0xc && val != 0xe) { | 
|  | 1097 | printk(KERN_INFO "HFC_multi: unknown CHIP_ID:%x\n", (u_int)val); | 
|  | 1098 | err = -EIO; | 
|  | 1099 | goto out; | 
|  | 1100 | } | 
|  | 1101 | rev = HFC_inb(hc, R_CHIP_RV); | 
|  | 1102 | printk(KERN_INFO | 
|  | 1103 | "HFC_multi: detected HFC with chip ID=0x%lx revision=%ld%s\n", | 
|  | 1104 | val, rev, (rev == 0) ? " (old FIFO handling)" : ""); | 
|  | 1105 | if (rev == 0) { | 
|  | 1106 | test_and_set_bit(HFC_CHIP_REVISION0, &hc->chip); | 
|  | 1107 | printk(KERN_WARNING | 
|  | 1108 | "HFC_multi: NOTE: Your chip is revision 0, " | 
|  | 1109 | "ask Cologne Chip for update. Newer chips " | 
|  | 1110 | "have a better FIFO handling. Old chips " | 
|  | 1111 | "still work but may have slightly lower " | 
|  | 1112 | "HDLC transmit performance.\n"); | 
|  | 1113 | } | 
|  | 1114 | if (rev > 1) { | 
|  | 1115 | printk(KERN_WARNING "HFC_multi: WARNING: This driver doesn't " | 
|  | 1116 | "consider chip revision = %ld. The chip / " | 
|  | 1117 | "bridge may not work.\n", rev); | 
|  | 1118 | } | 
|  | 1119 |  | 
|  | 1120 | /* set s-ram size */ | 
|  | 1121 | hc->Flen = 0x10; | 
|  | 1122 | hc->Zmin = 0x80; | 
|  | 1123 | hc->Zlen = 384; | 
|  | 1124 | hc->DTMFbase = 0x1000; | 
|  | 1125 | if (test_bit(HFC_CHIP_EXRAM_128, &hc->chip)) { | 
|  | 1126 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1127 | printk(KERN_DEBUG "%s: changing to 128K extenal RAM\n", | 
|  | 1128 | __func__); | 
|  | 1129 | hc->hw.r_ctrl |= V_EXT_RAM; | 
|  | 1130 | hc->hw.r_ram_sz = 1; | 
|  | 1131 | hc->Flen = 0x20; | 
|  | 1132 | hc->Zmin = 0xc0; | 
|  | 1133 | hc->Zlen = 1856; | 
|  | 1134 | hc->DTMFbase = 0x2000; | 
|  | 1135 | } | 
|  | 1136 | if (test_bit(HFC_CHIP_EXRAM_512, &hc->chip)) { | 
|  | 1137 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1138 | printk(KERN_DEBUG "%s: changing to 512K extenal RAM\n", | 
|  | 1139 | __func__); | 
|  | 1140 | hc->hw.r_ctrl |= V_EXT_RAM; | 
|  | 1141 | hc->hw.r_ram_sz = 2; | 
|  | 1142 | hc->Flen = 0x20; | 
|  | 1143 | hc->Zmin = 0xc0; | 
|  | 1144 | hc->Zlen = 8000; | 
|  | 1145 | hc->DTMFbase = 0x2000; | 
|  | 1146 | } | 
|  | 1147 | hc->max_trans = poll << 1; | 
|  | 1148 | if (hc->max_trans > hc->Zlen) | 
|  | 1149 | hc->max_trans = hc->Zlen; | 
|  | 1150 |  | 
|  | 1151 | /* Speech Design PLX bridge */ | 
|  | 1152 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 1153 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 1154 | printk(KERN_DEBUG "%s: initializing PLXSD card %d\n", | 
|  | 1155 | __func__, hc->id + 1); | 
|  | 1156 | spin_lock_irqsave(&plx_lock, plx_flags); | 
|  | 1157 | plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); | 
|  | 1158 | writel(PLX_GPIOC_INIT, plx_acc_32); | 
|  | 1159 | pv = readl(plx_acc_32); | 
|  | 1160 | /* The first and the last cards are terminating the PCM bus */ | 
|  | 1161 | pv |= PLX_TERM_ON; /* hc is currently the last */ | 
|  | 1162 | /* Disconnect the PCM */ | 
|  | 1163 | pv |= PLX_SLAVE_EN_N; | 
|  | 1164 | pv &= ~PLX_MASTER_EN; | 
|  | 1165 | pv &= ~PLX_SYNC_O_EN; | 
|  | 1166 | /* Put the DSP in Reset */ | 
|  | 1167 | pv &= ~PLX_DSP_RES_N; | 
|  | 1168 | writel(pv, plx_acc_32); | 
|  | 1169 | spin_unlock_irqrestore(&plx_lock, plx_flags); | 
|  | 1170 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1171 | printk(KERN_WARNING "%s: slave/term: PLX_GPIO=%x\n", | 
|  | 1172 | __func__, pv); | 
|  | 1173 | /* | 
|  | 1174 | * If we are the 3rd PLXSD card or higher, we must turn | 
|  | 1175 | * termination of last PLXSD card off. | 
|  | 1176 | */ | 
|  | 1177 | spin_lock_irqsave(&HFClock, hfc_flags); | 
|  | 1178 | plx_count = 0; | 
|  | 1179 | plx_last_hc = NULL; | 
|  | 1180 | list_for_each_entry_safe(pos, next, &HFClist, list) { | 
|  | 1181 | if (test_bit(HFC_CHIP_PLXSD, &pos->chip)) { | 
|  | 1182 | plx_count++; | 
|  | 1183 | if (pos != hc) | 
|  | 1184 | plx_last_hc = pos; | 
|  | 1185 | } | 
|  | 1186 | } | 
|  | 1187 | if (plx_count >= 3) { | 
|  | 1188 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 1189 | printk(KERN_DEBUG "%s: card %d is between, so " | 
|  | 1190 | "we disable termination\n", | 
|  | 1191 | __func__, plx_last_hc->id + 1); | 
|  | 1192 | spin_lock_irqsave(&plx_lock, plx_flags); | 
|  | 1193 | plx_acc_32 = (u_int *)(plx_last_hc->plx_membase | 
|  | 1194 | + PLX_GPIOC); | 
|  | 1195 | pv = readl(plx_acc_32); | 
|  | 1196 | pv &= ~PLX_TERM_ON; | 
|  | 1197 | writel(pv, plx_acc_32); | 
|  | 1198 | spin_unlock_irqrestore(&plx_lock, plx_flags); | 
|  | 1199 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1200 | printk(KERN_WARNING "%s: term off: PLX_GPIO=%x\n", | 
|  | 1201 | __func__, pv); | 
|  | 1202 | } | 
|  | 1203 | spin_unlock_irqrestore(&HFClock, hfc_flags); | 
|  | 1204 | hc->hw.r_pcm_md0 = V_F0_LEN; /* shift clock for DSP */ | 
|  | 1205 | } | 
|  | 1206 |  | 
|  | 1207 | /* we only want the real Z2 read-pointer for revision > 0 */ | 
|  | 1208 | if (!test_bit(HFC_CHIP_REVISION0, &hc->chip)) | 
|  | 1209 | hc->hw.r_ram_sz |= V_FZ_MD; | 
|  | 1210 |  | 
|  | 1211 | /* select pcm mode */ | 
|  | 1212 | if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) { | 
|  | 1213 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1214 | printk(KERN_DEBUG "%s: setting PCM into slave mode\n", | 
|  | 1215 | __func__); | 
|  | 1216 | } else | 
|  | 1217 | if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip) && !plxsd_master) { | 
|  | 1218 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1219 | printk(KERN_DEBUG "%s: setting PCM into master mode\n", | 
|  | 1220 | __func__); | 
|  | 1221 | hc->hw.r_pcm_md0 |= V_PCM_MD; | 
|  | 1222 | } else { | 
|  | 1223 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1224 | printk(KERN_DEBUG "%s: performing PCM auto detect\n", | 
|  | 1225 | __func__); | 
|  | 1226 | } | 
|  | 1227 |  | 
|  | 1228 | /* soft reset */ | 
|  | 1229 | HFC_outb(hc, R_CTRL, hc->hw.r_ctrl); | 
|  | 1230 | HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz); | 
|  | 1231 | HFC_outb(hc, R_FIFO_MD, 0); | 
|  | 1232 | hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES | V_RLD_EPR; | 
|  | 1233 | HFC_outb(hc, R_CIRM, hc->hw.r_cirm); | 
|  | 1234 | udelay(100); | 
|  | 1235 | hc->hw.r_cirm = 0; | 
|  | 1236 | HFC_outb(hc, R_CIRM, hc->hw.r_cirm); | 
|  | 1237 | udelay(100); | 
|  | 1238 | HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz); | 
|  | 1239 |  | 
|  | 1240 | /* Speech Design PLX bridge pcm and sync mode */ | 
|  | 1241 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 1242 | spin_lock_irqsave(&plx_lock, plx_flags); | 
|  | 1243 | plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); | 
|  | 1244 | pv = readl(plx_acc_32); | 
|  | 1245 | /* Connect PCM */ | 
|  | 1246 | if (hc->hw.r_pcm_md0 & V_PCM_MD) { | 
|  | 1247 | pv |= PLX_MASTER_EN | PLX_SLAVE_EN_N; | 
|  | 1248 | pv |= PLX_SYNC_O_EN; | 
|  | 1249 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1250 | printk(KERN_WARNING "%s: master: PLX_GPIO=%x\n", | 
|  | 1251 | __func__, pv); | 
|  | 1252 | } else { | 
|  | 1253 | pv &= ~(PLX_MASTER_EN | PLX_SLAVE_EN_N); | 
|  | 1254 | pv &= ~PLX_SYNC_O_EN; | 
|  | 1255 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1256 | printk(KERN_WARNING "%s: slave: PLX_GPIO=%x\n", | 
|  | 1257 | __func__, pv); | 
|  | 1258 | } | 
|  | 1259 | writel(pv, plx_acc_32); | 
|  | 1260 | spin_unlock_irqrestore(&plx_lock, plx_flags); | 
|  | 1261 | } | 
|  | 1262 |  | 
|  | 1263 | /* PCM setup */ | 
|  | 1264 | HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x90); | 
|  | 1265 | if (hc->slots == 32) | 
|  | 1266 | HFC_outb(hc, R_PCM_MD1, 0x00); | 
|  | 1267 | if (hc->slots == 64) | 
|  | 1268 | HFC_outb(hc, R_PCM_MD1, 0x10); | 
|  | 1269 | if (hc->slots == 128) | 
|  | 1270 | HFC_outb(hc, R_PCM_MD1, 0x20); | 
|  | 1271 | HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0xa0); | 
|  | 1272 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) | 
|  | 1273 | HFC_outb(hc, R_PCM_MD2, V_SYNC_SRC); /* sync via SYNC_I / O */ | 
|  | 1274 | else | 
|  | 1275 | HFC_outb(hc, R_PCM_MD2, 0x00); /* sync from interface */ | 
|  | 1276 | HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00); | 
|  | 1277 | for (i = 0; i < 256; i++) { | 
|  | 1278 | HFC_outb_nodebug(hc, R_SLOT, i); | 
|  | 1279 | HFC_outb_nodebug(hc, A_SL_CFG, 0); | 
|  | 1280 | HFC_outb_nodebug(hc, A_CONF, 0); | 
|  | 1281 | hc->slot_owner[i] = -1; | 
|  | 1282 | } | 
|  | 1283 |  | 
|  | 1284 | /* set clock speed */ | 
|  | 1285 | if (test_bit(HFC_CHIP_CLOCK2, &hc->chip)) { | 
|  | 1286 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1287 | printk(KERN_DEBUG | 
|  | 1288 | "%s: setting double clock\n", __func__); | 
|  | 1289 | HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK); | 
|  | 1290 | } | 
|  | 1291 |  | 
|  | 1292 | /* B410P GPIO */ | 
|  | 1293 | if (test_bit(HFC_CHIP_B410P, &hc->chip)) { | 
|  | 1294 | printk(KERN_NOTICE "Setting GPIOs\n"); | 
|  | 1295 | HFC_outb(hc, R_GPIO_SEL, 0x30); | 
|  | 1296 | HFC_outb(hc, R_GPIO_EN1, 0x3); | 
|  | 1297 | udelay(1000); | 
|  | 1298 | printk(KERN_NOTICE "calling vpm_init\n"); | 
|  | 1299 | vpm_init(hc); | 
|  | 1300 | } | 
|  | 1301 |  | 
|  | 1302 | /* check if R_F0_CNT counts (8 kHz frame count) */ | 
|  | 1303 | val = HFC_inb(hc, R_F0_CNTL); | 
|  | 1304 | val += HFC_inb(hc, R_F0_CNTH) << 8; | 
|  | 1305 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1306 | printk(KERN_DEBUG | 
|  | 1307 | "HFC_multi F0_CNT %ld after reset\n", val); | 
|  | 1308 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 1309 | set_current_state(TASK_UNINTERRUPTIBLE); | 
|  | 1310 | schedule_timeout((HZ/100)?:1); /* Timeout minimum 10ms */ | 
|  | 1311 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 1312 | val2 = HFC_inb(hc, R_F0_CNTL); | 
|  | 1313 | val2 += HFC_inb(hc, R_F0_CNTH) << 8; | 
|  | 1314 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1315 | printk(KERN_DEBUG | 
|  | 1316 | "HFC_multi F0_CNT %ld after 10 ms (1st try)\n", | 
|  | 1317 | val2); | 
|  | 1318 | if (val2 >= val+8) { /* 1 ms */ | 
|  | 1319 | /* it counts, so we keep the pcm mode */ | 
|  | 1320 | if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)) | 
|  | 1321 | printk(KERN_INFO "controller is PCM bus MASTER\n"); | 
|  | 1322 | else | 
|  | 1323 | if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) | 
|  | 1324 | printk(KERN_INFO "controller is PCM bus SLAVE\n"); | 
|  | 1325 | else { | 
|  | 1326 | test_and_set_bit(HFC_CHIP_PCM_SLAVE, &hc->chip); | 
|  | 1327 | printk(KERN_INFO "controller is PCM bus SLAVE " | 
|  | 1328 | "(auto detected)\n"); | 
|  | 1329 | } | 
|  | 1330 | } else { | 
|  | 1331 | /* does not count */ | 
|  | 1332 | if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)) { | 
|  | 1333 | controller_fail: | 
|  | 1334 | printk(KERN_ERR "HFC_multi ERROR, getting no 125us " | 
|  | 1335 | "pulse. Seems that controller fails.\n"); | 
|  | 1336 | err = -EIO; | 
|  | 1337 | goto out; | 
|  | 1338 | } | 
|  | 1339 | if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) { | 
|  | 1340 | printk(KERN_INFO "controller is PCM bus SLAVE " | 
|  | 1341 | "(ignoring missing PCM clock)\n"); | 
|  | 1342 | } else { | 
|  | 1343 | /* only one pcm master */ | 
|  | 1344 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip) | 
|  | 1345 | && plxsd_master) { | 
|  | 1346 | printk(KERN_ERR "HFC_multi ERROR, no clock " | 
|  | 1347 | "on another Speech Design card found. " | 
|  | 1348 | "Please be sure to connect PCM cable.\n"); | 
|  | 1349 | err = -EIO; | 
|  | 1350 | goto out; | 
|  | 1351 | } | 
|  | 1352 | /* retry with master clock */ | 
|  | 1353 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 1354 | spin_lock_irqsave(&plx_lock, plx_flags); | 
|  | 1355 | plx_acc_32 = (u_int *)(hc->plx_membase + | 
|  | 1356 | PLX_GPIOC); | 
|  | 1357 | pv = readl(plx_acc_32); | 
|  | 1358 | pv |= PLX_MASTER_EN | PLX_SLAVE_EN_N; | 
|  | 1359 | pv |= PLX_SYNC_O_EN; | 
|  | 1360 | writel(pv, plx_acc_32); | 
|  | 1361 | spin_unlock_irqrestore(&plx_lock, plx_flags); | 
|  | 1362 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1363 | printk(KERN_WARNING "%s: master: PLX_GPIO" | 
|  | 1364 | "=%x\n", __func__, pv); | 
|  | 1365 | } | 
|  | 1366 | hc->hw.r_pcm_md0 |= V_PCM_MD; | 
|  | 1367 | HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00); | 
|  | 1368 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 1369 | set_current_state(TASK_UNINTERRUPTIBLE); | 
|  | 1370 | schedule_timeout((HZ/100)?:1); /* Timeout min. 10ms */ | 
|  | 1371 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 1372 | val2 = HFC_inb(hc, R_F0_CNTL); | 
|  | 1373 | val2 += HFC_inb(hc, R_F0_CNTH) << 8; | 
|  | 1374 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1375 | printk(KERN_DEBUG "HFC_multi F0_CNT %ld after " | 
|  | 1376 | "10 ms (2nd try)\n", val2); | 
|  | 1377 | if (val2 >= val+8) { /* 1 ms */ | 
|  | 1378 | test_and_set_bit(HFC_CHIP_PCM_MASTER, | 
|  | 1379 | &hc->chip); | 
|  | 1380 | printk(KERN_INFO "controller is PCM bus MASTER " | 
|  | 1381 | "(auto detected)\n"); | 
|  | 1382 | } else | 
|  | 1383 | goto controller_fail; | 
|  | 1384 | } | 
|  | 1385 | } | 
|  | 1386 |  | 
|  | 1387 | /* Release the DSP Reset */ | 
|  | 1388 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 1389 | if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)) | 
|  | 1390 | plxsd_master = 1; | 
|  | 1391 | spin_lock_irqsave(&plx_lock, plx_flags); | 
|  | 1392 | plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); | 
|  | 1393 | pv = readl(plx_acc_32); | 
|  | 1394 | pv |=  PLX_DSP_RES_N; | 
|  | 1395 | writel(pv, plx_acc_32); | 
|  | 1396 | spin_unlock_irqrestore(&plx_lock, plx_flags); | 
|  | 1397 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1398 | printk(KERN_WARNING "%s: reset off: PLX_GPIO=%x\n", | 
|  | 1399 | __func__, pv); | 
|  | 1400 | } | 
|  | 1401 |  | 
|  | 1402 | /* pcm id */ | 
|  | 1403 | if (hc->pcm) | 
|  | 1404 | printk(KERN_INFO "controller has given PCM BUS ID %d\n", | 
|  | 1405 | hc->pcm); | 
|  | 1406 | else { | 
|  | 1407 | if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip) | 
|  | 1408 | || test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 1409 | PCM_cnt++; /* SD has proprietary bridging */ | 
|  | 1410 | } | 
|  | 1411 | hc->pcm = PCM_cnt; | 
|  | 1412 | printk(KERN_INFO "controller has PCM BUS ID %d " | 
|  | 1413 | "(auto selected)\n", hc->pcm); | 
|  | 1414 | } | 
|  | 1415 |  | 
|  | 1416 | /* set up timer */ | 
|  | 1417 | HFC_outb(hc, R_TI_WD, poll_timer); | 
|  | 1418 | hc->hw.r_irqmsk_misc |= V_TI_IRQMSK; | 
|  | 1419 |  | 
|  | 1420 | /* | 
|  | 1421 | * set up 125us interrupt, only if function pointer is available | 
|  | 1422 | * and module parameter timer is set | 
|  | 1423 | */ | 
|  | 1424 | if (timer && hfc_interrupt && register_interrupt) { | 
|  | 1425 | /* only one chip should use this interrupt */ | 
|  | 1426 | timer = 0; | 
|  | 1427 | interrupt_registered = 1; | 
|  | 1428 | hc->hw.r_irqmsk_misc |= V_PROC_IRQMSK; | 
|  | 1429 | /* deactivate other interrupts in ztdummy */ | 
|  | 1430 | register_interrupt(); | 
|  | 1431 | } | 
|  | 1432 |  | 
|  | 1433 | /* set E1 state machine IRQ */ | 
|  | 1434 | if (hc->type == 1) | 
|  | 1435 | hc->hw.r_irqmsk_misc |= V_STA_IRQMSK; | 
|  | 1436 |  | 
|  | 1437 | /* set DTMF detection */ | 
|  | 1438 | if (test_bit(HFC_CHIP_DTMF, &hc->chip)) { | 
|  | 1439 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1440 | printk(KERN_DEBUG "%s: enabling DTMF detection " | 
|  | 1441 | "for all B-channel\n", __func__); | 
|  | 1442 | hc->hw.r_dtmf = V_DTMF_EN | V_DTMF_STOP; | 
|  | 1443 | if (test_bit(HFC_CHIP_ULAW, &hc->chip)) | 
|  | 1444 | hc->hw.r_dtmf |= V_ULAW_SEL; | 
|  | 1445 | HFC_outb(hc, R_DTMF_N, 102 - 1); | 
|  | 1446 | hc->hw.r_irqmsk_misc |= V_DTMF_IRQMSK; | 
|  | 1447 | } | 
|  | 1448 |  | 
|  | 1449 | /* conference engine */ | 
|  | 1450 | if (test_bit(HFC_CHIP_ULAW, &hc->chip)) | 
|  | 1451 | r_conf_en = V_CONF_EN | V_ULAW; | 
|  | 1452 | else | 
|  | 1453 | r_conf_en = V_CONF_EN; | 
|  | 1454 | HFC_outb(hc, R_CONF_EN, r_conf_en); | 
|  | 1455 |  | 
|  | 1456 | /* setting leds */ | 
|  | 1457 | switch (hc->leds) { | 
|  | 1458 | case 1: /* HFC-E1 OEM */ | 
|  | 1459 | if (test_bit(HFC_CHIP_WATCHDOG, &hc->chip)) | 
|  | 1460 | HFC_outb(hc, R_GPIO_SEL, 0x32); | 
|  | 1461 | else | 
|  | 1462 | HFC_outb(hc, R_GPIO_SEL, 0x30); | 
|  | 1463 |  | 
|  | 1464 | HFC_outb(hc, R_GPIO_EN1, 0x0f); | 
|  | 1465 | HFC_outb(hc, R_GPIO_OUT1, 0x00); | 
|  | 1466 |  | 
|  | 1467 | HFC_outb(hc, R_GPIO_EN0, V_GPIO_EN2 | V_GPIO_EN3); | 
|  | 1468 | break; | 
|  | 1469 |  | 
|  | 1470 | case 2: /* HFC-4S OEM */ | 
|  | 1471 | case 3: | 
|  | 1472 | HFC_outb(hc, R_GPIO_SEL, 0xf0); | 
|  | 1473 | HFC_outb(hc, R_GPIO_EN1, 0xff); | 
|  | 1474 | HFC_outb(hc, R_GPIO_OUT1, 0x00); | 
|  | 1475 | break; | 
|  | 1476 | } | 
|  | 1477 |  | 
|  | 1478 | /* set master clock */ | 
|  | 1479 | if (hc->masterclk >= 0) { | 
|  | 1480 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1481 | printk(KERN_DEBUG "%s: setting ST master clock " | 
|  | 1482 | "to port %d (0..%d)\n", | 
|  | 1483 | __func__, hc->masterclk, hc->ports-1); | 
|  | 1484 | hc->hw.r_st_sync = hc->masterclk | V_AUTO_SYNC; | 
|  | 1485 | HFC_outb(hc, R_ST_SYNC, hc->hw.r_st_sync); | 
|  | 1486 | } | 
|  | 1487 |  | 
|  | 1488 | /* setting misc irq */ | 
|  | 1489 | HFC_outb(hc, R_IRQMSK_MISC, hc->hw.r_irqmsk_misc); | 
|  | 1490 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1491 | printk(KERN_DEBUG "r_irqmsk_misc.2: 0x%x\n", | 
|  | 1492 | hc->hw.r_irqmsk_misc); | 
|  | 1493 |  | 
|  | 1494 | /* RAM access test */ | 
|  | 1495 | HFC_outb(hc, R_RAM_ADDR0, 0); | 
|  | 1496 | HFC_outb(hc, R_RAM_ADDR1, 0); | 
|  | 1497 | HFC_outb(hc, R_RAM_ADDR2, 0); | 
|  | 1498 | for (i = 0; i < 256; i++) { | 
|  | 1499 | HFC_outb_nodebug(hc, R_RAM_ADDR0, i); | 
|  | 1500 | HFC_outb_nodebug(hc, R_RAM_DATA, ((i*3)&0xff)); | 
|  | 1501 | } | 
|  | 1502 | for (i = 0; i < 256; i++) { | 
|  | 1503 | HFC_outb_nodebug(hc, R_RAM_ADDR0, i); | 
|  | 1504 | HFC_inb_nodebug(hc, R_RAM_DATA); | 
|  | 1505 | rval = HFC_inb_nodebug(hc, R_INT_DATA); | 
|  | 1506 | if (rval != ((i * 3) & 0xff)) { | 
|  | 1507 | printk(KERN_DEBUG | 
|  | 1508 | "addr:%x val:%x should:%x\n", i, rval, | 
|  | 1509 | (i * 3) & 0xff); | 
|  | 1510 | err++; | 
|  | 1511 | } | 
|  | 1512 | } | 
|  | 1513 | if (err) { | 
|  | 1514 | printk(KERN_DEBUG "aborting - %d RAM access errors\n", err); | 
|  | 1515 | err = -EIO; | 
|  | 1516 | goto out; | 
|  | 1517 | } | 
|  | 1518 |  | 
|  | 1519 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 1520 | printk(KERN_DEBUG "%s: done\n", __func__); | 
|  | 1521 | out: | 
|  | 1522 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 1523 | return err; | 
|  | 1524 | } | 
|  | 1525 |  | 
|  | 1526 |  | 
|  | 1527 | /* | 
|  | 1528 | * control the watchdog | 
|  | 1529 | */ | 
|  | 1530 | static void | 
|  | 1531 | hfcmulti_watchdog(struct hfc_multi *hc) | 
|  | 1532 | { | 
|  | 1533 | hc->wdcount++; | 
|  | 1534 |  | 
|  | 1535 | if (hc->wdcount > 10) { | 
|  | 1536 | hc->wdcount = 0; | 
|  | 1537 | hc->wdbyte = hc->wdbyte == V_GPIO_OUT2 ? | 
|  | 1538 | V_GPIO_OUT3 : V_GPIO_OUT2; | 
|  | 1539 |  | 
|  | 1540 | /* printk("Sending Watchdog Kill %x\n",hc->wdbyte); */ | 
|  | 1541 | HFC_outb(hc, R_GPIO_EN0, V_GPIO_EN2 | V_GPIO_EN3); | 
|  | 1542 | HFC_outb(hc, R_GPIO_OUT0, hc->wdbyte); | 
|  | 1543 | } | 
|  | 1544 | } | 
|  | 1545 |  | 
|  | 1546 |  | 
|  | 1547 |  | 
|  | 1548 | /* | 
|  | 1549 | * output leds | 
|  | 1550 | */ | 
|  | 1551 | static void | 
|  | 1552 | hfcmulti_leds(struct hfc_multi *hc) | 
|  | 1553 | { | 
|  | 1554 | unsigned long lled; | 
|  | 1555 | unsigned long leddw; | 
|  | 1556 | int i, state, active, leds; | 
|  | 1557 | struct dchannel *dch; | 
|  | 1558 | int led[4]; | 
|  | 1559 |  | 
|  | 1560 | hc->ledcount += poll; | 
|  | 1561 | if (hc->ledcount > 4096) { | 
|  | 1562 | hc->ledcount -= 4096; | 
|  | 1563 | hc->ledstate = 0xAFFEAFFE; | 
|  | 1564 | } | 
|  | 1565 |  | 
|  | 1566 | switch (hc->leds) { | 
|  | 1567 | case 1: /* HFC-E1 OEM */ | 
|  | 1568 | /* 2 red blinking: NT mode deactivate | 
|  | 1569 | * 2 red steady:   TE mode deactivate | 
|  | 1570 | * left green:     L1 active | 
|  | 1571 | * left red:       frame sync, but no L1 | 
|  | 1572 | * right green:    L2 active | 
|  | 1573 | */ | 
|  | 1574 | if (hc->chan[hc->dslot].sync != 2) { /* no frame sync */ | 
|  | 1575 | if (hc->chan[hc->dslot].dch->dev.D.protocol | 
|  | 1576 | != ISDN_P_NT_E1) { | 
|  | 1577 | led[0] = 1; | 
|  | 1578 | led[1] = 1; | 
|  | 1579 | } else if (hc->ledcount>>11) { | 
|  | 1580 | led[0] = 1; | 
|  | 1581 | led[1] = 1; | 
|  | 1582 | } else { | 
|  | 1583 | led[0] = 0; | 
|  | 1584 | led[1] = 0; | 
|  | 1585 | } | 
|  | 1586 | led[2] = 0; | 
|  | 1587 | led[3] = 0; | 
|  | 1588 | } else { /* with frame sync */ | 
|  | 1589 | /* TODO make it work */ | 
|  | 1590 | led[0] = 0; | 
|  | 1591 | led[1] = 0; | 
|  | 1592 | led[2] = 0; | 
|  | 1593 | led[3] = 1; | 
|  | 1594 | } | 
|  | 1595 | leds = (led[0] | (led[1]<<2) | (led[2]<<1) | (led[3]<<3))^0xF; | 
|  | 1596 | /* leds are inverted */ | 
|  | 1597 | if (leds != (int)hc->ledstate) { | 
|  | 1598 | HFC_outb_nodebug(hc, R_GPIO_OUT1, leds); | 
|  | 1599 | hc->ledstate = leds; | 
|  | 1600 | } | 
|  | 1601 | break; | 
|  | 1602 |  | 
|  | 1603 | case 2: /* HFC-4S OEM */ | 
|  | 1604 | /* red blinking = PH_DEACTIVATE NT Mode | 
|  | 1605 | * red steady   = PH_DEACTIVATE TE Mode | 
|  | 1606 | * green steady = PH_ACTIVATE | 
|  | 1607 | */ | 
|  | 1608 | for (i = 0; i < 4; i++) { | 
|  | 1609 | state = 0; | 
|  | 1610 | active = -1; | 
|  | 1611 | dch = hc->chan[(i << 2) | 2].dch; | 
|  | 1612 | if (dch) { | 
|  | 1613 | state = dch->state; | 
|  | 1614 | if (dch->dev.D.protocol == ISDN_P_NT_S0) | 
|  | 1615 | active = 3; | 
|  | 1616 | else | 
|  | 1617 | active = 7; | 
|  | 1618 | } | 
|  | 1619 | if (state) { | 
|  | 1620 | if (state == active) { | 
|  | 1621 | led[i] = 1; /* led green */ | 
|  | 1622 | } else | 
|  | 1623 | if (dch->dev.D.protocol == ISDN_P_TE_S0) | 
|  | 1624 | /* TE mode: led red */ | 
|  | 1625 | led[i] = 2; | 
|  | 1626 | else | 
|  | 1627 | if (hc->ledcount>>11) | 
|  | 1628 | /* led red */ | 
|  | 1629 | led[i] = 2; | 
|  | 1630 | else | 
|  | 1631 | /* led off */ | 
|  | 1632 | led[i] = 0; | 
|  | 1633 | } else | 
|  | 1634 | led[i] = 0; /* led off */ | 
|  | 1635 | } | 
|  | 1636 | if (test_bit(HFC_CHIP_B410P, &hc->chip)) { | 
|  | 1637 | leds = 0; | 
|  | 1638 | for (i = 0; i < 4; i++) { | 
|  | 1639 | if (led[i] == 1) { | 
|  | 1640 | /*green*/ | 
|  | 1641 | leds |= (0x2 << (i * 2)); | 
|  | 1642 | } else if (led[i] == 2) { | 
|  | 1643 | /*red*/ | 
|  | 1644 | leds |= (0x1 << (i * 2)); | 
|  | 1645 | } | 
|  | 1646 | } | 
|  | 1647 | if (leds != (int)hc->ledstate) { | 
|  | 1648 | vpm_out(hc, 0, 0x1a8 + 3, leds); | 
|  | 1649 | hc->ledstate = leds; | 
|  | 1650 | } | 
|  | 1651 | } else { | 
|  | 1652 | leds = ((led[3] > 0) << 0) | ((led[1] > 0) << 1) | | 
|  | 1653 | ((led[0] > 0) << 2) | ((led[2] > 0) << 3) | | 
|  | 1654 | ((led[3] & 1) << 4) | ((led[1] & 1) << 5) | | 
|  | 1655 | ((led[0] & 1) << 6) | ((led[2] & 1) << 7); | 
|  | 1656 | if (leds != (int)hc->ledstate) { | 
|  | 1657 | HFC_outb_nodebug(hc, R_GPIO_EN1, leds & 0x0F); | 
|  | 1658 | HFC_outb_nodebug(hc, R_GPIO_OUT1, leds >> 4); | 
|  | 1659 | hc->ledstate = leds; | 
|  | 1660 | } | 
|  | 1661 | } | 
|  | 1662 | break; | 
|  | 1663 |  | 
|  | 1664 | case 3: /* HFC 1S/2S Beronet */ | 
|  | 1665 | /* red blinking = PH_DEACTIVATE NT Mode | 
|  | 1666 | * red steady   = PH_DEACTIVATE TE Mode | 
|  | 1667 | * green steady = PH_ACTIVATE | 
|  | 1668 | */ | 
|  | 1669 | for (i = 0; i < 2; i++) { | 
|  | 1670 | state = 0; | 
|  | 1671 | active = -1; | 
|  | 1672 | dch = hc->chan[(i << 2) | 2].dch; | 
|  | 1673 | if (dch) { | 
|  | 1674 | state = dch->state; | 
|  | 1675 | if (dch->dev.D.protocol == ISDN_P_NT_S0) | 
|  | 1676 | active = 3; | 
|  | 1677 | else | 
|  | 1678 | active = 7; | 
|  | 1679 | } | 
|  | 1680 | if (state) { | 
|  | 1681 | if (state == active) { | 
|  | 1682 | led[i] = 1; /* led green */ | 
|  | 1683 | } else | 
|  | 1684 | if (dch->dev.D.protocol == ISDN_P_TE_S0) | 
|  | 1685 | /* TE mode: led red */ | 
|  | 1686 | led[i] = 2; | 
|  | 1687 | else | 
|  | 1688 | if (hc->ledcount >> 11) | 
|  | 1689 | /* led red */ | 
|  | 1690 | led[i] = 2; | 
|  | 1691 | else | 
|  | 1692 | /* led off */ | 
|  | 1693 | led[i] = 0; | 
|  | 1694 | } else | 
|  | 1695 | led[i] = 0; /* led off */ | 
|  | 1696 | } | 
|  | 1697 |  | 
|  | 1698 |  | 
|  | 1699 | leds = (led[0] > 0) | ((led[1] > 0)<<1) | ((led[0]&1)<<2) | 
|  | 1700 | | ((led[1]&1)<<3); | 
|  | 1701 | if (leds != (int)hc->ledstate) { | 
|  | 1702 | HFC_outb_nodebug(hc, R_GPIO_EN1, | 
|  | 1703 | ((led[0] > 0) << 2) | ((led[1] > 0) << 3)); | 
|  | 1704 | HFC_outb_nodebug(hc, R_GPIO_OUT1, | 
|  | 1705 | ((led[0] & 1) << 2) | ((led[1] & 1) << 3)); | 
|  | 1706 | hc->ledstate = leds; | 
|  | 1707 | } | 
|  | 1708 | break; | 
|  | 1709 | case 8: /* HFC 8S+ Beronet */ | 
|  | 1710 | lled = 0; | 
|  | 1711 |  | 
|  | 1712 | for (i = 0; i < 8; i++) { | 
|  | 1713 | state = 0; | 
|  | 1714 | active = -1; | 
|  | 1715 | dch = hc->chan[(i << 2) | 2].dch; | 
|  | 1716 | if (dch) { | 
|  | 1717 | state = dch->state; | 
|  | 1718 | if (dch->dev.D.protocol == ISDN_P_NT_S0) | 
|  | 1719 | active = 3; | 
|  | 1720 | else | 
|  | 1721 | active = 7; | 
|  | 1722 | } | 
|  | 1723 | if (state) { | 
|  | 1724 | if (state == active) { | 
|  | 1725 | lled |= 0 << i; | 
|  | 1726 | } else | 
|  | 1727 | if (hc->ledcount >> 11) | 
|  | 1728 | lled |= 0 << i; | 
|  | 1729 | else | 
|  | 1730 | lled |= 1 << i; | 
|  | 1731 | } else | 
|  | 1732 | lled |= 1 << i; | 
|  | 1733 | } | 
|  | 1734 | leddw = lled << 24 | lled << 16 | lled << 8 | lled; | 
|  | 1735 | if (leddw != hc->ledstate) { | 
|  | 1736 | /* HFC_outb(hc, R_BRG_PCM_CFG, 1); | 
|  | 1737 | HFC_outb(c, R_BRG_PCM_CFG, (0x0 << 6) | 0x3); */ | 
|  | 1738 | /* was _io before */ | 
|  | 1739 | HFC_outb_nodebug(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK); | 
|  | 1740 | outw(0x4000, hc->pci_iobase + 4); | 
|  | 1741 | outl(leddw, hc->pci_iobase); | 
|  | 1742 | HFC_outb_nodebug(hc, R_BRG_PCM_CFG, V_PCM_CLK); | 
|  | 1743 | hc->ledstate = leddw; | 
|  | 1744 | } | 
|  | 1745 | break; | 
|  | 1746 | } | 
|  | 1747 | } | 
|  | 1748 | /* | 
|  | 1749 | * read dtmf coefficients | 
|  | 1750 | */ | 
|  | 1751 |  | 
|  | 1752 | static void | 
|  | 1753 | hfcmulti_dtmf(struct hfc_multi *hc) | 
|  | 1754 | { | 
|  | 1755 | s32		*coeff; | 
|  | 1756 | u_int		mantissa; | 
|  | 1757 | int		co, ch; | 
|  | 1758 | struct bchannel	*bch = NULL; | 
|  | 1759 | u8		exponent; | 
|  | 1760 | int		dtmf = 0; | 
|  | 1761 | int		addr; | 
|  | 1762 | u16		w_float; | 
|  | 1763 | struct sk_buff	*skb; | 
|  | 1764 | struct mISDNhead *hh; | 
|  | 1765 |  | 
|  | 1766 | if (debug & DEBUG_HFCMULTI_DTMF) | 
|  | 1767 | printk(KERN_DEBUG "%s: dtmf detection irq\n", __func__); | 
|  | 1768 | for (ch = 0; ch <= 31; ch++) { | 
|  | 1769 | /* only process enabled B-channels */ | 
|  | 1770 | bch = hc->chan[ch].bch; | 
|  | 1771 | if (!bch) | 
|  | 1772 | continue; | 
|  | 1773 | if (!hc->created[hc->chan[ch].port]) | 
|  | 1774 | continue; | 
|  | 1775 | if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) | 
|  | 1776 | continue; | 
|  | 1777 | if (debug & DEBUG_HFCMULTI_DTMF) | 
|  | 1778 | printk(KERN_DEBUG "%s: dtmf channel %d:", | 
|  | 1779 | __func__, ch); | 
|  | 1780 | coeff = &(hc->chan[ch].coeff[hc->chan[ch].coeff_count * 16]); | 
|  | 1781 | dtmf = 1; | 
|  | 1782 | for (co = 0; co < 8; co++) { | 
|  | 1783 | /* read W(n-1) coefficient */ | 
|  | 1784 | addr = hc->DTMFbase + ((co<<7) | (ch<<2)); | 
|  | 1785 | HFC_outb_nodebug(hc, R_RAM_ADDR0, addr); | 
|  | 1786 | HFC_outb_nodebug(hc, R_RAM_ADDR1, addr>>8); | 
|  | 1787 | HFC_outb_nodebug(hc, R_RAM_ADDR2, (addr>>16) | 
|  | 1788 | | V_ADDR_INC); | 
|  | 1789 | w_float = HFC_inb_nodebug(hc, R_RAM_DATA); | 
|  | 1790 | w_float |= (HFC_inb_nodebug(hc, R_RAM_DATA) << 8); | 
|  | 1791 | if (debug & DEBUG_HFCMULTI_DTMF) | 
|  | 1792 | printk(" %04x", w_float); | 
|  | 1793 |  | 
|  | 1794 | /* decode float (see chip doc) */ | 
|  | 1795 | mantissa = w_float & 0x0fff; | 
|  | 1796 | if (w_float & 0x8000) | 
|  | 1797 | mantissa |= 0xfffff000; | 
|  | 1798 | exponent = (w_float>>12) & 0x7; | 
|  | 1799 | if (exponent) { | 
|  | 1800 | mantissa ^= 0x1000; | 
|  | 1801 | mantissa <<= (exponent-1); | 
|  | 1802 | } | 
|  | 1803 |  | 
|  | 1804 | /* store coefficient */ | 
|  | 1805 | coeff[co<<1] = mantissa; | 
|  | 1806 |  | 
|  | 1807 | /* read W(n) coefficient */ | 
|  | 1808 | w_float = HFC_inb_nodebug(hc, R_RAM_DATA); | 
|  | 1809 | w_float |= (HFC_inb_nodebug(hc, R_RAM_DATA) << 8); | 
|  | 1810 | if (debug & DEBUG_HFCMULTI_DTMF) | 
|  | 1811 | printk(" %04x", w_float); | 
|  | 1812 |  | 
|  | 1813 | /* decode float (see chip doc) */ | 
|  | 1814 | mantissa = w_float & 0x0fff; | 
|  | 1815 | if (w_float & 0x8000) | 
|  | 1816 | mantissa |= 0xfffff000; | 
|  | 1817 | exponent = (w_float>>12) & 0x7; | 
|  | 1818 | if (exponent) { | 
|  | 1819 | mantissa ^= 0x1000; | 
|  | 1820 | mantissa <<= (exponent-1); | 
|  | 1821 | } | 
|  | 1822 |  | 
|  | 1823 | /* store coefficient */ | 
|  | 1824 | coeff[(co<<1)|1] = mantissa; | 
|  | 1825 | } | 
|  | 1826 | if (debug & DEBUG_HFCMULTI_DTMF) | 
|  | 1827 | printk("%s: DTMF ready %08x %08x %08x %08x " | 
|  | 1828 | "%08x %08x %08x %08x\n", __func__, | 
|  | 1829 | coeff[0], coeff[1], coeff[2], coeff[3], | 
|  | 1830 | coeff[4], coeff[5], coeff[6], coeff[7]); | 
|  | 1831 | hc->chan[ch].coeff_count++; | 
|  | 1832 | if (hc->chan[ch].coeff_count == 8) { | 
|  | 1833 | hc->chan[ch].coeff_count = 0; | 
|  | 1834 | skb = mI_alloc_skb(512, GFP_ATOMIC); | 
|  | 1835 | if (!skb) { | 
|  | 1836 | printk(KERN_WARNING "%s: No memory for skb\n", | 
|  | 1837 | __func__); | 
|  | 1838 | continue; | 
|  | 1839 | } | 
|  | 1840 | hh = mISDN_HEAD_P(skb); | 
|  | 1841 | hh->prim = PH_CONTROL_IND; | 
|  | 1842 | hh->id = DTMF_HFC_COEF; | 
|  | 1843 | memcpy(skb_put(skb, 512), hc->chan[ch].coeff, 512); | 
|  | 1844 | recv_Bchannel_skb(bch, skb); | 
|  | 1845 | } | 
|  | 1846 | } | 
|  | 1847 |  | 
|  | 1848 | /* restart DTMF processing */ | 
|  | 1849 | hc->dtmf = dtmf; | 
|  | 1850 | if (dtmf) | 
|  | 1851 | HFC_outb_nodebug(hc, R_DTMF, hc->hw.r_dtmf | V_RST_DTMF); | 
|  | 1852 | } | 
|  | 1853 |  | 
|  | 1854 |  | 
|  | 1855 | /* | 
|  | 1856 | * fill fifo as much as possible | 
|  | 1857 | */ | 
|  | 1858 |  | 
|  | 1859 | static void | 
|  | 1860 | hfcmulti_tx(struct hfc_multi *hc, int ch) | 
|  | 1861 | { | 
|  | 1862 | int i, ii, temp, len = 0; | 
|  | 1863 | int Zspace, z1, z2; /* must be int for calculation */ | 
|  | 1864 | int Fspace, f1, f2; | 
|  | 1865 | u_char *d; | 
|  | 1866 | int *txpending, slot_tx; | 
|  | 1867 | struct	bchannel *bch; | 
|  | 1868 | struct  dchannel *dch; | 
|  | 1869 | struct  sk_buff **sp = NULL; | 
|  | 1870 | int *idxp; | 
|  | 1871 |  | 
|  | 1872 | bch = hc->chan[ch].bch; | 
|  | 1873 | dch = hc->chan[ch].dch; | 
|  | 1874 | if ((!dch) && (!bch)) | 
|  | 1875 | return; | 
|  | 1876 |  | 
|  | 1877 | txpending = &hc->chan[ch].txpending; | 
|  | 1878 | slot_tx = hc->chan[ch].slot_tx; | 
|  | 1879 | if (dch) { | 
|  | 1880 | if (!test_bit(FLG_ACTIVE, &dch->Flags)) | 
|  | 1881 | return; | 
|  | 1882 | sp = &dch->tx_skb; | 
|  | 1883 | idxp = &dch->tx_idx; | 
|  | 1884 | } else { | 
|  | 1885 | if (!test_bit(FLG_ACTIVE, &bch->Flags)) | 
|  | 1886 | return; | 
|  | 1887 | sp = &bch->tx_skb; | 
|  | 1888 | idxp = &bch->tx_idx; | 
|  | 1889 | } | 
|  | 1890 | if (*sp) | 
|  | 1891 | len = (*sp)->len; | 
|  | 1892 |  | 
|  | 1893 | if ((!len) && *txpending != 1) | 
|  | 1894 | return; /* no data */ | 
|  | 1895 |  | 
|  | 1896 | if (test_bit(HFC_CHIP_B410P, &hc->chip) && | 
|  | 1897 | (hc->chan[ch].protocol == ISDN_P_B_RAW) && | 
|  | 1898 | (hc->chan[ch].slot_rx < 0) && | 
|  | 1899 | (hc->chan[ch].slot_tx < 0)) | 
|  | 1900 | HFC_outb_nodebug(hc, R_FIFO, 0x20 | (ch << 1)); | 
|  | 1901 | else | 
|  | 1902 | HFC_outb_nodebug(hc, R_FIFO, ch << 1); | 
|  | 1903 | HFC_wait_nodebug(hc); | 
|  | 1904 |  | 
|  | 1905 | if (*txpending == 2) { | 
|  | 1906 | /* reset fifo */ | 
|  | 1907 | HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 1908 | HFC_wait_nodebug(hc); | 
|  | 1909 | HFC_outb(hc, A_SUBCH_CFG, 0); | 
|  | 1910 | *txpending = 1; | 
|  | 1911 | } | 
|  | 1912 | next_frame: | 
|  | 1913 | if (dch || test_bit(FLG_HDLC, &bch->Flags)) { | 
|  | 1914 | f1 = HFC_inb_nodebug(hc, A_F1); | 
|  | 1915 | f2 = HFC_inb_nodebug(hc, A_F2); | 
|  | 1916 | while (f2 != (temp = HFC_inb_nodebug(hc, A_F2))) { | 
|  | 1917 | if (debug & DEBUG_HFCMULTI_FIFO) | 
|  | 1918 | printk(KERN_DEBUG | 
|  | 1919 | "%s(card %d): reread f2 because %d!=%d\n", | 
|  | 1920 | __func__, hc->id + 1, temp, f2); | 
|  | 1921 | f2 = temp; /* repeat until F2 is equal */ | 
|  | 1922 | } | 
|  | 1923 | Fspace = f2 - f1 - 1; | 
|  | 1924 | if (Fspace < 0) | 
|  | 1925 | Fspace += hc->Flen; | 
|  | 1926 | /* | 
|  | 1927 | * Old FIFO handling doesn't give us the current Z2 read | 
|  | 1928 | * pointer, so we cannot send the next frame before the fifo | 
|  | 1929 | * is empty. It makes no difference except for a slightly | 
|  | 1930 | * lower performance. | 
|  | 1931 | */ | 
|  | 1932 | if (test_bit(HFC_CHIP_REVISION0, &hc->chip)) { | 
|  | 1933 | if (f1 != f2) | 
|  | 1934 | Fspace = 0; | 
|  | 1935 | else | 
|  | 1936 | Fspace = 1; | 
|  | 1937 | } | 
|  | 1938 | /* one frame only for ST D-channels, to allow resending */ | 
|  | 1939 | if (hc->type != 1 && dch) { | 
|  | 1940 | if (f1 != f2) | 
|  | 1941 | Fspace = 0; | 
|  | 1942 | } | 
|  | 1943 | /* F-counter full condition */ | 
|  | 1944 | if (Fspace == 0) | 
|  | 1945 | return; | 
|  | 1946 | } | 
|  | 1947 | z1 = HFC_inw_nodebug(hc, A_Z1) - hc->Zmin; | 
|  | 1948 | z2 = HFC_inw_nodebug(hc, A_Z2) - hc->Zmin; | 
|  | 1949 | while (z2 != (temp = (HFC_inw_nodebug(hc, A_Z2) - hc->Zmin))) { | 
|  | 1950 | if (debug & DEBUG_HFCMULTI_FIFO) | 
|  | 1951 | printk(KERN_DEBUG "%s(card %d): reread z2 because " | 
|  | 1952 | "%d!=%d\n", __func__, hc->id + 1, temp, z2); | 
|  | 1953 | z2 = temp; /* repeat unti Z2 is equal */ | 
|  | 1954 | } | 
|  | 1955 | Zspace = z2 - z1; | 
|  | 1956 | if (Zspace <= 0) | 
|  | 1957 | Zspace += hc->Zlen; | 
|  | 1958 | Zspace -= 4; /* keep not too full, so pointers will not overrun */ | 
|  | 1959 | /* fill transparent data only to maxinum transparent load (minus 4) */ | 
|  | 1960 | if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) | 
|  | 1961 | Zspace = Zspace - hc->Zlen + hc->max_trans; | 
|  | 1962 | if (Zspace <= 0) /* no space of 4 bytes */ | 
|  | 1963 | return; | 
|  | 1964 |  | 
|  | 1965 | /* if no data */ | 
|  | 1966 | if (!len) { | 
|  | 1967 | if (z1 == z2) { /* empty */ | 
|  | 1968 | /* if done with FIFO audio data during PCM connection */ | 
|  | 1969 | if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && | 
|  | 1970 | *txpending && slot_tx >= 0) { | 
|  | 1971 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 1972 | printk(KERN_DEBUG | 
|  | 1973 | "%s: reconnecting PCM due to no " | 
|  | 1974 | "more FIFO data: channel %d " | 
|  | 1975 | "slot_tx %d\n", | 
|  | 1976 | __func__, ch, slot_tx); | 
|  | 1977 | /* connect slot */ | 
|  | 1978 | HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | | 
|  | 1979 | V_HDLC_TRP | V_IFF); | 
|  | 1980 | HFC_outb_nodebug(hc, R_FIFO, ch<<1 | 1); | 
|  | 1981 | HFC_wait_nodebug(hc); | 
|  | 1982 | HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | | 
|  | 1983 | V_HDLC_TRP | V_IFF); | 
|  | 1984 | HFC_outb_nodebug(hc, R_FIFO, ch<<1); | 
|  | 1985 | HFC_wait_nodebug(hc); | 
|  | 1986 | } | 
|  | 1987 | *txpending = 0; | 
|  | 1988 | } | 
|  | 1989 | return; /* no data */ | 
|  | 1990 | } | 
|  | 1991 |  | 
|  | 1992 | /* if audio data and connected slot */ | 
|  | 1993 | if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending) | 
|  | 1994 | && slot_tx >= 0) { | 
|  | 1995 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 1996 | printk(KERN_DEBUG "%s: disconnecting PCM due to " | 
|  | 1997 | "FIFO data: channel %d slot_tx %d\n", | 
|  | 1998 | __func__, ch, slot_tx); | 
|  | 1999 | /* disconnect slot */ | 
|  | 2000 | HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF); | 
|  | 2001 | HFC_outb_nodebug(hc, R_FIFO, ch<<1 | 1); | 
|  | 2002 | HFC_wait_nodebug(hc); | 
|  | 2003 | HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF); | 
|  | 2004 | HFC_outb_nodebug(hc, R_FIFO, ch<<1); | 
|  | 2005 | HFC_wait_nodebug(hc); | 
|  | 2006 | } | 
|  | 2007 | *txpending = 1; | 
|  | 2008 |  | 
|  | 2009 | /* show activity */ | 
|  | 2010 | hc->activity[hc->chan[ch].port] = 1; | 
|  | 2011 |  | 
|  | 2012 | /* fill fifo to what we have left */ | 
|  | 2013 | ii = len; | 
|  | 2014 | if (dch || test_bit(FLG_HDLC, &bch->Flags)) | 
|  | 2015 | temp = 1; | 
|  | 2016 | else | 
|  | 2017 | temp = 0; | 
|  | 2018 | i = *idxp; | 
|  | 2019 | d = (*sp)->data + i; | 
|  | 2020 | if (ii - i > Zspace) | 
|  | 2021 | ii = Zspace + i; | 
|  | 2022 | if (debug & DEBUG_HFCMULTI_FIFO) | 
|  | 2023 | printk(KERN_DEBUG "%s(card %d): fifo(%d) has %d bytes space " | 
|  | 2024 | "left (z1=%04x, z2=%04x) sending %d of %d bytes %s\n", | 
|  | 2025 | __func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i, | 
|  | 2026 | temp ? "HDLC":"TRANS"); | 
|  | 2027 |  | 
|  | 2028 |  | 
|  | 2029 | /* Have to prep the audio data */ | 
|  | 2030 | hc->write_fifo(hc, d, ii - i); | 
|  | 2031 | *idxp = ii; | 
|  | 2032 |  | 
|  | 2033 | /* if not all data has been written */ | 
|  | 2034 | if (ii != len) { | 
|  | 2035 | /* NOTE: fifo is started by the calling function */ | 
|  | 2036 | return; | 
|  | 2037 | } | 
|  | 2038 |  | 
|  | 2039 | /* if all data has been written, terminate frame */ | 
|  | 2040 | if (dch || test_bit(FLG_HDLC, &bch->Flags)) { | 
|  | 2041 | /* increment f-counter */ | 
|  | 2042 | HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_INC_F); | 
|  | 2043 | HFC_wait_nodebug(hc); | 
|  | 2044 | } | 
|  | 2045 |  | 
|  | 2046 | /* send confirm, since get_net_bframe will not do it with trans */ | 
|  | 2047 | if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) | 
|  | 2048 | confirm_Bsend(bch); | 
|  | 2049 |  | 
|  | 2050 | /* check for next frame */ | 
|  | 2051 | dev_kfree_skb(*sp); | 
|  | 2052 | if (bch && get_next_bframe(bch)) { /* hdlc is confirmed here */ | 
|  | 2053 | len = (*sp)->len; | 
|  | 2054 | goto next_frame; | 
|  | 2055 | } | 
|  | 2056 | if (dch && get_next_dframe(dch)) { | 
|  | 2057 | len = (*sp)->len; | 
|  | 2058 | goto next_frame; | 
|  | 2059 | } | 
|  | 2060 |  | 
|  | 2061 | /* | 
|  | 2062 | * now we have no more data, so in case of transparent, | 
|  | 2063 | * we set the last byte in fifo to 'silence' in case we will get | 
|  | 2064 | * no more data at all. this prevents sending an undefined value. | 
|  | 2065 | */ | 
|  | 2066 | if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags)) | 
|  | 2067 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); | 
|  | 2068 | } | 
|  | 2069 |  | 
|  | 2070 |  | 
|  | 2071 | /* NOTE: only called if E1 card is in active state */ | 
|  | 2072 | static void | 
|  | 2073 | hfcmulti_rx(struct hfc_multi *hc, int ch) | 
|  | 2074 | { | 
|  | 2075 | int temp; | 
|  | 2076 | int Zsize, z1, z2 = 0; /* = 0, to make GCC happy */ | 
|  | 2077 | int f1 = 0, f2 = 0; /* = 0, to make GCC happy */ | 
|  | 2078 | int again = 0; | 
|  | 2079 | struct	bchannel *bch; | 
|  | 2080 | struct  dchannel *dch; | 
|  | 2081 | struct sk_buff	*skb, **sp = NULL; | 
|  | 2082 | int	maxlen; | 
|  | 2083 |  | 
|  | 2084 | bch = hc->chan[ch].bch; | 
|  | 2085 | dch = hc->chan[ch].dch; | 
|  | 2086 | if ((!dch) && (!bch)) | 
|  | 2087 | return; | 
|  | 2088 | if (dch) { | 
|  | 2089 | if (!test_bit(FLG_ACTIVE, &dch->Flags)) | 
|  | 2090 | return; | 
|  | 2091 | sp = &dch->rx_skb; | 
|  | 2092 | maxlen = dch->maxlen; | 
|  | 2093 | } else { | 
|  | 2094 | if (!test_bit(FLG_ACTIVE, &bch->Flags)) | 
|  | 2095 | return; | 
|  | 2096 | sp = &bch->rx_skb; | 
|  | 2097 | maxlen = bch->maxlen; | 
|  | 2098 | } | 
|  | 2099 | next_frame: | 
|  | 2100 | /* on first AND before getting next valid frame, R_FIFO must be written | 
|  | 2101 | to. */ | 
|  | 2102 | if (test_bit(HFC_CHIP_B410P, &hc->chip) && | 
|  | 2103 | (hc->chan[ch].protocol == ISDN_P_B_RAW) && | 
|  | 2104 | (hc->chan[ch].slot_rx < 0) && | 
|  | 2105 | (hc->chan[ch].slot_tx < 0)) | 
|  | 2106 | HFC_outb_nodebug(hc, R_FIFO, 0x20 | (ch<<1) | 1); | 
|  | 2107 | else | 
|  | 2108 | HFC_outb_nodebug(hc, R_FIFO, (ch<<1)|1); | 
|  | 2109 | HFC_wait_nodebug(hc); | 
|  | 2110 |  | 
|  | 2111 | /* ignore if rx is off BUT change fifo (above) to start pending TX */ | 
|  | 2112 | if (hc->chan[ch].rx_off) | 
|  | 2113 | return; | 
|  | 2114 |  | 
|  | 2115 | if (dch || test_bit(FLG_HDLC, &bch->Flags)) { | 
|  | 2116 | f1 = HFC_inb_nodebug(hc, A_F1); | 
|  | 2117 | while (f1 != (temp = HFC_inb_nodebug(hc, A_F1))) { | 
|  | 2118 | if (debug & DEBUG_HFCMULTI_FIFO) | 
|  | 2119 | printk(KERN_DEBUG | 
|  | 2120 | "%s(card %d): reread f1 because %d!=%d\n", | 
|  | 2121 | __func__, hc->id + 1, temp, f1); | 
|  | 2122 | f1 = temp; /* repeat until F1 is equal */ | 
|  | 2123 | } | 
|  | 2124 | f2 = HFC_inb_nodebug(hc, A_F2); | 
|  | 2125 | } | 
|  | 2126 | z1 = HFC_inw_nodebug(hc, A_Z1) - hc->Zmin; | 
|  | 2127 | while (z1 != (temp = (HFC_inw_nodebug(hc, A_Z1) - hc->Zmin))) { | 
|  | 2128 | if (debug & DEBUG_HFCMULTI_FIFO) | 
|  | 2129 | printk(KERN_DEBUG "%s(card %d): reread z2 because " | 
|  | 2130 | "%d!=%d\n", __func__, hc->id + 1, temp, z2); | 
|  | 2131 | z1 = temp; /* repeat until Z1 is equal */ | 
|  | 2132 | } | 
|  | 2133 | z2 = HFC_inw_nodebug(hc, A_Z2) - hc->Zmin; | 
|  | 2134 | Zsize = z1 - z2; | 
|  | 2135 | if ((dch || test_bit(FLG_HDLC, &bch->Flags)) && f1 != f2) | 
|  | 2136 | /* complete hdlc frame */ | 
|  | 2137 | Zsize++; | 
|  | 2138 | if (Zsize < 0) | 
|  | 2139 | Zsize += hc->Zlen; | 
|  | 2140 | /* if buffer is empty */ | 
|  | 2141 | if (Zsize <= 0) | 
|  | 2142 | return; | 
|  | 2143 |  | 
|  | 2144 | if (*sp == NULL) { | 
|  | 2145 | *sp = mI_alloc_skb(maxlen + 3, GFP_ATOMIC); | 
|  | 2146 | if (*sp == NULL) { | 
|  | 2147 | printk(KERN_DEBUG "%s: No mem for rx_skb\n", | 
|  | 2148 | __func__); | 
|  | 2149 | return; | 
|  | 2150 | } | 
|  | 2151 | } | 
|  | 2152 | /* show activity */ | 
|  | 2153 | hc->activity[hc->chan[ch].port] = 1; | 
|  | 2154 |  | 
|  | 2155 | /* empty fifo with what we have */ | 
|  | 2156 | if (dch || test_bit(FLG_HDLC, &bch->Flags)) { | 
|  | 2157 | if (debug & DEBUG_HFCMULTI_FIFO) | 
|  | 2158 | printk(KERN_DEBUG "%s(card %d): fifo(%d) reading %d " | 
|  | 2159 | "bytes (z1=%04x, z2=%04x) HDLC %s (f1=%d, f2=%d) " | 
|  | 2160 | "got=%d (again %d)\n", __func__, hc->id + 1, ch, | 
|  | 2161 | Zsize, z1, z2, (f1 == f2) ? "fragment" : "COMPLETE", | 
|  | 2162 | f1, f2, Zsize + (*sp)->len, again); | 
|  | 2163 | /* HDLC */ | 
|  | 2164 | if ((Zsize + (*sp)->len) > (maxlen + 3)) { | 
|  | 2165 | if (debug & DEBUG_HFCMULTI_FIFO) | 
|  | 2166 | printk(KERN_DEBUG | 
|  | 2167 | "%s(card %d): hdlc-frame too large.\n", | 
|  | 2168 | __func__, hc->id + 1); | 
|  | 2169 | skb_trim(*sp, 0); | 
|  | 2170 | HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 2171 | HFC_wait_nodebug(hc); | 
|  | 2172 | return; | 
|  | 2173 | } | 
|  | 2174 |  | 
|  | 2175 | hc->read_fifo(hc, skb_put(*sp, Zsize), Zsize); | 
|  | 2176 |  | 
|  | 2177 | if (f1 != f2) { | 
|  | 2178 | /* increment Z2,F2-counter */ | 
|  | 2179 | HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_INC_F); | 
|  | 2180 | HFC_wait_nodebug(hc); | 
|  | 2181 | /* check size */ | 
|  | 2182 | if ((*sp)->len < 4) { | 
|  | 2183 | if (debug & DEBUG_HFCMULTI_FIFO) | 
|  | 2184 | printk(KERN_DEBUG | 
|  | 2185 | "%s(card %d): Frame below minimum " | 
|  | 2186 | "size\n", __func__, hc->id + 1); | 
|  | 2187 | skb_trim(*sp, 0); | 
|  | 2188 | goto next_frame; | 
|  | 2189 | } | 
|  | 2190 | /* there is at least one complete frame, check crc */ | 
|  | 2191 | if ((*sp)->data[(*sp)->len - 1]) { | 
|  | 2192 | if (debug & DEBUG_HFCMULTI_CRC) | 
|  | 2193 | printk(KERN_DEBUG | 
|  | 2194 | "%s: CRC-error\n", __func__); | 
|  | 2195 | skb_trim(*sp, 0); | 
|  | 2196 | goto next_frame; | 
|  | 2197 | } | 
|  | 2198 | skb_trim(*sp, (*sp)->len - 3); | 
|  | 2199 | if ((*sp)->len < MISDN_COPY_SIZE) { | 
|  | 2200 | skb = *sp; | 
|  | 2201 | *sp = mI_alloc_skb(skb->len, GFP_ATOMIC); | 
|  | 2202 | if (*sp) { | 
|  | 2203 | memcpy(skb_put(*sp, skb->len), | 
|  | 2204 | skb->data, skb->len); | 
|  | 2205 | skb_trim(skb, 0); | 
|  | 2206 | } else { | 
|  | 2207 | printk(KERN_DEBUG "%s: No mem\n", | 
|  | 2208 | __func__); | 
|  | 2209 | *sp = skb; | 
|  | 2210 | skb = NULL; | 
|  | 2211 | } | 
|  | 2212 | } else { | 
|  | 2213 | skb = NULL; | 
|  | 2214 | } | 
|  | 2215 | if (debug & DEBUG_HFCMULTI_FIFO) { | 
|  | 2216 | printk(KERN_DEBUG "%s(card %d):", | 
|  | 2217 | __func__, hc->id + 1); | 
|  | 2218 | temp = 0; | 
|  | 2219 | while (temp < (*sp)->len) | 
|  | 2220 | printk(" %02x", (*sp)->data[temp++]); | 
|  | 2221 | printk("\n"); | 
|  | 2222 | } | 
|  | 2223 | if (dch) | 
|  | 2224 | recv_Dchannel(dch); | 
|  | 2225 | else | 
|  | 2226 | recv_Bchannel(bch); | 
|  | 2227 | *sp = skb; | 
|  | 2228 | again++; | 
|  | 2229 | goto next_frame; | 
|  | 2230 | } | 
|  | 2231 | /* there is an incomplete frame */ | 
|  | 2232 | } else { | 
|  | 2233 | /* transparent */ | 
|  | 2234 | if (Zsize > skb_tailroom(*sp)) | 
|  | 2235 | Zsize = skb_tailroom(*sp); | 
|  | 2236 | hc->read_fifo(hc, skb_put(*sp, Zsize), Zsize); | 
|  | 2237 | if (((*sp)->len) < MISDN_COPY_SIZE) { | 
|  | 2238 | skb = *sp; | 
|  | 2239 | *sp = mI_alloc_skb(skb->len, GFP_ATOMIC); | 
|  | 2240 | if (*sp) { | 
|  | 2241 | memcpy(skb_put(*sp, skb->len), | 
|  | 2242 | skb->data, skb->len); | 
|  | 2243 | skb_trim(skb, 0); | 
|  | 2244 | } else { | 
|  | 2245 | printk(KERN_DEBUG "%s: No mem\n", __func__); | 
|  | 2246 | *sp = skb; | 
|  | 2247 | skb = NULL; | 
|  | 2248 | } | 
|  | 2249 | } else { | 
|  | 2250 | skb = NULL; | 
|  | 2251 | } | 
|  | 2252 | if (debug & DEBUG_HFCMULTI_FIFO) | 
|  | 2253 | printk(KERN_DEBUG | 
|  | 2254 | "%s(card %d): fifo(%d) reading %d bytes " | 
|  | 2255 | "(z1=%04x, z2=%04x) TRANS\n", | 
|  | 2256 | __func__, hc->id + 1, ch, Zsize, z1, z2); | 
|  | 2257 | /* only bch is transparent */ | 
|  | 2258 | recv_Bchannel(bch); | 
|  | 2259 | *sp = skb; | 
|  | 2260 | } | 
|  | 2261 | } | 
|  | 2262 |  | 
|  | 2263 |  | 
|  | 2264 | /* | 
|  | 2265 | * Interrupt handler | 
|  | 2266 | */ | 
|  | 2267 | static void | 
|  | 2268 | signal_state_up(struct dchannel *dch, int info, char *msg) | 
|  | 2269 | { | 
|  | 2270 | struct sk_buff	*skb; | 
|  | 2271 | int		id, data = info; | 
|  | 2272 |  | 
|  | 2273 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 2274 | printk(KERN_DEBUG "%s: %s\n", __func__, msg); | 
|  | 2275 |  | 
|  | 2276 | id = TEI_SAPI | (GROUP_TEI << 8); /* manager address */ | 
|  | 2277 |  | 
|  | 2278 | skb = _alloc_mISDN_skb(MPH_INFORMATION_IND, id, sizeof(data), &data, | 
|  | 2279 | GFP_ATOMIC); | 
|  | 2280 | if (!skb) | 
|  | 2281 | return; | 
|  | 2282 | recv_Dchannel_skb(dch, skb); | 
|  | 2283 | } | 
|  | 2284 |  | 
|  | 2285 | static inline void | 
|  | 2286 | handle_timer_irq(struct hfc_multi *hc) | 
|  | 2287 | { | 
|  | 2288 | int		ch, temp; | 
|  | 2289 | struct dchannel	*dch; | 
|  | 2290 | u_long		flags; | 
|  | 2291 |  | 
|  | 2292 | /* process queued resync jobs */ | 
|  | 2293 | if (hc->e1_resync) { | 
|  | 2294 | /* lock, so e1_resync gets not changed */ | 
|  | 2295 | spin_lock_irqsave(&HFClock, flags); | 
|  | 2296 | if (hc->e1_resync & 1) { | 
|  | 2297 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 2298 | printk(KERN_DEBUG "Enable SYNC_I\n"); | 
|  | 2299 | HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC); | 
|  | 2300 | /* disable JATT, if RX_SYNC is set */ | 
|  | 2301 | if (test_bit(HFC_CHIP_RX_SYNC, &hc->chip)) | 
|  | 2302 | HFC_outb(hc, R_SYNC_OUT, V_SYNC_E1_RX); | 
|  | 2303 | } | 
|  | 2304 | if (hc->e1_resync & 2) { | 
|  | 2305 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 2306 | printk(KERN_DEBUG "Enable jatt PLL\n"); | 
|  | 2307 | HFC_outb(hc, R_SYNC_CTRL, V_SYNC_OFFS); | 
|  | 2308 | } | 
|  | 2309 | if (hc->e1_resync & 4) { | 
|  | 2310 | if (debug & DEBUG_HFCMULTI_PLXSD) | 
|  | 2311 | printk(KERN_DEBUG | 
|  | 2312 | "Enable QUARTZ for HFC-E1\n"); | 
|  | 2313 | /* set jatt to quartz */ | 
|  | 2314 | HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC | 
|  | 2315 | | V_JATT_OFF); | 
|  | 2316 | /* switch to JATT, in case it is not already */ | 
|  | 2317 | HFC_outb(hc, R_SYNC_OUT, 0); | 
|  | 2318 | } | 
|  | 2319 | hc->e1_resync = 0; | 
|  | 2320 | spin_unlock_irqrestore(&HFClock, flags); | 
|  | 2321 | } | 
|  | 2322 |  | 
|  | 2323 | if (hc->type != 1 || hc->e1_state == 1) | 
|  | 2324 | for (ch = 0; ch <= 31; ch++) { | 
|  | 2325 | if (hc->created[hc->chan[ch].port]) { | 
|  | 2326 | hfcmulti_tx(hc, ch); | 
|  | 2327 | /* fifo is started when switching to rx-fifo */ | 
|  | 2328 | hfcmulti_rx(hc, ch); | 
|  | 2329 | if (hc->chan[ch].dch && | 
|  | 2330 | hc->chan[ch].nt_timer > -1) { | 
|  | 2331 | dch = hc->chan[ch].dch; | 
|  | 2332 | if (!(--hc->chan[ch].nt_timer)) { | 
|  | 2333 | schedule_event(dch, | 
|  | 2334 | FLG_PHCHANGE); | 
|  | 2335 | if (debug & | 
|  | 2336 | DEBUG_HFCMULTI_STATE) | 
|  | 2337 | printk(KERN_DEBUG | 
|  | 2338 | "%s: nt_timer at " | 
|  | 2339 | "state %x\n", | 
|  | 2340 | __func__, | 
|  | 2341 | dch->state); | 
|  | 2342 | } | 
|  | 2343 | } | 
|  | 2344 | } | 
|  | 2345 | } | 
|  | 2346 | if (hc->type == 1 && hc->created[0]) { | 
|  | 2347 | dch = hc->chan[hc->dslot].dch; | 
|  | 2348 | if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) { | 
|  | 2349 | /* LOS */ | 
|  | 2350 | temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_SIG_LOS; | 
|  | 2351 | if (!temp && hc->chan[hc->dslot].los) | 
|  | 2352 | signal_state_up(dch, L1_SIGNAL_LOS_ON, | 
|  | 2353 | "LOS detected"); | 
|  | 2354 | if (temp && !hc->chan[hc->dslot].los) | 
|  | 2355 | signal_state_up(dch, L1_SIGNAL_LOS_OFF, | 
|  | 2356 | "LOS gone"); | 
|  | 2357 | hc->chan[hc->dslot].los = temp; | 
|  | 2358 | } | 
|  | 2359 | if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[hc->dslot].cfg)) { | 
|  | 2360 | /* AIS */ | 
|  | 2361 | temp = HFC_inb_nodebug(hc, R_SYNC_STA) & V_AIS; | 
|  | 2362 | if (!temp && hc->chan[hc->dslot].ais) | 
|  | 2363 | signal_state_up(dch, L1_SIGNAL_AIS_ON, | 
|  | 2364 | "AIS detected"); | 
|  | 2365 | if (temp && !hc->chan[hc->dslot].ais) | 
|  | 2366 | signal_state_up(dch, L1_SIGNAL_AIS_OFF, | 
|  | 2367 | "AIS gone"); | 
|  | 2368 | hc->chan[hc->dslot].ais = temp; | 
|  | 2369 | } | 
|  | 2370 | if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[hc->dslot].cfg)) { | 
|  | 2371 | /* SLIP */ | 
|  | 2372 | temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_RX; | 
|  | 2373 | if (!temp && hc->chan[hc->dslot].slip_rx) | 
|  | 2374 | signal_state_up(dch, L1_SIGNAL_SLIP_RX, | 
|  | 2375 | " bit SLIP detected RX"); | 
|  | 2376 | hc->chan[hc->dslot].slip_rx = temp; | 
|  | 2377 | temp = HFC_inb_nodebug(hc, R_SLIP) & V_FOSLIP_TX; | 
|  | 2378 | if (!temp && hc->chan[hc->dslot].slip_tx) | 
|  | 2379 | signal_state_up(dch, L1_SIGNAL_SLIP_TX, | 
|  | 2380 | " bit SLIP detected TX"); | 
|  | 2381 | hc->chan[hc->dslot].slip_tx = temp; | 
|  | 2382 | } | 
|  | 2383 | if (test_bit(HFC_CFG_REPORT_RDI, &hc->chan[hc->dslot].cfg)) { | 
|  | 2384 | /* RDI */ | 
|  | 2385 | temp = HFC_inb_nodebug(hc, R_RX_SL0_0) & V_A; | 
|  | 2386 | if (!temp && hc->chan[hc->dslot].rdi) | 
|  | 2387 | signal_state_up(dch, L1_SIGNAL_RDI_ON, | 
|  | 2388 | "RDI detected"); | 
|  | 2389 | if (temp && !hc->chan[hc->dslot].rdi) | 
|  | 2390 | signal_state_up(dch, L1_SIGNAL_RDI_OFF, | 
|  | 2391 | "RDI gone"); | 
|  | 2392 | hc->chan[hc->dslot].rdi = temp; | 
|  | 2393 | } | 
|  | 2394 | temp = HFC_inb_nodebug(hc, R_JATT_DIR); | 
|  | 2395 | switch (hc->chan[hc->dslot].sync) { | 
|  | 2396 | case 0: | 
|  | 2397 | if ((temp & 0x60) == 0x60) { | 
|  | 2398 | if (debug & DEBUG_HFCMULTI_SYNC) | 
|  | 2399 | printk(KERN_DEBUG | 
|  | 2400 | "%s: (id=%d) E1 now " | 
|  | 2401 | "in clock sync\n", | 
|  | 2402 | __func__, hc->id); | 
|  | 2403 | HFC_outb(hc, R_RX_OFF, | 
|  | 2404 | hc->chan[hc->dslot].jitter | V_RX_INIT); | 
|  | 2405 | HFC_outb(hc, R_TX_OFF, | 
|  | 2406 | hc->chan[hc->dslot].jitter | V_RX_INIT); | 
|  | 2407 | hc->chan[hc->dslot].sync = 1; | 
|  | 2408 | goto check_framesync; | 
|  | 2409 | } | 
|  | 2410 | break; | 
|  | 2411 | case 1: | 
|  | 2412 | if ((temp & 0x60) != 0x60) { | 
|  | 2413 | if (debug & DEBUG_HFCMULTI_SYNC) | 
|  | 2414 | printk(KERN_DEBUG | 
|  | 2415 | "%s: (id=%d) E1 " | 
|  | 2416 | "lost clock sync\n", | 
|  | 2417 | __func__, hc->id); | 
|  | 2418 | hc->chan[hc->dslot].sync = 0; | 
|  | 2419 | break; | 
|  | 2420 | } | 
|  | 2421 | check_framesync: | 
|  | 2422 | temp = HFC_inb_nodebug(hc, R_SYNC_STA); | 
|  | 2423 | if (temp == 0x27) { | 
|  | 2424 | if (debug & DEBUG_HFCMULTI_SYNC) | 
|  | 2425 | printk(KERN_DEBUG | 
|  | 2426 | "%s: (id=%d) E1 " | 
|  | 2427 | "now in frame sync\n", | 
|  | 2428 | __func__, hc->id); | 
|  | 2429 | hc->chan[hc->dslot].sync = 2; | 
|  | 2430 | } | 
|  | 2431 | break; | 
|  | 2432 | case 2: | 
|  | 2433 | if ((temp & 0x60) != 0x60) { | 
|  | 2434 | if (debug & DEBUG_HFCMULTI_SYNC) | 
|  | 2435 | printk(KERN_DEBUG | 
|  | 2436 | "%s: (id=%d) E1 lost " | 
|  | 2437 | "clock & frame sync\n", | 
|  | 2438 | __func__, hc->id); | 
|  | 2439 | hc->chan[hc->dslot].sync = 0; | 
|  | 2440 | break; | 
|  | 2441 | } | 
|  | 2442 | temp = HFC_inb_nodebug(hc, R_SYNC_STA); | 
|  | 2443 | if (temp != 0x27) { | 
|  | 2444 | if (debug & DEBUG_HFCMULTI_SYNC) | 
|  | 2445 | printk(KERN_DEBUG | 
|  | 2446 | "%s: (id=%d) E1 " | 
|  | 2447 | "lost frame sync\n", | 
|  | 2448 | __func__, hc->id); | 
|  | 2449 | hc->chan[hc->dslot].sync = 1; | 
|  | 2450 | } | 
|  | 2451 | break; | 
|  | 2452 | } | 
|  | 2453 | } | 
|  | 2454 |  | 
|  | 2455 | if (test_bit(HFC_CHIP_WATCHDOG, &hc->chip)) | 
|  | 2456 | hfcmulti_watchdog(hc); | 
|  | 2457 |  | 
|  | 2458 | if (hc->leds) | 
|  | 2459 | hfcmulti_leds(hc); | 
|  | 2460 | } | 
|  | 2461 |  | 
|  | 2462 | static void | 
|  | 2463 | ph_state_irq(struct hfc_multi *hc, u_char r_irq_statech) | 
|  | 2464 | { | 
|  | 2465 | struct dchannel	*dch; | 
|  | 2466 | int		ch; | 
|  | 2467 | int		active; | 
|  | 2468 | u_char		st_status, temp; | 
|  | 2469 |  | 
|  | 2470 | /* state machine */ | 
|  | 2471 | for (ch = 0; ch <= 31; ch++) { | 
|  | 2472 | if (hc->chan[ch].dch) { | 
|  | 2473 | dch = hc->chan[ch].dch; | 
|  | 2474 | if (r_irq_statech & 1) { | 
|  | 2475 | HFC_outb_nodebug(hc, R_ST_SEL, | 
|  | 2476 | hc->chan[ch].port); | 
|  | 2477 | /* undocumented: delay after R_ST_SEL */ | 
|  | 2478 | udelay(1); | 
|  | 2479 | /* undocumented: status changes during read */ | 
|  | 2480 | st_status = HFC_inb_nodebug(hc, A_ST_RD_STATE); | 
|  | 2481 | while (st_status != (temp = | 
|  | 2482 | HFC_inb_nodebug(hc, A_ST_RD_STATE))) { | 
|  | 2483 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 2484 | printk(KERN_DEBUG "%s: reread " | 
|  | 2485 | "STATE because %d!=%d\n", | 
|  | 2486 | __func__, temp, | 
|  | 2487 | st_status); | 
|  | 2488 | st_status = temp; /* repeat */ | 
|  | 2489 | } | 
|  | 2490 |  | 
|  | 2491 | /* Speech Design TE-sync indication */ | 
|  | 2492 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip) && | 
|  | 2493 | dch->dev.D.protocol == ISDN_P_TE_S0) { | 
|  | 2494 | if (st_status & V_FR_SYNC_ST) | 
|  | 2495 | hc->syncronized |= | 
|  | 2496 | (1 << hc->chan[ch].port); | 
|  | 2497 | else | 
|  | 2498 | hc->syncronized &= | 
|  | 2499 | ~(1 << hc->chan[ch].port); | 
|  | 2500 | } | 
|  | 2501 | dch->state = st_status & 0x0f; | 
|  | 2502 | if (dch->dev.D.protocol == ISDN_P_NT_S0) | 
|  | 2503 | active = 3; | 
|  | 2504 | else | 
|  | 2505 | active = 7; | 
|  | 2506 | if (dch->state == active) { | 
|  | 2507 | HFC_outb_nodebug(hc, R_FIFO, | 
|  | 2508 | (ch << 1) | 1); | 
|  | 2509 | HFC_wait_nodebug(hc); | 
|  | 2510 | HFC_outb_nodebug(hc, | 
|  | 2511 | R_INC_RES_FIFO, V_RES_F); | 
|  | 2512 | HFC_wait_nodebug(hc); | 
|  | 2513 | dch->tx_idx = 0; | 
|  | 2514 | } | 
|  | 2515 | schedule_event(dch, FLG_PHCHANGE); | 
|  | 2516 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 2517 | printk(KERN_DEBUG | 
|  | 2518 | "%s: S/T newstate %x port %d\n", | 
|  | 2519 | __func__, dch->state, | 
|  | 2520 | hc->chan[ch].port); | 
|  | 2521 | } | 
|  | 2522 | r_irq_statech >>= 1; | 
|  | 2523 | } | 
|  | 2524 | } | 
|  | 2525 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) | 
|  | 2526 | plxsd_checksync(hc, 0); | 
|  | 2527 | } | 
|  | 2528 |  | 
|  | 2529 | static void | 
|  | 2530 | fifo_irq(struct hfc_multi *hc, int block) | 
|  | 2531 | { | 
|  | 2532 | int	ch, j; | 
|  | 2533 | struct dchannel	*dch; | 
|  | 2534 | struct bchannel	*bch; | 
|  | 2535 | u_char r_irq_fifo_bl; | 
|  | 2536 |  | 
|  | 2537 | r_irq_fifo_bl = HFC_inb_nodebug(hc, R_IRQ_FIFO_BL0 + block); | 
|  | 2538 | j = 0; | 
|  | 2539 | while (j < 8) { | 
|  | 2540 | ch = (block << 2) + (j >> 1); | 
|  | 2541 | dch = hc->chan[ch].dch; | 
|  | 2542 | bch = hc->chan[ch].bch; | 
|  | 2543 | if (((!dch) && (!bch)) || (!hc->created[hc->chan[ch].port])) { | 
|  | 2544 | j += 2; | 
|  | 2545 | continue; | 
|  | 2546 | } | 
|  | 2547 | if (dch && (r_irq_fifo_bl & (1 << j)) && | 
|  | 2548 | test_bit(FLG_ACTIVE, &dch->Flags)) { | 
|  | 2549 | hfcmulti_tx(hc, ch); | 
|  | 2550 | /* start fifo */ | 
|  | 2551 | HFC_outb_nodebug(hc, R_FIFO, 0); | 
|  | 2552 | HFC_wait_nodebug(hc); | 
|  | 2553 | } | 
|  | 2554 | if (bch && (r_irq_fifo_bl & (1 << j)) && | 
|  | 2555 | test_bit(FLG_ACTIVE, &bch->Flags)) { | 
|  | 2556 | hfcmulti_tx(hc, ch); | 
|  | 2557 | /* start fifo */ | 
|  | 2558 | HFC_outb_nodebug(hc, R_FIFO, 0); | 
|  | 2559 | HFC_wait_nodebug(hc); | 
|  | 2560 | } | 
|  | 2561 | j++; | 
|  | 2562 | if (dch && (r_irq_fifo_bl & (1 << j)) && | 
|  | 2563 | test_bit(FLG_ACTIVE, &dch->Flags)) { | 
|  | 2564 | hfcmulti_rx(hc, ch); | 
|  | 2565 | } | 
|  | 2566 | if (bch && (r_irq_fifo_bl & (1 << j)) && | 
|  | 2567 | test_bit(FLG_ACTIVE, &bch->Flags)) { | 
|  | 2568 | hfcmulti_rx(hc, ch); | 
|  | 2569 | } | 
|  | 2570 | j++; | 
|  | 2571 | } | 
|  | 2572 | } | 
|  | 2573 |  | 
|  | 2574 | #ifdef IRQ_DEBUG | 
|  | 2575 | int irqsem; | 
|  | 2576 | #endif | 
|  | 2577 | static irqreturn_t | 
|  | 2578 | hfcmulti_interrupt(int intno, void *dev_id) | 
|  | 2579 | { | 
|  | 2580 | #ifdef IRQCOUNT_DEBUG | 
|  | 2581 | static int iq1 = 0, iq2 = 0, iq3 = 0, iq4 = 0, | 
|  | 2582 | iq5 = 0, iq6 = 0, iqcnt = 0; | 
|  | 2583 | #endif | 
|  | 2584 | static int		count; | 
|  | 2585 | struct hfc_multi	*hc = dev_id; | 
|  | 2586 | struct dchannel		*dch; | 
|  | 2587 | u_char			r_irq_statech, status, r_irq_misc, r_irq_oview; | 
|  | 2588 | int			i; | 
|  | 2589 | u_short			*plx_acc, wval; | 
|  | 2590 | u_char			e1_syncsta, temp; | 
|  | 2591 | u_long			flags; | 
|  | 2592 |  | 
|  | 2593 | if (!hc) { | 
|  | 2594 | printk(KERN_ERR "HFC-multi: Spurious interrupt!\n"); | 
|  | 2595 | return IRQ_NONE; | 
|  | 2596 | } | 
|  | 2597 |  | 
|  | 2598 | spin_lock(&hc->lock); | 
|  | 2599 |  | 
|  | 2600 | #ifdef IRQ_DEBUG | 
|  | 2601 | if (irqsem) | 
|  | 2602 | printk(KERN_ERR "irq for card %d during irq from " | 
|  | 2603 | "card %d, this is no bug.\n", hc->id + 1, irqsem); | 
|  | 2604 | irqsem = hc->id + 1; | 
|  | 2605 | #endif | 
|  | 2606 |  | 
|  | 2607 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 2608 | spin_lock_irqsave(&plx_lock, flags); | 
|  | 2609 | plx_acc = (u_short *)(hc->plx_membase + PLX_INTCSR); | 
|  | 2610 | wval = readw(plx_acc); | 
|  | 2611 | spin_unlock_irqrestore(&plx_lock, flags); | 
|  | 2612 | if (!(wval & PLX_INTCSR_LINTI1_STATUS)) | 
|  | 2613 | goto irq_notforus; | 
|  | 2614 | } | 
|  | 2615 |  | 
|  | 2616 | status = HFC_inb_nodebug(hc, R_STATUS); | 
|  | 2617 | r_irq_statech = HFC_inb_nodebug(hc, R_IRQ_STATECH); | 
|  | 2618 | #ifdef IRQCOUNT_DEBUG | 
|  | 2619 | if (r_irq_statech) | 
|  | 2620 | iq1++; | 
|  | 2621 | if (status & V_DTMF_STA) | 
|  | 2622 | iq2++; | 
|  | 2623 | if (status & V_LOST_STA) | 
|  | 2624 | iq3++; | 
|  | 2625 | if (status & V_EXT_IRQSTA) | 
|  | 2626 | iq4++; | 
|  | 2627 | if (status & V_MISC_IRQSTA) | 
|  | 2628 | iq5++; | 
|  | 2629 | if (status & V_FR_IRQSTA) | 
|  | 2630 | iq6++; | 
|  | 2631 | if (iqcnt++ > 5000) { | 
|  | 2632 | printk(KERN_ERR "iq1:%x iq2:%x iq3:%x iq4:%x iq5:%x iq6:%x\n", | 
|  | 2633 | iq1, iq2, iq3, iq4, iq5, iq6); | 
|  | 2634 | iqcnt = 0; | 
|  | 2635 | } | 
|  | 2636 | #endif | 
|  | 2637 | if (!r_irq_statech && | 
|  | 2638 | !(status & (V_DTMF_STA | V_LOST_STA | V_EXT_IRQSTA | | 
|  | 2639 | V_MISC_IRQSTA | V_FR_IRQSTA))) { | 
|  | 2640 | /* irq is not for us */ | 
|  | 2641 | goto irq_notforus; | 
|  | 2642 | } | 
|  | 2643 | hc->irqcnt++; | 
|  | 2644 | if (r_irq_statech) { | 
|  | 2645 | if (hc->type != 1) | 
|  | 2646 | ph_state_irq(hc, r_irq_statech); | 
|  | 2647 | } | 
|  | 2648 | if (status & V_EXT_IRQSTA) | 
|  | 2649 | ; /* external IRQ */ | 
|  | 2650 | if (status & V_LOST_STA) { | 
|  | 2651 | /* LOST IRQ */ | 
|  | 2652 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_LOST); /* clear irq! */ | 
|  | 2653 | } | 
|  | 2654 | if (status & V_MISC_IRQSTA) { | 
|  | 2655 | /* misc IRQ */ | 
|  | 2656 | r_irq_misc = HFC_inb_nodebug(hc, R_IRQ_MISC); | 
|  | 2657 | if (r_irq_misc & V_STA_IRQ) { | 
|  | 2658 | if (hc->type == 1) { | 
|  | 2659 | /* state machine */ | 
|  | 2660 | dch = hc->chan[hc->dslot].dch; | 
|  | 2661 | e1_syncsta = HFC_inb_nodebug(hc, R_SYNC_STA); | 
|  | 2662 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip) | 
|  | 2663 | && hc->e1_getclock) { | 
|  | 2664 | if (e1_syncsta & V_FR_SYNC_E1) | 
|  | 2665 | hc->syncronized = 1; | 
|  | 2666 | else | 
|  | 2667 | hc->syncronized = 0; | 
|  | 2668 | } | 
|  | 2669 | /* undocumented: status changes during read */ | 
|  | 2670 | dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA); | 
|  | 2671 | while (dch->state != (temp = | 
|  | 2672 | HFC_inb_nodebug(hc, R_E1_RD_STA))) { | 
|  | 2673 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 2674 | printk(KERN_DEBUG "%s: reread " | 
|  | 2675 | "STATE because %d!=%d\n", | 
|  | 2676 | __func__, temp, | 
|  | 2677 | dch->state); | 
|  | 2678 | dch->state = temp; /* repeat */ | 
|  | 2679 | } | 
|  | 2680 | dch->state = HFC_inb_nodebug(hc, R_E1_RD_STA) | 
|  | 2681 | & 0x7; | 
|  | 2682 | schedule_event(dch, FLG_PHCHANGE); | 
|  | 2683 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 2684 | printk(KERN_DEBUG | 
|  | 2685 | "%s: E1 (id=%d) newstate %x\n", | 
|  | 2686 | __func__, hc->id, dch->state); | 
|  | 2687 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) | 
|  | 2688 | plxsd_checksync(hc, 0); | 
|  | 2689 | } | 
|  | 2690 | } | 
|  | 2691 | if (r_irq_misc & V_TI_IRQ) | 
|  | 2692 | handle_timer_irq(hc); | 
|  | 2693 |  | 
|  | 2694 | if (r_irq_misc & V_DTMF_IRQ) { | 
|  | 2695 | /* -> DTMF IRQ */ | 
|  | 2696 | hfcmulti_dtmf(hc); | 
|  | 2697 | } | 
|  | 2698 | /* TODO: REPLACE !!!! 125 us Interrupts are not acceptable  */ | 
|  | 2699 | if (r_irq_misc & V_IRQ_PROC) { | 
|  | 2700 | /* IRQ every 125us */ | 
|  | 2701 | count++; | 
|  | 2702 | /* generate 1kHz signal */ | 
|  | 2703 | if (count == 8) { | 
|  | 2704 | if (hfc_interrupt) | 
|  | 2705 | hfc_interrupt(); | 
|  | 2706 | count = 0; | 
|  | 2707 | } | 
|  | 2708 | } | 
|  | 2709 |  | 
|  | 2710 | } | 
|  | 2711 | if (status & V_FR_IRQSTA) { | 
|  | 2712 | /* FIFO IRQ */ | 
|  | 2713 | r_irq_oview = HFC_inb_nodebug(hc, R_IRQ_OVIEW); | 
|  | 2714 | for (i = 0; i < 8; i++) { | 
|  | 2715 | if (r_irq_oview & (1 << i)) | 
|  | 2716 | fifo_irq(hc, i); | 
|  | 2717 | } | 
|  | 2718 | } | 
|  | 2719 |  | 
|  | 2720 | #ifdef IRQ_DEBUG | 
|  | 2721 | irqsem = 0; | 
|  | 2722 | #endif | 
|  | 2723 | spin_unlock(&hc->lock); | 
|  | 2724 | return IRQ_HANDLED; | 
|  | 2725 |  | 
|  | 2726 | irq_notforus: | 
|  | 2727 | #ifdef IRQ_DEBUG | 
|  | 2728 | irqsem = 0; | 
|  | 2729 | #endif | 
|  | 2730 | spin_unlock(&hc->lock); | 
|  | 2731 | return IRQ_NONE; | 
|  | 2732 | } | 
|  | 2733 |  | 
|  | 2734 |  | 
|  | 2735 | /* | 
|  | 2736 | * timer callback for D-chan busy resolution. Currently no function | 
|  | 2737 | */ | 
|  | 2738 |  | 
|  | 2739 | static void | 
|  | 2740 | hfcmulti_dbusy_timer(struct hfc_multi *hc) | 
|  | 2741 | { | 
|  | 2742 | } | 
|  | 2743 |  | 
|  | 2744 |  | 
|  | 2745 | /* | 
|  | 2746 | * activate/deactivate hardware for selected channels and mode | 
|  | 2747 | * | 
|  | 2748 | * configure B-channel with the given protocol | 
|  | 2749 | * ch eqals to the HFC-channel (0-31) | 
|  | 2750 | * ch is the number of channel (0-4,4-7,8-11,12-15,16-19,20-23,24-27,28-31 | 
|  | 2751 | * for S/T, 1-31 for E1) | 
|  | 2752 | * the hdlc interrupts will be set/unset | 
|  | 2753 | */ | 
|  | 2754 | static int | 
|  | 2755 | mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, | 
|  | 2756 | int bank_tx, int slot_rx, int bank_rx) | 
|  | 2757 | { | 
|  | 2758 | int flow_tx = 0, flow_rx = 0, routing = 0; | 
|  | 2759 | int oslot_tx, oslot_rx; | 
|  | 2760 | int conf; | 
|  | 2761 |  | 
|  | 2762 | if (ch < 0 || ch > 31) | 
|  | 2763 | return EINVAL; | 
|  | 2764 | oslot_tx = hc->chan[ch].slot_tx; | 
|  | 2765 | oslot_rx = hc->chan[ch].slot_rx; | 
|  | 2766 | conf = hc->chan[ch].conf; | 
|  | 2767 |  | 
|  | 2768 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 2769 | printk(KERN_DEBUG | 
|  | 2770 | "%s: card %d channel %d protocol %x slot old=%d new=%d " | 
|  | 2771 | "bank new=%d (TX) slot old=%d new=%d bank new=%d (RX)\n", | 
|  | 2772 | __func__, hc->id, ch, protocol, oslot_tx, slot_tx, | 
|  | 2773 | bank_tx, oslot_rx, slot_rx, bank_rx); | 
|  | 2774 |  | 
|  | 2775 | if (oslot_tx >= 0 && slot_tx != oslot_tx) { | 
|  | 2776 | /* remove from slot */ | 
|  | 2777 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 2778 | printk(KERN_DEBUG "%s: remove from slot %d (TX)\n", | 
|  | 2779 | __func__, oslot_tx); | 
|  | 2780 | if (hc->slot_owner[oslot_tx<<1] == ch) { | 
|  | 2781 | HFC_outb(hc, R_SLOT, oslot_tx << 1); | 
|  | 2782 | HFC_outb(hc, A_SL_CFG, 0); | 
|  | 2783 | HFC_outb(hc, A_CONF, 0); | 
|  | 2784 | hc->slot_owner[oslot_tx<<1] = -1; | 
|  | 2785 | } else { | 
|  | 2786 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 2787 | printk(KERN_DEBUG | 
|  | 2788 | "%s: we are not owner of this tx slot " | 
|  | 2789 | "anymore, channel %d is.\n", | 
|  | 2790 | __func__, hc->slot_owner[oslot_tx<<1]); | 
|  | 2791 | } | 
|  | 2792 | } | 
|  | 2793 |  | 
|  | 2794 | if (oslot_rx >= 0 && slot_rx != oslot_rx) { | 
|  | 2795 | /* remove from slot */ | 
|  | 2796 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 2797 | printk(KERN_DEBUG | 
|  | 2798 | "%s: remove from slot %d (RX)\n", | 
|  | 2799 | __func__, oslot_rx); | 
|  | 2800 | if (hc->slot_owner[(oslot_rx << 1) | 1] == ch) { | 
|  | 2801 | HFC_outb(hc, R_SLOT, (oslot_rx << 1) | V_SL_DIR); | 
|  | 2802 | HFC_outb(hc, A_SL_CFG, 0); | 
|  | 2803 | hc->slot_owner[(oslot_rx << 1) | 1] = -1; | 
|  | 2804 | } else { | 
|  | 2805 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 2806 | printk(KERN_DEBUG | 
|  | 2807 | "%s: we are not owner of this rx slot " | 
|  | 2808 | "anymore, channel %d is.\n", | 
|  | 2809 | __func__, | 
|  | 2810 | hc->slot_owner[(oslot_rx << 1) | 1]); | 
|  | 2811 | } | 
|  | 2812 | } | 
|  | 2813 |  | 
|  | 2814 | if (slot_tx < 0) { | 
|  | 2815 | flow_tx = 0x80; /* FIFO->ST */ | 
|  | 2816 | /* disable pcm slot */ | 
|  | 2817 | hc->chan[ch].slot_tx = -1; | 
|  | 2818 | hc->chan[ch].bank_tx = 0; | 
|  | 2819 | } else { | 
|  | 2820 | /* set pcm slot */ | 
|  | 2821 | if (hc->chan[ch].txpending) | 
|  | 2822 | flow_tx = 0x80; /* FIFO->ST */ | 
|  | 2823 | else | 
|  | 2824 | flow_tx = 0xc0; /* PCM->ST */ | 
|  | 2825 | /* put on slot */ | 
|  | 2826 | routing = bank_tx ? 0xc0 : 0x80; | 
|  | 2827 | if (conf >= 0 || bank_tx > 1) | 
|  | 2828 | routing = 0x40; /* loop */ | 
|  | 2829 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 2830 | printk(KERN_DEBUG "%s: put channel %d to slot %d bank" | 
|  | 2831 | " %d flow %02x routing %02x conf %d (TX)\n", | 
|  | 2832 | __func__, ch, slot_tx, bank_tx, | 
|  | 2833 | flow_tx, routing, conf); | 
|  | 2834 | HFC_outb(hc, R_SLOT, slot_tx << 1); | 
|  | 2835 | HFC_outb(hc, A_SL_CFG, (ch<<1) | routing); | 
|  | 2836 | HFC_outb(hc, A_CONF, (conf < 0) ? 0 : (conf | V_CONF_SL)); | 
|  | 2837 | hc->slot_owner[slot_tx << 1] = ch; | 
|  | 2838 | hc->chan[ch].slot_tx = slot_tx; | 
|  | 2839 | hc->chan[ch].bank_tx = bank_tx; | 
|  | 2840 | } | 
|  | 2841 | if (slot_rx < 0) { | 
|  | 2842 | /* disable pcm slot */ | 
|  | 2843 | flow_rx = 0x80; /* ST->FIFO */ | 
|  | 2844 | hc->chan[ch].slot_rx = -1; | 
|  | 2845 | hc->chan[ch].bank_rx = 0; | 
|  | 2846 | } else { | 
|  | 2847 | /* set pcm slot */ | 
|  | 2848 | if (hc->chan[ch].txpending) | 
|  | 2849 | flow_rx = 0x80; /* ST->FIFO */ | 
|  | 2850 | else | 
|  | 2851 | flow_rx = 0xc0; /* ST->(FIFO,PCM) */ | 
|  | 2852 | /* put on slot */ | 
|  | 2853 | routing = bank_rx?0x80:0xc0; /* reversed */ | 
|  | 2854 | if (conf >= 0 || bank_rx > 1) | 
|  | 2855 | routing = 0x40; /* loop */ | 
|  | 2856 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 2857 | printk(KERN_DEBUG "%s: put channel %d to slot %d bank" | 
|  | 2858 | " %d flow %02x routing %02x conf %d (RX)\n", | 
|  | 2859 | __func__, ch, slot_rx, bank_rx, | 
|  | 2860 | flow_rx, routing, conf); | 
|  | 2861 | HFC_outb(hc, R_SLOT, (slot_rx<<1) | V_SL_DIR); | 
|  | 2862 | HFC_outb(hc, A_SL_CFG, (ch<<1) | V_CH_DIR | routing); | 
|  | 2863 | hc->slot_owner[(slot_rx<<1)|1] = ch; | 
|  | 2864 | hc->chan[ch].slot_rx = slot_rx; | 
|  | 2865 | hc->chan[ch].bank_rx = bank_rx; | 
|  | 2866 | } | 
|  | 2867 |  | 
|  | 2868 | switch (protocol) { | 
|  | 2869 | case (ISDN_P_NONE): | 
|  | 2870 | /* disable TX fifo */ | 
|  | 2871 | HFC_outb(hc, R_FIFO, ch << 1); | 
|  | 2872 | HFC_wait(hc); | 
|  | 2873 | HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | V_IFF); | 
|  | 2874 | HFC_outb(hc, A_SUBCH_CFG, 0); | 
|  | 2875 | HFC_outb(hc, A_IRQ_MSK, 0); | 
|  | 2876 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 2877 | HFC_wait(hc); | 
|  | 2878 | /* disable RX fifo */ | 
|  | 2879 | HFC_outb(hc, R_FIFO, (ch<<1)|1); | 
|  | 2880 | HFC_wait(hc); | 
|  | 2881 | HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00); | 
|  | 2882 | HFC_outb(hc, A_SUBCH_CFG, 0); | 
|  | 2883 | HFC_outb(hc, A_IRQ_MSK, 0); | 
|  | 2884 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 2885 | HFC_wait(hc); | 
|  | 2886 | if (hc->chan[ch].bch && hc->type != 1) { | 
|  | 2887 | hc->hw.a_st_ctrl0[hc->chan[ch].port] &= | 
|  | 2888 | ((ch & 0x3) == 0)? ~V_B1_EN: ~V_B2_EN; | 
|  | 2889 | HFC_outb(hc, R_ST_SEL, hc->chan[ch].port); | 
|  | 2890 | /* undocumented: delay after R_ST_SEL */ | 
|  | 2891 | udelay(1); | 
|  | 2892 | HFC_outb(hc, A_ST_CTRL0, | 
|  | 2893 | hc->hw.a_st_ctrl0[hc->chan[ch].port]); | 
|  | 2894 | } | 
|  | 2895 | if (hc->chan[ch].bch) { | 
|  | 2896 | test_and_clear_bit(FLG_HDLC, &hc->chan[ch].bch->Flags); | 
|  | 2897 | test_and_clear_bit(FLG_TRANSPARENT, | 
|  | 2898 | &hc->chan[ch].bch->Flags); | 
|  | 2899 | } | 
|  | 2900 | break; | 
|  | 2901 | case (ISDN_P_B_RAW): /* B-channel */ | 
|  | 2902 |  | 
|  | 2903 | if (test_bit(HFC_CHIP_B410P, &hc->chip) && | 
|  | 2904 | (hc->chan[ch].slot_rx < 0) && | 
|  | 2905 | (hc->chan[ch].slot_tx < 0)) { | 
|  | 2906 |  | 
|  | 2907 | printk(KERN_DEBUG | 
|  | 2908 | "Setting B-channel %d to echo cancelable " | 
|  | 2909 | "state on PCM slot %d\n", ch, | 
|  | 2910 | ((ch / 4) * 8) + ((ch % 4) * 4) + 1); | 
|  | 2911 | printk(KERN_DEBUG | 
|  | 2912 | "Enabling pass through for channel\n"); | 
|  | 2913 | vpm_out(hc, ch, ((ch / 4) * 8) + | 
|  | 2914 | ((ch % 4) * 4) + 1, 0x01); | 
|  | 2915 | /* rx path */ | 
|  | 2916 | /* S/T -> PCM */ | 
|  | 2917 | HFC_outb(hc, R_FIFO, (ch << 1)); | 
|  | 2918 | HFC_wait(hc); | 
|  | 2919 | HFC_outb(hc, A_CON_HDLC, 0xc0 | V_HDLC_TRP | V_IFF); | 
|  | 2920 | HFC_outb(hc, R_SLOT, (((ch / 4) * 8) + | 
|  | 2921 | ((ch % 4) * 4) + 1) << 1); | 
|  | 2922 | HFC_outb(hc, A_SL_CFG, 0x80 | (ch << 1)); | 
|  | 2923 |  | 
|  | 2924 | /* PCM -> FIFO */ | 
|  | 2925 | HFC_outb(hc, R_FIFO, 0x20 | (ch << 1) | 1); | 
|  | 2926 | HFC_wait(hc); | 
|  | 2927 | HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF); | 
|  | 2928 | HFC_outb(hc, A_SUBCH_CFG, 0); | 
|  | 2929 | HFC_outb(hc, A_IRQ_MSK, 0); | 
|  | 2930 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 2931 | HFC_wait(hc); | 
|  | 2932 | HFC_outb(hc, R_SLOT, ((((ch / 4) * 8) + | 
|  | 2933 | ((ch % 4) * 4) + 1) << 1) | 1); | 
|  | 2934 | HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1) | 1); | 
|  | 2935 |  | 
|  | 2936 | /* tx path */ | 
|  | 2937 | /* PCM -> S/T */ | 
|  | 2938 | HFC_outb(hc, R_FIFO, (ch << 1) | 1); | 
|  | 2939 | HFC_wait(hc); | 
|  | 2940 | HFC_outb(hc, A_CON_HDLC, 0xc0 | V_HDLC_TRP | V_IFF); | 
|  | 2941 | HFC_outb(hc, R_SLOT, ((((ch / 4) * 8) + | 
|  | 2942 | ((ch % 4) * 4)) << 1) | 1); | 
|  | 2943 | HFC_outb(hc, A_SL_CFG, 0x80 | 0x40 | (ch << 1) | 1); | 
|  | 2944 |  | 
|  | 2945 | /* FIFO -> PCM */ | 
|  | 2946 | HFC_outb(hc, R_FIFO, 0x20 | (ch << 1)); | 
|  | 2947 | HFC_wait(hc); | 
|  | 2948 | HFC_outb(hc, A_CON_HDLC, 0x20 | V_HDLC_TRP | V_IFF); | 
|  | 2949 | HFC_outb(hc, A_SUBCH_CFG, 0); | 
|  | 2950 | HFC_outb(hc, A_IRQ_MSK, 0); | 
|  | 2951 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 2952 | HFC_wait(hc); | 
|  | 2953 | /* tx silence */ | 
|  | 2954 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); | 
|  | 2955 | HFC_outb(hc, R_SLOT, (((ch / 4) * 8) + | 
|  | 2956 | ((ch % 4) * 4)) << 1); | 
|  | 2957 | HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1)); | 
|  | 2958 | } else { | 
|  | 2959 | /* enable TX fifo */ | 
|  | 2960 | HFC_outb(hc, R_FIFO, ch << 1); | 
|  | 2961 | HFC_wait(hc); | 
|  | 2962 | HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | | 
|  | 2963 | V_HDLC_TRP | V_IFF); | 
|  | 2964 | HFC_outb(hc, A_SUBCH_CFG, 0); | 
|  | 2965 | HFC_outb(hc, A_IRQ_MSK, 0); | 
|  | 2966 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 2967 | HFC_wait(hc); | 
|  | 2968 | /* tx silence */ | 
|  | 2969 | HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence); | 
|  | 2970 | /* enable RX fifo */ | 
|  | 2971 | HFC_outb(hc, R_FIFO, (ch<<1)|1); | 
|  | 2972 | HFC_wait(hc); | 
|  | 2973 | HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 | V_HDLC_TRP); | 
|  | 2974 | HFC_outb(hc, A_SUBCH_CFG, 0); | 
|  | 2975 | HFC_outb(hc, A_IRQ_MSK, 0); | 
|  | 2976 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 2977 | HFC_wait(hc); | 
|  | 2978 | } | 
|  | 2979 | if (hc->type != 1) { | 
|  | 2980 | hc->hw.a_st_ctrl0[hc->chan[ch].port] |= | 
|  | 2981 | ((ch & 0x3) == 0) ? V_B1_EN : V_B2_EN; | 
|  | 2982 | HFC_outb(hc, R_ST_SEL, hc->chan[ch].port); | 
|  | 2983 | /* undocumented: delay after R_ST_SEL */ | 
|  | 2984 | udelay(1); | 
|  | 2985 | HFC_outb(hc, A_ST_CTRL0, | 
|  | 2986 | hc->hw.a_st_ctrl0[hc->chan[ch].port]); | 
|  | 2987 | } | 
|  | 2988 | if (hc->chan[ch].bch) | 
|  | 2989 | test_and_set_bit(FLG_TRANSPARENT, | 
|  | 2990 | &hc->chan[ch].bch->Flags); | 
|  | 2991 | break; | 
|  | 2992 | case (ISDN_P_B_HDLC): /* B-channel */ | 
|  | 2993 | case (ISDN_P_TE_S0): /* D-channel */ | 
|  | 2994 | case (ISDN_P_NT_S0): | 
|  | 2995 | case (ISDN_P_TE_E1): | 
|  | 2996 | case (ISDN_P_NT_E1): | 
|  | 2997 | /* enable TX fifo */ | 
|  | 2998 | HFC_outb(hc, R_FIFO, ch<<1); | 
|  | 2999 | HFC_wait(hc); | 
|  | 3000 | if (hc->type == 1 || hc->chan[ch].bch) { | 
|  | 3001 | /* E1 or B-channel */ | 
|  | 3002 | HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04); | 
|  | 3003 | HFC_outb(hc, A_SUBCH_CFG, 0); | 
|  | 3004 | } else { | 
|  | 3005 | /* D-Channel without HDLC fill flags */ | 
|  | 3006 | HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04 | V_IFF); | 
|  | 3007 | HFC_outb(hc, A_SUBCH_CFG, 2); | 
|  | 3008 | } | 
|  | 3009 | HFC_outb(hc, A_IRQ_MSK, V_IRQ); | 
|  | 3010 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 3011 | HFC_wait(hc); | 
|  | 3012 | /* enable RX fifo */ | 
|  | 3013 | HFC_outb(hc, R_FIFO, (ch<<1)|1); | 
|  | 3014 | HFC_wait(hc); | 
|  | 3015 | HFC_outb(hc, A_CON_HDLC, flow_rx | 0x04); | 
|  | 3016 | if (hc->type == 1 || hc->chan[ch].bch) | 
|  | 3017 | HFC_outb(hc, A_SUBCH_CFG, 0); /* full 8 bits */ | 
|  | 3018 | else | 
|  | 3019 | HFC_outb(hc, A_SUBCH_CFG, 2); /* 2 bits dchannel */ | 
|  | 3020 | HFC_outb(hc, A_IRQ_MSK, V_IRQ); | 
|  | 3021 | HFC_outb(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 3022 | HFC_wait(hc); | 
|  | 3023 | if (hc->chan[ch].bch) { | 
|  | 3024 | test_and_set_bit(FLG_HDLC, &hc->chan[ch].bch->Flags); | 
|  | 3025 | if (hc->type != 1) { | 
|  | 3026 | hc->hw.a_st_ctrl0[hc->chan[ch].port] |= | 
|  | 3027 | ((ch&0x3) == 0) ? V_B1_EN : V_B2_EN; | 
|  | 3028 | HFC_outb(hc, R_ST_SEL, hc->chan[ch].port); | 
|  | 3029 | /* undocumented: delay after R_ST_SEL */ | 
|  | 3030 | udelay(1); | 
|  | 3031 | HFC_outb(hc, A_ST_CTRL0, | 
|  | 3032 | hc->hw.a_st_ctrl0[hc->chan[ch].port]); | 
|  | 3033 | } | 
|  | 3034 | } | 
|  | 3035 | break; | 
|  | 3036 | default: | 
|  | 3037 | printk(KERN_DEBUG "%s: protocol not known %x\n", | 
|  | 3038 | __func__, protocol); | 
|  | 3039 | hc->chan[ch].protocol = ISDN_P_NONE; | 
|  | 3040 | return -ENOPROTOOPT; | 
|  | 3041 | } | 
|  | 3042 | hc->chan[ch].protocol = protocol; | 
|  | 3043 | return 0; | 
|  | 3044 | } | 
|  | 3045 |  | 
|  | 3046 |  | 
|  | 3047 | /* | 
|  | 3048 | * connect/disconnect PCM | 
|  | 3049 | */ | 
|  | 3050 |  | 
|  | 3051 | static void | 
|  | 3052 | hfcmulti_pcm(struct hfc_multi *hc, int ch, int slot_tx, int bank_tx, | 
|  | 3053 | int slot_rx, int bank_rx) | 
|  | 3054 | { | 
|  | 3055 | if (slot_rx < 0 || slot_rx < 0 || bank_tx < 0 || bank_rx < 0) { | 
|  | 3056 | /* disable PCM */ | 
|  | 3057 | mode_hfcmulti(hc, ch, hc->chan[ch].protocol, -1, 0, -1, 0); | 
|  | 3058 | return; | 
|  | 3059 | } | 
|  | 3060 |  | 
|  | 3061 | /* enable pcm */ | 
|  | 3062 | mode_hfcmulti(hc, ch, hc->chan[ch].protocol, slot_tx, bank_tx, | 
|  | 3063 | slot_rx, bank_rx); | 
|  | 3064 | } | 
|  | 3065 |  | 
|  | 3066 | /* | 
|  | 3067 | * set/disable conference | 
|  | 3068 | */ | 
|  | 3069 |  | 
|  | 3070 | static void | 
|  | 3071 | hfcmulti_conf(struct hfc_multi *hc, int ch, int num) | 
|  | 3072 | { | 
|  | 3073 | if (num >= 0 && num <= 7) | 
|  | 3074 | hc->chan[ch].conf = num; | 
|  | 3075 | else | 
|  | 3076 | hc->chan[ch].conf = -1; | 
|  | 3077 | mode_hfcmulti(hc, ch, hc->chan[ch].protocol, hc->chan[ch].slot_tx, | 
|  | 3078 | hc->chan[ch].bank_tx, hc->chan[ch].slot_rx, | 
|  | 3079 | hc->chan[ch].bank_rx); | 
|  | 3080 | } | 
|  | 3081 |  | 
|  | 3082 |  | 
|  | 3083 | /* | 
|  | 3084 | * set/disable sample loop | 
|  | 3085 | */ | 
|  | 3086 |  | 
|  | 3087 | /* NOTE: this function is experimental and therefore disabled */ | 
|  | 3088 |  | 
|  | 3089 | /* | 
|  | 3090 | * Layer 1 callback function | 
|  | 3091 | */ | 
|  | 3092 | static int | 
|  | 3093 | hfcm_l1callback(struct dchannel *dch, u_int cmd) | 
|  | 3094 | { | 
|  | 3095 | struct hfc_multi	*hc = dch->hw; | 
|  | 3096 | u_long	flags; | 
|  | 3097 |  | 
|  | 3098 | switch (cmd) { | 
|  | 3099 | case INFO3_P8: | 
|  | 3100 | case INFO3_P10: | 
|  | 3101 | break; | 
|  | 3102 | case HW_RESET_REQ: | 
|  | 3103 | /* start activation */ | 
|  | 3104 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3105 | if (hc->type == 1) { | 
|  | 3106 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3107 | printk(KERN_DEBUG | 
|  | 3108 | "%s: HW_RESET_REQ no BRI\n", | 
|  | 3109 | __func__); | 
|  | 3110 | } else { | 
|  | 3111 | HFC_outb(hc, R_ST_SEL, hc->chan[dch->slot].port); | 
|  | 3112 | /* undocumented: delay after R_ST_SEL */ | 
|  | 3113 | udelay(1); | 
|  | 3114 | HFC_outb(hc, A_ST_WR_STATE, V_ST_LD_STA | 3); /* F3 */ | 
|  | 3115 | udelay(6); /* wait at least 5,21us */ | 
|  | 3116 | HFC_outb(hc, A_ST_WR_STATE, 3); | 
|  | 3117 | HFC_outb(hc, A_ST_WR_STATE, 3 | (V_ST_ACT*3)); | 
|  | 3118 | /* activate */ | 
|  | 3119 | } | 
|  | 3120 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3121 | l1_event(dch->l1, HW_POWERUP_IND); | 
|  | 3122 | break; | 
|  | 3123 | case HW_DEACT_REQ: | 
|  | 3124 | /* start deactivation */ | 
|  | 3125 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3126 | if (hc->type == 1) { | 
|  | 3127 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3128 | printk(KERN_DEBUG | 
|  | 3129 | "%s: HW_DEACT_REQ no BRI\n", | 
|  | 3130 | __func__); | 
|  | 3131 | } else { | 
|  | 3132 | HFC_outb(hc, R_ST_SEL, hc->chan[dch->slot].port); | 
|  | 3133 | /* undocumented: delay after R_ST_SEL */ | 
|  | 3134 | udelay(1); | 
|  | 3135 | HFC_outb(hc, A_ST_WR_STATE, V_ST_ACT*2); | 
|  | 3136 | /* deactivate */ | 
|  | 3137 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 3138 | hc->syncronized &= | 
|  | 3139 | ~(1 << hc->chan[dch->slot].port); | 
|  | 3140 | plxsd_checksync(hc, 0); | 
|  | 3141 | } | 
|  | 3142 | } | 
|  | 3143 | skb_queue_purge(&dch->squeue); | 
|  | 3144 | if (dch->tx_skb) { | 
|  | 3145 | dev_kfree_skb(dch->tx_skb); | 
|  | 3146 | dch->tx_skb = NULL; | 
|  | 3147 | } | 
|  | 3148 | dch->tx_idx = 0; | 
|  | 3149 | if (dch->rx_skb) { | 
|  | 3150 | dev_kfree_skb(dch->rx_skb); | 
|  | 3151 | dch->rx_skb = NULL; | 
|  | 3152 | } | 
|  | 3153 | test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); | 
|  | 3154 | if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) | 
|  | 3155 | del_timer(&dch->timer); | 
|  | 3156 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3157 | break; | 
|  | 3158 | case HW_POWERUP_REQ: | 
|  | 3159 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3160 | if (hc->type == 1) { | 
|  | 3161 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3162 | printk(KERN_DEBUG | 
|  | 3163 | "%s: HW_POWERUP_REQ no BRI\n", | 
|  | 3164 | __func__); | 
|  | 3165 | } else { | 
|  | 3166 | HFC_outb(hc, R_ST_SEL, hc->chan[dch->slot].port); | 
|  | 3167 | /* undocumented: delay after R_ST_SEL */ | 
|  | 3168 | udelay(1); | 
|  | 3169 | HFC_outb(hc, A_ST_WR_STATE, 3 | 0x10); /* activate */ | 
|  | 3170 | udelay(6); /* wait at least 5,21us */ | 
|  | 3171 | HFC_outb(hc, A_ST_WR_STATE, 3); /* activate */ | 
|  | 3172 | } | 
|  | 3173 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3174 | break; | 
|  | 3175 | case PH_ACTIVATE_IND: | 
|  | 3176 | test_and_set_bit(FLG_ACTIVE, &dch->Flags); | 
|  | 3177 | _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL, | 
|  | 3178 | GFP_ATOMIC); | 
|  | 3179 | break; | 
|  | 3180 | case PH_DEACTIVATE_IND: | 
|  | 3181 | test_and_clear_bit(FLG_ACTIVE, &dch->Flags); | 
|  | 3182 | _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL, | 
|  | 3183 | GFP_ATOMIC); | 
|  | 3184 | break; | 
|  | 3185 | default: | 
|  | 3186 | if (dch->debug & DEBUG_HW) | 
|  | 3187 | printk(KERN_DEBUG "%s: unknown command %x\n", | 
|  | 3188 | __func__, cmd); | 
|  | 3189 | return -1; | 
|  | 3190 | } | 
|  | 3191 | return 0; | 
|  | 3192 | } | 
|  | 3193 |  | 
|  | 3194 | /* | 
|  | 3195 | * Layer2 -> Layer 1 Transfer | 
|  | 3196 | */ | 
|  | 3197 |  | 
|  | 3198 | static int | 
|  | 3199 | handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) | 
|  | 3200 | { | 
|  | 3201 | struct mISDNdevice	*dev = container_of(ch, struct mISDNdevice, D); | 
|  | 3202 | struct dchannel		*dch = container_of(dev, struct dchannel, dev); | 
|  | 3203 | struct hfc_multi	*hc = dch->hw; | 
|  | 3204 | struct mISDNhead	*hh = mISDN_HEAD_P(skb); | 
|  | 3205 | int			ret = -EINVAL; | 
|  | 3206 | unsigned int		id; | 
|  | 3207 | u_long			flags; | 
|  | 3208 |  | 
|  | 3209 | switch (hh->prim) { | 
|  | 3210 | case PH_DATA_REQ: | 
|  | 3211 | if (skb->len < 1) | 
|  | 3212 | break; | 
|  | 3213 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3214 | ret = dchannel_senddata(dch, skb); | 
|  | 3215 | if (ret > 0) { /* direct TX */ | 
|  | 3216 | id = hh->id; /* skb can be freed */ | 
|  | 3217 | hfcmulti_tx(hc, dch->slot); | 
|  | 3218 | ret = 0; | 
|  | 3219 | /* start fifo */ | 
|  | 3220 | HFC_outb(hc, R_FIFO, 0); | 
|  | 3221 | HFC_wait(hc); | 
|  | 3222 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3223 | queue_ch_frame(ch, PH_DATA_CNF, id, NULL); | 
|  | 3224 | } else | 
|  | 3225 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3226 | return ret; | 
|  | 3227 | case PH_ACTIVATE_REQ: | 
|  | 3228 | if (dch->dev.D.protocol != ISDN_P_TE_S0) { | 
|  | 3229 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3230 | ret = 0; | 
|  | 3231 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3232 | printk(KERN_DEBUG | 
|  | 3233 | "%s: PH_ACTIVATE port %d (0..%d)\n", | 
|  | 3234 | __func__, hc->chan[dch->slot].port, | 
|  | 3235 | hc->ports-1); | 
|  | 3236 | /* start activation */ | 
|  | 3237 | if (hc->type == 1) { | 
|  | 3238 | ph_state_change(dch); | 
|  | 3239 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 3240 | printk(KERN_DEBUG | 
|  | 3241 | "%s: E1 report state %x \n", | 
|  | 3242 | __func__, dch->state); | 
|  | 3243 | } else { | 
|  | 3244 | HFC_outb(hc, R_ST_SEL, | 
|  | 3245 | hc->chan[dch->slot].port); | 
|  | 3246 | /* undocumented: delay after R_ST_SEL */ | 
|  | 3247 | udelay(1); | 
|  | 3248 | HFC_outb(hc, A_ST_WR_STATE, V_ST_LD_STA | 1); | 
|  | 3249 | /* G1 */ | 
|  | 3250 | udelay(6); /* wait at least 5,21us */ | 
|  | 3251 | HFC_outb(hc, A_ST_WR_STATE, 1); | 
|  | 3252 | HFC_outb(hc, A_ST_WR_STATE, 1 | | 
|  | 3253 | (V_ST_ACT*3)); /* activate */ | 
|  | 3254 | dch->state = 1; | 
|  | 3255 | } | 
|  | 3256 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3257 | } else | 
|  | 3258 | ret = l1_event(dch->l1, hh->prim); | 
|  | 3259 | break; | 
|  | 3260 | case PH_DEACTIVATE_REQ: | 
|  | 3261 | test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); | 
|  | 3262 | if (dch->dev.D.protocol != ISDN_P_TE_S0) { | 
|  | 3263 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3264 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3265 | printk(KERN_DEBUG | 
|  | 3266 | "%s: PH_DEACTIVATE port %d (0..%d)\n", | 
|  | 3267 | __func__, hc->chan[dch->slot].port, | 
|  | 3268 | hc->ports-1); | 
|  | 3269 | /* start deactivation */ | 
|  | 3270 | if (hc->type == 1) { | 
|  | 3271 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3272 | printk(KERN_DEBUG | 
|  | 3273 | "%s: PH_DEACTIVATE no BRI\n", | 
|  | 3274 | __func__); | 
|  | 3275 | } else { | 
|  | 3276 | HFC_outb(hc, R_ST_SEL, | 
|  | 3277 | hc->chan[dch->slot].port); | 
|  | 3278 | /* undocumented: delay after R_ST_SEL */ | 
|  | 3279 | udelay(1); | 
|  | 3280 | HFC_outb(hc, A_ST_WR_STATE, V_ST_ACT * 2); | 
|  | 3281 | /* deactivate */ | 
|  | 3282 | dch->state = 1; | 
|  | 3283 | } | 
|  | 3284 | skb_queue_purge(&dch->squeue); | 
|  | 3285 | if (dch->tx_skb) { | 
|  | 3286 | dev_kfree_skb(dch->tx_skb); | 
|  | 3287 | dch->tx_skb = NULL; | 
|  | 3288 | } | 
|  | 3289 | dch->tx_idx = 0; | 
|  | 3290 | if (dch->rx_skb) { | 
|  | 3291 | dev_kfree_skb(dch->rx_skb); | 
|  | 3292 | dch->rx_skb = NULL; | 
|  | 3293 | } | 
|  | 3294 | test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); | 
|  | 3295 | if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) | 
|  | 3296 | del_timer(&dch->timer); | 
|  | 3297 | #ifdef FIXME | 
|  | 3298 | if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags)) | 
|  | 3299 | dchannel_sched_event(&hc->dch, D_CLEARBUSY); | 
|  | 3300 | #endif | 
|  | 3301 | ret = 0; | 
|  | 3302 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3303 | } else | 
|  | 3304 | ret = l1_event(dch->l1, hh->prim); | 
|  | 3305 | break; | 
|  | 3306 | } | 
|  | 3307 | if (!ret) | 
|  | 3308 | dev_kfree_skb(skb); | 
|  | 3309 | return ret; | 
|  | 3310 | } | 
|  | 3311 |  | 
|  | 3312 | static void | 
|  | 3313 | deactivate_bchannel(struct bchannel *bch) | 
|  | 3314 | { | 
|  | 3315 | struct hfc_multi	*hc = bch->hw; | 
|  | 3316 | u_long			flags; | 
|  | 3317 |  | 
|  | 3318 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3319 | if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) { | 
|  | 3320 | dev_kfree_skb(bch->next_skb); | 
|  | 3321 | bch->next_skb = NULL; | 
|  | 3322 | } | 
|  | 3323 | if (bch->tx_skb) { | 
|  | 3324 | dev_kfree_skb(bch->tx_skb); | 
|  | 3325 | bch->tx_skb = NULL; | 
|  | 3326 | } | 
|  | 3327 | bch->tx_idx = 0; | 
|  | 3328 | if (bch->rx_skb) { | 
|  | 3329 | dev_kfree_skb(bch->rx_skb); | 
|  | 3330 | bch->rx_skb = NULL; | 
|  | 3331 | } | 
|  | 3332 | hc->chan[bch->slot].coeff_count = 0; | 
|  | 3333 | test_and_clear_bit(FLG_ACTIVE, &bch->Flags); | 
|  | 3334 | test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); | 
|  | 3335 | hc->chan[bch->slot].rx_off = 0; | 
|  | 3336 | hc->chan[bch->slot].conf = -1; | 
|  | 3337 | mode_hfcmulti(hc, bch->slot, ISDN_P_NONE, -1, 0, -1, 0); | 
|  | 3338 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3339 | } | 
|  | 3340 |  | 
|  | 3341 | static int | 
|  | 3342 | handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb) | 
|  | 3343 | { | 
|  | 3344 | struct bchannel		*bch = container_of(ch, struct bchannel, ch); | 
|  | 3345 | struct hfc_multi	*hc = bch->hw; | 
|  | 3346 | int			ret = -EINVAL; | 
|  | 3347 | struct mISDNhead	*hh = mISDN_HEAD_P(skb); | 
|  | 3348 | unsigned int		id; | 
|  | 3349 | u_long			flags; | 
|  | 3350 |  | 
|  | 3351 | switch (hh->prim) { | 
|  | 3352 | case PH_DATA_REQ: | 
|  | 3353 | if (!skb->len) | 
|  | 3354 | break; | 
|  | 3355 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3356 | ret = bchannel_senddata(bch, skb); | 
|  | 3357 | if (ret > 0) { /* direct TX */ | 
|  | 3358 | id = hh->id; /* skb can be freed */ | 
|  | 3359 | hfcmulti_tx(hc, bch->slot); | 
|  | 3360 | ret = 0; | 
|  | 3361 | /* start fifo */ | 
|  | 3362 | HFC_outb_nodebug(hc, R_FIFO, 0); | 
|  | 3363 | HFC_wait_nodebug(hc); | 
|  | 3364 | if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) { | 
|  | 3365 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3366 | queue_ch_frame(ch, PH_DATA_CNF, id, NULL); | 
|  | 3367 | } else | 
|  | 3368 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3369 | } else | 
|  | 3370 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3371 | return ret; | 
|  | 3372 | case PH_ACTIVATE_REQ: | 
|  | 3373 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3374 | printk(KERN_DEBUG "%s: PH_ACTIVATE ch %d (0..32)\n", | 
|  | 3375 | __func__, bch->slot); | 
|  | 3376 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3377 | /* activate B-channel if not already activated */ | 
|  | 3378 | if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) { | 
|  | 3379 | hc->chan[bch->slot].txpending = 0; | 
|  | 3380 | ret = mode_hfcmulti(hc, bch->slot, | 
|  | 3381 | ch->protocol, | 
|  | 3382 | hc->chan[bch->slot].slot_tx, | 
|  | 3383 | hc->chan[bch->slot].bank_tx, | 
|  | 3384 | hc->chan[bch->slot].slot_rx, | 
|  | 3385 | hc->chan[bch->slot].bank_rx); | 
|  | 3386 | if (!ret) { | 
|  | 3387 | if (ch->protocol == ISDN_P_B_RAW && !hc->dtmf | 
|  | 3388 | && test_bit(HFC_CHIP_DTMF, &hc->chip)) { | 
|  | 3389 | /* start decoder */ | 
|  | 3390 | hc->dtmf = 1; | 
|  | 3391 | if (debug & DEBUG_HFCMULTI_DTMF) | 
|  | 3392 | printk(KERN_DEBUG | 
|  | 3393 | "%s: start dtmf decoder\n", | 
|  | 3394 | __func__); | 
|  | 3395 | HFC_outb(hc, R_DTMF, hc->hw.r_dtmf | | 
|  | 3396 | V_RST_DTMF); | 
|  | 3397 | } | 
|  | 3398 | } | 
|  | 3399 | } else | 
|  | 3400 | ret = 0; | 
|  | 3401 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3402 | if (!ret) | 
|  | 3403 | _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, NULL, | 
|  | 3404 | GFP_KERNEL); | 
|  | 3405 | break; | 
|  | 3406 | case PH_CONTROL_REQ: | 
|  | 3407 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3408 | switch (hh->id) { | 
|  | 3409 | case HFC_SPL_LOOP_ON: /* set sample loop */ | 
|  | 3410 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3411 | printk(KERN_DEBUG | 
|  | 3412 | "%s: HFC_SPL_LOOP_ON (len = %d)\n", | 
|  | 3413 | __func__, skb->len); | 
|  | 3414 | ret = 0; | 
|  | 3415 | break; | 
|  | 3416 | case HFC_SPL_LOOP_OFF: /* set silence */ | 
|  | 3417 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3418 | printk(KERN_DEBUG "%s: HFC_SPL_LOOP_OFF\n", | 
|  | 3419 | __func__); | 
|  | 3420 | ret = 0; | 
|  | 3421 | break; | 
|  | 3422 | default: | 
|  | 3423 | printk(KERN_ERR | 
|  | 3424 | "%s: unknown PH_CONTROL_REQ info %x\n", | 
|  | 3425 | __func__, hh->id); | 
|  | 3426 | ret = -EINVAL; | 
|  | 3427 | } | 
|  | 3428 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3429 | break; | 
|  | 3430 | case PH_DEACTIVATE_REQ: | 
|  | 3431 | deactivate_bchannel(bch); /* locked there */ | 
|  | 3432 | _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, NULL, | 
|  | 3433 | GFP_KERNEL); | 
|  | 3434 | ret = 0; | 
|  | 3435 | break; | 
|  | 3436 | } | 
|  | 3437 | if (!ret) | 
|  | 3438 | dev_kfree_skb(skb); | 
|  | 3439 | return ret; | 
|  | 3440 | } | 
|  | 3441 |  | 
|  | 3442 | /* | 
|  | 3443 | * bchannel control function | 
|  | 3444 | */ | 
|  | 3445 | static int | 
|  | 3446 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | 
|  | 3447 | { | 
|  | 3448 | int			ret = 0; | 
|  | 3449 | struct dsp_features	*features = | 
|  | 3450 | (struct dsp_features *)(*((u_long *)&cq->p1)); | 
|  | 3451 | struct hfc_multi	*hc = bch->hw; | 
|  | 3452 | int			slot_tx; | 
|  | 3453 | int			bank_tx; | 
|  | 3454 | int			slot_rx; | 
|  | 3455 | int			bank_rx; | 
|  | 3456 | int			num; | 
|  | 3457 |  | 
|  | 3458 | switch (cq->op) { | 
|  | 3459 | case MISDN_CTRL_GETOP: | 
|  | 3460 | cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP | 
|  | 3461 | | MISDN_CTRL_RX_OFF; | 
|  | 3462 | break; | 
|  | 3463 | case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */ | 
|  | 3464 | hc->chan[bch->slot].rx_off = !!cq->p1; | 
|  | 3465 | if (!hc->chan[bch->slot].rx_off) { | 
|  | 3466 | /* reset fifo on rx on */ | 
|  | 3467 | HFC_outb_nodebug(hc, R_FIFO, (bch->slot << 1) | 1); | 
|  | 3468 | HFC_wait_nodebug(hc); | 
|  | 3469 | HFC_outb_nodebug(hc, R_INC_RES_FIFO, V_RES_F); | 
|  | 3470 | HFC_wait_nodebug(hc); | 
|  | 3471 | } | 
|  | 3472 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3473 | printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n", | 
|  | 3474 | __func__, bch->nr, hc->chan[bch->slot].rx_off); | 
|  | 3475 | break; | 
|  | 3476 | case MISDN_CTRL_HW_FEATURES: /* fill features structure */ | 
|  | 3477 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3478 | printk(KERN_DEBUG "%s: HW_FEATURE request\n", | 
|  | 3479 | __func__); | 
|  | 3480 | /* create confirm */ | 
|  | 3481 | features->hfc_id = hc->id; | 
|  | 3482 | if (test_bit(HFC_CHIP_DTMF, &hc->chip)) | 
|  | 3483 | features->hfc_dtmf = 1; | 
|  | 3484 | features->hfc_loops = 0; | 
|  | 3485 | if (test_bit(HFC_CHIP_B410P, &hc->chip)) { | 
|  | 3486 | features->hfc_echocanhw = 1; | 
|  | 3487 | } else { | 
|  | 3488 | features->pcm_id = hc->pcm; | 
|  | 3489 | features->pcm_slots = hc->slots; | 
|  | 3490 | features->pcm_banks = 2; | 
|  | 3491 | } | 
|  | 3492 | break; | 
|  | 3493 | case MISDN_CTRL_HFC_PCM_CONN: /* connect to pcm timeslot (0..N) */ | 
|  | 3494 | slot_tx = cq->p1 & 0xff; | 
|  | 3495 | bank_tx = cq->p1 >> 8; | 
|  | 3496 | slot_rx = cq->p2 & 0xff; | 
|  | 3497 | bank_rx = cq->p2 >> 8; | 
|  | 3498 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3499 | printk(KERN_DEBUG | 
|  | 3500 | "%s: HFC_PCM_CONN slot %d bank %d (TX) " | 
|  | 3501 | "slot %d bank %d (RX)\n", | 
|  | 3502 | __func__, slot_tx, bank_tx, | 
|  | 3503 | slot_rx, bank_rx); | 
|  | 3504 | if (slot_tx < hc->slots && bank_tx <= 2 && | 
|  | 3505 | slot_rx < hc->slots && bank_rx <= 2) | 
|  | 3506 | hfcmulti_pcm(hc, bch->slot, | 
|  | 3507 | slot_tx, bank_tx, slot_rx, bank_rx); | 
|  | 3508 | else { | 
|  | 3509 | printk(KERN_WARNING | 
|  | 3510 | "%s: HFC_PCM_CONN slot %d bank %d (TX) " | 
|  | 3511 | "slot %d bank %d (RX) out of range\n", | 
|  | 3512 | __func__, slot_tx, bank_tx, | 
|  | 3513 | slot_rx, bank_rx); | 
|  | 3514 | ret = -EINVAL; | 
|  | 3515 | } | 
|  | 3516 | break; | 
|  | 3517 | case MISDN_CTRL_HFC_PCM_DISC: /* release interface from pcm timeslot */ | 
|  | 3518 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3519 | printk(KERN_DEBUG "%s: HFC_PCM_DISC\n", | 
|  | 3520 | __func__); | 
|  | 3521 | hfcmulti_pcm(hc, bch->slot, -1, 0, -1, 0); | 
|  | 3522 | break; | 
|  | 3523 | case MISDN_CTRL_HFC_CONF_JOIN: /* join conference (0..7) */ | 
|  | 3524 | num = cq->p1 & 0xff; | 
|  | 3525 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3526 | printk(KERN_DEBUG "%s: HFC_CONF_JOIN conf %d\n", | 
|  | 3527 | __func__, num); | 
|  | 3528 | if (num <= 7) | 
|  | 3529 | hfcmulti_conf(hc, bch->slot, num); | 
|  | 3530 | else { | 
|  | 3531 | printk(KERN_WARNING | 
|  | 3532 | "%s: HW_CONF_JOIN conf %d out of range\n", | 
|  | 3533 | __func__, num); | 
|  | 3534 | ret = -EINVAL; | 
|  | 3535 | } | 
|  | 3536 | break; | 
|  | 3537 | case MISDN_CTRL_HFC_CONF_SPLIT: /* split conference */ | 
|  | 3538 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3539 | printk(KERN_DEBUG "%s: HFC_CONF_SPLIT\n", __func__); | 
|  | 3540 | hfcmulti_conf(hc, bch->slot, -1); | 
|  | 3541 | break; | 
|  | 3542 | case MISDN_CTRL_HFC_ECHOCAN_ON: | 
|  | 3543 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3544 | printk(KERN_DEBUG "%s: HFC_ECHOCAN_ON\n", __func__); | 
|  | 3545 | if (test_bit(HFC_CHIP_B410P, &hc->chip)) | 
|  | 3546 | vpm_echocan_on(hc, bch->slot, cq->p1); | 
|  | 3547 | else | 
|  | 3548 | ret = -EINVAL; | 
|  | 3549 | break; | 
|  | 3550 |  | 
|  | 3551 | case MISDN_CTRL_HFC_ECHOCAN_OFF: | 
|  | 3552 | if (debug & DEBUG_HFCMULTI_MSG) | 
|  | 3553 | printk(KERN_DEBUG "%s: HFC_ECHOCAN_OFF\n", | 
|  | 3554 | __func__); | 
|  | 3555 | if (test_bit(HFC_CHIP_B410P, &hc->chip)) | 
|  | 3556 | vpm_echocan_off(hc, bch->slot); | 
|  | 3557 | else | 
|  | 3558 | ret = -EINVAL; | 
|  | 3559 | break; | 
|  | 3560 | default: | 
|  | 3561 | printk(KERN_WARNING "%s: unknown Op %x\n", | 
|  | 3562 | __func__, cq->op); | 
|  | 3563 | ret = -EINVAL; | 
|  | 3564 | break; | 
|  | 3565 | } | 
|  | 3566 | return ret; | 
|  | 3567 | } | 
|  | 3568 |  | 
|  | 3569 | static int | 
|  | 3570 | hfcm_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg) | 
|  | 3571 | { | 
|  | 3572 | struct bchannel		*bch = container_of(ch, struct bchannel, ch); | 
|  | 3573 | struct hfc_multi	*hc = bch->hw; | 
|  | 3574 | int			err = -EINVAL; | 
|  | 3575 | u_long	flags; | 
|  | 3576 |  | 
|  | 3577 | if (bch->debug & DEBUG_HW) | 
|  | 3578 | printk(KERN_DEBUG "%s: cmd:%x %p\n", | 
|  | 3579 | __func__, cmd, arg); | 
|  | 3580 | switch (cmd) { | 
|  | 3581 | case CLOSE_CHANNEL: | 
|  | 3582 | test_and_clear_bit(FLG_OPEN, &bch->Flags); | 
|  | 3583 | if (test_bit(FLG_ACTIVE, &bch->Flags)) | 
|  | 3584 | deactivate_bchannel(bch); /* locked there */ | 
|  | 3585 | ch->protocol = ISDN_P_NONE; | 
|  | 3586 | ch->peer = NULL; | 
|  | 3587 | module_put(THIS_MODULE); | 
|  | 3588 | err = 0; | 
|  | 3589 | break; | 
|  | 3590 | case CONTROL_CHANNEL: | 
|  | 3591 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3592 | err = channel_bctrl(bch, arg); | 
|  | 3593 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3594 | break; | 
|  | 3595 | default: | 
|  | 3596 | printk(KERN_WARNING "%s: unknown prim(%x)\n", | 
|  | 3597 | __func__, cmd); | 
|  | 3598 | } | 
|  | 3599 | return err; | 
|  | 3600 | } | 
|  | 3601 |  | 
|  | 3602 | /* | 
|  | 3603 | * handle D-channel events | 
|  | 3604 | * | 
|  | 3605 | * handle state change event | 
|  | 3606 | */ | 
|  | 3607 | static void | 
|  | 3608 | ph_state_change(struct dchannel *dch) | 
|  | 3609 | { | 
|  | 3610 | struct hfc_multi *hc = dch->hw; | 
|  | 3611 | int ch, i; | 
|  | 3612 |  | 
|  | 3613 | if (!dch) { | 
|  | 3614 | printk(KERN_WARNING "%s: ERROR given dch is NULL\n", | 
|  | 3615 | __func__); | 
|  | 3616 | return; | 
|  | 3617 | } | 
|  | 3618 | ch = dch->slot; | 
|  | 3619 |  | 
|  | 3620 | if (hc->type == 1) { | 
|  | 3621 | if (dch->dev.D.protocol == ISDN_P_TE_E1) { | 
|  | 3622 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 3623 | printk(KERN_DEBUG | 
|  | 3624 | "%s: E1 TE (id=%d) newstate %x\n", | 
|  | 3625 | __func__, hc->id, dch->state); | 
|  | 3626 | } else { | 
|  | 3627 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 3628 | printk(KERN_DEBUG | 
|  | 3629 | "%s: E1 NT (id=%d) newstate %x\n", | 
|  | 3630 | __func__, hc->id, dch->state); | 
|  | 3631 | } | 
|  | 3632 | switch (dch->state) { | 
|  | 3633 | case (1): | 
|  | 3634 | if (hc->e1_state != 1) { | 
|  | 3635 | for (i = 1; i <= 31; i++) { | 
|  | 3636 | /* reset fifos on e1 activation */ | 
|  | 3637 | HFC_outb_nodebug(hc, R_FIFO, (i << 1) | 1); | 
|  | 3638 | HFC_wait_nodebug(hc); | 
|  | 3639 | HFC_outb_nodebug(hc, | 
|  | 3640 | R_INC_RES_FIFO, V_RES_F); | 
|  | 3641 | HFC_wait_nodebug(hc); | 
|  | 3642 | } | 
|  | 3643 | } | 
|  | 3644 | test_and_set_bit(FLG_ACTIVE, &dch->Flags); | 
|  | 3645 | _queue_data(&dch->dev.D, PH_ACTIVATE_IND, | 
|  | 3646 | MISDN_ID_ANY, 0, NULL, GFP_ATOMIC); | 
|  | 3647 | break; | 
|  | 3648 |  | 
|  | 3649 | default: | 
|  | 3650 | if (hc->e1_state != 1) | 
|  | 3651 | return; | 
|  | 3652 | test_and_clear_bit(FLG_ACTIVE, &dch->Flags); | 
|  | 3653 | _queue_data(&dch->dev.D, PH_DEACTIVATE_IND, | 
|  | 3654 | MISDN_ID_ANY, 0, NULL, GFP_ATOMIC); | 
|  | 3655 | } | 
|  | 3656 | hc->e1_state = dch->state; | 
|  | 3657 | } else { | 
|  | 3658 | if (dch->dev.D.protocol == ISDN_P_TE_S0) { | 
|  | 3659 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 3660 | printk(KERN_DEBUG | 
|  | 3661 | "%s: S/T TE newstate %x\n", | 
|  | 3662 | __func__, dch->state); | 
|  | 3663 | switch (dch->state) { | 
|  | 3664 | case (0): | 
|  | 3665 | l1_event(dch->l1, HW_RESET_IND); | 
|  | 3666 | break; | 
|  | 3667 | case (3): | 
|  | 3668 | l1_event(dch->l1, HW_DEACT_IND); | 
|  | 3669 | break; | 
|  | 3670 | case (5): | 
|  | 3671 | case (8): | 
|  | 3672 | l1_event(dch->l1, ANYSIGNAL); | 
|  | 3673 | break; | 
|  | 3674 | case (6): | 
|  | 3675 | l1_event(dch->l1, INFO2); | 
|  | 3676 | break; | 
|  | 3677 | case (7): | 
|  | 3678 | l1_event(dch->l1, INFO4_P8); | 
|  | 3679 | break; | 
|  | 3680 | } | 
|  | 3681 | } else { | 
|  | 3682 | if (debug & DEBUG_HFCMULTI_STATE) | 
|  | 3683 | printk(KERN_DEBUG "%s: S/T NT newstate %x\n", | 
|  | 3684 | __func__, dch->state); | 
|  | 3685 | switch (dch->state) { | 
|  | 3686 | case (2): | 
|  | 3687 | if (hc->chan[ch].nt_timer == 0) { | 
|  | 3688 | hc->chan[ch].nt_timer = -1; | 
|  | 3689 | HFC_outb(hc, R_ST_SEL, | 
|  | 3690 | hc->chan[ch].port); | 
|  | 3691 | /* undocumented: delay after R_ST_SEL */ | 
|  | 3692 | udelay(1); | 
|  | 3693 | HFC_outb(hc, A_ST_WR_STATE, 4 | | 
|  | 3694 | V_ST_LD_STA); /* G4 */ | 
|  | 3695 | udelay(6); /* wait at least 5,21us */ | 
|  | 3696 | HFC_outb(hc, A_ST_WR_STATE, 4); | 
|  | 3697 | dch->state = 4; | 
|  | 3698 | } else { | 
|  | 3699 | /* one extra count for the next event */ | 
|  | 3700 | hc->chan[ch].nt_timer = | 
|  | 3701 | nt_t1_count[poll_timer] + 1; | 
|  | 3702 | HFC_outb(hc, R_ST_SEL, | 
|  | 3703 | hc->chan[ch].port); | 
|  | 3704 | /* undocumented: delay after R_ST_SEL */ | 
|  | 3705 | udelay(1); | 
|  | 3706 | /* allow G2 -> G3 transition */ | 
|  | 3707 | HFC_outb(hc, A_ST_WR_STATE, 2 | | 
|  | 3708 | V_SET_G2_G3); | 
|  | 3709 | } | 
|  | 3710 | break; | 
|  | 3711 | case (1): | 
|  | 3712 | hc->chan[ch].nt_timer = -1; | 
|  | 3713 | test_and_clear_bit(FLG_ACTIVE, &dch->Flags); | 
|  | 3714 | _queue_data(&dch->dev.D, PH_DEACTIVATE_IND, | 
|  | 3715 | MISDN_ID_ANY, 0, NULL, GFP_ATOMIC); | 
|  | 3716 | break; | 
|  | 3717 | case (4): | 
|  | 3718 | hc->chan[ch].nt_timer = -1; | 
|  | 3719 | break; | 
|  | 3720 | case (3): | 
|  | 3721 | hc->chan[ch].nt_timer = -1; | 
|  | 3722 | test_and_set_bit(FLG_ACTIVE, &dch->Flags); | 
|  | 3723 | _queue_data(&dch->dev.D, PH_ACTIVATE_IND, | 
|  | 3724 | MISDN_ID_ANY, 0, NULL, GFP_ATOMIC); | 
|  | 3725 | break; | 
|  | 3726 | } | 
|  | 3727 | } | 
|  | 3728 | } | 
|  | 3729 | } | 
|  | 3730 |  | 
|  | 3731 | /* | 
|  | 3732 | * called for card mode init message | 
|  | 3733 | */ | 
|  | 3734 |  | 
|  | 3735 | static void | 
|  | 3736 | hfcmulti_initmode(struct dchannel *dch) | 
|  | 3737 | { | 
|  | 3738 | struct hfc_multi *hc = dch->hw; | 
|  | 3739 | u_char		a_st_wr_state, r_e1_wr_sta; | 
|  | 3740 | int		i, pt; | 
|  | 3741 |  | 
|  | 3742 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 3743 | printk(KERN_DEBUG "%s: entered\n", __func__); | 
|  | 3744 |  | 
|  | 3745 | if (hc->type == 1) { | 
|  | 3746 | hc->chan[hc->dslot].slot_tx = -1; | 
|  | 3747 | hc->chan[hc->dslot].slot_rx = -1; | 
|  | 3748 | hc->chan[hc->dslot].conf = -1; | 
|  | 3749 | if (hc->dslot) { | 
|  | 3750 | mode_hfcmulti(hc, hc->dslot, dch->dev.D.protocol, | 
|  | 3751 | -1, 0, -1, 0); | 
|  | 3752 | dch->timer.function = (void *) hfcmulti_dbusy_timer; | 
|  | 3753 | dch->timer.data = (long) dch; | 
|  | 3754 | init_timer(&dch->timer); | 
|  | 3755 | } | 
|  | 3756 | for (i = 1; i <= 31; i++) { | 
|  | 3757 | if (i == hc->dslot) | 
|  | 3758 | continue; | 
|  | 3759 | hc->chan[i].slot_tx = -1; | 
|  | 3760 | hc->chan[i].slot_rx = -1; | 
|  | 3761 | hc->chan[i].conf = -1; | 
|  | 3762 | mode_hfcmulti(hc, i, ISDN_P_NONE, -1, 0, -1, 0); | 
|  | 3763 | } | 
|  | 3764 | /* E1 */ | 
|  | 3765 | if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[hc->dslot].cfg)) { | 
|  | 3766 | HFC_outb(hc, R_LOS0, 255); /* 2 ms */ | 
|  | 3767 | HFC_outb(hc, R_LOS1, 255); /* 512 ms */ | 
|  | 3768 | } | 
|  | 3769 | if (test_bit(HFC_CFG_OPTICAL, &hc->chan[hc->dslot].cfg)) { | 
|  | 3770 | HFC_outb(hc, R_RX0, 0); | 
|  | 3771 | hc->hw.r_tx0 = 0 | V_OUT_EN; | 
|  | 3772 | } else { | 
|  | 3773 | HFC_outb(hc, R_RX0, 1); | 
|  | 3774 | hc->hw.r_tx0 = 1 | V_OUT_EN; | 
|  | 3775 | } | 
|  | 3776 | hc->hw.r_tx1 = V_ATX | V_NTRI; | 
|  | 3777 | HFC_outb(hc, R_TX0, hc->hw.r_tx0); | 
|  | 3778 | HFC_outb(hc, R_TX1, hc->hw.r_tx1); | 
|  | 3779 | HFC_outb(hc, R_TX_FR0, 0x00); | 
|  | 3780 | HFC_outb(hc, R_TX_FR1, 0xf8); | 
|  | 3781 |  | 
|  | 3782 | if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg)) | 
|  | 3783 | HFC_outb(hc, R_TX_FR2, V_TX_MF | V_TX_E | V_NEG_E); | 
|  | 3784 |  | 
|  | 3785 | HFC_outb(hc, R_RX_FR0, V_AUTO_RESYNC | V_AUTO_RECO | 0); | 
|  | 3786 |  | 
|  | 3787 | if (test_bit(HFC_CFG_CRC4, &hc->chan[hc->dslot].cfg)) | 
|  | 3788 | HFC_outb(hc, R_RX_FR1, V_RX_MF | V_RX_MF_SYNC); | 
|  | 3789 |  | 
|  | 3790 | if (dch->dev.D.protocol == ISDN_P_NT_E1) { | 
|  | 3791 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 3792 | printk(KERN_DEBUG "%s: E1 port is NT-mode\n", | 
|  | 3793 | __func__); | 
|  | 3794 | r_e1_wr_sta = 0; /* G0 */ | 
|  | 3795 | hc->e1_getclock = 0; | 
|  | 3796 | } else { | 
|  | 3797 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 3798 | printk(KERN_DEBUG "%s: E1 port is TE-mode\n", | 
|  | 3799 | __func__); | 
|  | 3800 | r_e1_wr_sta = 0; /* F0 */ | 
|  | 3801 | hc->e1_getclock = 1; | 
|  | 3802 | } | 
|  | 3803 | if (test_bit(HFC_CHIP_RX_SYNC, &hc->chip)) | 
|  | 3804 | HFC_outb(hc, R_SYNC_OUT, V_SYNC_E1_RX); | 
|  | 3805 | else | 
|  | 3806 | HFC_outb(hc, R_SYNC_OUT, 0); | 
|  | 3807 | if (test_bit(HFC_CHIP_E1CLOCK_GET, &hc->chip)) | 
|  | 3808 | hc->e1_getclock = 1; | 
|  | 3809 | if (test_bit(HFC_CHIP_E1CLOCK_PUT, &hc->chip)) | 
|  | 3810 | hc->e1_getclock = 0; | 
|  | 3811 | if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) { | 
|  | 3812 | /* SLAVE (clock master) */ | 
|  | 3813 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 3814 | printk(KERN_DEBUG | 
|  | 3815 | "%s: E1 port is clock master " | 
|  | 3816 | "(clock from PCM)\n", __func__); | 
|  | 3817 | HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC | V_PCM_SYNC); | 
|  | 3818 | } else { | 
|  | 3819 | if (hc->e1_getclock) { | 
|  | 3820 | /* MASTER (clock slave) */ | 
|  | 3821 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 3822 | printk(KERN_DEBUG | 
|  | 3823 | "%s: E1 port is clock slave " | 
|  | 3824 | "(clock to PCM)\n", __func__); | 
|  | 3825 | HFC_outb(hc, R_SYNC_CTRL, V_SYNC_OFFS); | 
|  | 3826 | } else { | 
|  | 3827 | /* MASTER (clock master) */ | 
|  | 3828 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 3829 | printk(KERN_DEBUG "%s: E1 port is " | 
|  | 3830 | "clock master " | 
|  | 3831 | "(clock from QUARTZ)\n", | 
|  | 3832 | __func__); | 
|  | 3833 | HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC | | 
|  | 3834 | V_PCM_SYNC | V_JATT_OFF); | 
|  | 3835 | HFC_outb(hc, R_SYNC_OUT, 0); | 
|  | 3836 | } | 
|  | 3837 | } | 
|  | 3838 | HFC_outb(hc, R_JATT_ATT, 0x9c); /* undoc register */ | 
|  | 3839 | HFC_outb(hc, R_PWM_MD, V_PWM0_MD); | 
|  | 3840 | HFC_outb(hc, R_PWM0, 0x50); | 
|  | 3841 | HFC_outb(hc, R_PWM1, 0xff); | 
|  | 3842 | /* state machine setup */ | 
|  | 3843 | HFC_outb(hc, R_E1_WR_STA, r_e1_wr_sta | V_E1_LD_STA); | 
|  | 3844 | udelay(6); /* wait at least 5,21us */ | 
|  | 3845 | HFC_outb(hc, R_E1_WR_STA, r_e1_wr_sta); | 
|  | 3846 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 3847 | hc->syncronized = 0; | 
|  | 3848 | plxsd_checksync(hc, 0); | 
|  | 3849 | } | 
|  | 3850 | } else { | 
|  | 3851 | i = dch->slot; | 
|  | 3852 | hc->chan[i].slot_tx = -1; | 
|  | 3853 | hc->chan[i].slot_rx = -1; | 
|  | 3854 | hc->chan[i].conf = -1; | 
|  | 3855 | mode_hfcmulti(hc, i, dch->dev.D.protocol, -1, 0, -1, 0); | 
|  | 3856 | dch->timer.function = (void *)hfcmulti_dbusy_timer; | 
|  | 3857 | dch->timer.data = (long) dch; | 
|  | 3858 | init_timer(&dch->timer); | 
|  | 3859 | hc->chan[i - 2].slot_tx = -1; | 
|  | 3860 | hc->chan[i - 2].slot_rx = -1; | 
|  | 3861 | hc->chan[i - 2].conf = -1; | 
|  | 3862 | mode_hfcmulti(hc, i - 2, ISDN_P_NONE, -1, 0, -1, 0); | 
|  | 3863 | hc->chan[i - 1].slot_tx = -1; | 
|  | 3864 | hc->chan[i - 1].slot_rx = -1; | 
|  | 3865 | hc->chan[i - 1].conf = -1; | 
|  | 3866 | mode_hfcmulti(hc, i - 1, ISDN_P_NONE, -1, 0, -1, 0); | 
|  | 3867 | /* ST */ | 
|  | 3868 | pt = hc->chan[i].port; | 
|  | 3869 | /* select interface */ | 
|  | 3870 | HFC_outb(hc, R_ST_SEL, pt); | 
|  | 3871 | /* undocumented: delay after R_ST_SEL */ | 
|  | 3872 | udelay(1); | 
|  | 3873 | if (dch->dev.D.protocol == ISDN_P_NT_S0) { | 
|  | 3874 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 3875 | printk(KERN_DEBUG | 
|  | 3876 | "%s: ST port %d is NT-mode\n", | 
|  | 3877 | __func__, pt); | 
|  | 3878 | /* clock delay */ | 
|  | 3879 | HFC_outb(hc, A_ST_CLK_DLY, clockdelay_nt); | 
|  | 3880 | a_st_wr_state = 1; /* G1 */ | 
|  | 3881 | hc->hw.a_st_ctrl0[pt] = V_ST_MD; | 
|  | 3882 | } else { | 
|  | 3883 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 3884 | printk(KERN_DEBUG | 
|  | 3885 | "%s: ST port %d is TE-mode\n", | 
|  | 3886 | __func__, pt); | 
|  | 3887 | /* clock delay */ | 
|  | 3888 | HFC_outb(hc, A_ST_CLK_DLY, clockdelay_te); | 
|  | 3889 | a_st_wr_state = 2; /* F2 */ | 
|  | 3890 | hc->hw.a_st_ctrl0[pt] = 0; | 
|  | 3891 | } | 
|  | 3892 | if (!test_bit(HFC_CFG_NONCAP_TX, &hc->chan[i].cfg)) | 
|  | 3893 | hc->hw.a_st_ctrl0[pt] |= V_TX_LI; | 
|  | 3894 | /* line setup */ | 
|  | 3895 | HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[pt]); | 
|  | 3896 | /* disable E-channel */ | 
|  | 3897 | if ((dch->dev.D.protocol == ISDN_P_NT_S0) || | 
|  | 3898 | test_bit(HFC_CFG_DIS_ECHANNEL, &hc->chan[i].cfg)) | 
|  | 3899 | HFC_outb(hc, A_ST_CTRL1, V_E_IGNO); | 
|  | 3900 | else | 
|  | 3901 | HFC_outb(hc, A_ST_CTRL1, 0); | 
|  | 3902 | /* enable B-channel receive */ | 
|  | 3903 | HFC_outb(hc, A_ST_CTRL2,  V_B1_RX_EN | V_B2_RX_EN); | 
|  | 3904 | /* state machine setup */ | 
|  | 3905 | HFC_outb(hc, A_ST_WR_STATE, a_st_wr_state | V_ST_LD_STA); | 
|  | 3906 | udelay(6); /* wait at least 5,21us */ | 
|  | 3907 | HFC_outb(hc, A_ST_WR_STATE, a_st_wr_state); | 
|  | 3908 | hc->hw.r_sci_msk |= 1 << pt; | 
|  | 3909 | /* state machine interrupts */ | 
|  | 3910 | HFC_outb(hc, R_SCI_MSK, hc->hw.r_sci_msk); | 
|  | 3911 | /* unset sync on port */ | 
|  | 3912 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 3913 | hc->syncronized &= | 
|  | 3914 | ~(1 << hc->chan[dch->slot].port); | 
|  | 3915 | plxsd_checksync(hc, 0); | 
|  | 3916 | } | 
|  | 3917 | } | 
|  | 3918 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 3919 | printk("%s: done\n", __func__); | 
|  | 3920 | } | 
|  | 3921 |  | 
|  | 3922 |  | 
|  | 3923 | static int | 
|  | 3924 | open_dchannel(struct hfc_multi *hc, struct dchannel *dch, | 
|  | 3925 | struct channel_req *rq) | 
|  | 3926 | { | 
|  | 3927 | int	err = 0; | 
|  | 3928 | u_long	flags; | 
|  | 3929 |  | 
|  | 3930 | if (debug & DEBUG_HW_OPEN) | 
|  | 3931 | printk(KERN_DEBUG "%s: dev(%d) open from %p\n", __func__, | 
|  | 3932 | dch->dev.id, __builtin_return_address(0)); | 
|  | 3933 | if (rq->protocol == ISDN_P_NONE) | 
|  | 3934 | return -EINVAL; | 
|  | 3935 | if ((dch->dev.D.protocol != ISDN_P_NONE) && | 
|  | 3936 | (dch->dev.D.protocol != rq->protocol)) { | 
|  | 3937 | if (debug & DEBUG_HFCMULTI_MODE) | 
|  | 3938 | printk(KERN_WARNING "%s: change protocol %x to %x\n", | 
|  | 3939 | __func__, dch->dev.D.protocol, rq->protocol); | 
|  | 3940 | } | 
|  | 3941 | if ((dch->dev.D.protocol == ISDN_P_TE_S0) | 
|  | 3942 | && (rq->protocol != ISDN_P_TE_S0)) | 
|  | 3943 | l1_event(dch->l1, CLOSE_CHANNEL); | 
|  | 3944 | if (dch->dev.D.protocol != rq->protocol) { | 
|  | 3945 | if (rq->protocol == ISDN_P_TE_S0) { | 
|  | 3946 | err = create_l1(dch, hfcm_l1callback); | 
|  | 3947 | if (err) | 
|  | 3948 | return err; | 
|  | 3949 | } | 
|  | 3950 | dch->dev.D.protocol = rq->protocol; | 
|  | 3951 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 3952 | hfcmulti_initmode(dch); | 
|  | 3953 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 3954 | } | 
|  | 3955 |  | 
|  | 3956 | if (((rq->protocol == ISDN_P_NT_S0) && (dch->state == 3)) || | 
|  | 3957 | ((rq->protocol == ISDN_P_TE_S0) && (dch->state == 7)) || | 
|  | 3958 | ((rq->protocol == ISDN_P_NT_E1) && (dch->state == 1)) || | 
|  | 3959 | ((rq->protocol == ISDN_P_TE_E1) && (dch->state == 1))) { | 
|  | 3960 | _queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY, | 
|  | 3961 | 0, NULL, GFP_KERNEL); | 
|  | 3962 | } | 
|  | 3963 | rq->ch = &dch->dev.D; | 
|  | 3964 | if (!try_module_get(THIS_MODULE)) | 
|  | 3965 | printk(KERN_WARNING "%s:cannot get module\n", __func__); | 
|  | 3966 | return 0; | 
|  | 3967 | } | 
|  | 3968 |  | 
|  | 3969 | static int | 
|  | 3970 | open_bchannel(struct hfc_multi *hc, struct dchannel *dch, | 
|  | 3971 | struct channel_req *rq) | 
|  | 3972 | { | 
|  | 3973 | struct bchannel	*bch; | 
|  | 3974 | int		ch; | 
|  | 3975 |  | 
| Karsten Keil | ff4cc1d | 2008-07-30 18:26:58 +0200 | [diff] [blame] | 3976 | if (!test_channelmap(rq->adr.channel, dch->dev.channelmap)) | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 3977 | return -EINVAL; | 
|  | 3978 | if (rq->protocol == ISDN_P_NONE) | 
|  | 3979 | return -EINVAL; | 
|  | 3980 | if (hc->type == 1) | 
|  | 3981 | ch = rq->adr.channel; | 
|  | 3982 | else | 
|  | 3983 | ch = (rq->adr.channel - 1) + (dch->slot - 2); | 
|  | 3984 | bch = hc->chan[ch].bch; | 
|  | 3985 | if (!bch) { | 
|  | 3986 | printk(KERN_ERR "%s:internal error ch %d has no bch\n", | 
|  | 3987 | __func__, ch); | 
|  | 3988 | return -EINVAL; | 
|  | 3989 | } | 
|  | 3990 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | 
|  | 3991 | return -EBUSY; /* b-channel can be only open once */ | 
|  | 3992 | bch->ch.protocol = rq->protocol; | 
|  | 3993 | hc->chan[ch].rx_off = 0; | 
|  | 3994 | rq->ch = &bch->ch; | 
|  | 3995 | if (!try_module_get(THIS_MODULE)) | 
|  | 3996 | printk(KERN_WARNING "%s:cannot get module\n", __func__); | 
|  | 3997 | return 0; | 
|  | 3998 | } | 
|  | 3999 |  | 
|  | 4000 | /* | 
|  | 4001 | * device control function | 
|  | 4002 | */ | 
|  | 4003 | static int | 
|  | 4004 | channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq) | 
|  | 4005 | { | 
|  | 4006 | int	ret = 0; | 
|  | 4007 |  | 
|  | 4008 | switch (cq->op) { | 
|  | 4009 | case MISDN_CTRL_GETOP: | 
|  | 4010 | cq->op = 0; | 
|  | 4011 | break; | 
|  | 4012 | default: | 
|  | 4013 | printk(KERN_WARNING "%s: unknown Op %x\n", | 
|  | 4014 | __func__, cq->op); | 
|  | 4015 | ret = -EINVAL; | 
|  | 4016 | break; | 
|  | 4017 | } | 
|  | 4018 | return ret; | 
|  | 4019 | } | 
|  | 4020 |  | 
|  | 4021 | static int | 
|  | 4022 | hfcm_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg) | 
|  | 4023 | { | 
|  | 4024 | struct mISDNdevice	*dev = container_of(ch, struct mISDNdevice, D); | 
|  | 4025 | struct dchannel		*dch = container_of(dev, struct dchannel, dev); | 
|  | 4026 | struct hfc_multi	*hc = dch->hw; | 
|  | 4027 | struct channel_req	*rq; | 
|  | 4028 | int			err = 0; | 
|  | 4029 | u_long			flags; | 
|  | 4030 |  | 
|  | 4031 | if (dch->debug & DEBUG_HW) | 
|  | 4032 | printk(KERN_DEBUG "%s: cmd:%x %p\n", | 
|  | 4033 | __func__, cmd, arg); | 
|  | 4034 | switch (cmd) { | 
|  | 4035 | case OPEN_CHANNEL: | 
|  | 4036 | rq = arg; | 
|  | 4037 | switch (rq->protocol) { | 
|  | 4038 | case ISDN_P_TE_S0: | 
|  | 4039 | case ISDN_P_NT_S0: | 
|  | 4040 | if (hc->type == 1) { | 
|  | 4041 | err = -EINVAL; | 
|  | 4042 | break; | 
|  | 4043 | } | 
|  | 4044 | err = open_dchannel(hc, dch, rq); /* locked there */ | 
|  | 4045 | break; | 
|  | 4046 | case ISDN_P_TE_E1: | 
|  | 4047 | case ISDN_P_NT_E1: | 
|  | 4048 | if (hc->type != 1) { | 
|  | 4049 | err = -EINVAL; | 
|  | 4050 | break; | 
|  | 4051 | } | 
|  | 4052 | err = open_dchannel(hc, dch, rq); /* locked there */ | 
|  | 4053 | break; | 
|  | 4054 | default: | 
|  | 4055 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4056 | err = open_bchannel(hc, dch, rq); | 
|  | 4057 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4058 | } | 
|  | 4059 | break; | 
|  | 4060 | case CLOSE_CHANNEL: | 
|  | 4061 | if (debug & DEBUG_HW_OPEN) | 
|  | 4062 | printk(KERN_DEBUG "%s: dev(%d) close from %p\n", | 
|  | 4063 | __func__, dch->dev.id, | 
|  | 4064 | __builtin_return_address(0)); | 
|  | 4065 | module_put(THIS_MODULE); | 
|  | 4066 | break; | 
|  | 4067 | case CONTROL_CHANNEL: | 
|  | 4068 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4069 | err = channel_dctrl(dch, arg); | 
|  | 4070 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4071 | break; | 
|  | 4072 | default: | 
|  | 4073 | if (dch->debug & DEBUG_HW) | 
|  | 4074 | printk(KERN_DEBUG "%s: unknown command %x\n", | 
|  | 4075 | __func__, cmd); | 
|  | 4076 | err = -EINVAL; | 
|  | 4077 | } | 
|  | 4078 | return err; | 
|  | 4079 | } | 
|  | 4080 |  | 
|  | 4081 | /* | 
|  | 4082 | * initialize the card | 
|  | 4083 | */ | 
|  | 4084 |  | 
|  | 4085 | /* | 
|  | 4086 | * start timer irq, wait some time and check if we have interrupts. | 
|  | 4087 | * if not, reset chip and try again. | 
|  | 4088 | */ | 
|  | 4089 | static int | 
|  | 4090 | init_card(struct hfc_multi *hc) | 
|  | 4091 | { | 
|  | 4092 | int	err = -EIO; | 
|  | 4093 | u_long	flags; | 
|  | 4094 | u_short	*plx_acc; | 
|  | 4095 | u_long	plx_flags; | 
|  | 4096 |  | 
|  | 4097 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4098 | printk(KERN_DEBUG "%s: entered\n", __func__); | 
|  | 4099 |  | 
|  | 4100 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4101 | /* set interrupts but leave global interrupt disabled */ | 
|  | 4102 | hc->hw.r_irq_ctrl = V_FIFO_IRQ; | 
|  | 4103 | disable_hwirq(hc); | 
|  | 4104 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4105 |  | 
|  | 4106 | if (request_irq(hc->pci_dev->irq, hfcmulti_interrupt, IRQF_SHARED, | 
|  | 4107 | "HFC-multi", hc)) { | 
|  | 4108 | printk(KERN_WARNING "mISDN: Could not get interrupt %d.\n", | 
|  | 4109 | hc->pci_dev->irq); | 
|  | 4110 | return -EIO; | 
|  | 4111 | } | 
|  | 4112 | hc->irq = hc->pci_dev->irq; | 
|  | 4113 |  | 
|  | 4114 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 4115 | spin_lock_irqsave(&plx_lock, plx_flags); | 
|  | 4116 | plx_acc = (u_short *)(hc->plx_membase+PLX_INTCSR); | 
|  | 4117 | writew((PLX_INTCSR_PCIINT_ENABLE | PLX_INTCSR_LINTI1_ENABLE), | 
|  | 4118 | plx_acc); /* enable PCI & LINT1 irq */ | 
|  | 4119 | spin_unlock_irqrestore(&plx_lock, plx_flags); | 
|  | 4120 | } | 
|  | 4121 |  | 
|  | 4122 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4123 | printk(KERN_DEBUG "%s: IRQ %d count %d\n", | 
|  | 4124 | __func__, hc->irq, hc->irqcnt); | 
|  | 4125 | err = init_chip(hc); | 
|  | 4126 | if (err) | 
|  | 4127 | goto error; | 
|  | 4128 | /* | 
|  | 4129 | * Finally enable IRQ output | 
|  | 4130 | * this is only allowed, if an IRQ routine is allready | 
|  | 4131 | * established for this HFC, so don't do that earlier | 
|  | 4132 | */ | 
|  | 4133 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4134 | enable_hwirq(hc); | 
|  | 4135 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4136 | /* printk(KERN_DEBUG "no master irq set!!!\n"); */ | 
|  | 4137 | set_current_state(TASK_UNINTERRUPTIBLE); | 
|  | 4138 | schedule_timeout((100*HZ)/1000); /* Timeout 100ms */ | 
|  | 4139 | /* turn IRQ off until chip is completely initialized */ | 
|  | 4140 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4141 | disable_hwirq(hc); | 
|  | 4142 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4143 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4144 | printk(KERN_DEBUG "%s: IRQ %d count %d\n", | 
|  | 4145 | __func__, hc->irq, hc->irqcnt); | 
|  | 4146 | if (hc->irqcnt) { | 
|  | 4147 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4148 | printk(KERN_DEBUG "%s: done\n", __func__); | 
|  | 4149 |  | 
|  | 4150 | return 0; | 
|  | 4151 | } | 
|  | 4152 | if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) { | 
|  | 4153 | printk(KERN_INFO "ignoring missing interrupts\n"); | 
|  | 4154 | return 0; | 
|  | 4155 | } | 
|  | 4156 |  | 
|  | 4157 | printk(KERN_ERR "HFC PCI: IRQ(%d) getting no interrupts during init.\n", | 
|  | 4158 | hc->irq); | 
|  | 4159 |  | 
|  | 4160 | err = -EIO; | 
|  | 4161 |  | 
|  | 4162 | error: | 
|  | 4163 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 4164 | spin_lock_irqsave(&plx_lock, plx_flags); | 
|  | 4165 | plx_acc = (u_short *)(hc->plx_membase+PLX_INTCSR); | 
|  | 4166 | writew(0x00, plx_acc); /*disable IRQs*/ | 
|  | 4167 | spin_unlock_irqrestore(&plx_lock, plx_flags); | 
|  | 4168 | } | 
|  | 4169 |  | 
|  | 4170 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4171 | printk(KERN_WARNING "%s: free irq %d\n", __func__, hc->irq); | 
|  | 4172 | if (hc->irq) { | 
|  | 4173 | free_irq(hc->irq, hc); | 
|  | 4174 | hc->irq = 0; | 
|  | 4175 | } | 
|  | 4176 |  | 
|  | 4177 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4178 | printk(KERN_DEBUG "%s: done (err=%d)\n", __func__, err); | 
|  | 4179 | return err; | 
|  | 4180 | } | 
|  | 4181 |  | 
|  | 4182 | /* | 
|  | 4183 | * find pci device and set it up | 
|  | 4184 | */ | 
|  | 4185 |  | 
|  | 4186 | static int | 
|  | 4187 | setup_pci(struct hfc_multi *hc, struct pci_dev *pdev, | 
|  | 4188 | const struct pci_device_id *ent) | 
|  | 4189 | { | 
|  | 4190 | struct hm_map	*m = (struct hm_map *)ent->driver_data; | 
|  | 4191 |  | 
|  | 4192 | printk(KERN_INFO | 
|  | 4193 | "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n", | 
|  | 4194 | m->vendor_name, m->card_name, m->clock2 ? "double" : "normal"); | 
|  | 4195 |  | 
|  | 4196 | hc->pci_dev = pdev; | 
|  | 4197 | if (m->clock2) | 
|  | 4198 | test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip); | 
|  | 4199 |  | 
|  | 4200 | if (ent->device == 0xB410) { | 
|  | 4201 | test_and_set_bit(HFC_CHIP_B410P, &hc->chip); | 
|  | 4202 | test_and_set_bit(HFC_CHIP_PCM_MASTER, &hc->chip); | 
|  | 4203 | test_and_clear_bit(HFC_CHIP_PCM_SLAVE, &hc->chip); | 
|  | 4204 | hc->slots = 32; | 
|  | 4205 | } | 
|  | 4206 |  | 
|  | 4207 | if (hc->pci_dev->irq <= 0) { | 
|  | 4208 | printk(KERN_WARNING "HFC-multi: No IRQ for PCI card found.\n"); | 
|  | 4209 | return -EIO; | 
|  | 4210 | } | 
|  | 4211 | if (pci_enable_device(hc->pci_dev)) { | 
|  | 4212 | printk(KERN_WARNING "HFC-multi: Error enabling PCI card.\n"); | 
|  | 4213 | return -EIO; | 
|  | 4214 | } | 
|  | 4215 | hc->leds = m->leds; | 
|  | 4216 | hc->ledstate = 0xAFFEAFFE; | 
|  | 4217 | hc->opticalsupport = m->opticalsupport; | 
|  | 4218 |  | 
|  | 4219 | /* set memory access methods */ | 
|  | 4220 | if (m->io_mode) /* use mode from card config */ | 
|  | 4221 | hc->io_mode = m->io_mode; | 
|  | 4222 | switch (hc->io_mode) { | 
|  | 4223 | case HFC_IO_MODE_PLXSD: | 
|  | 4224 | test_and_set_bit(HFC_CHIP_PLXSD, &hc->chip); | 
|  | 4225 | hc->slots = 128; /* required */ | 
|  | 4226 | /* fall through */ | 
|  | 4227 | case HFC_IO_MODE_PCIMEM: | 
|  | 4228 | hc->HFC_outb = HFC_outb_pcimem; | 
|  | 4229 | hc->HFC_inb = HFC_inb_pcimem; | 
|  | 4230 | hc->HFC_inw = HFC_inw_pcimem; | 
|  | 4231 | hc->HFC_wait = HFC_wait_pcimem; | 
|  | 4232 | hc->read_fifo = read_fifo_pcimem; | 
|  | 4233 | hc->write_fifo = write_fifo_pcimem; | 
|  | 4234 | break; | 
|  | 4235 | case HFC_IO_MODE_REGIO: | 
|  | 4236 | hc->HFC_outb = HFC_outb_regio; | 
|  | 4237 | hc->HFC_inb = HFC_inb_regio; | 
|  | 4238 | hc->HFC_inw = HFC_inw_regio; | 
|  | 4239 | hc->HFC_wait = HFC_wait_regio; | 
|  | 4240 | hc->read_fifo = read_fifo_regio; | 
|  | 4241 | hc->write_fifo = write_fifo_regio; | 
|  | 4242 | break; | 
|  | 4243 | default: | 
|  | 4244 | printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n"); | 
|  | 4245 | pci_disable_device(hc->pci_dev); | 
|  | 4246 | return -EIO; | 
|  | 4247 | } | 
|  | 4248 | hc->HFC_outb_nodebug = hc->HFC_outb; | 
|  | 4249 | hc->HFC_inb_nodebug = hc->HFC_inb; | 
|  | 4250 | hc->HFC_inw_nodebug = hc->HFC_inw; | 
|  | 4251 | hc->HFC_wait_nodebug = hc->HFC_wait; | 
|  | 4252 | #ifdef HFC_REGISTER_DEBUG | 
|  | 4253 | hc->HFC_outb = HFC_outb_debug; | 
|  | 4254 | hc->HFC_inb = HFC_inb_debug; | 
|  | 4255 | hc->HFC_inw = HFC_inw_debug; | 
|  | 4256 | hc->HFC_wait = HFC_wait_debug; | 
|  | 4257 | #endif | 
|  | 4258 | hc->pci_iobase = 0; | 
|  | 4259 | hc->pci_membase = NULL; | 
|  | 4260 | hc->plx_membase = NULL; | 
|  | 4261 |  | 
|  | 4262 | switch (hc->io_mode) { | 
|  | 4263 | case HFC_IO_MODE_PLXSD: | 
|  | 4264 | hc->plx_origmembase =  hc->pci_dev->resource[0].start; | 
|  | 4265 | /* MEMBASE 1 is PLX PCI Bridge */ | 
|  | 4266 |  | 
|  | 4267 | if (!hc->plx_origmembase) { | 
|  | 4268 | printk(KERN_WARNING | 
|  | 4269 | "HFC-multi: No IO-Memory for PCI PLX bridge found\n"); | 
|  | 4270 | pci_disable_device(hc->pci_dev); | 
|  | 4271 | return -EIO; | 
|  | 4272 | } | 
|  | 4273 |  | 
|  | 4274 | hc->plx_membase = ioremap(hc->plx_origmembase, 0x80); | 
|  | 4275 | if (!hc->plx_membase) { | 
|  | 4276 | printk(KERN_WARNING | 
|  | 4277 | "HFC-multi: failed to remap plx address space. " | 
|  | 4278 | "(internal error)\n"); | 
|  | 4279 | pci_disable_device(hc->pci_dev); | 
|  | 4280 | return -EIO; | 
|  | 4281 | } | 
|  | 4282 | printk(KERN_INFO | 
|  | 4283 | "HFC-multi: plx_membase:%#lx plx_origmembase:%#lx\n", | 
|  | 4284 | (u_long)hc->plx_membase, hc->plx_origmembase); | 
|  | 4285 |  | 
|  | 4286 | hc->pci_origmembase =  hc->pci_dev->resource[2].start; | 
|  | 4287 | /* MEMBASE 1 is PLX PCI Bridge */ | 
|  | 4288 | if (!hc->pci_origmembase) { | 
|  | 4289 | printk(KERN_WARNING | 
|  | 4290 | "HFC-multi: No IO-Memory for PCI card found\n"); | 
|  | 4291 | pci_disable_device(hc->pci_dev); | 
|  | 4292 | return -EIO; | 
|  | 4293 | } | 
|  | 4294 |  | 
|  | 4295 | hc->pci_membase = ioremap(hc->pci_origmembase, 0x400); | 
|  | 4296 | if (!hc->pci_membase) { | 
|  | 4297 | printk(KERN_WARNING "HFC-multi: failed to remap io " | 
|  | 4298 | "address space. (internal error)\n"); | 
|  | 4299 | pci_disable_device(hc->pci_dev); | 
|  | 4300 | return -EIO; | 
|  | 4301 | } | 
|  | 4302 |  | 
|  | 4303 | printk(KERN_INFO | 
|  | 4304 | "card %d: defined at MEMBASE %#lx (%#lx) IRQ %d HZ %d " | 
|  | 4305 | "leds-type %d\n", | 
|  | 4306 | hc->id, (u_long)hc->pci_membase, hc->pci_origmembase, | 
|  | 4307 | hc->pci_dev->irq, HZ, hc->leds); | 
|  | 4308 | pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO); | 
|  | 4309 | break; | 
|  | 4310 | case HFC_IO_MODE_PCIMEM: | 
|  | 4311 | hc->pci_origmembase = hc->pci_dev->resource[1].start; | 
|  | 4312 | if (!hc->pci_origmembase) { | 
|  | 4313 | printk(KERN_WARNING | 
|  | 4314 | "HFC-multi: No IO-Memory for PCI card found\n"); | 
|  | 4315 | pci_disable_device(hc->pci_dev); | 
|  | 4316 | return -EIO; | 
|  | 4317 | } | 
|  | 4318 |  | 
|  | 4319 | hc->pci_membase = ioremap(hc->pci_origmembase, 256); | 
|  | 4320 | if (!hc->pci_membase) { | 
|  | 4321 | printk(KERN_WARNING | 
|  | 4322 | "HFC-multi: failed to remap io address space. " | 
|  | 4323 | "(internal error)\n"); | 
|  | 4324 | pci_disable_device(hc->pci_dev); | 
|  | 4325 | return -EIO; | 
|  | 4326 | } | 
|  | 4327 | printk(KERN_INFO "card %d: defined at MEMBASE %#lx (%#lx) IRQ %d " | 
|  | 4328 | "HZ %d leds-type %d\n", hc->id, (u_long)hc->pci_membase, | 
|  | 4329 | hc->pci_origmembase, hc->pci_dev->irq, HZ, hc->leds); | 
|  | 4330 | pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO); | 
|  | 4331 | break; | 
|  | 4332 | case HFC_IO_MODE_REGIO: | 
|  | 4333 | hc->pci_iobase = (u_int) hc->pci_dev->resource[0].start; | 
|  | 4334 | if (!hc->pci_iobase) { | 
|  | 4335 | printk(KERN_WARNING | 
|  | 4336 | "HFC-multi: No IO for PCI card found\n"); | 
|  | 4337 | pci_disable_device(hc->pci_dev); | 
|  | 4338 | return -EIO; | 
|  | 4339 | } | 
|  | 4340 |  | 
|  | 4341 | if (!request_region(hc->pci_iobase, 8, "hfcmulti")) { | 
|  | 4342 | printk(KERN_WARNING "HFC-multi: failed to request " | 
|  | 4343 | "address space at 0x%08lx (internal error)\n", | 
|  | 4344 | hc->pci_iobase); | 
|  | 4345 | pci_disable_device(hc->pci_dev); | 
|  | 4346 | return -EIO; | 
|  | 4347 | } | 
|  | 4348 |  | 
|  | 4349 | printk(KERN_INFO | 
|  | 4350 | "%s %s: defined at IOBASE %#x IRQ %d HZ %d leds-type %d\n", | 
|  | 4351 | m->vendor_name, m->card_name, (u_int) hc->pci_iobase, | 
|  | 4352 | hc->pci_dev->irq, HZ, hc->leds); | 
|  | 4353 | pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_REGIO); | 
|  | 4354 | break; | 
|  | 4355 | default: | 
|  | 4356 | printk(KERN_WARNING "HFC-multi: Invalid IO mode.\n"); | 
|  | 4357 | pci_disable_device(hc->pci_dev); | 
|  | 4358 | return -EIO; | 
|  | 4359 | } | 
|  | 4360 |  | 
|  | 4361 | pci_set_drvdata(hc->pci_dev, hc); | 
|  | 4362 |  | 
|  | 4363 | /* At this point the needed PCI config is done */ | 
|  | 4364 | /* fifos are still not enabled */ | 
|  | 4365 | return 0; | 
|  | 4366 | } | 
|  | 4367 |  | 
|  | 4368 |  | 
|  | 4369 | /* | 
|  | 4370 | * remove port | 
|  | 4371 | */ | 
|  | 4372 |  | 
|  | 4373 | static void | 
|  | 4374 | release_port(struct hfc_multi *hc, struct dchannel *dch) | 
|  | 4375 | { | 
|  | 4376 | int	pt, ci, i = 0; | 
|  | 4377 | u_long	flags; | 
|  | 4378 | struct bchannel *pb; | 
|  | 4379 |  | 
|  | 4380 | ci = dch->slot; | 
|  | 4381 | pt = hc->chan[ci].port; | 
|  | 4382 |  | 
|  | 4383 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4384 | printk(KERN_DEBUG "%s: entered for port %d\n", | 
|  | 4385 | __func__, pt + 1); | 
|  | 4386 |  | 
|  | 4387 | if (pt >= hc->ports) { | 
|  | 4388 | printk(KERN_WARNING "%s: ERROR port out of range (%d).\n", | 
|  | 4389 | __func__, pt + 1); | 
|  | 4390 | return; | 
|  | 4391 | } | 
|  | 4392 |  | 
|  | 4393 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4394 | printk(KERN_DEBUG "%s: releasing port=%d\n", | 
|  | 4395 | __func__, pt + 1); | 
|  | 4396 |  | 
|  | 4397 | if (dch->dev.D.protocol == ISDN_P_TE_S0) | 
|  | 4398 | l1_event(dch->l1, CLOSE_CHANNEL); | 
|  | 4399 |  | 
|  | 4400 | hc->chan[ci].dch = NULL; | 
|  | 4401 |  | 
|  | 4402 | if (hc->created[pt]) { | 
|  | 4403 | hc->created[pt] = 0; | 
|  | 4404 | mISDN_unregister_device(&dch->dev); | 
|  | 4405 | } | 
|  | 4406 |  | 
|  | 4407 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4408 |  | 
|  | 4409 | if (dch->timer.function) { | 
|  | 4410 | del_timer(&dch->timer); | 
|  | 4411 | dch->timer.function = NULL; | 
|  | 4412 | } | 
|  | 4413 |  | 
|  | 4414 | if (hc->type == 1) { /* E1 */ | 
|  | 4415 | /* remove sync */ | 
|  | 4416 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 4417 | hc->syncronized = 0; | 
|  | 4418 | plxsd_checksync(hc, 1); | 
|  | 4419 | } | 
|  | 4420 | /* free channels */ | 
|  | 4421 | for (i = 0; i <= 31; i++) { | 
|  | 4422 | if (hc->chan[i].bch) { | 
|  | 4423 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4424 | printk(KERN_DEBUG | 
|  | 4425 | "%s: free port %d channel %d\n", | 
|  | 4426 | __func__, hc->chan[i].port+1, i); | 
|  | 4427 | pb = hc->chan[i].bch; | 
|  | 4428 | hc->chan[i].bch = NULL; | 
|  | 4429 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4430 | mISDN_freebchannel(pb); | 
|  | 4431 | kfree(pb); | 
|  | 4432 | kfree(hc->chan[i].coeff); | 
|  | 4433 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4434 | } | 
|  | 4435 | } | 
|  | 4436 | } else { | 
|  | 4437 | /* remove sync */ | 
|  | 4438 | if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { | 
|  | 4439 | hc->syncronized &= | 
|  | 4440 | ~(1 << hc->chan[ci].port); | 
|  | 4441 | plxsd_checksync(hc, 1); | 
|  | 4442 | } | 
|  | 4443 | /* free channels */ | 
|  | 4444 | if (hc->chan[ci - 2].bch) { | 
|  | 4445 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4446 | printk(KERN_DEBUG | 
|  | 4447 | "%s: free port %d channel %d\n", | 
|  | 4448 | __func__, hc->chan[ci - 2].port+1, | 
|  | 4449 | ci - 2); | 
|  | 4450 | pb = hc->chan[ci - 2].bch; | 
|  | 4451 | hc->chan[ci - 2].bch = NULL; | 
|  | 4452 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4453 | mISDN_freebchannel(pb); | 
|  | 4454 | kfree(pb); | 
|  | 4455 | kfree(hc->chan[ci - 2].coeff); | 
|  | 4456 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4457 | } | 
|  | 4458 | if (hc->chan[ci - 1].bch) { | 
|  | 4459 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4460 | printk(KERN_DEBUG | 
|  | 4461 | "%s: free port %d channel %d\n", | 
|  | 4462 | __func__, hc->chan[ci - 1].port+1, | 
|  | 4463 | ci - 1); | 
|  | 4464 | pb = hc->chan[ci - 1].bch; | 
|  | 4465 | hc->chan[ci - 1].bch = NULL; | 
|  | 4466 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4467 | mISDN_freebchannel(pb); | 
|  | 4468 | kfree(pb); | 
|  | 4469 | kfree(hc->chan[ci - 1].coeff); | 
|  | 4470 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4471 | } | 
|  | 4472 | } | 
|  | 4473 |  | 
|  | 4474 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4475 |  | 
|  | 4476 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4477 | printk(KERN_DEBUG "%s: free port %d channel D\n", __func__, pt); | 
|  | 4478 | mISDN_freedchannel(dch); | 
|  | 4479 | kfree(dch); | 
|  | 4480 |  | 
|  | 4481 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4482 | printk(KERN_DEBUG "%s: done!\n", __func__); | 
|  | 4483 | } | 
|  | 4484 |  | 
|  | 4485 | static void | 
|  | 4486 | release_card(struct hfc_multi *hc) | 
|  | 4487 | { | 
|  | 4488 | u_long	flags; | 
|  | 4489 | int	ch; | 
|  | 4490 |  | 
|  | 4491 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4492 | printk(KERN_WARNING "%s: release card (%d) entered\n", | 
|  | 4493 | __func__, hc->id); | 
|  | 4494 |  | 
|  | 4495 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 4496 | disable_hwirq(hc); | 
|  | 4497 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 4498 |  | 
|  | 4499 | udelay(1000); | 
|  | 4500 |  | 
|  | 4501 | /* dimm leds */ | 
|  | 4502 | if (hc->leds) | 
|  | 4503 | hfcmulti_leds(hc); | 
|  | 4504 |  | 
|  | 4505 | /* disable D-channels & B-channels */ | 
|  | 4506 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4507 | printk(KERN_DEBUG "%s: disable all channels (d and b)\n", | 
|  | 4508 | __func__); | 
|  | 4509 | for (ch = 0; ch <= 31; ch++) { | 
|  | 4510 | if (hc->chan[ch].dch) | 
|  | 4511 | release_port(hc, hc->chan[ch].dch); | 
|  | 4512 | } | 
|  | 4513 |  | 
|  | 4514 | /* release hardware & irq */ | 
|  | 4515 | if (hc->irq) { | 
|  | 4516 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4517 | printk(KERN_WARNING "%s: free irq %d\n", | 
|  | 4518 | __func__, hc->irq); | 
|  | 4519 | free_irq(hc->irq, hc); | 
|  | 4520 | hc->irq = 0; | 
|  | 4521 |  | 
|  | 4522 | } | 
|  | 4523 | release_io_hfcmulti(hc); | 
|  | 4524 |  | 
|  | 4525 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4526 | printk(KERN_WARNING "%s: remove instance from list\n", | 
|  | 4527 | __func__); | 
|  | 4528 | list_del(&hc->list); | 
|  | 4529 |  | 
|  | 4530 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4531 | printk(KERN_WARNING "%s: delete instance\n", __func__); | 
|  | 4532 | if (hc == syncmaster) | 
|  | 4533 | syncmaster = NULL; | 
|  | 4534 | kfree(hc); | 
|  | 4535 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4536 | printk(KERN_WARNING "%s: card successfully removed\n", | 
|  | 4537 | __func__); | 
|  | 4538 | } | 
|  | 4539 |  | 
|  | 4540 | static int | 
|  | 4541 | init_e1_port(struct hfc_multi *hc, struct hm_map *m) | 
|  | 4542 | { | 
|  | 4543 | struct dchannel	*dch; | 
|  | 4544 | struct bchannel	*bch; | 
|  | 4545 | int		ch, ret = 0; | 
|  | 4546 | char		name[MISDN_MAX_IDLEN]; | 
|  | 4547 |  | 
|  | 4548 | dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL); | 
|  | 4549 | if (!dch) | 
|  | 4550 | return -ENOMEM; | 
|  | 4551 | dch->debug = debug; | 
|  | 4552 | mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change); | 
|  | 4553 | dch->hw = hc; | 
|  | 4554 | dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1); | 
|  | 4555 | dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | | 
|  | 4556 | (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); | 
|  | 4557 | dch->dev.D.send = handle_dmsg; | 
|  | 4558 | dch->dev.D.ctrl = hfcm_dctrl; | 
|  | 4559 | dch->dev.nrbchan = (hc->dslot)?30:31; | 
|  | 4560 | dch->slot = hc->dslot; | 
|  | 4561 | hc->chan[hc->dslot].dch = dch; | 
|  | 4562 | hc->chan[hc->dslot].port = 0; | 
|  | 4563 | hc->chan[hc->dslot].nt_timer = -1; | 
|  | 4564 | for (ch = 1; ch <= 31; ch++) { | 
|  | 4565 | if (ch == hc->dslot) /* skip dchannel */ | 
|  | 4566 | continue; | 
|  | 4567 | bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL); | 
|  | 4568 | if (!bch) { | 
|  | 4569 | printk(KERN_ERR "%s: no memory for bchannel\n", | 
|  | 4570 | __func__); | 
|  | 4571 | ret = -ENOMEM; | 
|  | 4572 | goto free_chan; | 
|  | 4573 | } | 
|  | 4574 | hc->chan[ch].coeff = kzalloc(512, GFP_KERNEL); | 
|  | 4575 | if (!hc->chan[ch].coeff) { | 
|  | 4576 | printk(KERN_ERR "%s: no memory for coeffs\n", | 
|  | 4577 | __func__); | 
|  | 4578 | ret = -ENOMEM; | 
|  | 4579 | goto free_chan; | 
|  | 4580 | } | 
|  | 4581 | bch->nr = ch; | 
|  | 4582 | bch->slot = ch; | 
|  | 4583 | bch->debug = debug; | 
|  | 4584 | mISDN_initbchannel(bch, MAX_DATA_MEM); | 
|  | 4585 | bch->hw = hc; | 
|  | 4586 | bch->ch.send = handle_bmsg; | 
|  | 4587 | bch->ch.ctrl = hfcm_bctrl; | 
|  | 4588 | bch->ch.nr = ch; | 
|  | 4589 | list_add(&bch->ch.list, &dch->dev.bchannels); | 
|  | 4590 | hc->chan[ch].bch = bch; | 
|  | 4591 | hc->chan[ch].port = 0; | 
| Karsten Keil | ff4cc1d | 2008-07-30 18:26:58 +0200 | [diff] [blame] | 4592 | set_channelmap(bch->nr, dch->dev.channelmap); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 4593 | } | 
|  | 4594 | /* set optical line type */ | 
|  | 4595 | if (port[Port_cnt] & 0x001) { | 
|  | 4596 | if (!m->opticalsupport)  { | 
|  | 4597 | printk(KERN_INFO | 
|  | 4598 | "This board has no optical " | 
|  | 4599 | "support\n"); | 
|  | 4600 | } else { | 
|  | 4601 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4602 | printk(KERN_DEBUG | 
|  | 4603 | "%s: PORT set optical " | 
|  | 4604 | "interfacs: card(%d) " | 
|  | 4605 | "port(%d)\n", | 
|  | 4606 | __func__, | 
|  | 4607 | HFC_cnt + 1, 1); | 
|  | 4608 | test_and_set_bit(HFC_CFG_OPTICAL, | 
|  | 4609 | &hc->chan[hc->dslot].cfg); | 
|  | 4610 | } | 
|  | 4611 | } | 
|  | 4612 | /* set LOS report */ | 
|  | 4613 | if (port[Port_cnt] & 0x004) { | 
|  | 4614 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4615 | printk(KERN_DEBUG "%s: PORT set " | 
|  | 4616 | "LOS report: card(%d) port(%d)\n", | 
|  | 4617 | __func__, HFC_cnt + 1, 1); | 
|  | 4618 | test_and_set_bit(HFC_CFG_REPORT_LOS, | 
|  | 4619 | &hc->chan[hc->dslot].cfg); | 
|  | 4620 | } | 
|  | 4621 | /* set AIS report */ | 
|  | 4622 | if (port[Port_cnt] & 0x008) { | 
|  | 4623 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4624 | printk(KERN_DEBUG "%s: PORT set " | 
|  | 4625 | "AIS report: card(%d) port(%d)\n", | 
|  | 4626 | __func__, HFC_cnt + 1, 1); | 
|  | 4627 | test_and_set_bit(HFC_CFG_REPORT_AIS, | 
|  | 4628 | &hc->chan[hc->dslot].cfg); | 
|  | 4629 | } | 
|  | 4630 | /* set SLIP report */ | 
|  | 4631 | if (port[Port_cnt] & 0x010) { | 
|  | 4632 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4633 | printk(KERN_DEBUG | 
|  | 4634 | "%s: PORT set SLIP report: " | 
|  | 4635 | "card(%d) port(%d)\n", | 
|  | 4636 | __func__, HFC_cnt + 1, 1); | 
|  | 4637 | test_and_set_bit(HFC_CFG_REPORT_SLIP, | 
|  | 4638 | &hc->chan[hc->dslot].cfg); | 
|  | 4639 | } | 
|  | 4640 | /* set RDI report */ | 
|  | 4641 | if (port[Port_cnt] & 0x020) { | 
|  | 4642 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4643 | printk(KERN_DEBUG | 
|  | 4644 | "%s: PORT set RDI report: " | 
|  | 4645 | "card(%d) port(%d)\n", | 
|  | 4646 | __func__, HFC_cnt + 1, 1); | 
|  | 4647 | test_and_set_bit(HFC_CFG_REPORT_RDI, | 
|  | 4648 | &hc->chan[hc->dslot].cfg); | 
|  | 4649 | } | 
|  | 4650 | /* set CRC-4 Mode */ | 
|  | 4651 | if (!(port[Port_cnt] & 0x100)) { | 
|  | 4652 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4653 | printk(KERN_DEBUG "%s: PORT turn on CRC4 report:" | 
|  | 4654 | " card(%d) port(%d)\n", | 
|  | 4655 | __func__, HFC_cnt + 1, 1); | 
|  | 4656 | test_and_set_bit(HFC_CFG_CRC4, | 
|  | 4657 | &hc->chan[hc->dslot].cfg); | 
|  | 4658 | } else { | 
|  | 4659 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4660 | printk(KERN_DEBUG "%s: PORT turn off CRC4" | 
|  | 4661 | " report: card(%d) port(%d)\n", | 
|  | 4662 | __func__, HFC_cnt + 1, 1); | 
|  | 4663 | } | 
|  | 4664 | /* set forced clock */ | 
|  | 4665 | if (port[Port_cnt] & 0x0200) { | 
|  | 4666 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4667 | printk(KERN_DEBUG "%s: PORT force getting clock from " | 
|  | 4668 | "E1: card(%d) port(%d)\n", | 
|  | 4669 | __func__, HFC_cnt + 1, 1); | 
|  | 4670 | test_and_set_bit(HFC_CHIP_E1CLOCK_GET, &hc->chip); | 
|  | 4671 | } else | 
|  | 4672 | if (port[Port_cnt] & 0x0400) { | 
|  | 4673 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4674 | printk(KERN_DEBUG "%s: PORT force putting clock to " | 
|  | 4675 | "E1: card(%d) port(%d)\n", | 
|  | 4676 | __func__, HFC_cnt + 1, 1); | 
|  | 4677 | test_and_set_bit(HFC_CHIP_E1CLOCK_PUT, &hc->chip); | 
|  | 4678 | } | 
|  | 4679 | /* set JATT PLL */ | 
|  | 4680 | if (port[Port_cnt] & 0x0800) { | 
|  | 4681 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4682 | printk(KERN_DEBUG "%s: PORT disable JATT PLL on " | 
|  | 4683 | "E1: card(%d) port(%d)\n", | 
|  | 4684 | __func__, HFC_cnt + 1, 1); | 
|  | 4685 | test_and_set_bit(HFC_CHIP_RX_SYNC, &hc->chip); | 
|  | 4686 | } | 
|  | 4687 | /* set elastic jitter buffer */ | 
|  | 4688 | if (port[Port_cnt] & 0x3000) { | 
|  | 4689 | hc->chan[hc->dslot].jitter = (port[Port_cnt]>>12) & 0x3; | 
|  | 4690 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4691 | printk(KERN_DEBUG | 
|  | 4692 | "%s: PORT set elastic " | 
|  | 4693 | "buffer to %d: card(%d) port(%d)\n", | 
|  | 4694 | __func__, hc->chan[hc->dslot].jitter, | 
|  | 4695 | HFC_cnt + 1, 1); | 
|  | 4696 | } else | 
|  | 4697 | hc->chan[hc->dslot].jitter = 2; /* default */ | 
|  | 4698 | snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1); | 
|  | 4699 | ret = mISDN_register_device(&dch->dev, name); | 
|  | 4700 | if (ret) | 
|  | 4701 | goto free_chan; | 
|  | 4702 | hc->created[0] = 1; | 
|  | 4703 | return ret; | 
|  | 4704 | free_chan: | 
|  | 4705 | release_port(hc, dch); | 
|  | 4706 | return ret; | 
|  | 4707 | } | 
|  | 4708 |  | 
|  | 4709 | static int | 
|  | 4710 | init_multi_port(struct hfc_multi *hc, int pt) | 
|  | 4711 | { | 
|  | 4712 | struct dchannel	*dch; | 
|  | 4713 | struct bchannel	*bch; | 
|  | 4714 | int		ch, i, ret = 0; | 
|  | 4715 | char		name[MISDN_MAX_IDLEN]; | 
|  | 4716 |  | 
|  | 4717 | dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL); | 
|  | 4718 | if (!dch) | 
|  | 4719 | return -ENOMEM; | 
|  | 4720 | dch->debug = debug; | 
|  | 4721 | mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, ph_state_change); | 
|  | 4722 | dch->hw = hc; | 
|  | 4723 | dch->dev.Dprotocols = (1 << ISDN_P_TE_S0) | (1 << ISDN_P_NT_S0); | 
|  | 4724 | dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | | 
|  | 4725 | (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); | 
|  | 4726 | dch->dev.D.send = handle_dmsg; | 
|  | 4727 | dch->dev.D.ctrl = hfcm_dctrl; | 
|  | 4728 | dch->dev.nrbchan = 2; | 
|  | 4729 | i = pt << 2; | 
|  | 4730 | dch->slot = i + 2; | 
|  | 4731 | hc->chan[i + 2].dch = dch; | 
|  | 4732 | hc->chan[i + 2].port = pt; | 
|  | 4733 | hc->chan[i + 2].nt_timer = -1; | 
|  | 4734 | for (ch = 0; ch < dch->dev.nrbchan; ch++) { | 
|  | 4735 | bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL); | 
|  | 4736 | if (!bch) { | 
|  | 4737 | printk(KERN_ERR "%s: no memory for bchannel\n", | 
|  | 4738 | __func__); | 
|  | 4739 | ret = -ENOMEM; | 
|  | 4740 | goto free_chan; | 
|  | 4741 | } | 
|  | 4742 | hc->chan[i + ch].coeff = kzalloc(512, GFP_KERNEL); | 
|  | 4743 | if (!hc->chan[i + ch].coeff) { | 
|  | 4744 | printk(KERN_ERR "%s: no memory for coeffs\n", | 
|  | 4745 | __func__); | 
|  | 4746 | ret = -ENOMEM; | 
|  | 4747 | goto free_chan; | 
|  | 4748 | } | 
|  | 4749 | bch->nr = ch + 1; | 
|  | 4750 | bch->slot = i + ch; | 
|  | 4751 | bch->debug = debug; | 
|  | 4752 | mISDN_initbchannel(bch, MAX_DATA_MEM); | 
|  | 4753 | bch->hw = hc; | 
|  | 4754 | bch->ch.send = handle_bmsg; | 
|  | 4755 | bch->ch.ctrl = hfcm_bctrl; | 
|  | 4756 | bch->ch.nr = ch + 1; | 
|  | 4757 | list_add(&bch->ch.list, &dch->dev.bchannels); | 
|  | 4758 | hc->chan[i + ch].bch = bch; | 
|  | 4759 | hc->chan[i + ch].port = pt; | 
| Karsten Keil | ff4cc1d | 2008-07-30 18:26:58 +0200 | [diff] [blame] | 4760 | set_channelmap(bch->nr, dch->dev.channelmap); | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 4761 | } | 
|  | 4762 | /* set master clock */ | 
|  | 4763 | if (port[Port_cnt] & 0x001) { | 
|  | 4764 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4765 | printk(KERN_DEBUG | 
|  | 4766 | "%s: PROTOCOL set master clock: " | 
|  | 4767 | "card(%d) port(%d)\n", | 
|  | 4768 | __func__, HFC_cnt + 1, pt + 1); | 
|  | 4769 | if (dch->dev.D.protocol != ISDN_P_TE_S0) { | 
|  | 4770 | printk(KERN_ERR "Error: Master clock " | 
|  | 4771 | "for port(%d) of card(%d) is only" | 
|  | 4772 | " possible with TE-mode\n", | 
|  | 4773 | pt + 1, HFC_cnt + 1); | 
|  | 4774 | ret = -EINVAL; | 
|  | 4775 | goto free_chan; | 
|  | 4776 | } | 
|  | 4777 | if (hc->masterclk >= 0) { | 
|  | 4778 | printk(KERN_ERR "Error: Master clock " | 
|  | 4779 | "for port(%d) of card(%d) already " | 
|  | 4780 | "defined for port(%d)\n", | 
|  | 4781 | pt + 1, HFC_cnt + 1, hc->masterclk+1); | 
|  | 4782 | ret = -EINVAL; | 
|  | 4783 | goto free_chan; | 
|  | 4784 | } | 
|  | 4785 | hc->masterclk = pt; | 
|  | 4786 | } | 
|  | 4787 | /* set transmitter line to non capacitive */ | 
|  | 4788 | if (port[Port_cnt] & 0x002) { | 
|  | 4789 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4790 | printk(KERN_DEBUG | 
|  | 4791 | "%s: PROTOCOL set non capacitive " | 
|  | 4792 | "transmitter: card(%d) port(%d)\n", | 
|  | 4793 | __func__, HFC_cnt + 1, pt + 1); | 
|  | 4794 | test_and_set_bit(HFC_CFG_NONCAP_TX, | 
|  | 4795 | &hc->chan[i + 2].cfg); | 
|  | 4796 | } | 
|  | 4797 | /* disable E-channel */ | 
|  | 4798 | if (port[Port_cnt] & 0x004) { | 
|  | 4799 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4800 | printk(KERN_DEBUG | 
|  | 4801 | "%s: PROTOCOL disable E-channel: " | 
|  | 4802 | "card(%d) port(%d)\n", | 
|  | 4803 | __func__, HFC_cnt + 1, pt + 1); | 
|  | 4804 | test_and_set_bit(HFC_CFG_DIS_ECHANNEL, | 
|  | 4805 | &hc->chan[i + 2].cfg); | 
|  | 4806 | } | 
|  | 4807 | snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d/%d", | 
|  | 4808 | hc->type, HFC_cnt + 1, pt + 1); | 
|  | 4809 | ret = mISDN_register_device(&dch->dev, name); | 
|  | 4810 | if (ret) | 
|  | 4811 | goto free_chan; | 
|  | 4812 | hc->created[pt] = 1; | 
|  | 4813 | return ret; | 
|  | 4814 | free_chan: | 
|  | 4815 | release_port(hc, dch); | 
|  | 4816 | return ret; | 
|  | 4817 | } | 
|  | 4818 |  | 
|  | 4819 | static int | 
|  | 4820 | hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent) | 
|  | 4821 | { | 
|  | 4822 | struct hm_map	*m = (struct hm_map *)ent->driver_data; | 
|  | 4823 | int		ret_err = 0; | 
|  | 4824 | int		pt; | 
|  | 4825 | struct hfc_multi	*hc; | 
|  | 4826 | u_long		flags; | 
|  | 4827 | u_char		dips = 0, pmj = 0; /* dip settings, port mode Jumpers */ | 
|  | 4828 |  | 
|  | 4829 | if (HFC_cnt >= MAX_CARDS) { | 
|  | 4830 | printk(KERN_ERR "too many cards (max=%d).\n", | 
|  | 4831 | MAX_CARDS); | 
|  | 4832 | return -EINVAL; | 
|  | 4833 | } | 
|  | 4834 | if ((type[HFC_cnt] & 0xff) && (type[HFC_cnt] & 0xff) != m->type) { | 
|  | 4835 | printk(KERN_WARNING "HFC-MULTI: Card '%s:%s' type %d found but " | 
|  | 4836 | "type[%d] %d was supplied as module parameter\n", | 
|  | 4837 | m->vendor_name, m->card_name, m->type, HFC_cnt, | 
|  | 4838 | type[HFC_cnt] & 0xff); | 
|  | 4839 | printk(KERN_WARNING "HFC-MULTI: Load module without parameters " | 
|  | 4840 | "first, to see cards and their types."); | 
|  | 4841 | return -EINVAL; | 
|  | 4842 | } | 
|  | 4843 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4844 | printk(KERN_DEBUG "%s: Registering %s:%s chip type %d (0x%x)\n", | 
|  | 4845 | __func__, m->vendor_name, m->card_name, m->type, | 
|  | 4846 | type[HFC_cnt]); | 
|  | 4847 |  | 
|  | 4848 | /* allocate card+fifo structure */ | 
|  | 4849 | hc = kzalloc(sizeof(struct hfc_multi), GFP_KERNEL); | 
|  | 4850 | if (!hc) { | 
|  | 4851 | printk(KERN_ERR "No kmem for HFC-Multi card\n"); | 
|  | 4852 | return -ENOMEM; | 
|  | 4853 | } | 
|  | 4854 | spin_lock_init(&hc->lock); | 
|  | 4855 | hc->mtyp = m; | 
|  | 4856 | hc->type =  m->type; | 
|  | 4857 | hc->ports = m->ports; | 
|  | 4858 | hc->id = HFC_cnt; | 
|  | 4859 | hc->pcm = pcm[HFC_cnt]; | 
|  | 4860 | hc->io_mode = iomode[HFC_cnt]; | 
|  | 4861 | if (dslot[HFC_cnt] < 0) { | 
|  | 4862 | hc->dslot = 0; | 
|  | 4863 | printk(KERN_INFO "HFC-E1 card has disabled D-channel, but " | 
|  | 4864 | "31 B-channels\n"); | 
|  | 4865 | } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32) { | 
|  | 4866 | hc->dslot = dslot[HFC_cnt]; | 
|  | 4867 | printk(KERN_INFO "HFC-E1 card has alternating D-channel on " | 
|  | 4868 | "time slot %d\n", dslot[HFC_cnt]); | 
|  | 4869 | } else | 
|  | 4870 | hc->dslot = 16; | 
|  | 4871 |  | 
|  | 4872 | /* set chip specific features */ | 
|  | 4873 | hc->masterclk = -1; | 
|  | 4874 | if (type[HFC_cnt] & 0x100) { | 
|  | 4875 | test_and_set_bit(HFC_CHIP_ULAW, &hc->chip); | 
|  | 4876 | silence = 0xff; /* ulaw silence */ | 
|  | 4877 | } else | 
|  | 4878 | silence = 0x2a; /* alaw silence */ | 
|  | 4879 | if (!(type[HFC_cnt] & 0x200)) | 
|  | 4880 | test_and_set_bit(HFC_CHIP_DTMF, &hc->chip); | 
|  | 4881 |  | 
|  | 4882 | if (type[HFC_cnt] & 0x800) | 
|  | 4883 | test_and_set_bit(HFC_CHIP_PCM_SLAVE, &hc->chip); | 
|  | 4884 | if (type[HFC_cnt] & 0x1000) { | 
|  | 4885 | test_and_set_bit(HFC_CHIP_PCM_MASTER, &hc->chip); | 
|  | 4886 | test_and_clear_bit(HFC_CHIP_PCM_SLAVE, &hc->chip); | 
|  | 4887 | } | 
|  | 4888 | if (type[HFC_cnt] & 0x4000) | 
|  | 4889 | test_and_set_bit(HFC_CHIP_EXRAM_128, &hc->chip); | 
|  | 4890 | if (type[HFC_cnt] & 0x8000) | 
|  | 4891 | test_and_set_bit(HFC_CHIP_EXRAM_512, &hc->chip); | 
|  | 4892 | hc->slots = 32; | 
|  | 4893 | if (type[HFC_cnt] & 0x10000) | 
|  | 4894 | hc->slots = 64; | 
|  | 4895 | if (type[HFC_cnt] & 0x20000) | 
|  | 4896 | hc->slots = 128; | 
|  | 4897 | if (type[HFC_cnt] & 0x80000) { | 
|  | 4898 | test_and_set_bit(HFC_CHIP_WATCHDOG, &hc->chip); | 
|  | 4899 | hc->wdcount = 0; | 
|  | 4900 | hc->wdbyte = V_GPIO_OUT2; | 
|  | 4901 | printk(KERN_NOTICE "Watchdog enabled\n"); | 
|  | 4902 | } | 
|  | 4903 |  | 
|  | 4904 | /* setup pci, hc->slots may change due to PLXSD */ | 
|  | 4905 | ret_err = setup_pci(hc, pdev, ent); | 
|  | 4906 | if (ret_err) { | 
|  | 4907 | if (hc == syncmaster) | 
|  | 4908 | syncmaster = NULL; | 
|  | 4909 | kfree(hc); | 
|  | 4910 | return ret_err; | 
|  | 4911 | } | 
|  | 4912 |  | 
|  | 4913 | /* crate channels */ | 
|  | 4914 | for (pt = 0; pt < hc->ports; pt++) { | 
|  | 4915 | if (Port_cnt >= MAX_PORTS) { | 
|  | 4916 | printk(KERN_ERR "too many ports (max=%d).\n", | 
|  | 4917 | MAX_PORTS); | 
|  | 4918 | ret_err = -EINVAL; | 
|  | 4919 | goto free_card; | 
|  | 4920 | } | 
|  | 4921 | if (hc->type == 1) | 
|  | 4922 | ret_err = init_e1_port(hc, m); | 
|  | 4923 | else | 
|  | 4924 | ret_err = init_multi_port(hc, pt); | 
|  | 4925 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 4926 | printk(KERN_DEBUG | 
|  | 4927 | "%s: Registering D-channel, card(%d) port(%d)" | 
|  | 4928 | "result %d\n", | 
|  | 4929 | __func__, HFC_cnt + 1, pt, ret_err); | 
|  | 4930 |  | 
|  | 4931 | if (ret_err) { | 
|  | 4932 | while (pt) { /* release already registered ports */ | 
|  | 4933 | pt--; | 
|  | 4934 | release_port(hc, hc->chan[(pt << 2) + 2].dch); | 
|  | 4935 | } | 
|  | 4936 | goto free_card; | 
|  | 4937 | } | 
|  | 4938 | Port_cnt++; | 
|  | 4939 | } | 
|  | 4940 |  | 
|  | 4941 | /* disp switches */ | 
|  | 4942 | switch (m->dip_type) { | 
|  | 4943 | case DIP_4S: | 
|  | 4944 | /* | 
|  | 4945 | * get DIP Setting for beroNet 1S/2S/4S cards | 
|  | 4946 | *  check if Port Jumper config matches | 
|  | 4947 | * module param 'protocol' | 
|  | 4948 | * DIP Setting: (collect GPIO 13/14/15 (R_GPIO_IN1) + | 
|  | 4949 | * GPI 19/23 (R_GPI_IN2)) | 
|  | 4950 | */ | 
|  | 4951 | dips = ((~HFC_inb(hc, R_GPIO_IN1) & 0xE0) >> 5) | | 
|  | 4952 | ((~HFC_inb(hc, R_GPI_IN2) & 0x80) >> 3) | | 
|  | 4953 | (~HFC_inb(hc, R_GPI_IN2) & 0x08); | 
|  | 4954 |  | 
|  | 4955 | /* Port mode (TE/NT) jumpers */ | 
|  | 4956 | pmj = ((HFC_inb(hc, R_GPI_IN3) >> 4)  & 0xf); | 
|  | 4957 |  | 
|  | 4958 | if (test_bit(HFC_CHIP_B410P, &hc->chip)) | 
|  | 4959 | pmj = ~pmj & 0xf; | 
|  | 4960 |  | 
|  | 4961 | printk(KERN_INFO "%s: %s DIPs(0x%x) jumpers(0x%x)\n", | 
|  | 4962 | m->vendor_name, m->card_name, dips, pmj); | 
|  | 4963 | break; | 
|  | 4964 | case DIP_8S: | 
|  | 4965 | /* | 
|  | 4966 | * get DIP Setting for beroNet 8S0+ cards | 
|  | 4967 | * | 
|  | 4968 | * enable PCI auxbridge function | 
|  | 4969 | */ | 
|  | 4970 | HFC_outb(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK); | 
|  | 4971 | /* prepare access to auxport */ | 
|  | 4972 | outw(0x4000, hc->pci_iobase + 4); | 
|  | 4973 | /* | 
|  | 4974 | * some dummy reads are required to | 
|  | 4975 | * read valid DIP switch data | 
|  | 4976 | */ | 
|  | 4977 | dips = inb(hc->pci_iobase); | 
|  | 4978 | dips = inb(hc->pci_iobase); | 
|  | 4979 | dips = inb(hc->pci_iobase); | 
|  | 4980 | dips = ~inb(hc->pci_iobase) & 0x3F; | 
|  | 4981 | outw(0x0, hc->pci_iobase + 4); | 
|  | 4982 | /* disable PCI auxbridge function */ | 
|  | 4983 | HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK); | 
|  | 4984 | printk(KERN_INFO "%s: %s DIPs(0x%x)\n", | 
|  | 4985 | m->vendor_name, m->card_name, dips); | 
|  | 4986 | break; | 
|  | 4987 | case DIP_E1: | 
|  | 4988 | /* | 
|  | 4989 | * get DIP Setting for beroNet E1 cards | 
|  | 4990 | * DIP Setting: collect GPI 4/5/6/7 (R_GPI_IN0) | 
|  | 4991 | */ | 
|  | 4992 | dips = (~HFC_inb(hc, R_GPI_IN0) & 0xF0)>>4; | 
|  | 4993 | printk(KERN_INFO "%s: %s DIPs(0x%x)\n", | 
|  | 4994 | m->vendor_name, m->card_name, dips); | 
|  | 4995 | break; | 
|  | 4996 | } | 
|  | 4997 |  | 
|  | 4998 | /* add to list */ | 
|  | 4999 | spin_lock_irqsave(&HFClock, flags); | 
|  | 5000 | list_add_tail(&hc->list, &HFClist); | 
|  | 5001 | spin_unlock_irqrestore(&HFClock, flags); | 
|  | 5002 |  | 
|  | 5003 | /* initialize hardware */ | 
|  | 5004 | ret_err = init_card(hc); | 
|  | 5005 | if (ret_err) { | 
|  | 5006 | printk(KERN_ERR "init card returns %d\n", ret_err); | 
|  | 5007 | release_card(hc); | 
|  | 5008 | return ret_err; | 
|  | 5009 | } | 
|  | 5010 |  | 
|  | 5011 | /* start IRQ and return */ | 
|  | 5012 | spin_lock_irqsave(&hc->lock, flags); | 
|  | 5013 | enable_hwirq(hc); | 
|  | 5014 | spin_unlock_irqrestore(&hc->lock, flags); | 
|  | 5015 | return 0; | 
|  | 5016 |  | 
|  | 5017 | free_card: | 
|  | 5018 | release_io_hfcmulti(hc); | 
|  | 5019 | if (hc == syncmaster) | 
|  | 5020 | syncmaster = NULL; | 
|  | 5021 | kfree(hc); | 
|  | 5022 | return ret_err; | 
|  | 5023 | } | 
|  | 5024 |  | 
|  | 5025 | static void __devexit hfc_remove_pci(struct pci_dev *pdev) | 
|  | 5026 | { | 
|  | 5027 | struct hfc_multi	*card = pci_get_drvdata(pdev); | 
|  | 5028 | u_long			flags; | 
|  | 5029 |  | 
|  | 5030 | if (debug) | 
|  | 5031 | printk(KERN_INFO "removing hfc_multi card vendor:%x " | 
|  | 5032 | "device:%x subvendor:%x subdevice:%x\n", | 
|  | 5033 | pdev->vendor, pdev->device, | 
|  | 5034 | pdev->subsystem_vendor, pdev->subsystem_device); | 
|  | 5035 |  | 
|  | 5036 | if (card) { | 
|  | 5037 | spin_lock_irqsave(&HFClock, flags); | 
|  | 5038 | release_card(card); | 
|  | 5039 | spin_unlock_irqrestore(&HFClock, flags); | 
|  | 5040 | }  else { | 
|  | 5041 | if (debug) | 
|  | 5042 | printk(KERN_WARNING "%s: drvdata allready removed\n", | 
|  | 5043 | __func__); | 
|  | 5044 | } | 
|  | 5045 | } | 
|  | 5046 |  | 
|  | 5047 | #define	VENDOR_CCD	"Cologne Chip AG" | 
|  | 5048 | #define	VENDOR_BN	"beroNet GmbH" | 
|  | 5049 | #define	VENDOR_DIG	"Digium Inc." | 
|  | 5050 | #define VENDOR_JH	"Junghanns.NET GmbH" | 
|  | 5051 | #define VENDOR_PRIM	"PrimuX" | 
|  | 5052 |  | 
|  | 5053 | static const struct hm_map hfcm_map[] = { | 
|  | 5054 | /*0*/	{VENDOR_BN, "HFC-1S Card (mini PCI)", 4, 1, 1, 3, 0, DIP_4S, 0}, | 
| Karsten Keil | 31981db | 2008-08-02 16:40:37 +0200 | [diff] [blame] | 5055 | /*1*/	{VENDOR_BN, "HFC-2S Card", 4, 2, 1, 3, 0, DIP_4S, 0}, | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 5056 | /*2*/	{VENDOR_BN, "HFC-2S Card (mini PCI)", 4, 2, 1, 3, 0, DIP_4S, 0}, | 
|  | 5057 | /*3*/	{VENDOR_BN, "HFC-4S Card", 4, 4, 1, 2, 0, DIP_4S, 0}, | 
|  | 5058 | /*4*/	{VENDOR_BN, "HFC-4S Card (mini PCI)", 4, 4, 1, 2, 0, 0, 0}, | 
|  | 5059 | /*5*/	{VENDOR_CCD, "HFC-4S Eval (old)", 4, 4, 0, 0, 0, 0, 0}, | 
| Karsten Keil | 31981db | 2008-08-02 16:40:37 +0200 | [diff] [blame] | 5060 | /*6*/	{VENDOR_CCD, "HFC-4S IOB4ST", 4, 4, 1, 2, 0, DIP_4S, 0}, | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 5061 | /*7*/	{VENDOR_CCD, "HFC-4S", 4, 4, 1, 2, 0, 0, 0}, | 
|  | 5062 | /*8*/	{VENDOR_DIG, "HFC-4S Card", 4, 4, 0, 2, 0, 0, HFC_IO_MODE_REGIO}, | 
|  | 5063 | /*9*/	{VENDOR_CCD, "HFC-4S Swyx 4xS0 SX2 QuadBri", 4, 4, 1, 2, 0, 0, 0}, | 
|  | 5064 | /*10*/	{VENDOR_JH, "HFC-4S (junghanns 2.0)", 4, 4, 1, 2, 0, 0, 0}, | 
|  | 5065 | /*11*/	{VENDOR_PRIM, "HFC-2S Primux Card", 4, 2, 0, 0, 0, 0, 0}, | 
|  | 5066 |  | 
|  | 5067 | /*12*/	{VENDOR_BN, "HFC-8S Card", 8, 8, 1, 0, 0, 0, 0}, | 
|  | 5068 | /*13*/	{VENDOR_BN, "HFC-8S Card (+)", 8, 8, 1, 8, 0, DIP_8S, | 
|  | 5069 | HFC_IO_MODE_REGIO}, | 
|  | 5070 | /*14*/	{VENDOR_CCD, "HFC-8S Eval (old)", 8, 8, 0, 0, 0, 0, 0}, | 
|  | 5071 | /*15*/	{VENDOR_CCD, "HFC-8S IOB4ST Recording", 8, 8, 1, 0, 0, 0, 0}, | 
|  | 5072 |  | 
|  | 5073 | /*16*/	{VENDOR_CCD, "HFC-8S IOB8ST", 8, 8, 1, 0, 0, 0, 0}, | 
|  | 5074 | /*17*/	{VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0}, | 
|  | 5075 | /*18*/	{VENDOR_CCD, "HFC-8S", 8, 8, 1, 0, 0, 0, 0}, | 
|  | 5076 |  | 
|  | 5077 | /*19*/	{VENDOR_BN, "HFC-E1 Card", 1, 1, 0, 1, 0, DIP_E1, 0}, | 
|  | 5078 | /*20*/	{VENDOR_BN, "HFC-E1 Card (mini PCI)", 1, 1, 0, 1, 0, 0, 0}, | 
|  | 5079 | /*21*/	{VENDOR_BN, "HFC-E1+ Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0}, | 
|  | 5080 | /*22*/	{VENDOR_BN, "HFC-E1 Card (Dual)", 1, 1, 0, 1, 0, DIP_E1, 0}, | 
|  | 5081 |  | 
|  | 5082 | /*23*/	{VENDOR_CCD, "HFC-E1 Eval (old)", 1, 1, 0, 0, 0, 0, 0}, | 
|  | 5083 | /*24*/	{VENDOR_CCD, "HFC-E1 IOB1E1", 1, 1, 0, 1, 0, 0, 0}, | 
|  | 5084 | /*25*/	{VENDOR_CCD, "HFC-E1", 1, 1, 0, 1, 0, 0, 0}, | 
|  | 5085 |  | 
|  | 5086 | /*26*/	{VENDOR_CCD, "HFC-4S Speech Design", 4, 4, 0, 0, 0, 0, | 
|  | 5087 | HFC_IO_MODE_PLXSD}, | 
|  | 5088 | /*27*/	{VENDOR_CCD, "HFC-E1 Speech Design", 1, 1, 0, 0, 0, 0, | 
|  | 5089 | HFC_IO_MODE_PLXSD}, | 
|  | 5090 | /*28*/	{VENDOR_CCD, "HFC-4S OpenVox", 4, 4, 1, 0, 0, 0, 0}, | 
|  | 5091 | /*29*/	{VENDOR_CCD, "HFC-2S OpenVox", 4, 2, 1, 0, 0, 0, 0}, | 
|  | 5092 | /*30*/	{VENDOR_CCD, "HFC-8S OpenVox", 8, 8, 1, 0, 0, 0, 0}, | 
|  | 5093 | }; | 
|  | 5094 |  | 
|  | 5095 | #undef H | 
|  | 5096 | #define H(x)	((unsigned long)&hfcm_map[x]) | 
|  | 5097 | static struct pci_device_id hfmultipci_ids[] __devinitdata = { | 
|  | 5098 |  | 
|  | 5099 | /* Cards with HFC-4S Chip */ | 
|  | 5100 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5101 | PCI_SUBDEVICE_ID_CCD_BN1SM, 0, 0, H(0)}, /* BN1S mini PCI */ | 
|  | 5102 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5103 | PCI_SUBDEVICE_ID_CCD_BN2S, 0, 0, H(1)}, /* BN2S */ | 
|  | 5104 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5105 | PCI_SUBDEVICE_ID_CCD_BN2SM, 0, 0, H(2)}, /* BN2S mini PCI */ | 
|  | 5106 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5107 | PCI_SUBDEVICE_ID_CCD_BN4S, 0, 0, H(3)}, /* BN4S */ | 
|  | 5108 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5109 | PCI_SUBDEVICE_ID_CCD_BN4SM, 0, 0, H(4)}, /* BN4S mini PCI */ | 
|  | 5110 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5111 | PCI_DEVICE_ID_CCD_HFC4S, 0, 0, H(5)}, /* Old Eval */ | 
|  | 5112 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5113 | PCI_SUBDEVICE_ID_CCD_IOB4ST, 0, 0, H(6)}, /* IOB4ST */ | 
|  | 5114 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5115 | PCI_SUBDEVICE_ID_CCD_HFC4S, 0, 0, H(7)}, /* 4S */ | 
|  | 5116 | { PCI_VENDOR_ID_DIGIUM, PCI_DEVICE_ID_DIGIUM_HFC4S, | 
|  | 5117 | PCI_VENDOR_ID_DIGIUM, PCI_DEVICE_ID_DIGIUM_HFC4S, 0, 0, H(8)}, | 
|  | 5118 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5119 | PCI_SUBDEVICE_ID_CCD_SWYX4S, 0, 0, H(9)}, /* 4S Swyx */ | 
|  | 5120 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5121 | PCI_SUBDEVICE_ID_CCD_JH4S20, 0, 0, H(10)}, | 
|  | 5122 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5123 | PCI_SUBDEVICE_ID_CCD_PMX2S, 0, 0, H(11)}, /* Primux */ | 
|  | 5124 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5125 | PCI_SUBDEVICE_ID_CCD_OV4S, 0, 0, H(28)}, /* OpenVox 4 */ | 
|  | 5126 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 
|  | 5127 | PCI_SUBDEVICE_ID_CCD_OV2S, 0, 0, H(29)}, /* OpenVox 2 */ | 
|  | 5128 |  | 
|  | 5129 | /* Cards with HFC-8S Chip */ | 
|  | 5130 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 
|  | 5131 | PCI_SUBDEVICE_ID_CCD_BN8S, 0, 0, H(12)}, /* BN8S */ | 
|  | 5132 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 
|  | 5133 | PCI_SUBDEVICE_ID_CCD_BN8SP, 0, 0, H(13)}, /* BN8S+ */ | 
|  | 5134 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 
|  | 5135 | PCI_DEVICE_ID_CCD_HFC8S, 0, 0, H(14)}, /* old Eval */ | 
|  | 5136 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 
|  | 5137 | PCI_SUBDEVICE_ID_CCD_IOB8STR, 0, 0, H(15)}, | 
|  | 5138 | /* IOB8ST Recording */ | 
|  | 5139 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 
|  | 5140 | PCI_SUBDEVICE_ID_CCD_IOB8ST, 0, 0, H(16)}, /* IOB8ST  */ | 
|  | 5141 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 
|  | 5142 | PCI_SUBDEVICE_ID_CCD_IOB8ST_1, 0, 0, H(17)}, /* IOB8ST  */ | 
|  | 5143 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 
|  | 5144 | PCI_SUBDEVICE_ID_CCD_HFC8S, 0, 0, H(18)}, /* 8S */ | 
|  | 5145 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 
|  | 5146 | PCI_SUBDEVICE_ID_CCD_OV8S, 0, 0, H(30)}, /* OpenVox 8 */ | 
|  | 5147 |  | 
|  | 5148 |  | 
|  | 5149 | /* Cards with HFC-E1 Chip */ | 
|  | 5150 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD, | 
|  | 5151 | PCI_SUBDEVICE_ID_CCD_BNE1, 0, 0, H(19)}, /* BNE1 */ | 
|  | 5152 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD, | 
|  | 5153 | PCI_SUBDEVICE_ID_CCD_BNE1M, 0, 0, H(20)}, /* BNE1 mini PCI */ | 
|  | 5154 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD, | 
|  | 5155 | PCI_SUBDEVICE_ID_CCD_BNE1DP, 0, 0, H(21)}, /* BNE1 + (Dual) */ | 
|  | 5156 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD, | 
|  | 5157 | PCI_SUBDEVICE_ID_CCD_BNE1D, 0, 0, H(22)}, /* BNE1 (Dual) */ | 
|  | 5158 |  | 
|  | 5159 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD, | 
|  | 5160 | PCI_DEVICE_ID_CCD_HFCE1, 0, 0, H(23)}, /* Old Eval */ | 
|  | 5161 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD, | 
|  | 5162 | PCI_SUBDEVICE_ID_CCD_IOB1E1, 0, 0, H(24)}, /* IOB1E1 */ | 
|  | 5163 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_VENDOR_ID_CCD, | 
|  | 5164 | PCI_SUBDEVICE_ID_CCD_HFCE1, 0, 0, H(25)}, /* E1 */ | 
|  | 5165 |  | 
|  | 5166 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_CCD, | 
|  | 5167 | PCI_SUBDEVICE_ID_CCD_SPD4S, 0, 0, H(26)}, /* PLX PCI Bridge */ | 
|  | 5168 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_CCD, | 
|  | 5169 | PCI_SUBDEVICE_ID_CCD_SPDE1, 0, 0, H(27)}, /* PLX PCI Bridge */ | 
|  | 5170 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_ANY_ID, PCI_ANY_ID, | 
|  | 5171 | 0, 0, 0}, | 
|  | 5172 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_ANY_ID, PCI_ANY_ID, | 
|  | 5173 | 0, 0, 0}, | 
|  | 5174 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFCE1, PCI_ANY_ID, PCI_ANY_ID, | 
|  | 5175 | 0, 0, 0}, | 
|  | 5176 | {0, } | 
|  | 5177 | }; | 
|  | 5178 | #undef H | 
|  | 5179 |  | 
|  | 5180 | MODULE_DEVICE_TABLE(pci, hfmultipci_ids); | 
|  | 5181 |  | 
|  | 5182 | static int | 
|  | 5183 | hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 
|  | 5184 | { | 
|  | 5185 | struct hm_map	*m = (struct hm_map *)ent->driver_data; | 
|  | 5186 | int		ret; | 
|  | 5187 |  | 
|  | 5188 | if (m == NULL) { | 
|  | 5189 | if (ent->vendor == PCI_VENDOR_ID_CCD) | 
|  | 5190 | if (ent->device == PCI_DEVICE_ID_CCD_HFC4S || | 
|  | 5191 | ent->device == PCI_DEVICE_ID_CCD_HFC8S || | 
|  | 5192 | ent->device == PCI_DEVICE_ID_CCD_HFCE1) | 
|  | 5193 | printk(KERN_ERR | 
|  | 5194 | "unknown HFC multiport controller " | 
|  | 5195 | "(vendor:%x device:%x subvendor:%x " | 
|  | 5196 | "subdevice:%x) Please contact the " | 
|  | 5197 | "driver maintainer for support.\n", | 
|  | 5198 | ent->vendor, ent->device, | 
|  | 5199 | ent->subvendor, ent->subdevice); | 
|  | 5200 | return -ENODEV; | 
|  | 5201 | } | 
|  | 5202 | ret = hfcmulti_init(pdev, ent); | 
|  | 5203 | if (ret) | 
|  | 5204 | return ret; | 
|  | 5205 | HFC_cnt++; | 
|  | 5206 | printk(KERN_INFO "%d devices registered\n", HFC_cnt); | 
|  | 5207 | return 0; | 
|  | 5208 | } | 
|  | 5209 |  | 
|  | 5210 | static struct pci_driver hfcmultipci_driver = { | 
|  | 5211 | .name		= "hfc_multi", | 
|  | 5212 | .probe		= hfcmulti_probe, | 
|  | 5213 | .remove		= __devexit_p(hfc_remove_pci), | 
|  | 5214 | .id_table	= hfmultipci_ids, | 
|  | 5215 | }; | 
|  | 5216 |  | 
|  | 5217 | static void __exit | 
|  | 5218 | HFCmulti_cleanup(void) | 
|  | 5219 | { | 
|  | 5220 | struct hfc_multi *card, *next; | 
|  | 5221 |  | 
|  | 5222 | /* unload interrupt function symbol */ | 
|  | 5223 | if (hfc_interrupt) | 
|  | 5224 | symbol_put(ztdummy_extern_interrupt); | 
|  | 5225 | if (register_interrupt) | 
|  | 5226 | symbol_put(ztdummy_register_interrupt); | 
|  | 5227 | if (unregister_interrupt) { | 
|  | 5228 | if (interrupt_registered) { | 
|  | 5229 | interrupt_registered = 0; | 
|  | 5230 | unregister_interrupt(); | 
|  | 5231 | } | 
|  | 5232 | symbol_put(ztdummy_unregister_interrupt); | 
|  | 5233 | } | 
|  | 5234 |  | 
|  | 5235 | list_for_each_entry_safe(card, next, &HFClist, list) | 
|  | 5236 | release_card(card); | 
|  | 5237 | /* get rid of all devices of this driver */ | 
|  | 5238 | pci_unregister_driver(&hfcmultipci_driver); | 
|  | 5239 | } | 
|  | 5240 |  | 
|  | 5241 | static int __init | 
|  | 5242 | HFCmulti_init(void) | 
|  | 5243 | { | 
|  | 5244 | int err; | 
|  | 5245 |  | 
|  | 5246 | #ifdef IRQ_DEBUG | 
|  | 5247 | printk(KERN_ERR "%s: IRQ_DEBUG IS ENABLED!\n", __func__); | 
|  | 5248 | #endif | 
|  | 5249 |  | 
|  | 5250 | spin_lock_init(&HFClock); | 
|  | 5251 | spin_lock_init(&plx_lock); | 
|  | 5252 |  | 
|  | 5253 | if (debug & DEBUG_HFCMULTI_INIT) | 
|  | 5254 | printk(KERN_DEBUG "%s: init entered\n", __func__); | 
|  | 5255 |  | 
| Karsten Keil | af69fb3 | 2008-07-27 02:00:43 +0200 | [diff] [blame] | 5256 | hfc_interrupt = symbol_get(ztdummy_extern_interrupt); | 
|  | 5257 | register_interrupt = symbol_get(ztdummy_register_interrupt); | 
|  | 5258 | unregister_interrupt = symbol_get(ztdummy_unregister_interrupt); | 
|  | 5259 | printk(KERN_INFO "mISDN: HFC-multi driver %s\n", | 
|  | 5260 | hfcmulti_revision); | 
|  | 5261 |  | 
|  | 5262 | switch (poll) { | 
|  | 5263 | case 0: | 
|  | 5264 | poll_timer = 6; | 
|  | 5265 | poll = 128; | 
|  | 5266 | break; | 
|  | 5267 | /* | 
|  | 5268 | * wenn dieses break nochmal verschwindet, | 
|  | 5269 | * gibt es heisse ohren :-) | 
|  | 5270 | * "without the break you will get hot ears ???" | 
|  | 5271 | */ | 
|  | 5272 | case 8: | 
|  | 5273 | poll_timer = 2; | 
|  | 5274 | break; | 
|  | 5275 | case 16: | 
|  | 5276 | poll_timer = 3; | 
|  | 5277 | break; | 
|  | 5278 | case 32: | 
|  | 5279 | poll_timer = 4; | 
|  | 5280 | break; | 
|  | 5281 | case 64: | 
|  | 5282 | poll_timer = 5; | 
|  | 5283 | break; | 
|  | 5284 | case 128: | 
|  | 5285 | poll_timer = 6; | 
|  | 5286 | break; | 
|  | 5287 | case 256: | 
|  | 5288 | poll_timer = 7; | 
|  | 5289 | break; | 
|  | 5290 | default: | 
|  | 5291 | printk(KERN_ERR | 
|  | 5292 | "%s: Wrong poll value (%d).\n", __func__, poll); | 
|  | 5293 | err = -EINVAL; | 
|  | 5294 | return err; | 
|  | 5295 |  | 
|  | 5296 | } | 
|  | 5297 |  | 
|  | 5298 | err = pci_register_driver(&hfcmultipci_driver); | 
|  | 5299 | if (err < 0) { | 
|  | 5300 | printk(KERN_ERR "error registering pci driver: %x\n", err); | 
|  | 5301 | if (hfc_interrupt) | 
|  | 5302 | symbol_put(ztdummy_extern_interrupt); | 
|  | 5303 | if (register_interrupt) | 
|  | 5304 | symbol_put(ztdummy_register_interrupt); | 
|  | 5305 | if (unregister_interrupt) { | 
|  | 5306 | if (interrupt_registered) { | 
|  | 5307 | interrupt_registered = 0; | 
|  | 5308 | unregister_interrupt(); | 
|  | 5309 | } | 
|  | 5310 | symbol_put(ztdummy_unregister_interrupt); | 
|  | 5311 | } | 
|  | 5312 | return err; | 
|  | 5313 | } | 
|  | 5314 | return 0; | 
|  | 5315 | } | 
|  | 5316 |  | 
|  | 5317 |  | 
|  | 5318 | module_init(HFCmulti_init); | 
|  | 5319 | module_exit(HFCmulti_cleanup); |