]>
Commit | Line | Data |
---|---|---|
6f7365e2 JR |
1 | --- linux/drivers/net/wan/Kconfig 2008-01-24 23:58:37.000000000 +0100 |
2 | +++ linux/drivers/net/wan/Kconfig 2008-01-30 14:04:26.000000000 +0100 | |
3 | @@ -167,6 +167,21 @@ | |
4 | comment "X.25/LAPB support is disabled" | |
5 | depends on HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y | |
6 | ||
7 | +config TAHOE9XX | |
8 | + tristate "Tahoe 9xx support" | |
9 | + depends on HDLC && PCI | |
10 | + help | |
11 | + This driver is for Tahoe 931/932/971/972 cards | |
12 | + If you have such a card, say Y or M here and see | |
13 | + <http://www.tahoe.pl/> | |
14 | + | |
15 | + If you want to compile the driver as a module ( = code which can be | |
16 | + inserted in and removed from the running kernel whenever you want), | |
17 | + say M here and read <file:Documentation/modules.txt>. The module | |
18 | + will be called tahoe9xx.o. | |
19 | + | |
20 | + If unsure, say N here. | |
21 | + | |
22 | config PCI200SYN | |
23 | tristate "Goramo PCI200SYN support" | |
24 | depends on HDLC && PCI | |
25 | --- linux/drivers/net/wan/Makefile 2008-01-24 23:58:37.000000000 +0100 | |
26 | +++ linux/drivers/net/wan/Makefile 2008-01-30 14:04:26.000000000 +0100 | |
27 | @@ -39,6 +39,7 @@ | |
28 | obj-$(CONFIG_PC300) += pc300.o | |
29 | obj-$(CONFIG_N2) += n2.o | |
30 | obj-$(CONFIG_C101) += c101.o | |
31 | +obj-$(CONFIG_TAHOE9XX) += tahoe9xx.o | |
32 | obj-$(CONFIG_WANXL) += wanxl.o | |
33 | obj-$(CONFIG_PCI200SYN) += pci200syn.o | |
34 | obj-$(CONFIG_PC300TOO) += pc300too.o | |
35 | --- linux/drivers/net/wan/tahoe9xx.c 1970-01-01 01:00:00.000000000 +0100 | |
36 | +++ linux/drivers/net/wan/tahoe9xx.c 2008-01-30 14:27:09.000000000 +0100 | |
37 | @@ -0,0 +1,824 @@ | |
38 | +/* | |
39 | + * Tahoe 9xx synchronous serial card driver for Linux | |
40 | + * | |
41 | + * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl> | |
42 | + * Copyright (C) 2003 Piotr Kaczmarzyk <piotr@tahoe.pl> | |
43 | + * | |
44 | + * This program is free software; you can redistribute it and/or modify it | |
45 | + * under the terms of version 2 of the GNU General Public License | |
46 | + * as published by the Free Software Foundation. | |
47 | + * | |
48 | + * For information see http://hq.pm.waw.pl/hdlc/ | |
49 | + * | |
50 | + * Sources of information: | |
51 | + * Hitachi HD64570 SCA User's Manual | |
52 | + * PLX Technology Inc. PCI9052 Data Book | |
53 | + * Dallas Semiconductor DS21554 Datasheet | |
54 | + */ | |
55 | + | |
56 | +#include <linux/module.h> | |
57 | +#include <linux/kernel.h> | |
58 | +#include <linux/slab.h> | |
59 | +#include <linux/sched.h> | |
60 | +#include <linux/types.h> | |
61 | +#include <linux/fcntl.h> | |
62 | +#include <linux/in.h> | |
63 | +#include <linux/string.h> | |
64 | +#include <linux/errno.h> | |
65 | +#include <linux/init.h> | |
66 | +#include <linux/ioport.h> | |
67 | +#include <linux/moduleparam.h> | |
68 | +#include <linux/netdevice.h> | |
69 | +#include <linux/hdlc.h> | |
70 | +#include <linux/pci.h> | |
71 | +#include <asm/delay.h> | |
72 | +#include <asm/io.h> | |
73 | + | |
74 | +#include "hd64570.h" | |
75 | + | |
76 | +static const char* version = "Tahoe 9xx driver version: 1.16t"; | |
77 | +static const char* devname = "TAHOE9XX"; | |
78 | + | |
79 | +#define TAHOE9XX_PLX_SIZE 0x80 /* PLX control window size (128b) */ | |
80 | +#define TAHOE9XX_SCA_SIZE 0x100 /* SCA window size (256b) */ | |
81 | +#define ALL_PAGES_ALWAYS_MAPPED | |
82 | +#define NEED_DETECT_RAM | |
83 | +#define NEED_SCA_MSCI_INTR | |
84 | +#define MAX_TX_BUFFERS 10 | |
85 | + | |
86 | +#define CLOCK_BASE 9216000 | |
87 | + | |
88 | +#define G703_AMI 0 | |
89 | +#define G703_HDB3 1 | |
90 | + | |
91 | +#define DEFAULT_LICR 0x80 | |
92 | + | |
93 | +#define PCI_VENDOR_ID_TAHOE 0x8246 | |
94 | +#define PCI_DEVICE_ID_TAHOE931 0x0931 | |
95 | +#define PCI_DEVICE_ID_TAHOE932 0x0932 | |
96 | +#define PCI_DEVICE_ID_TAHOE971 0x0971 | |
97 | +#define PCI_DEVICE_ID_TAHOE972 0x0972 | |
98 | + | |
99 | +/* | |
100 | + * PLX PCI9052 local configuration and shared runtime registers. | |
101 | + * This structure can be used to access 9052 registers (memory mapped). | |
102 | + */ | |
103 | +typedef struct { | |
104 | + u32 loc_addr_range[4]; /* 00-0Ch : Local Address Ranges */ | |
105 | + u32 loc_rom_range; /* 10h : Local ROM Range */ | |
106 | + u32 loc_addr_base[4]; /* 14-20h : Local Address Base Addrs */ | |
107 | + u32 loc_rom_base; /* 24h : Local ROM Base */ | |
108 | + u32 loc_bus_descr[4]; /* 28-34h : Local Bus Descriptors */ | |
109 | + u32 rom_bus_descr; /* 38h : ROM Bus Descriptor */ | |
110 | + u32 cs_base[4]; /* 3C-48h : Chip Select Base Addrs */ | |
111 | + u32 intr_ctrl_stat; /* 4Ch : Interrupt Control/Status */ | |
112 | + u32 init_ctrl; /* 50h : EEPROM ctrl, Init Ctrl, etc */ | |
113 | +}plx9052; | |
114 | + | |
115 | + | |
116 | + | |
117 | + | |
118 | + | |
119 | +typedef struct ds21554_s { | |
120 | + u8 vcr1; /* Counter: Violation Error */ | |
121 | + u8 vcr2; | |
122 | + u8 crccr1; /* Counter: CRC4 Error */ | |
123 | + u8 crccr2; | |
124 | + u8 ebcr1; /* Counter: E-bit Error (FEBE) */ | |
125 | + u8 ebcr2; | |
126 | + u8 sr1; /* Status: Status Register 1 */ | |
127 | + u8 sr2; /* Status: Status Register 2 */ | |
128 | + u8 rir; /* Status: Receive Information */ | |
129 | + u8 reserved1[6]; | |
130 | + u8 idr; /* Misc: Device Indentification */ | |
131 | + u8 rcr1; /* Control: Receive Control 1 */ | |
132 | + u8 rcr2; /* Control: Receive Control 2 */ | |
133 | + u8 tcr1; /* Control: Transmit Control 1 */ | |
134 | + u8 tcr2; /* Control: Transmit Control 2 */ | |
135 | + u8 ccr1; /* Control: Common Control 1 */ | |
136 | + u8 test1; | |
137 | + u8 imr1; /* Interrupt Mask 1 */ | |
138 | + u8 imr2; /* Interrupt Mask 2 */ | |
139 | + u8 licr; /* Control: Line interface */ | |
140 | + u8 test2; | |
141 | + u8 ccr2; /* Control: Common Control 2 */ | |
142 | + u8 ccr3; /* Control: Common Control 3 */ | |
143 | + u8 tsacr; /* Control: Transmit Sa bit */ | |
144 | + u8 ccr6; /* Control: Common Control 6 */ | |
145 | + u8 ssr; /* Status: Synchronizer Status */ | |
146 | + u8 rnaf; /* Receive non-align frame */ | |
147 | + u8 taf; /* Transmit align frame */ | |
148 | + u8 tnaf; /* Transmit non-align frame */ | |
149 | + u8 tcbr1; /* Transmit channel blocking */ | |
150 | + u8 tcbr2; | |
151 | + u8 tcbr3; | |
152 | + u8 tcbr4; | |
153 | + u8 tir1; /* Transmit idle */ | |
154 | + u8 tir2; | |
155 | + u8 tir3; | |
156 | + u8 tir4; | |
157 | + u8 tidr; /* Transmit idle definition */ | |
158 | + u8 rcbr1; /* Receive channel blocking */ | |
159 | + u8 rcbr2; | |
160 | + u8 rcbr3; | |
161 | + u8 rcbr4; | |
162 | + u8 raf; /* Receive align frame */ | |
163 | + u8 rs1; /* Receive signalling */ | |
164 | + u8 rs2; | |
165 | + u8 rs3; | |
166 | + u8 rs4; | |
167 | + u8 rs5; | |
168 | + u8 rs6; | |
169 | + u8 rs7; | |
170 | + u8 rs8; | |
171 | + u8 rs9; | |
172 | + u8 rs10; | |
173 | + u8 rs11; | |
174 | + u8 rs12; | |
175 | + u8 rs13; | |
176 | + u8 rs14; | |
177 | + u8 rs15; | |
178 | + u8 rs16; | |
179 | + u8 ts1; /* Transmit signaling */ | |
180 | + u8 ts2; | |
181 | + u8 ts3; | |
182 | + u8 ts4; | |
183 | + u8 ts5; | |
184 | + u8 ts6; | |
185 | + u8 ts7; | |
186 | + u8 ts8; | |
187 | + u8 ts9; | |
188 | + u8 ts10; | |
189 | + u8 ts11; | |
190 | + u8 ts12; | |
191 | + u8 ts13; | |
192 | + u8 ts14; | |
193 | + u8 ts15; | |
194 | + u8 ts16; | |
195 | + u8 tsiaf; /* Transmit Si Bits Align Frame */ | |
196 | + u8 tsinaf; /* Transmit Si Bits Non-align Frame */ | |
197 | + u8 tra; /* Transmit Remote Alarm Bits */ | |
198 | + u8 tsa4; /* Transmit Sa Bits */ | |
199 | + u8 tsa5; | |
200 | + u8 tsa6; | |
201 | + u8 tsa7; | |
202 | + u8 tsa8; | |
203 | + u8 rsiaf; /* Receive Si Bits Align Frame */ | |
204 | + u8 rsinaf; /* Receive Si Bits Non-Align Frame */ | |
205 | + u8 rra; /* Receive Remote Alarm Bits */ | |
206 | + u8 rsa4; /* Receive Sa Bits */ | |
207 | + u8 rsa5; | |
208 | + u8 rsa6; | |
209 | + u8 rsa7; | |
210 | + u8 rsa8; | |
211 | + u8 tc1; /* Transmit channel */ | |
212 | + u8 tc2; | |
213 | + u8 tc3; | |
214 | + u8 tc4; | |
215 | + u8 tc5; | |
216 | + u8 tc6; | |
217 | + u8 tc7; | |
218 | + u8 tc8; | |
219 | + u8 tc9; | |
220 | + u8 tc10; | |
221 | + u8 tc11; | |
222 | + u8 tc12; | |
223 | + u8 tc13; | |
224 | + u8 tc14; | |
225 | + u8 tc15; | |
226 | + u8 tc16; | |
227 | + u8 tc17; | |
228 | + u8 tc18; | |
229 | + u8 tc19; | |
230 | + u8 tc20; | |
231 | + u8 tc21; | |
232 | + u8 tc22; | |
233 | + u8 tc23; | |
234 | + u8 tc24; | |
235 | + u8 tc25; | |
236 | + u8 tc26; | |
237 | + u8 tc27; | |
238 | + u8 tc28; | |
239 | + u8 tc29; | |
240 | + u8 tc30; | |
241 | + u8 tc31; | |
242 | + u8 tc32; | |
243 | + u8 rc1; /* Receive channel */ | |
244 | + u8 rc2; | |
245 | + u8 rc3; | |
246 | + u8 rc4; | |
247 | + u8 rc5; | |
248 | + u8 rc6; | |
249 | + u8 rc7; | |
250 | + u8 rc8; | |
251 | + u8 rc9; | |
252 | + u8 rc10; | |
253 | + u8 rc11; | |
254 | + u8 rc12; | |
255 | + u8 rc13; | |
256 | + u8 rc14; | |
257 | + u8 rc15; | |
258 | + u8 rc16; | |
259 | + u8 rc17; | |
260 | + u8 rc18; | |
261 | + u8 rc19; | |
262 | + u8 rc20; | |
263 | + u8 rc21; | |
264 | + u8 rc22; | |
265 | + u8 rc23; | |
266 | + u8 rc24; | |
267 | + u8 rc25; | |
268 | + u8 rc26; | |
269 | + u8 rc27; | |
270 | + u8 rc28; | |
271 | + u8 rc29; | |
272 | + u8 rc30; | |
273 | + u8 rc31; | |
274 | + u8 rc32; | |
275 | + u8 tcc1; /* Transmit channel control */ | |
276 | + u8 tcc2; | |
277 | + u8 tcc3; | |
278 | + u8 tcc4; | |
279 | + u8 rcc1; /* Receive channel control */ | |
280 | + u8 rcc2; | |
281 | + u8 rcc3; | |
282 | + u8 rcc4; | |
283 | + u8 ccr4; /* Control: Common Control 4 */ | |
284 | + u8 tds0m; /* Transmit DS0 Monitor */ | |
285 | + u8 ccr5; /* Control: Common Control 5 */ | |
286 | + u8 rds0m; /* Receive DS0 Monitor */ | |
287 | + u8 test3; | |
288 | + u8 reserved2[3]; | |
289 | + u8 hcr; /* HDLC Control */ | |
290 | + u8 hsr; /* HDLC Status */ | |
291 | + u8 himr; /* HDLC Interrupt Mask */ | |
292 | + u8 rhir; /* Receive HDLC Information */ | |
293 | + u8 rhfr; /* Receive HDLC FIFO */ | |
294 | + u8 ibo; /* Interleave Bus Operation */ | |
295 | + u8 thir; /* Transmit HDLC Information */ | |
296 | + u8 thfr; /* Transmit HDLC FIFO */ | |
297 | + u8 rdc1; /* Receive HDLC DS0 Control 1 */ | |
298 | + u8 rdc2; /* Receive HDLC DS0 Control 2 */ | |
299 | + u8 tdc1; /* Transmit HDLC DS0 Control 1 */ | |
300 | + u8 tdc2; /* Transmit HDLC DS0 Control 2 */ | |
301 | + u8 reserved3[4]; | |
302 | +} ds21554_t; | |
303 | + | |
304 | +typedef struct port_s { | |
305 | + struct net_device *dev; | |
306 | + struct card_s *card; | |
307 | + spinlock_t lock; /* TX lock */ | |
308 | + te1_settings settings; | |
309 | + int rxpart; /* partial frame received, next frame invalid*/ | |
310 | + unsigned short encoding; | |
311 | + unsigned short parity; | |
312 | + u16 rxin; /* rx ring buffer 'in' pointer */ | |
313 | + u16 txin; /* tx ring buffer 'in' and 'last' pointers */ | |
314 | + u16 txlast; | |
315 | + u8 rxs, txs, tmc; /* SCA registers */ | |
316 | + u8 phy_node; /* physical port # - 0 or 1 */ | |
317 | + u32 dsphys; /* DS21544 memory base (physical) */ | |
318 | + ds21554_t* dsbase; /* DS21544 memory base (virtual) */ | |
319 | + u8 g703_on; /* Enable/disable G.703 transceiver */ | |
320 | + u8 g703_coding; /* G.703 line coding */ | |
321 | + u8 g703_idlecode; /* G.703 idle timeslots contents */ | |
322 | +}port_t; | |
323 | + | |
324 | +typedef struct card_s { | |
325 | + u8* __iomem rambase; /* buffer memory base (virtual) */ | |
326 | + u8* __iomem scabase; /* SCA memory base (virtual) */ | |
327 | + plx9052* __iomem plxbase; /* PLX registers memory base (virtual) */ | |
328 | + u16 rx_ring_buffers; /* number of buffers in a ring */ | |
329 | + u16 tx_ring_buffers; | |
330 | + u16 buff_offset; /* offset of first buffer of first channel */ | |
331 | + u8 irq; /* interrupt request level */ | |
332 | + u8 no_ports; /* number of ports */ | |
333 | + char dev_name[10]; /* device name */ | |
334 | + port_t ports[2]; | |
335 | +}card_t; | |
336 | + | |
337 | +#define sca_in(reg, card) readb(card->scabase + (reg)) | |
338 | +#define sca_out(value, reg, card) writeb(value, card->scabase + (reg)) | |
339 | +#define sca_inw(reg, card) readw(card->scabase + (reg)) | |
340 | +#define sca_outw(value, reg, card) writew(value, card->scabase + (reg)) | |
341 | +#define sca_inl(reg, card) readl(card->scabase + (reg)) | |
342 | +#define sca_outl(value, reg, card) writel(value, card->scabase + (reg)) | |
343 | + | |
344 | +#define port_to_card(port) (port->card) | |
345 | +#define log_node(port) (port->phy_node) | |
346 | +#define phy_node(port) (port->phy_node) | |
347 | +#define winbase(card) (card->rambase) | |
348 | +#define get_port(card, port) (&card->ports[port]) | |
349 | +#define sca_flush(card) (sca_in(IER0, card)); | |
350 | + | |
351 | +static inline void new_memcpy_toio(char __iomem *dest, char *src, int length) | |
352 | +{ | |
353 | + int len; | |
354 | + | |
355 | + do { | |
356 | + len = length > 64 ? 64 : length; /* 32 */ | |
357 | + memcpy_toio(dest, src, len); | |
358 | + dest += len; | |
359 | + src += len; | |
360 | + length -= len; | |
361 | + readb(dest); | |
362 | + } while (len); | |
363 | +} | |
364 | + | |
365 | +#undef memcpy_toio | |
366 | +#define memcpy_toio new_memcpy_toio | |
367 | + | |
368 | +#include "hd64570.c" | |
369 | + | |
370 | +void init_ds21554(port_t *port); | |
371 | + | |
372 | +static void t9xx_set_iface(port_t *port) | |
373 | +{ | |
374 | + card_t *card = port->card; | |
375 | + u8 msci = get_msci(port); | |
376 | + u8 rxs = port->rxs & CLK_BRG_MASK; | |
377 | + u8 txs = port->txs & CLK_BRG_MASK; | |
378 | + | |
379 | + if (port->dsbase) { | |
380 | + init_ds21554(port); | |
381 | + } | |
382 | + | |
383 | + rxs |= CLK_LINE_RX; /* RXC input */ | |
384 | + txs |= CLK_LINE_TX; /* TXC input */ | |
385 | + | |
386 | + port->rxs = rxs; | |
387 | + port->txs = txs; | |
388 | + sca_out(rxs, msci + RXS, card); | |
389 | + sca_out(txs, msci + TXS, card); | |
390 | + sca_set_port(port); | |
391 | +} | |
392 | + | |
393 | + | |
394 | + | |
395 | +static int t9xx_open(struct net_device *dev) | |
396 | +{ | |
397 | + port_t *port = dev_to_port(dev); | |
398 | + | |
399 | + int result = hdlc_open(dev); | |
400 | + if (result) | |
401 | + return result; | |
402 | + | |
403 | + sca_open(dev); | |
404 | + t9xx_set_iface(port); | |
405 | + sca_flush(port_to_card(port)); | |
406 | + return 0; | |
407 | +} | |
408 | + | |
409 | + | |
410 | + | |
411 | +static int t9xx_close(struct net_device *dev) | |
412 | +{ | |
413 | + sca_close(dev); | |
414 | + sca_flush(port_to_card(dev_to_port(dev))); | |
415 | + hdlc_close(dev); | |
416 | + return 0; | |
417 | +} | |
418 | + | |
419 | + | |
420 | + | |
421 | +static int t9xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |
422 | +{ | |
423 | + const size_t size = sizeof(te1_settings); | |
424 | + te1_settings new_line; | |
425 | + te1_settings __user *line = ifr->ifr_settings.ifs_ifsu.te1; | |
426 | + port_t *port = dev_to_port(dev); | |
427 | + | |
428 | +#ifdef DEBUG_RINGS | |
429 | + if (cmd == SIOCDEVPRIVATE) { | |
430 | + sca_dump_rings(dev); | |
431 | + return 0; | |
432 | + } | |
433 | +#endif | |
434 | + if (cmd != SIOCWANDEV) | |
435 | + return hdlc_ioctl(dev, ifr, cmd); | |
436 | + | |
437 | + switch(ifr->ifr_settings.type) { | |
438 | + case IF_GET_IFACE: | |
439 | + if (port->dsbase) | |
440 | + ifr->ifr_settings.type = IF_IFACE_E1; | |
441 | + else | |
442 | + ifr->ifr_settings.type = IF_IFACE_V35; | |
443 | + if (ifr->ifr_settings.size < size) { | |
444 | + ifr->ifr_settings.size = size; /* data size wanted */ | |
445 | + return -ENOBUFS; | |
446 | + } | |
447 | + if (copy_to_user(line, &port->settings, size)) | |
448 | + return -EFAULT; | |
449 | + return 0; | |
450 | + | |
451 | + case IF_IFACE_E1: | |
452 | + case IF_IFACE_V35: | |
453 | + if (!capable(CAP_NET_ADMIN)) | |
454 | + return -EPERM; | |
455 | + | |
456 | + if (copy_from_user(&new_line, line, size)) | |
457 | + return -EFAULT; | |
458 | + | |
459 | + if (new_line.clock_type != CLOCK_EXT) | |
460 | + return -EINVAL; /* No such clock setting */ | |
461 | + | |
462 | + if (new_line.loopback > 3) | |
463 | + return -EINVAL; | |
464 | + | |
465 | + memcpy(&port->settings, &new_line, size); /* Update settings */ | |
466 | + t9xx_set_iface(port); | |
467 | + sca_flush(port_to_card(port)); | |
468 | + return 0; | |
469 | + | |
470 | + default: | |
471 | + return hdlc_ioctl(dev, ifr, cmd); | |
472 | + } | |
473 | +} | |
474 | + | |
475 | + | |
476 | + | |
477 | +static void t9xx_pci_remove_one(struct pci_dev *pdev) | |
478 | +{ | |
479 | + int i, ports; | |
480 | + card_t *card = pci_get_drvdata(pdev); | |
481 | + | |
482 | + if ((pdev->subsystem_device == PCI_DEVICE_ID_TAHOE932) || | |
483 | + (pdev->subsystem_device == PCI_DEVICE_ID_TAHOE972)) | |
484 | + ports = 2; | |
485 | + else | |
486 | + ports = 1; | |
487 | + for(i = 0; i < ports; i++) | |
488 | + if (card->ports[i].card) { | |
489 | + struct net_device *dev = port_to_dev(&card->ports[i]); | |
490 | + unregister_hdlc_device(dev); | |
491 | + } | |
492 | + | |
493 | + if (card->rambase) | |
494 | + iounmap(card->rambase); | |
495 | + if (card->scabase) | |
496 | + iounmap(card->scabase); | |
497 | + if (card->plxbase) | |
498 | + iounmap(card->plxbase); | |
499 | + | |
500 | + pci_release_regions(pdev); | |
501 | + pci_disable_device(pdev); | |
502 | + pci_set_drvdata(pdev, NULL); | |
503 | + if (card->ports[0].dev) | |
504 | + free_netdev(card->ports[0].dev); | |
505 | + if ((ports == 2) && (card->ports[1].dev)) | |
506 | + free_netdev(card->ports[1].dev); | |
507 | + kfree(card); | |
508 | +} | |
509 | + | |
510 | +static void ds21554_update_licr(port_t *port) | |
511 | +{ | |
512 | + port->dsbase->licr = DEFAULT_LICR | (port->settings.egl << 4) | (port->g703_on == 0); | |
513 | +} | |
514 | + | |
515 | +static void ds21554_update_registers(port_t *port) | |
516 | +{ | |
517 | + ds21554_t *ds = port->dsbase; | |
518 | + | |
519 | + if (port->settings.slot_map == 0xffffffff) { | |
520 | + /* Unframed */ | |
521 | + ds->ccr1 = 0x08 | (port->g703_coding << 6) | (port->g703_coding << 2); | |
522 | + ds->tcr1 = 0x40; | |
523 | + ds->tcr2 = 0x00; | |
524 | + ds->ccr2 = 0x80; //84 | |
525 | + ds->tir1 = 0; ds->tir2 = 0; ds->tir3 = 0; ds->tir4 = 0; | |
526 | + ds->tcc1 = 0; ds->tcc2 = 0; ds->tcc3 = 0; ds->tcc4 = 0; | |
527 | + ds->rcc1 = 0; ds->rcc2 = 0; ds->rcc3 = 0; ds->rcc4 = 0; | |
528 | + ds->rcbr1 = 0xff; ds->rcbr2 = 0xff; | |
529 | + ds->rcbr3 = 0xff; ds->rcbr4 = 0xff; | |
530 | + ds->tcbr1 = 0xff; ds->tcbr2 = 0xff; | |
531 | + ds->tcbr3 = 0xff; ds->tcbr4 = 0xff; | |
532 | + ds->tsacr = 0x00; | |
533 | + ds->tdc1 = 0x00; | |
534 | + | |
535 | + ds->rcr2 = 0x04; | |
536 | + ds->ccr3 = 0x02; | |
537 | + | |
538 | + ds->ccr6 = 0x03; /* elastic buffers reset */ | |
539 | + udelay(1000); | |
540 | + ds->ccr6 = 0x00; /* elastic buffers reset */ | |
541 | + | |
542 | + ds->ccr5 = 0x60; /* elastic buffers align */ | |
543 | + udelay(1000); | |
544 | + ds->ccr5 = 0x00; | |
545 | + } else { | |
546 | + ds->ccr1 = 0x08 | (port->g703_coding << 6) | (port->g703_coding << 2) | |
547 | + | (port->settings.crc4 << 4) | (port->settings.crc4); | |
548 | + ds->tcr1 = 0x00; | |
549 | + ds->ccr2 = 0x94; /* Automatic alarm generation */ | |
550 | + | |
551 | + /* Receive channels */ | |
552 | + ds->rcbr1 = port->settings.slot_map & 0xff; | |
553 | + ds->rcbr2 = (port->settings.slot_map >> 8) & 0xff; | |
554 | + ds->rcbr3 = (port->settings.slot_map >> 16) & 0xff; | |
555 | + ds->rcbr4 = (port->settings.slot_map >> 24) & 0xff; | |
556 | + | |
557 | + /* Transmit channels */ | |
558 | + ds->tcbr1 = port->settings.slot_map & 0xff; | |
559 | + ds->tcbr2 = (port->settings.slot_map >> 8) & 0xff; | |
560 | + ds->tcbr3 = (port->settings.slot_map >> 16) & 0xff; | |
561 | + ds->tcbr4 = (port->settings.slot_map >> 24) & 0xff; | |
562 | + | |
563 | + /* Transmit idle */ | |
564 | + /* (remaining timeslots are filled with idle code) */ | |
565 | + ds->tir1 = ~port->settings.slot_map & 0xfe; /* Slot 0 is never idle */ | |
566 | + ds->tir2 = (~port->settings.slot_map >> 8) & 0xff; | |
567 | + ds->tir3 = (~port->settings.slot_map >> 16) & 0xff; | |
568 | + ds->tir4 = (~port->settings.slot_map >> 24) & 0xff; | |
569 | + ds->rcr2 = 0x06; /* RSYSCLK = 2048, rx elastic store enabled */ | |
570 | + ds->ccr3 = 0x82; /* TSYSCLK = 2048, tx elastic store enabled */ | |
571 | + | |
572 | + ds->ccr6 = 0x07; /* elastic buffers reset */ | |
573 | + udelay(1000); | |
574 | + ds->ccr6 = 0x04; /* elastic buffers reset */ | |
575 | + | |
576 | + ds->ccr5 = 0x60; /* elastic buffers align */ | |
577 | + udelay(1000); | |
578 | + ds->ccr5 = 0x00; | |
579 | + } | |
580 | +} | |
581 | + | |
582 | +void init_ds21554(port_t *port) | |
583 | +{ | |
584 | + ds21554_t *ds = port->dsbase; | |
585 | + | |
586 | + ds->ccr2 = 0x04; | |
587 | + udelay(1000); | |
588 | + ds->ccr5 = 0x80; /* Line Interface Reset */ | |
589 | + udelay(1000); | |
590 | + | |
591 | + ds->ccr5 = 0xe0; /* Elastic Buffers Reset */ | |
592 | + udelay(1000); | |
593 | + ds->ccr5 = 0x00; | |
594 | + ds->ccr6 = 0x04; /* TCLK from RCLK */ | |
595 | + ds->tcr2 = 0x00; | |
596 | + ds21554_update_licr(port); | |
597 | + | |
598 | + /* Setup HDB3, CRC4, CAS/CCS, G.802 */ | |
599 | + ds21554_update_registers(port); | |
600 | + | |
601 | + ds->ccr2 = 0x94; /* Automatic alarm generation */ | |
602 | + | |
603 | + ds->taf = 0x1b; | |
604 | + ds->tnaf = 0x40; | |
605 | + | |
606 | + ds21554_update_registers(port); | |
607 | + | |
608 | + ds->tidr = port->g703_idlecode; | |
609 | + | |
610 | +// ds->ccr4 |= 0x40; | |
611 | +} | |
612 | + | |
613 | + | |
614 | +static int __devinit t9xx_pci_init_one(struct pci_dev *pdev, | |
615 | + const struct pci_device_id *ent) | |
616 | +{ | |
617 | + card_t *card; | |
618 | + u8 rev_id, tahoe97x = 0; | |
619 | + u32 __iomem *p; | |
620 | + int i; | |
621 | + u32 ramsize; | |
622 | + u32 ramphys; /* buffer memory base */ | |
623 | + u32 scaphys; /* SCA memory base */ | |
624 | + u32 plxphys; /* PLX registers memory base */ | |
625 | + | |
626 | +#ifndef MODULE | |
627 | + static int printed_version; | |
628 | + if (!printed_version++) | |
629 | + printk(KERN_INFO "%s\n", version); | |
630 | +#endif | |
631 | + | |
632 | + i = pci_enable_device(pdev); | |
633 | + if (i) | |
634 | + return i; | |
635 | + | |
636 | + i = pci_request_regions(pdev, "Tahoe9xx"); | |
637 | + if (i) { | |
638 | + pci_disable_device(pdev); | |
639 | + return i; | |
640 | + } | |
641 | + | |
642 | + card = kmalloc(sizeof(card_t), GFP_KERNEL); | |
643 | + if (card == NULL) { | |
644 | + printk(KERN_ERR "%s: unable to allocate memory\n", card->dev_name); | |
645 | + pci_release_regions(pdev); | |
646 | + pci_disable_device(pdev); | |
647 | + return -ENOBUFS; | |
648 | + } | |
649 | + memset(card, 0, sizeof(card_t)); | |
650 | + pci_set_drvdata(pdev, card); | |
651 | + card->ports[0].dev = alloc_hdlcdev(&card->ports[0]); | |
652 | + card->ports[1].dev = alloc_hdlcdev(&card->ports[1]); | |
653 | + if (!card->ports[0].dev || !card->ports[1].dev) { | |
654 | + printk(KERN_ERR "tahoe9xx: unable to allocate memory\n"); | |
655 | + t9xx_pci_remove_one(pdev); | |
656 | + return -ENOMEM; | |
657 | + } | |
658 | + | |
659 | + sprintf(card->dev_name, "Tahoe"); | |
660 | + switch (pdev->subsystem_device) { | |
661 | + case PCI_DEVICE_ID_TAHOE931: | |
662 | + strcat(card->dev_name, "931"); | |
663 | + card->no_ports = 1; | |
664 | + break; | |
665 | + case PCI_DEVICE_ID_TAHOE932: | |
666 | + strcat(card->dev_name, "932"); | |
667 | + card->no_ports = 2; | |
668 | + break; | |
669 | + case PCI_DEVICE_ID_TAHOE971: | |
670 | + strcat(card->dev_name, "971"); | |
671 | + tahoe97x = 1; | |
672 | + card->no_ports = 1; | |
673 | + break; | |
674 | + case PCI_DEVICE_ID_TAHOE972: | |
675 | + strcat(card->dev_name, "972"); | |
676 | + tahoe97x = 1; | |
677 | + card->no_ports = 2; | |
678 | + break; | |
679 | + default: | |
680 | + strcat(card->dev_name, "9xx"); | |
681 | + card->no_ports = 0; | |
682 | + break; | |
683 | + } | |
684 | + | |
685 | + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); | |
686 | + if (pci_resource_len(pdev, 0) != TAHOE9XX_PLX_SIZE || | |
687 | + pci_resource_len(pdev, 2) != TAHOE9XX_SCA_SIZE || | |
688 | + pci_resource_len(pdev, 3) < 16384) { | |
689 | + printk(KERN_ERR "%s: invalid card EEPROM parameters\n", card->dev_name); | |
690 | + t9xx_pci_remove_one(pdev); | |
691 | + return -EFAULT; | |
692 | + } | |
693 | + | |
694 | + plxphys = pci_resource_start(pdev,0) & PCI_BASE_ADDRESS_MEM_MASK; | |
695 | + card->plxbase = ioremap(plxphys, TAHOE9XX_PLX_SIZE); | |
696 | + | |
697 | + scaphys = pci_resource_start(pdev,2) & PCI_BASE_ADDRESS_MEM_MASK; | |
698 | + card->scabase = ioremap(scaphys, TAHOE9XX_SCA_SIZE); | |
699 | + | |
700 | + ramphys = pci_resource_start(pdev,3) & PCI_BASE_ADDRESS_MEM_MASK; | |
701 | + card->rambase = ioremap(ramphys, pci_resource_len(pdev,3)); | |
702 | + | |
703 | + if (tahoe97x) { | |
704 | + for (i=0; i < card->no_ports; i++) { | |
705 | + card->ports[i].dsphys = pci_resource_start(pdev,4+i) & PCI_BASE_ADDRESS_MEM_MASK; | |
706 | + card->ports[i].dsbase = (ds21554_t *)ioremap(card->ports[i].dsphys, pci_resource_len(pdev,4+i)); | |
707 | + } | |
708 | + } else { | |
709 | + for (i=0; i < card->no_ports; i++) | |
710 | + card->ports[i].dsbase = (ds21554_t *)0; | |
711 | + } | |
712 | + | |
713 | + if (card->plxbase == NULL || | |
714 | + card->scabase == NULL || | |
715 | + card->rambase == NULL) { | |
716 | + printk(KERN_ERR "tahoe9xx: ioremap() failed\n"); | |
717 | + t9xx_pci_remove_one(pdev); | |
718 | + } | |
719 | + | |
720 | + /* Reset PLX */ | |
721 | + p = &card->plxbase->init_ctrl; | |
722 | + writel(readl(p) | 0x40000000, p); | |
723 | + readl(p); /* Flush the write - do not use sca_flush */ | |
724 | + udelay(1); | |
725 | + | |
726 | + writel(readl(p) & ~0x40000000, p); | |
727 | + readl(p); /* Flush the write - do not use sca_flush */ | |
728 | + udelay(1); | |
729 | + | |
730 | + ramsize = sca_detect_ram(card, card->rambase, | |
731 | + pci_resource_len(pdev,3)); | |
732 | + | |
733 | + /* number of TX + RX buffers for one port - this is dual port card */ | |
734 | + i = ramsize / (2 * (sizeof(pkt_desc) + HDLC_MAX_MRU)); | |
735 | + card->tx_ring_buffers = min(i / 2, MAX_TX_BUFFERS); | |
736 | + card->rx_ring_buffers = i - card->tx_ring_buffers; | |
737 | + | |
738 | + card->buff_offset = 2 * sizeof(pkt_desc) * (card->tx_ring_buffers + | |
739 | + card->rx_ring_buffers); | |
740 | + | |
741 | + printk(KERN_INFO "%s: %u KB RAM at 0x%x, IRQ%u, using %u TX +" | |
742 | + " %u RX packets rings\n", card->dev_name, ramsize / 1024, | |
743 | + ramphys, pdev->irq, | |
744 | + card->tx_ring_buffers, card->rx_ring_buffers); | |
745 | + if (tahoe97x) { | |
746 | + for (i=0; i < card->no_ports; i++) { | |
747 | + /* Make sure DS21554 is there */ | |
748 | + card->ports[i].dsbase->idr = 0x00; | |
749 | + card->ports[i].dsbase->tc1 = 0xaa; | |
750 | + card->ports[i].dsbase->rc1 = 0x55; | |
751 | + if (((card->ports[i].dsbase->idr & 0xf0) == 0xa0) && (card->ports[i].dsbase->tc1 == 0xaa) && (card->ports[i].dsbase->rc1 == 0x55)) { | |
752 | + printk(KERN_INFO "%s: DS21554 (port %d) detected at 0x%x\n", card->dev_name, i, card->ports[i].dsphys); | |
753 | + /* Clear registers */ | |
754 | + memset(card->ports[i].dsbase, 0, 256); | |
755 | + /* Default settings */ | |
756 | + card->ports[i].g703_on = 1; | |
757 | + card->ports[i].settings.egl = 0; | |
758 | + card->ports[i].g703_coding = G703_HDB3; | |
759 | + card->ports[i].g703_idlecode = 0x54; | |
760 | + card->ports[i].settings.crc4 = 1; | |
761 | + /* Unframed */ | |
762 | + card->ports[i].settings.slot_map = 0xffffffff; | |
763 | + init_ds21554(&card->ports[i]); | |
764 | + } else | |
765 | + printk(KERN_INFO "%s: DS21554 (port %d) test failed!\n", card->dev_name, i); | |
766 | + } | |
767 | + } | |
768 | + | |
769 | + if (card->tx_ring_buffers < 1) { | |
770 | + printk(KERN_ERR "%s: RAM test failed\n", card->dev_name); | |
771 | + t9xx_pci_remove_one(pdev); | |
772 | + return -EFAULT; | |
773 | + } | |
774 | + | |
775 | + /* Enable interrupts on the PCI bridge */ | |
776 | + p = &card->plxbase->intr_ctrl_stat; | |
777 | + writew(readw(p) | 0x0040, p); | |
778 | + | |
779 | + /* Allocate IRQ */ | |
780 | + if(request_irq(pdev->irq, sca_intr, IRQF_SHARED, devname, card)) { | |
781 | + printk(KERN_WARNING "%s: could not allocate IRQ%d.\n", card->dev_name, | |
782 | + pdev->irq); | |
783 | + t9xx_pci_remove_one(pdev); | |
784 | + return -EBUSY; | |
785 | + } | |
786 | + card->irq = pdev->irq; | |
787 | + | |
788 | + sca_init(card, 0); | |
789 | + | |
790 | + for(i = 0; i < card->no_ports; i++) { | |
791 | + port_t *port = &card->ports[i]; | |
792 | + struct net_device *dev = port_to_dev(port); | |
793 | + hdlc_device *hdlc = dev_to_hdlc(dev); | |
794 | + port->phy_node = i; | |
795 | + | |
796 | + spin_lock_init(&port->lock); | |
797 | + dev->irq = card->irq; | |
798 | + dev->mem_start = ramphys; | |
799 | + dev->mem_end = ramphys + ramsize - 1; | |
800 | + dev->tx_queue_len = 50; | |
801 | + dev->do_ioctl = t9xx_ioctl; | |
802 | + dev->open = t9xx_open; | |
803 | + dev->stop = t9xx_close; | |
804 | + hdlc->attach = sca_attach; | |
805 | + hdlc->xmit = sca_xmit; | |
806 | + port->settings.clock_type = CLOCK_EXT; | |
807 | + port->card = card; | |
808 | + if(register_hdlc_device(dev)) { | |
809 | + printk(KERN_ERR "%s: unable to register hdlc " | |
810 | + "device\n", card->dev_name); | |
811 | + port->card = NULL; | |
812 | + t9xx_pci_remove_one(pdev); | |
813 | + return -ENOBUFS; | |
814 | + } | |
815 | + sca_init_sync_port(port); /* Set up SCA memory */ | |
816 | + | |
817 | + printk(KERN_INFO "%s: %s node %d\n", | |
818 | + dev->name, card->dev_name, port->phy_node); | |
819 | + } | |
820 | + | |
821 | + sca_flush(card); | |
822 | + return 0; | |
823 | +} | |
824 | + | |
825 | + | |
826 | + | |
827 | +static struct pci_device_id t9xx_pci_tbl[] __devinitdata = { | |
828 | + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, | |
829 | + PCI_VENDOR_ID_TAHOE, PCI_ANY_ID, | |
830 | + 0, 0, 0 }, | |
831 | + { 0, } | |
832 | +}; | |
833 | + | |
834 | +static struct pci_driver t9xx_pci_driver = { | |
835 | + name: "Tahoe9xx", | |
836 | + id_table: t9xx_pci_tbl, | |
837 | + probe: t9xx_pci_init_one, | |
838 | + remove: t9xx_pci_remove_one, | |
839 | +}; | |
840 | + | |
841 | +static int __init t9xx_init_module(void) | |
842 | +{ | |
843 | +#ifdef MODULE | |
844 | + printk(KERN_INFO "%s\n", version); | |
845 | +#endif | |
846 | + return pci_register_driver(&t9xx_pci_driver); | |
847 | +} | |
848 | + | |
849 | + | |
850 | + | |
851 | +static void __exit t9xx_cleanup_module(void) | |
852 | +{ | |
853 | + pci_unregister_driver(&t9xx_pci_driver); | |
854 | +} | |
855 | + | |
856 | +MODULE_AUTHOR("Piotr Kaczmarzyk <piotr@tahoe.pl>"); | |
857 | +MODULE_DESCRIPTION("Tahoe 9xx serial port driver"); | |
858 | +MODULE_LICENSE("GPL v2"); | |
859 | +MODULE_DEVICE_TABLE(pci, t9xx_pci_tbl); | |
860 | +module_init(t9xx_init_module); | |
861 | +module_exit(t9xx_cleanup_module); | |
862 | --- linux/include/linux/hdlc/ioctl.h 2008-01-24 23:58:37.000000000 +0100 | |
863 | +++ linux/include/linux/hdlc/ioctl.h 2008-01-30 14:04:26.000000000 +0100 | |
864 | @@ -45,6 +45,8 @@ | |
865 | unsigned int clock_type; /* internal, external, TX-internal etc. */ | |
866 | unsigned short loopback; | |
867 | unsigned int slot_map; | |
868 | + unsigned short crc4; | |
869 | + unsigned short egl; | |
870 | } te1_settings; /* T1, E1 */ | |
871 | ||
872 | typedef struct { |