2 * Hardware-level driver for the SliceCOM board for Linux kernels 2.4.X
4 * Current maintainer / latest changes: Pasztor Szilard <don@itc.hu>
6 * Original author: Bartok Istvan <bartoki@itc.hu>
7 * Based on skeleton by Tivadar Szemethy <tiv@itc.hu>
11 * - clean up some code, make it more portable
12 * - busted direct hardware access through mapped memory
13 * - fix a possible race
14 * - prevent procfs buffer overflow
17 * - support for the pcicom board, lots of rearrangements
18 * - handle modem status lines
21 * - fix for falc version 1.0
24 * - fix for bad localbus
27 #define VERSION "0.51"
28 #define VERSIONSTR "SliceCOM v" VERSION ", 2002/01/07\n"
30 #include <linux/config.h>
31 #include <linux/ctype.h>
32 #include <linux/module.h>
33 #include <linux/types.h>
34 #include <linux/netdevice.h>
35 #include <linux/proc_fs.h>
36 #include <linux/ioport.h>
37 #include <linux/pci.h>
38 #include <linux/init.h>
40 #include <asm/delay.h>
41 #include <asm/types.h>
42 #include <asm/uaccess.h>
48 #include "../include/comx.h"
49 #include "../include/munich32x.h"
50 #include "../include/falc-lh.h"
53 #include "munich32x.h"
57 MODULE_AUTHOR("Bartok Istvan <bartoki@itc.hu>, Gergely Madarasz <gorgo@itc.hu>, Szilard Pasztor <don@itc.hu>");
58 MODULE_DESCRIPTION("Hardware-level driver for the SliceCOM and PciCOM (WelCOM) adapters");
59 MODULE_LICENSE("GPL");
61 * TODO: az ilyenek a comxhw.h -ban szoktak lenni, idovel menjenek majd oda:
64 #define FILENAME_BOARDNUM "boardnum" /* /proc/comx/comx0.1/boardnum */
65 #define FILENAME_TIMESLOTS "timeslots" /* /proc/comx/comx0.1/timeslots */
66 #define FILENAME_FRAMING "framing" /* /proc/comx/comx0.1/framing */
67 #define FILENAME_LINECODE "linecode" /* /proc/comx/comx0.1/linecode */
68 #define FILENAME_CLOCK_SOURCE "clock_source" /* /proc/comx/comx0.1/clock_source */
69 #define FILENAME_LOOPBACK "loopback" /* /proc/comx/comx0.1/loopback */
70 #define FILENAME_REG "reg" /* /proc/comx/comx0.1/reg */
71 #define FILENAME_LBIREG "lbireg" /* /proc/comx/comx0.1/lbireg */
73 #define SLICECOM_BOARDNUM_DEFAULT 0
75 #define SLICECOM_FRAMING_CRC4 1
76 #define SLICECOM_FRAMING_NO_CRC4 2
77 #define SLICECOM_FRAMING_DEFAULT SLICECOM_FRAMING_CRC4
79 #define SLICECOM_LINECODE_HDB3 1
80 #define SLICECOM_LINECODE_AMI 2
81 #define SLICECOM_LINECODE_DEFAULT SLICECOM_LINECODE_HDB3
83 #define SLICECOM_CLOCK_SOURCE_LINE 1
84 #define SLICECOM_CLOCK_SOURCE_INTERNAL 2
85 #define SLICECOM_CLOCK_SOURCE_DEFAULT SLICECOM_CLOCK_SOURCE_LINE
87 #define SLICECOM_LOOPBACK_NONE 1
88 #define SLICECOM_LOOPBACK_LOCAL 2
89 #define SLICECOM_LOOPBACK_REMOTE 3
90 #define SLICECOM_LOOPBACK_DEFAULT SLICECOM_LOOPBACK_NONE
92 #define MUNICH_VIRT(addr) (void *)(&bar1[addr])
94 struct slicecom_stringtable
100 /* A convention: keep "default" the last not NULL when reading from /proc,
101 "error" is an indication that something went wrong, we have an undefined value */
103 struct slicecom_stringtable slicecom_framings[] =
105 {"crc4", SLICECOM_FRAMING_CRC4},
106 {"no-crc4", SLICECOM_FRAMING_NO_CRC4},
107 {"default", SLICECOM_FRAMING_DEFAULT},
111 struct slicecom_stringtable slicecom_linecodes[] =
113 {"hdb3", SLICECOM_LINECODE_HDB3},
114 {"ami", SLICECOM_LINECODE_AMI},
115 {"default", SLICECOM_LINECODE_DEFAULT},
119 struct slicecom_stringtable slicecom_clock_sources[] =
121 {"line", SLICECOM_CLOCK_SOURCE_LINE},
122 {"internal", SLICECOM_CLOCK_SOURCE_INTERNAL},
123 {"default", SLICECOM_CLOCK_SOURCE_DEFAULT},
127 struct slicecom_stringtable slicecom_loopbacks[] =
129 {"none", SLICECOM_LOOPBACK_NONE},
130 {"local", SLICECOM_LOOPBACK_LOCAL},
131 {"remote", SLICECOM_LOOPBACK_REMOTE},
132 {"default", SLICECOM_LOOPBACK_DEFAULT},
137 * Some tunable values...
139 * Note: when tuning values which change the length of text in
140 * /proc/comx/comx[n]/status, keep in mind that it must be shorter then
144 #define MAX_BOARDS 4 /* ezzel 4 kartya lehet a gepben: 0..3 */
145 #define RX_DESC_MAX 8 /* Rx ring size, must be >= 4 */
146 #define TX_DESC_MAX 4 /* Tx ring size, must be >= 2 */
147 /* a sokkal hosszabb Tx ring mar ronthatja a nem-FIFO packet */
148 /* schedulerek (fair queueing, stb.) hatekonysagat. */
149 #define MAX_WORK 10 /* TOD: update the info max. ennyi-1 esemenyt dolgoz fel egy interrupt hivasnal */
152 * These are tunable too, but don't touch them without fully understanding what is happening
155 #define UDELAY 20 /* We wait UDELAY usecs with disabled interrupts before and */
156 /* after each command to avoid writing into each other's */
157 /* ccb->action_spec. A _send_packet nem var, mert azt az */
158 /* _interrupt()-bol is meghivhatja a LINE_tx() */
161 * Just to avoid warnings about implicit declarations:
164 static int MUNICH_close(struct net_device *dev);
165 static struct comx_hardware slicecomhw;
166 static struct comx_hardware pcicomhw;
168 static unsigned long flags;
169 static spinlock_t mister_lock = SPIN_LOCK_UNLOCKED;
171 typedef volatile struct /* Time Slot Assignment */
173 u32 rxfillmask:8, // ----------------------------+------+
175 rxchannel:5, // ----------------------+---+ | |
176 rti:1, // ---------------------+| | | |
177 res2:2, // -------------------++|| | | |
179 txfillmask:8, // ----------+------+ |||| | | |
181 txchannel:5, // ----+---+ | | |||| | | |
182 tti:1, // ---+| | | | |||| | | |
183 res1:2; // -++|| | | | |||| | | |
185 // 10987654 32109876 54321098 76543210
188 typedef volatile struct /* Receive Descriptor */
190 u32 zero1:16, no:13, hi:1, hold:1, zero2:1;
195 u32 zero3:8, status:8, bno:13, zero4:1, c:1, fe:1;
198 typedef volatile struct /* Transmit Descriptor */
200 u32 fnum:11, csm:1, no13:1, zero1:2, v110:1, no:13, hi:1, hold:1, fe:1;
207 typedef volatile struct /* Channel Specification */
209 u32 iftf:1, mode:2, fa:1, trv:2, crc:1, inv:1, cs:1, tflag:7, ra:1, ro:1,
210 th:1, ta:1, to:1, ti:1, ri:1, nitbs:1, fit:1, fir:1, re:1, te:1, ch:1,
216 u32 itbs:6, zero1:26;
220 typedef volatile struct /* Configuration Control Block */
225 timeslot_spec_t timeslot_spec[32];
226 channel_spec_t channel_spec[32];
227 u32 current_rx_desc[32];
228 u32 current_tx_desc[32];
229 u32 csa; /* Control Start Address. CSA = *CCBA; CCB = *CSA */
230 /* MUNICH does it like: CCB = *( *CCBA ) */
233 typedef volatile struct /* Entry in the interrupt queue */
238 #define MUNICH_INTQLEN 63 /* Rx/Tx Interrupt Queue Length
239 (not the real len, but the TIQL/RIQL value) */
240 #define MUNICH_INTQMAX ( 16*(MUNICH_INTQLEN+1) ) /* Rx/Tx/Periph Interrupt Queue size in munich_intq_t's */
241 #define MUNICH_INTQSIZE ( 4*MUNICH_INTQMAX ) /* Rx/Tx/Periph Interrupt Queue size in bytes */
243 #define MUNICH_PIQLEN 4 /* Peripheral Interrupt Queue Length. Unlike the RIQL/TIQL, */
244 #define MUNICH_PIQMAX ( 4*MUNICH_PIQLEN ) /* PIQL register needs it like this */
245 #define MUNICH_PIQSIZE ( 4*MUNICH_PIQMAX )
247 typedef volatile u32 vol_u32; /* TOD: ezek megszunnek ha atirom readw()/writew()-re - kész */
248 typedef volatile u8 vol_u8;
250 typedef volatile struct /* counters of E1-errors and errored seconds, see rfc2495 */
252 /* use here only unsigned ints, we depend on it when calculating the sum for the last N intervals */
254 unsigned line_code_violations, /* AMI: bipolar violations, HDB3: hdb3 violations */
255 path_code_violations, /* FAS errors and CRC4 errors */
256 e_bit_errors, /* E-Bit Errors (the remote side received from us with CRC4-error) */
257 slip_secs, /* number of seconds with (receive) Controlled Slip(s) */
258 fr_loss_secs, /* number of seconds an Out Of Frame defect was detected */
259 line_err_secs, /* number of seconds with one or more Line Code Violations */
260 degraded_mins, /* Degraded Minute - the estimated error rate is >1E-6, but <1E-3 */
261 errored_secs, /* Errored Second - at least one of these happened:
262 - Path Code Violation
263 - Out Of Frame defect
266 - not incremented during an Unavailable Second */
267 bursty_err_secs, /* Bursty Errored Second: (rfc2495 says it does not apply to E1)
268 - Path Code Violations >1, but <320
269 - not a Severely Errored Second
271 - not incremented during an Unavailabla Second */
272 severely_err_secs, /* Severely Errored Second:
273 - CRC4: >=832 Path COde Violations || >0 Out Of Frame defects
274 - noCRC4: >=2048 Line Code Violations
275 - not incremented during an Unavailable Second */
276 unavail_secs; /* number of Unavailable Seconds. Unavailable state is said after:
277 - 10 contiguous Severely Errored Seconds
278 - or RAI || AIS || LOF || LOS
279 - (any) loopback has been set */
282 * we do not strictly comply to the rfc: we do not retroactively reduce errored_secs,
283 * bursty_err_secs, severely_err_secs when 'unavailable state' is reached
288 typedef volatile struct /* ezek board-adatok, nem lehetnek a slicecom_privdata -ban */
290 int use_count; /* num. of interfaces using the board */
291 int irq; /* a kartya irq-ja. belemasoljuk a dev->irq -kba is, de csak hogy */
292 /* szebb legyen az ifconfig outputja */
293 /* ha != 0, az azt jelenti hogy az az irq most nekunk sikeresen */
294 /* le van foglalva */
295 struct pci_dev *pci; /* a kartya PCI strukturaja. NULL, ha nincs kartya */
296 u32 *bar1; /* pci->base_address[0] ioremap()-ed by munich_probe(), */
297 /* on x86 can be used both as a bus or virtual address. */
298 /* These are the Munich's registers */
299 u8 *lbi; /* pci->base_address[1] ioremap()-ed by munich_probe(), */
300 /* this is a 256-byte range, the start of the LBI on the board */
301 munich_ccb_t *ccb; /* virtual address of CCB */
302 munich_intq_t *tiq; /* Tx Interrupt Queue */
303 munich_intq_t *riq; /* Rx Interrupt Queue */
304 munich_intq_t *piq; /* Peripheral Interrupt Queue (FALC interrupts arrive here) */
305 int tiq_ptr, /* A 'current' helyek a tiq/riq/piq -ban. */
306 riq_ptr, /* amikor feldolgoztam az interruptokat, a legelso ures */
307 piq_ptr; /* interrupt_information szora mutatnak. */
308 struct net_device *twins[32]; /* MUNICH channel -> network interface assignment */
310 unsigned long lastcheck; /* When were the Rx rings last checked. Time in jiffies */
312 struct timer_list modemline_timer;
315 char framing; /* a beallitasok tarolasa */
320 char devname[30]; /* what to show in /proc/interrupts */
321 unsigned histogram[MAX_WORK]; /* number of processed events in the interrupt loop */
322 unsigned stat_pri_races; /* number of special events, we try to handle them */
323 unsigned stat_pti_races;
324 unsigned stat_pri_races_missed; /* when it can not be handled, because of MAX_WORK */
325 unsigned stat_pti_races_missed;
327 #define SLICECOM_BOARD_INTERVALS_SIZE 97
328 e1_stats_t intervals[SLICECOM_BOARD_INTERVALS_SIZE]; /* E1 line statistics */
329 unsigned current_interval; /* pointer to the current interval */
330 unsigned elapsed_seconds; /* elapsed seconds from the start of the current interval */
331 unsigned ses_seconds; /* counter of contiguous Severely Errored Seconds */
332 unsigned is_unavailable; /* set to 1 after 10 contiguous Severely Errored Seconds */
333 unsigned no_ses_seconds; /* contiguous Severely Error -free seconds in unavail state */
335 unsigned deg_elapsed_seconds; /* for counting the 'Degraded Mins' */
336 unsigned deg_cumulated_errors;
338 struct module *owner; /* pointer to our module to avoid module load races */
341 struct slicecom_privdata
343 int busy; /* transmitter busy - number of packets in the Tx ring */
344 int channel; /* Munich logical channel ('channel-group' in Cisco) */
346 u32 timeslots; /* i-th bit means i-th timeslot is our */
348 int tx_ring_hist[TX_DESC_MAX]; /* histogram: number of packets in Tx ring when _send_packet is called */
350 tx_desc_t tx_desc[TX_DESC_MAX]; /* the ring of Tx descriptors */
351 u8 tx_data[TX_DESC_MAX][TXBUFFER_SIZE]; /* buffers for data to transmit */
352 int tx_desc_ptr; /* hanyadik descriptornal tartunk a beirassal */
353 /* ahol ez all, oda irtunk utoljara */
355 rx_desc_t rx_desc[RX_DESC_MAX]; /* the ring of Rx descriptors */
356 u8 rx_data[RX_DESC_MAX][RXBUFFER_SIZE]; /* buffers for received data */
357 int rx_desc_ptr; /* hanyadik descriptornal tartunk az olvasassal */
362 static u32 reg, reg_ertek; /* why static: don't write stack trash into regs if strtoul() fails */
364 static u8 lbireg_ertek; /* why static: don't write stack trash into regs if strtoul() fails */
366 static munich_board_t slicecom_boards[MAX_BOARDS];
367 static munich_board_t pcicom_boards[MAX_BOARDS];
370 * Reprogram Idle Channel Registers in the FALC - send special code in not used channels
371 * Should be called from the open and close, when the timeslot assignment changes
374 void rework_idle_channels(struct net_device *dev)
376 struct comx_channel *ch = netdev_priv(dev);
377 struct slicecom_privdata *hw = ch->HW_privdata;
378 munich_board_t *board = slicecom_boards + hw->boardnum;
379 munich_ccb_t *ccb = board->ccb;
381 u8 *lbi = board->lbi;
385 spin_lock_irqsave(&mister_lock, flags);
387 for (i = 0; i < 4; i++)
390 for (j = 0; j < 8; j++)
391 if (ccb->timeslot_spec[8 * i + j].tti == 0) tmp ^= (0x80 >> j);
392 writeb(tmp, lbi + 0x30 + i);
395 spin_unlock_irqrestore(&mister_lock, flags);
399 * Set PCM framing - /proc/comx/comx0/framing
402 void slicecom_set_framing(int boardnum, int value)
404 u8 *lbi = slicecom_boards[boardnum].lbi;
406 spin_lock_irqsave(&mister_lock, flags);
408 slicecom_boards[boardnum].framing = value;
411 case SLICECOM_FRAMING_CRC4:
412 writeb(readb(lbi + FMR1) | 8, lbi + FMR1);
413 writeb((readb(lbi + FMR2) & 0x3f) | 0x80, lbi + FMR2);
415 case SLICECOM_FRAMING_NO_CRC4:
416 writeb(readb(lbi + FMR1) & 0xf7, lbi + FMR1);
417 writeb(readb(lbi + FMR2) & 0x3f, lbi + FMR2);
420 printk("slicecom: board %d: unhandled " FILENAME_FRAMING
421 " value %d\n", boardnum, value);
424 spin_unlock_irqrestore(&mister_lock, flags);
428 * Set PCM linecode - /proc/comx/comx0/linecode
431 void slicecom_set_linecode(int boardnum, int value)
433 u8 *lbi = slicecom_boards[boardnum].lbi;
435 spin_lock_irqsave(&mister_lock, flags);
437 slicecom_boards[boardnum].linecode = value;
440 case SLICECOM_LINECODE_HDB3:
441 writeb(readb(lbi + FMR0) | 0xf0, lbi + FMR0);
443 case SLICECOM_LINECODE_AMI:
444 writeb((readb(lbi + FMR0) & 0x0f) | 0xa0, lbi + FMR0);
447 printk("slicecom: board %d: unhandled " FILENAME_LINECODE
448 " value %d\n", boardnum, value);
450 spin_unlock_irqrestore(&mister_lock, flags);
454 * Set PCM clock source - /proc/comx/comx0/clock_source
457 void slicecom_set_clock_source(int boardnum, int value)
459 u8 *lbi = slicecom_boards[boardnum].lbi;
461 spin_lock_irqsave(&mister_lock, flags);
463 slicecom_boards[boardnum].clock_source = value;
466 case SLICECOM_CLOCK_SOURCE_LINE:
467 writeb(readb(lbi + LIM0) & ~1, lbi + LIM0);
469 case SLICECOM_CLOCK_SOURCE_INTERNAL:
470 writeb(readb(lbi + LIM0) | 1, lbi + LIM0);
473 printk("slicecom: board %d: unhandled " FILENAME_CLOCK_SOURCE
474 " value %d\n", boardnum, value);
476 spin_unlock_irqrestore(&mister_lock, flags);
480 * Set loopbacks - /proc/comx/comx0/loopback
483 void slicecom_set_loopback(int boardnum, int value)
485 u8 *lbi = slicecom_boards[boardnum].lbi;
487 spin_lock_irqsave(&mister_lock, flags);
489 slicecom_boards[boardnum].loopback = value;
492 case SLICECOM_LOOPBACK_NONE:
493 writeb(readb(lbi + LIM0) & ~2, lbi + LIM0); /* Local Loop OFF */
494 writeb(readb(lbi + LIM1) & ~2, lbi + LIM1); /* Remote Loop OFF */
496 case SLICECOM_LOOPBACK_LOCAL:
497 writeb(readb(lbi + LIM1) & ~2, lbi + LIM1); /* Remote Loop OFF */
498 writeb(readb(lbi + LIM0) | 2, lbi + LIM0); /* Local Loop ON */
500 case SLICECOM_LOOPBACK_REMOTE:
501 writeb(readb(lbi + LIM0) & ~2, lbi + LIM0); /* Local Loop OFF */
502 writeb(readb(lbi + LIM1) | 2, lbi + LIM1); /* Remote Loop ON */
505 printk("slicecom: board %d: unhandled " FILENAME_LOOPBACK
506 " value %d\n", boardnum, value);
508 spin_unlock_irqrestore(&mister_lock, flags);
512 * Update E1 line status LEDs on the adapter
515 void slicecom_update_leds(munich_board_t * board)
517 u32 *bar1 = board->bar1;
518 u8 *lbi = board->lbi;
523 spin_lock_irqsave(&mister_lock, flags);
526 frs0 = readb(lbi + FRS0); /* FRS0 bits described on page 137 */
530 leds |= 0x2000; /* Green LED: Input signal seems to be OK, no LOS, no LFA */
532 leds |= 0x8000; /* Red LED: Receiving Remote Alarm */
534 writel(leds, MUNICH_VIRT(GPDATA));
536 if (leds == 0x2000 && !board->lineup)
539 for (i = 0; i < 32; i++)
541 if (board->twins[i] && (board->twins[i]->flags & IFF_RUNNING))
543 struct comx_channel *ch = board->twins[i]->priv;
545 if (!test_and_set_bit(0, &ch->lineup_pending))
547 ch->lineup_timer.function = comx_lineup_func;
548 ch->lineup_timer.data = (unsigned long)board->twins[i];
549 ch->lineup_timer.expires = jiffies + HZ * ch->lineup_delay;
550 add_timer(&ch->lineup_timer);
555 else if (leds != 0x2000 && board->lineup)
558 for (i = 0; i < 32; i++)
559 if (board->twins[i] && (board->twins[i]->flags & IFF_RUNNING))
561 struct comx_channel *ch = board->twins[i]->priv;
563 if (test_and_clear_bit(0, &ch->lineup_pending))
564 del_timer(&ch->lineup_timer);
565 else if (ch->line_status & LINE_UP)
567 ch->line_status &= ~LINE_UP;
569 ch->LINE_status(board->twins[i], ch->line_status);
573 spin_unlock_irqrestore(&mister_lock, flags);
577 * This function gets called every second when the FALC issues the interrupt.
578 * Hardware counters contain error counts for last 1-second time interval.
579 * We add them to the global counters here.
580 * Read rfc2495 to understand this.
583 void slicecom_update_line_counters(munich_board_t * board)
585 e1_stats_t *curr_int = &board->intervals[board->current_interval];
587 u8 *lbi = board->lbi;
589 unsigned framing_errors, code_violations, path_code_violations, crc4_errors,
591 unsigned slip_detected, /* this one has logical value, not the number of slips! */
592 out_of_frame_defect, /* logical value */
593 ais_defect, /* logical value */
594 errored_sec, bursty_err_sec, severely_err_sec = 0, failure_sec;
595 u8 isr2, isr3, isr5, frs0;
597 spin_lock_irqsave(&mister_lock, flags);
599 isr2 = readb(lbi + ISR2); /* ISR0-5 described on page 156 */
600 isr3 = readb(lbi + ISR3);
601 isr5 = readb(lbi + ISR5);
602 frs0 = readb(lbi + FRS0); /* FRS0 described on page 137 */
606 code_violations = readb(lbi + CVCL) + (readb(lbi + CVCH) << 8);
607 framing_errors = readb(lbi + FECL) + (readb(lbi + FECH) << 8);
608 crc4_errors = readb(lbi + CEC1L) + (readb(lbi + CEC1H) << 8);
609 e_bit_errors = readb(lbi + EBCL) + (readb(lbi + EBCH) << 8);
610 slip_detected = isr3 & (ISR3_RSN | ISR3_RSP);
612 path_code_violations = framing_errors + crc4_errors;
614 curr_int->line_code_violations += code_violations;
615 curr_int->path_code_violations += path_code_violations;
616 curr_int->e_bit_errors += e_bit_errors;
618 /* Performance Defects: */
620 /* there was an LFA in the last second, but maybe disappeared: */
621 out_of_frame_defect = (isr2 & ISR2_LFA) || (frs0 & FRS0_LFA);
623 /* there was an AIS in the last second, but maybe disappeared: */
624 ais_defect = (isr2 & ISR2_AIS) || (frs0 & FRS0_AIS);
626 /* Performance Parameters: */
628 if (out_of_frame_defect)
629 curr_int->fr_loss_secs++;
631 curr_int->line_err_secs++;
633 errored_sec = ((board->framing == SLICECOM_FRAMING_NO_CRC4) &&
634 (code_violations)) || path_code_violations ||
635 out_of_frame_defect || slip_detected || ais_defect;
637 bursty_err_sec = !out_of_frame_defect && !ais_defect &&
638 (path_code_violations > 1) && (path_code_violations < 320);
640 switch (board->framing)
642 case SLICECOM_FRAMING_CRC4:
643 severely_err_sec = out_of_frame_defect ||
644 (path_code_violations >= 832);
646 case SLICECOM_FRAMING_NO_CRC4:
647 severely_err_sec = (code_violations >= 2048);
652 * failure_sec: true if there was a condition leading to a failure
653 * (and leading to unavailable state) in this second:
656 failure_sec = (isr2 & ISR2_RA) || (frs0 & FRS0_RRA) /* Remote/Far End/Distant Alarm Failure */
657 || ais_defect || out_of_frame_defect /* AIS or LOF Failure */
658 || (isr2 & ISR2_LOS) || (frs0 & FRS0_LOS) /* Loss Of Signal Failure */
659 || (board->loopback != SLICECOM_LOOPBACK_NONE); /* Loopback has been set */
661 if (board->is_unavailable)
663 if (severely_err_sec)
664 board->no_ses_seconds = 0;
666 board->no_ses_seconds++;
668 if ((board->no_ses_seconds >= 10) && !failure_sec)
670 board->is_unavailable = 0;
671 board->ses_seconds = 0;
672 board->no_ses_seconds = 0;
677 if (severely_err_sec)
678 board->ses_seconds++;
680 board->ses_seconds = 0;
682 if ((board->ses_seconds >= 10) || failure_sec)
684 board->is_unavailable = 1;
685 board->ses_seconds = 0;
686 board->no_ses_seconds = 0;
690 if (board->is_unavailable)
691 curr_int->unavail_secs++;
695 curr_int->slip_secs++;
696 curr_int->errored_secs += errored_sec;
697 curr_int->bursty_err_secs += bursty_err_sec;
698 curr_int->severely_err_secs += severely_err_sec;
701 /* the RFC does not say clearly which errors to count here, we try to count bit errors */
703 if (!board->is_unavailable && !severely_err_sec)
705 board->deg_cumulated_errors += code_violations;
706 board->deg_elapsed_seconds++;
707 if (board->deg_elapsed_seconds >= 60)
709 if (board->deg_cumulated_errors >= 123)
710 curr_int->degraded_mins++;
711 board->deg_cumulated_errors = 0;
712 board->deg_elapsed_seconds = 0;
717 board->elapsed_seconds++;
718 if (board->elapsed_seconds >= 900)
720 board->current_interval =
721 (board->current_interval + 1) % SLICECOM_BOARD_INTERVALS_SIZE;
722 memset((void *)&board->intervals[board->current_interval], 0,
724 board->elapsed_seconds = 0;
727 spin_unlock_irqrestore(&mister_lock, flags);
730 static void pcicom_modemline(unsigned long b)
732 munich_board_t *board = (munich_board_t *) b;
733 struct net_device *dev = board->twins[0];
734 struct comx_channel *ch = netdev_priv(dev);
737 regs = readl((void *)(&board->bar1[GPDATA]));
738 if ((ch->line_status & LINE_UP) && (regs & 0x0800))
740 ch->line_status &= ~LINE_UP;
744 ch->LINE_status(dev, ch->line_status);
748 if (!(ch->line_status & LINE_UP) && !(regs & 0x0800))
750 ch->line_status |= LINE_UP;
754 ch->LINE_status(dev, ch->line_status);
758 mod_timer((struct timer_list *)&board->modemline_timer, jiffies + HZ);
762 * Is it possible to transmit ?
763 * Called (may be called) by the protocol layer
766 static int MUNICH_txe(struct net_device *dev)
768 struct comx_channel *ch = netdev_priv(dev);
769 struct slicecom_privdata *hw = ch->HW_privdata;
771 return (hw->busy < TX_DESC_MAX - 1);
775 * Hw probe function. Detects all the boards in the system,
776 * and fills up slicecom_boards[] and pcicom_boards[]
777 * Returns 0 on success.
778 * We do not disable interrupts!
780 static int munich_probe(void)
784 int slicecom_boardnum;
788 munich_board_t *board;
790 for (boardnum = 0; boardnum < MAX_BOARDS; boardnum++)
792 pcicom_boards[boardnum].pci = 0;
793 pcicom_boards[boardnum].bar1 = 0;
794 pcicom_boards[boardnum].lbi = 0;
795 slicecom_boards[boardnum].pci = 0;
796 slicecom_boards[boardnum].bar1 = 0;
797 slicecom_boards[boardnum].lbi = 0;
802 slicecom_boardnum = 0;
806 boardnum < MAX_BOARDS && (pci = pci_find_device(PCI_VENDOR_ID_SIEMENS,
807 PCI_DEVICE_ID_SIEMENS_MUNICH32X, pci)); boardnum++)
809 if (pci_enable_device(pci))
812 printk("munich_probe: munich chip found, IRQ %d\n", pci->irq);
814 bar1 = ioremap_nocache(pci->resource[0].start, 0x100);
815 lbi = ioremap_nocache(pci->resource[1].start, 0x100);
819 pci_write_config_dword(pci, MUNICH_PCI_PCIRES, 0xe0000);
820 set_current_state(TASK_UNINTERRUPTIBLE);
822 pci_write_config_dword(pci, MUNICH_PCI_PCIRES, 0);
823 set_current_state(TASK_UNINTERRUPTIBLE);
825 /* check the type of the card */
826 writel(LREG0_MAGIC, MUNICH_VIRT(LREG0));
827 writel(LREG1_MAGIC, MUNICH_VIRT(LREG1));
828 writel(LREG2_MAGIC, MUNICH_VIRT(LREG2));
829 writel(LREG3_MAGIC, MUNICH_VIRT(LREG3));
830 writel(LREG4_MAGIC, MUNICH_VIRT(LREG4));
831 writel(LREG5_MAGIC, MUNICH_VIRT(LREG5));
832 writel(LCONF_MAGIC2,MUNICH_VIRT(LCONF)); /* enable the DMSM */
834 if ((readb(lbi + VSTR) == 0x13) || (readb(lbi + VSTR) == 0x10))
836 board = slicecom_boards + slicecom_boardnum;
837 sprintf((char *)board->devname, "slicecom%d",
842 else if ((readb(lbi + VSTR) == 0x6) || (readb(lbi + GIS) == 0x6))
844 board = pcicom_boards + pcicom_boardnum;
845 sprintf((char *)board->devname, "pcicom%d", pcicom_boardnum);
851 printk("munich_probe: %s board found\n", board->devname);
852 writel(LCONF_MAGIC1, MUNICH_VIRT(LCONF)); /* reset the DMSM */
856 board->framing = SLICECOM_FRAMING_DEFAULT;
857 board->linecode = SLICECOM_LINECODE_DEFAULT;
858 board->clock_source = SLICECOM_CLOCK_SOURCE_DEFAULT;
859 board->loopback = SLICECOM_LOOPBACK_DEFAULT;
860 board->owner = THIS_MODULE;
864 printk("munich_probe: Board error, VSTR: %02X\n",
866 iounmap((void *)bar1);
867 iounmap((void *)lbi);
872 printk("munich_probe: ioremap() failed, not enabling this board!\n");
873 /* .pci = NULL, so the MUNICH_open will not try to open it */
874 if (bar1) iounmap((void *)bar1);
875 if (lbi) iounmap((void *)lbi);
879 if (!pci && !boardnum)
881 printk("munich_probe: no PCI present!\n");
885 if (pcicom_boardnum + slicecom_boardnum == 0)
888 ("munich_probe: Couldn't find any munich board: vendor:device %x:%x not found\n",
889 PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_MUNICH32X);
895 printk("%d pcicom board(s) found.\n", pcicom_boardnum);
896 if (slicecom_boardnum)
897 printk("%d slicecom board(s) found.\n", slicecom_boardnum);
903 * Reset the hardware. Get called only from within this module if needed.
906 static int slicecom_reset(struct net_device *dev)
908 struct comx_channel *ch = netdev_priv(dev);
910 printk("slicecom_reset: resetting the hardware\n");
912 /* Begin to reset the hardware */
914 if (ch->HW_set_clock)
915 ch->HW_set_clock(dev);
925 * Called by the protocol layer
927 * FRAME_ACCEPTED: frame is being transmited, transmitter is busy
928 * FRAME_QUEUED: frame is being transmitted, there's more room in
929 * the transmitter for additional packet(s)
931 * FRAME_DROPPED: there was some error
934 static int MUNICH_send_packet(struct net_device *dev, struct sk_buff *skb)
936 struct comx_channel *ch = netdev_priv(dev);
937 struct slicecom_privdata *hw = ch->HW_privdata;
939 /* Send it to the debug facility too if needed: */
941 if (ch->debug_flags & DEBUG_HW_TX)
942 comx_debug_bytes(dev, skb->data, skb->len, "MUNICH_send_packet");
944 /* If the line is inactive, don't accept: */
946 /* TODO: atgondolni hogy mi is legyen itt */
947 /* if (!(ch->line_status & LINE_UP)) return FRAME_DROPPED; */
949 /* More check, to be sure: */
951 if (skb->len > TXBUFFER_SIZE)
953 ch->stats.tx_errors++;
958 /* Maybe you have to disable irq's while programming the hw: */
960 spin_lock_irqsave(&mister_lock, flags);
962 /* And more check: */
964 if (hw->busy >= TX_DESC_MAX - 1)
967 "%s: Transmitter called while busy... dropping frame, busy = %d\n",
968 dev->name, hw->busy);
969 spin_unlock_irqrestore(&mister_lock, flags);
971 return FRAME_DROPPED;
975 hw->tx_ring_hist[hw->busy]++;
978 printk("slicecom: %s: FATAL: busy = %d\n", dev->name, hw->busy);
981 // printk("slicecom: %s: _send_packet called, busy = %d\n", dev->name, hw->busy );
983 /* Packet can go, update stats: */
985 ch->stats.tx_packets++;
986 ch->stats.tx_bytes += skb->len;
988 /* Pass the packet to the HW: */
989 /* Step forward with the transmit descriptors: */
991 hw->tx_desc_ptr = (hw->tx_desc_ptr + 1) % TX_DESC_MAX;
993 memcpy(&(hw->tx_data[hw->tx_desc_ptr][0]), skb->data, skb->len);
994 hw->tx_desc[hw->tx_desc_ptr].no = skb->len;
996 /* We don't issue any command, just step with the HOLD bit */
998 hw->tx_desc[hw->tx_desc_ptr].hold = 1;
999 hw->tx_desc[(hw->tx_desc_ptr + TX_DESC_MAX - 1) % TX_DESC_MAX].hold = 0;
1004 /* csomag kerult a Tx ringbe: */
1010 if (ch->debug_flags & DEBUG_HW_TX)
1011 comx_debug(dev, "%s: MUNICH_send_packet was successful\n\n", dev->name);
1013 if (hw->busy >= TX_DESC_MAX - 1)
1015 spin_unlock_irqrestore(&mister_lock, flags);
1016 return FRAME_ACCEPTED;
1019 spin_unlock_irqrestore(&mister_lock, flags);
1023 return FRAME_QUEUED;
1027 * Interrupt handler routine.
1028 * Called by the Linux kernel.
1029 * BEWARE! The interrupts are enabled on the call!
1031 static irqreturn_t MUNICH_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1033 struct sk_buff *skb;
1036 int work; /* hany esemenyt kezeltem mar le */
1039 u32 stat, /* az esemenyek, amiket a ebben a loop korben le kell meg kezelni */
1040 race_stat = 0, /* race eseten ebben uzenek magamnak hogy mit kell meg lekezelni */
1041 ack; /* ezt fogom a vegen a STAT-ba irni, kiveszek belole 1-1 bitet ha */
1043 /* az adott dolgot nem kell ack-olni mert volt vele munkam, es */
1044 /* legjobb ha visszaterek ide megegyszer */
1045 munich_intq_t int_info;
1047 struct net_device *dev;
1048 struct comx_channel *ch;
1049 struct slicecom_privdata *hw;
1050 munich_board_t *board = (munich_board_t *) dev_id;
1053 // , boardnum = (int)dev_id;
1055 // board = munich_boards + boardnum;
1059 // Do not uncomment this under heavy load! :->
1060 // printk("MUNICH_interrupt: masked STAT=0x%08x, tiq=0x%08x, riq=0x%08x, piq=0x%08x\n", stat, board->tiq[0].all, board->riq[0].all, board->piq[0].all );
1062 for (work = 0; (stat = (race_stat | (readl(MUNICH_VIRT(STAT)) & ~STAT_NOT_HANDLED_BY_INTERRUPT))) && (work < MAX_WORK - 1); work++)
1064 ack = stat & (STAT_PRI | STAT_PTI | STAT_LBII);
1066 /* Handle the interrupt information in the Rx queue. We don't really trust */
1067 /* info from this queue, because it can be overflowed, so later check */
1068 /* every Rx ring for received packets. But there are some errors which can't */
1069 /* be counted from the Rx rings, so we parse it. */
1071 int_info = board->riq[board->riq_ptr];
1072 if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info van */
1074 ack &= ~STAT_PRI; /* don't ack the interrupt, we had some work to do */
1076 channel = PCM_INT_CHANNEL(int_info.all);
1077 dev = board->twins[channel];
1082 ("MUNICH_interrupt: got an Rx interrupt info for NULL device "
1083 "%s.twins[%d], int_info = 0x%08x\n", board->devname,
1084 channel, int_info.all);
1085 goto go_for_next_interrupt;
1088 ch = netdev_priv(dev);
1089 hw = (struct slicecom_privdata *)ch->HW_privdata;
1091 // printk("Rx STAT=0x%08x int_info=0x%08x rx_desc_ptr=%d rx_desc.status=0x%01x\n",
1092 // stat, int_info.all, hw->rx_desc_ptr, hw->rx_desc[ hw->rx_desc_ptr ].status );
1094 if (int_info.all & PCM_INT_HI)
1095 printk("SliceCOM: %s: Host Initiated interrupt\n", dev->name);
1096 if (int_info.all & PCM_INT_IFC)
1097 printk("SliceCOM: %s: Idle/Flag Change\n", dev->name);
1098 /* TOD: jo ez az Idle/Flag Change valamire? - azonnal latszik belole hogy mikor ad a masik oldal */
1099 /* TOD: ilyen IT most nem is jon, mert ki van maszkolva az interrupt, biztosan kell ez? */
1101 if (int_info.all & PCM_INT_FO)
1102 /* Internal buffer (RB) overrun */
1103 ch->stats.rx_over_errors++; /* TOD: Ez azt jelenti hogy a belso RB nem volt hozzaferheto, es ezert kihagyott valamit. De nem csak csomag lehetett, hanem esemeny, stb. is. lasd page 247. Ezzel a 'cat status'-hoz igazodok, de a netdevice.h szerint nem egyertelmu hogy ide ez kellene. Nem lehet hogy rx_missed ? */
1104 /* DE: nem gotozok sehova, elvileg jo igy */
1105 /* kesobb meg visszaterek az FO-ra, ha packet-FO volt. Keresd a "packet-FO"-t. */
1106 if (int_info.all & PCM_INT_FI) /* frame received, but we do not trust the int_info queue */
1107 if (int_info.all & PCM_INT_SF)
1108 { /* Short Frame: rovidebb mint a CRC */
1109 /* "rovidebb mint CRC+2byte" vizsgalat a "CRC+2"-nel */
1110 ch->stats.rx_length_errors++; /* TOD: noveljem? ne noveljem? */
1111 goto go_for_next_interrupt;
1114 go_for_next_interrupt: /* One step in the interrupt queue */
1115 board->riq[board->riq_ptr].all = 0; /* megjelolom hogy itt meg nem jart a hw */
1116 board->riq_ptr = (board->riq_ptr + 1) % MUNICH_INTQMAX;
1120 /* Check every Rx ring for incomed packets: */
1122 for (channel = 0; channel < 32; channel++)
1124 dev = board->twins[channel];
1128 ch = netdev_priv(dev);
1129 hw = (struct slicecom_privdata *)ch->HW_privdata;
1131 rx_status = hw->rx_desc[hw->rx_desc_ptr].status;
1133 if (!(rx_status & 0x80)) /* mar jart itt a hardver */
1135 ack &= ~STAT_PRI; /* Don't ack, we had some work */
1137 /* Ez most egy kicsit zuros, mert itt mar nem latom az int_infot */
1138 if (rx_status & RX_STATUS_ROF)
1139 ch->stats.rx_over_errors++; /* TOD: 'cat status'-hoz igazodok */
1141 if (rx_status & RX_STATUS_RA)
1142 /* Abort received or issued on channel */
1143 ch->stats.rx_frame_errors++; /* or HOLD bit in the descriptor */
1144 /* TOD: 'cat status'-hoz igazodok */
1146 if (rx_status & RX_STATUS_LFD)
1147 { /* Long Frame (longer then MFL in the MODE1) */
1148 ch->stats.rx_length_errors++;
1149 goto go_for_next_frame;
1152 if (rx_status & RX_STATUS_NOB)
1153 { /* Not n*8 bits long frame - frame alignment */
1154 ch->stats.rx_frame_errors++; /* ez viszont nem igazodik a 'cat status'-hoz */
1155 goto go_for_next_frame;
1158 if (rx_status & RX_STATUS_CRCO)
1160 ch->stats.rx_crc_errors++;
1161 goto go_for_next_frame;
1164 if (rx_status & RX_STATUS_SF)
1165 { /* Short Frame: rovidebb mint CRC+2byte */
1166 ch->stats.rx_errors++; /* The HW does not set PCI_INT_ERR bit for this one, see page 246 */
1167 ch->stats.rx_length_errors++;
1168 goto go_for_next_frame;
1173 printk("SliceCOM: %s: unhandled rx_status: 0x%02x\n",
1174 dev->name, rx_status);
1175 goto go_for_next_frame;
1178 /* frame received without errors: */
1180 length = hw->rx_desc[hw->rx_desc_ptr].bno;
1181 ch->stats.rx_packets++; /* Count only 'good' packets */
1182 ch->stats.rx_bytes += length;
1184 /* Allocate a larger skb and reserve the heading for efficiency: */
1186 if ((skb = dev_alloc_skb(length + 16)) == NULL)
1188 ch->stats.rx_dropped++;
1189 goto go_for_next_frame;
1192 /* Do bookkeeping: */
1194 skb_reserve(skb, 16);
1195 skb_put(skb, length);
1198 /* Now copy the data into the buffer: */
1200 memcpy(skb->data, &(hw->rx_data[hw->rx_desc_ptr][0]), length);
1202 /* DEL: UGLY HACK!!!! */
1203 if (*((int *)skb->data) == 0x02000000 &&
1204 *(((int *)skb->data) + 1) == 0x3580008f)
1206 printk("%s: swapping hack\n", dev->name);
1207 *((int *)skb->data) = 0x3580008f;
1208 *(((int *)skb->data) + 1) = 0x02000000;
1211 if (ch->debug_flags & DEBUG_HW_RX)
1212 comx_debug_skb(dev, skb, "MUNICH_interrupt receiving");
1214 /* Pass it to the protocol entity: */
1216 ch->LINE_rx(dev, skb);
1219 /* DEL: rafutott-e a HOLD bitre -detektalas */
1221 if( ((rx_desc_t*)phys_to_virt(board->ccb->current_rx_desc[channel]))->hold
1222 && ((rx_desc_t*)phys_to_virt(board->ccb->current_rx_desc[channel]))->status != 0xff)
1223 hw->rafutott++; /* rafutott: hanyszor volt olyan hogy a current descriptoron HOLD bit volt, es a hw mar befejezte az irast (azaz a hw rafutott a HOLD bitre) */
1226 // if( jiffies % 2 ) /* DELL: okozzunk egy kis Rx ring slipet :) */
1228 /* Step forward with the receive descriptors: */
1229 /* if you change this, change the copy of it below too! Search for: "RxSlip" */
1230 hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 1) % RX_DESC_MAX].hold = 1;
1231 hw->rx_desc[hw->rx_desc_ptr].status = 0xFF; /* megjelolom hogy itt meg nem jart a hw */
1232 hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 2) % RX_DESC_MAX].hold = 0;
1233 hw->rx_desc_ptr = (hw->rx_desc_ptr + 1) % RX_DESC_MAX;
1243 // if( stat & STAT_PTI ) /* TOD: primko megvalositas: mindig csak egy esemenyt dolgozok fel, */
1244 /* es nem torlom a STAT-ot, ezert ujra visszajon ide a rendszer. Amikor */
1245 /* jon interrupt, de nincs mit feldolgozni, akkor torlom a STAT-ot. */
1246 /* 'needs a rewrite', de elso megoldasnak jo lesz */
1248 int_info = board->tiq[board->tiq_ptr];
1249 if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info van */
1251 ack &= ~STAT_PTI; /* don't ack the interrupt, we had some work to do */
1253 channel = PCM_INT_CHANNEL(int_info.all);
1254 dev = board->twins[channel];
1258 printk("MUNICH_interrupt: got a Tx interrupt for NULL device "
1259 "%s.twins[%d], int_info = 0x%08x\n",
1260 board->isx21 ? "pcicom" : "slicecom", channel, int_info.all);
1261 goto go_for_next_tx_interrupt;
1264 ch = netdev_priv(dev);
1265 hw = (struct slicecom_privdata *)ch->HW_privdata;
1267 // printk("Tx STAT=0x%08x int_info=0x%08x tiq_ptr=%d\n", stat, int_info.all, board->tiq_ptr );
1269 if (int_info.all & PCM_INT_FE2)
1270 { /* "Tx available" */
1273 else if (int_info.all & PCM_INT_FO)
1274 { /* Internal buffer (RB) overrun */
1275 ch->stats.rx_over_errors++;
1279 printk("slicecom: %s: unhandled Tx int_info: 0x%08x\n",
1280 dev->name, int_info.all);
1283 go_for_next_tx_interrupt:
1284 board->tiq[board->tiq_ptr].all = 0;
1285 board->tiq_ptr = (board->tiq_ptr + 1) % MUNICH_INTQMAX;
1288 /* Check every Tx ring for incoming packets: */
1290 for (channel = 0; channel < 32; channel++)
1292 dev = board->twins[channel];
1298 ch = netdev_priv(dev);
1299 hw = (struct slicecom_privdata *)ch->HW_privdata;
1301 /* We don't trust the "Tx available" info from the TIQ, but check */
1302 /* every ring if there is some free room */
1304 if (ch->init_status && netif_running(dev))
1306 newbusy = ( TX_DESC_MAX + (& hw->tx_desc[ hw->tx_desc_ptr ]) -
1307 (tx_desc_t*)phys_to_virt(board->ccb->current_tx_desc[ hw->channel ]) ) % TX_DESC_MAX;
1311 printk("slicecom: %s: FATAL: fresly computed busy = %d, HW: 0x%p, SW: 0x%p\n",
1313 phys_to_virt(board->ccb->current_tx_desc[hw->channel]),
1314 & hw->tx_desc[hw->tx_desc_ptr]);
1317 /* Fogyott valami a Tx ringbol? */
1319 if (newbusy < hw->busy)
1321 // ack &= ~STAT_PTI; /* Don't ack, we had some work */
1324 ch->LINE_tx(dev); /* Report it to protocol driver */
1326 else if (newbusy > hw->busy)
1327 printk("slicecom: %s: newbusy > hw->busy, this should not happen!\n", dev->name);
1333 int_info = board->piq[board->piq_ptr];
1334 if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info van */
1336 ack &= ~STAT_LBII; /* don't ack the interrupt, we had some work to do */
1338 /* We do not really use (yet) the interrupt info from this queue, */
1340 // printk("slicecom: %s: LBI Interrupt event: %08x\n", board->devname, int_info.all);
1344 slicecom_update_leds(board);
1345 slicecom_update_line_counters(board);
1348 goto go_for_next_lbi_interrupt; /* To avoid warning about unused label */
1350 go_for_next_lbi_interrupt: /* One step in the interrupt queue */
1351 board->piq[board->piq_ptr].all = 0; /* megjelolom hogy itt meg nem jart a hw */
1352 board->piq_ptr = (board->piq_ptr + 1) % MUNICH_PIQMAX;
1356 writel(ack, MUNICH_VIRT(STAT));
1358 if (stat & STAT_TSPA)
1360 // printk("slicecom: %s: PCM TSP Asynchronous\n", board->devname);
1361 writel(STAT_TSPA, MUNICH_VIRT(STAT));
1365 if (stat & STAT_RSPA)
1367 // printk("slicecom: %s: PCM RSP Asynchronous\n", board->devname);
1368 writel(STAT_RSPA, MUNICH_VIRT(STAT));
1373 printk("MUNICH_interrupt: unhandled interrupt, STAT=0x%08x\n",
1375 writel(stat, MUNICH_VIRT(STAT)); /* ha valamit megsem kezeltunk le, azert ack-ot kuldunk neki */
1379 board->histogram[work]++;
1381 /* We can miss these if we reach the MAX_WORK */
1382 /* Count it to see how often it happens */
1384 if (race_stat & STAT_PRI)
1385 board->stat_pri_races_missed++;
1386 if (race_stat & STAT_PTI)
1387 board->stat_pti_races_missed++;
1392 * Hardware open routine.
1393 * Called by comx (upper) layer when the user wants to bring up the interface
1395 * Initializes hardware, allocates resources etc.
1396 * Returns 0 on OK, or standard error value on error.
1399 static int MUNICH_open(struct net_device *dev)
1401 struct comx_channel *ch = netdev_priv(dev);
1402 struct slicecom_privdata *hw = ch->HW_privdata;
1403 struct proc_dir_entry *procfile = ch->procdir->subdir;
1404 munich_board_t *board;
1410 unsigned long flags, jiffs;
1413 u32 timeslots = hw->timeslots;
1415 board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
1420 /* TODO: a timeslotok ellenorzese kell majd ide .. hat, biztos? mar a write_proc-ban is
1421 ellenorzom valamennyire.
1422 if (!dev->io || !dev->irq) return -ENODEV;
1427 printk("MUNICH_open: no %s board with boardnum = %d\n",
1428 ch->hardware->name, hw->boardnum);
1432 spin_lock_irqsave(&mister_lock, flags);
1433 /* lock the section to avoid race with multiple opens and make sure
1434 that no interrupts get called while this lock is active */
1436 if (board->use_count == 0) /* bring up the board if it was unused */
1437 /* if fails, frees allocated resources and returns. */
1438 /* TOD: is it safe? nem kellene resetelni a kartyat? */
1440 printk("MUNICH_open: %s: bringing up board\n", board->devname);
1442 /* Clean up the board's static struct if messed: */
1444 for (i = 0; i < 32; i++)
1445 board->twins[i] = NULL;
1446 for (i = 0; i < MAX_WORK; i++)
1447 board->histogram[i] = 0;
1452 board->ccb = kmalloc(sizeof(munich_ccb_t), GFP_KERNEL);
1453 if (board->ccb == NULL)
1455 spin_unlock_irqrestore(&mister_lock, flags);
1458 memset((void *)board->ccb, 0, sizeof(munich_ccb_t));
1459 board->ccb->csa = virt_to_phys(board->ccb);
1461 for (i = 0; i < 32; i++)
1463 ccb->timeslot_spec[i].tti = 1;
1464 ccb->timeslot_spec[i].rti = 1;
1467 /* Interrupt queues: */
1469 board->tiq = kmalloc(MUNICH_INTQSIZE, GFP_KERNEL);
1470 if (board->tiq == NULL)
1472 spin_unlock_irqrestore(&mister_lock, flags);
1475 memset((void *)board->tiq, 0, MUNICH_INTQSIZE);
1477 board->riq = kmalloc(MUNICH_INTQSIZE, GFP_KERNEL);
1478 if (board->riq == NULL)
1480 spin_unlock_irqrestore(&mister_lock, flags);
1483 memset((void *)board->riq, 0, MUNICH_INTQSIZE);
1485 board->piq = kmalloc(MUNICH_PIQSIZE, GFP_KERNEL);
1486 if (board->piq == NULL)
1488 spin_unlock_irqrestore(&mister_lock, flags);
1491 memset((void *)board->piq, 0, MUNICH_PIQSIZE);
1501 /* (char*) cast to avoid warning about discarding volatile: */
1502 if (request_irq(board->pci->irq, MUNICH_interrupt, 0,
1503 (char *)board->devname, (void *)board))
1505 printk("MUNICH_open: %s: unable to obtain irq %d\n", board->devname,
1507 /* TOD: free other resources (a sok malloc feljebb) */
1508 spin_unlock_irqrestore(&mister_lock, flags);
1511 board->irq = board->pci->irq; /* csak akkor legyen != 0, ha tenyleg le van foglalva nekunk */
1513 /* Programming device: */
1515 /* Reset the board like a power-on: */
1517 - It is not a real power-on: if a DMA transaction fails with master abort, the board
1518 stays in half-dead state.
1519 - It doesn't reset the FALC line driver */
1521 pci_write_config_dword(board->pci, MUNICH_PCI_PCIRES, 0xe0000);
1522 set_current_state(TASK_UNINTERRUPTIBLE);
1523 schedule_timeout(1);
1524 pci_write_config_dword(board->pci, MUNICH_PCI_PCIRES, 0);
1525 set_current_state(TASK_UNINTERRUPTIBLE);
1526 schedule_timeout(1);
1528 writel(virt_to_phys(&ccb->csa), MUNICH_VIRT(CCBA));
1529 writel(virt_to_phys( board->tiq ), MUNICH_VIRT(TIQBA));
1530 writel(MUNICH_INTQLEN, MUNICH_VIRT(TIQL));
1531 writel(virt_to_phys( board->riq ), MUNICH_VIRT(RIQBA));
1532 writel(MUNICH_INTQLEN, MUNICH_VIRT(RIQL));
1533 writel(virt_to_phys( board->piq ), MUNICH_VIRT(PIQBA));
1534 writel(MUNICH_PIQLEN, MUNICH_VIRT(PIQL));
1536 /* Put the magic values into the registers: */
1538 writel(MODE1_MAGIC, MUNICH_VIRT(MODE1));
1539 writel(MODE2_MAGIC, MUNICH_VIRT(MODE2));
1541 writel(LREG0_MAGIC, MUNICH_VIRT(LREG0));
1542 writel(LREG1_MAGIC, MUNICH_VIRT(LREG1));
1543 writel(LREG2_MAGIC, MUNICH_VIRT(LREG2));
1544 writel(LREG3_MAGIC, MUNICH_VIRT(LREG3));
1545 writel(LREG4_MAGIC, MUNICH_VIRT(LREG4));
1546 writel(LREG5_MAGIC, MUNICH_VIRT(LREG5));
1548 writel(LCONF_MAGIC1, MUNICH_VIRT(LCONF)); /* reset the DMSM */
1549 writel(LCONF_MAGIC2, MUNICH_VIRT(LCONF)); /* enable the DMSM */
1551 writel(~0, MUNICH_VIRT(TXPOLL));
1552 writel(board->isx21 ? 0x1400 : 0xa000, MUNICH_VIRT(GPDIR));
1554 if (readl(MUNICH_VIRT(STAT))) writel(readl(MUNICH_VIRT(STAT)), MUNICH_VIRT(STAT));
1556 ccb->action_spec = CCB_ACTIONSPEC_RES | CCB_ACTIONSPEC_IA;
1557 writel(CMD_ARPCM, MUNICH_VIRT(CMD)); /* Start the PCM core reset */
1558 set_current_state(TASK_UNINTERRUPTIBLE);
1559 schedule_timeout(1);
1561 stat = 0; /* Wait for the action to complete max. 1 second */
1563 while (!((stat = readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCMF)) && time_before(jiffies, jiffs + HZ))
1565 set_current_state(TASK_UNINTERRUPTIBLE);
1566 schedule_timeout(1);
1569 if (stat & STAT_PCMF)
1572 "MUNICH_open: %s: Initial ARPCM failed. STAT=0x%08x\n",
1573 board->devname, stat);
1574 writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT));
1575 free_irq(board->irq, (void *)board); /* TOD: free other resources too *//* maybe shut down hw? */
1577 spin_unlock_irqrestore(&mister_lock, flags);
1580 else if (!(stat & STAT_PCMA))
1583 "MUNICH_open: %s: Initial ARPCM timeout. STAT=0x%08x\n",
1584 board->devname, stat);
1585 free_irq(board->irq, (void *)board); /* TOD: free other resources too *//* maybe shut off the hw? */
1587 spin_unlock_irqrestore(&mister_lock, flags);
1591 writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT)); /* Acknowledge */
1593 if (board->isx21) writel(0, MUNICH_VIRT(GPDATA));
1595 printk("MUNICH_open: %s: succesful HW-open took %ld jiffies\n",
1596 board->devname, jiffies - jiffs);
1598 /* Set up the FALC hanging on the Local Bus: */
1602 writeb(0x0e, lbi + FMR1);
1603 writeb(0, lbi + LIM0);
1604 writeb(0xb0, lbi + LIM1); /* TODO: input threshold */
1605 writeb(0xf7, lbi + XPM0);
1606 writeb(0x02, lbi + XPM1);
1607 writeb(0x00, lbi + XPM2);
1608 writeb(0xf0, lbi + FMR0);
1609 writeb(0x80, lbi + PCD);
1610 writeb(0x80, lbi + PCR);
1611 writeb(0x00, lbi + LIM2);
1612 writeb(0x07, lbi + XC0);
1613 writeb(0x3d, lbi + XC1);
1614 writeb(0x05, lbi + RC0);
1615 writeb(0x00, lbi + RC1);
1616 writeb(0x83, lbi + FMR2);
1617 writeb(0x9f, lbi + XSW);
1618 writeb(0x0f, lbi + XSP);
1619 writeb(0x00, lbi + TSWM);
1620 writeb(0xe0, lbi + MODE);
1621 writeb(0xff, lbi + IDLE); /* Idle Code to send in unused timeslots */
1622 writeb(0x83, lbi + IPC); /* interrupt query line mode: Push/pull output, active high */
1623 writeb(0xbf, lbi + IMR3); /* send an interrupt every second */
1625 slicecom_set_framing(hw->boardnum, board->framing);
1626 slicecom_set_linecode(hw->boardnum, board->linecode);
1627 slicecom_set_clock_source(hw->boardnum, board->clock_source);
1628 slicecom_set_loopback(hw->boardnum, board->loopback);
1630 memset((void *)board->intervals, 0, sizeof(board->intervals));
1631 board->current_interval = 0;
1632 board->elapsed_seconds = 0;
1633 board->ses_seconds = 0;
1634 board->is_unavailable = 0;
1635 board->no_ses_seconds = 0;
1636 board->deg_elapsed_seconds = 0;
1637 board->deg_cumulated_errors = 0;
1640 /* Enable the interrupts last */
1641 /* These interrupts will be enabled. We do not need the others. */
1643 writel(readl(MUNICH_VIRT(IMASK)) & ~(STAT_PTI | STAT_PRI | STAT_LBII | STAT_TSPA | STAT_RSPA), MUNICH_VIRT(IMASK));
1646 spin_unlock_irqrestore(&mister_lock, flags);
1648 dev->irq = board->irq; /* hogy szep legyen az ifconfig outputja */
1649 ccb = board->ccb; /* TODO: ez igy csunya egy kicsit hogy benn is meg kinn is beletoltom :( */
1651 spin_lock_irqsave(&mister_lock, flags);
1653 set_current_state(TASK_UNINTERRUPTIBLE);
1654 schedule_timeout(1);
1656 /* Check if the selected timeslots aren't used already */
1658 for (i = 0; i < 32; i++)
1659 if (((1 << i) & timeslots) && !ccb->timeslot_spec[i].tti)
1661 printk("MUNICH_open: %s: timeslot %d already used by %s\n",
1662 dev->name, i, board->twins[ccb->timeslot_spec[i].txchannel]->name);
1663 spin_unlock_irqrestore(&mister_lock, flags);
1664 return -EBUSY; /* TODO: lehet hogy valami mas errno kellene? */
1667 /* find a free channel: */
1668 /* TODO: ugly, rewrite it */
1670 for (channel = 0; channel <= 32; channel++)
1673 { /* not found a free one */
1675 ("MUNICH_open: %s: FATAL: can not find a free channel - this should not happen!\n",
1677 spin_unlock_irqrestore(&mister_lock, flags);
1680 if (board->twins[channel] == NULL)
1681 break; /* found the first free one */
1684 board->lastcheck = jiffies; /* avoid checking uninitialized hardware channel */
1686 /* Open the channel. If fails, calls MUNICH_close() to properly free resources and stop the HW */
1688 hw->channel = channel;
1689 board->twins[channel] = dev;
1691 board->use_count++; /* meg nem nyitottuk meg a csatornat, de a twins-ben
1692 mar elfoglaltunk egyet, es ha a _close-t akarjuk hivni, akkor ez kell. */
1693 for (i = 0; i < 32; i++)
1694 if ((1 << i) & timeslots)
1696 ccb->timeslot_spec[i].tti = 0;
1697 ccb->timeslot_spec[i].txchannel = channel;
1698 ccb->timeslot_spec[i].txfillmask = ~0;
1700 ccb->timeslot_spec[i].rti = 0;
1701 ccb->timeslot_spec[i].rxchannel = channel;
1702 ccb->timeslot_spec[i].rxfillmask = ~0;
1705 if (!board->isx21) rework_idle_channels(dev);
1707 memset((void *)&(hw->tx_desc), 0, TX_DESC_MAX * sizeof(tx_desc_t));
1708 memset((void *)&(hw->rx_desc), 0, RX_DESC_MAX * sizeof(rx_desc_t));
1710 for (i = 0; i < TX_DESC_MAX; i++)
1712 hw->tx_desc[i].fe = 1;
1713 hw->tx_desc[i].fnum = 2;
1714 hw->tx_desc[i].data = virt_to_phys( & (hw->tx_data[i][0]) );
1715 hw->tx_desc[i].next = virt_to_phys( & (hw->tx_desc[ (i+1) % TX_DESC_MAX ]) );
1718 hw->tx_desc_ptr = 0; /* we will send an initial packet so it is correct: "oda irtunk utoljara" */
1720 hw->tx_desc[hw->tx_desc_ptr].hold = 1;
1721 hw->tx_desc[hw->tx_desc_ptr].no = 1; /* TOD: inkabb csak 0 hosszut kuldjunk ki az initkor? */
1723 for (i = 0; i < RX_DESC_MAX; i++)
1725 hw->rx_desc[i].no = RXBUFFER_SIZE;
1726 hw->rx_desc[i].data = virt_to_phys(&(hw->rx_data[i][0]));
1727 hw->rx_desc[i].next = virt_to_phys(&(hw->rx_desc[(i+1) % RX_DESC_MAX]));
1728 hw->rx_desc[i].status = 0xFF;
1730 hw->rx_desc_ptr = 0;
1732 hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 2) % RX_DESC_MAX].hold = 1;
1734 memset((void *)&ccb->channel_spec[channel], 0, sizeof(channel_spec_t));
1736 ccb->channel_spec[channel].ti = 0; /* Transmit off */
1737 ccb->channel_spec[channel].to = 1;
1738 ccb->channel_spec[channel].ta = 0;
1740 ccb->channel_spec[channel].th = 1; /* Transmit hold */
1742 ccb->channel_spec[channel].ri = 0; /* Receive off */
1743 ccb->channel_spec[channel].ro = 1;
1744 ccb->channel_spec[channel].ra = 0;
1746 ccb->channel_spec[channel].mode = 3; /* HDLC */
1748 ccb->action_spec = CCB_ACTIONSPEC_IN | (channel << 8);
1749 writel(CMD_ARPCM, MUNICH_VIRT(CMD));
1750 set_current_state(TASK_UNINTERRUPTIBLE);
1751 schedule_timeout(1);
1753 spin_unlock_irqrestore(&mister_lock, flags);
1757 while (!((stat = readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCMF)) && time_before(jiffies, jiffs + HZ))
1759 set_current_state(TASK_UNINTERRUPTIBLE);
1760 schedule_timeout(1);
1763 if (stat & STAT_PCMF)
1765 printk(KERN_ERR "MUNICH_open: %s: %s channel %d off failed\n",
1766 dev->name, board->devname, channel);
1767 writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT));
1771 else if (!(stat & STAT_PCMA))
1773 printk(KERN_ERR "MUNICH_open: %s: %s channel %d off timeout\n",
1774 dev->name, board->devname, channel);
1779 writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT));
1780 // printk("MUNICH_open: %s: succesful channel off took %ld jiffies\n", board->devname, jiffies-jiffs);
1782 spin_lock_irqsave(&mister_lock, flags);
1784 set_current_state(TASK_UNINTERRUPTIBLE);
1785 schedule_timeout(1);
1787 ccb->channel_spec[channel].ifc = 1; /* 1 .. 'Idle/Flag change' interrupt letiltva */
1788 ccb->channel_spec[channel].fit = 1;
1789 ccb->channel_spec[channel].nitbs = 1;
1790 ccb->channel_spec[channel].itbs = 2;
1792 /* TODOO: lehet hogy jo lenne igy, de utana kellene nezni hogy nem okoz-e fragmentaciot */
1793 // ccb->channel_spec[channel].itbs = 2 * number_of_timeslots;
1794 // printk("open: %s: number_of_timeslots: %d\n", dev->name, number_of_timeslots);
1796 ccb->channel_spec[channel].mode = 3; /* HDLC */
1797 ccb->channel_spec[channel].ftda = virt_to_phys(&(hw->tx_desc));
1798 ccb->channel_spec[channel].frda = virt_to_phys(&(hw->rx_desc[0]));
1800 ccb->channel_spec[channel].ti = 1; /* Transmit init */
1801 ccb->channel_spec[channel].to = 0;
1802 ccb->channel_spec[channel].ta = 1;
1804 ccb->channel_spec[channel].th = 0;
1806 ccb->channel_spec[channel].ri = 1; /* Receive init */
1807 ccb->channel_spec[channel].ro = 0;
1808 ccb->channel_spec[channel].ra = 1;
1810 ccb->action_spec = CCB_ACTIONSPEC_ICO | (channel << 8);
1811 writel(CMD_ARPCM, MUNICH_VIRT(CMD)); /* Start the channel init */
1812 set_current_state(TASK_UNINTERRUPTIBLE);
1813 schedule_timeout(1);
1815 spin_unlock_irqrestore(&mister_lock, flags);
1817 stat = 0; /* Wait for the action to complete max. 1 second */
1819 while (!((stat = readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCMF)) && time_before(jiffies, jiffs + HZ))
1821 set_current_state(TASK_UNINTERRUPTIBLE);
1822 schedule_timeout(1);
1825 if (stat & STAT_PCMF)
1827 printk(KERN_ERR "MUNICH_open: %s: channel open ARPCM failed\n",
1829 writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT));
1833 else if (!(stat & STAT_PCMA))
1835 printk(KERN_ERR "MUNICH_open: %s: channel open ARPCM timeout\n",
1841 writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT));
1842 // printk("MUNICH_open: %s: succesful channel open took %ld jiffies\n", board->devname, jiffies-jiffs);
1844 spin_lock_irqsave(&mister_lock, flags);
1846 ccb->channel_spec[channel].nitbs = 0; /* once ITBS defined, these must be 0 */
1847 ccb->channel_spec[channel].itbs = 0;
1851 init_timer(&board->modemline_timer);
1852 board->modemline_timer.data = (unsigned long)board;
1853 board->modemline_timer.function = pcicom_modemline;
1854 board->modemline_timer.expires = jiffies + HZ;
1855 add_timer((struct timer_list *)&board->modemline_timer);
1858 /* It is done. Declare that we're open: */
1859 hw->busy = 0; /* It may be 1 if the frame at Tx init already ended, but it is not */
1860 /* a real problem: we compute hw->busy on every interrupt */
1862 ch->init_status |= HW_OPEN;
1864 /* Initialize line state: */
1866 ch->line_status |= LINE_UP;
1868 ch->line_status &= ~LINE_UP;
1870 /* Remove w attribute from /proc files associated to hw parameters:
1871 no write when the device is open */
1873 for (; procfile; procfile = procfile->next)
1874 if (strcmp(procfile->name, FILENAME_BOARDNUM) == 0 ||
1875 strcmp(procfile->name, FILENAME_TIMESLOTS) == 0)
1876 procfile->mode = S_IFREG | 0444;
1878 spin_unlock_irqrestore(&mister_lock, flags);
1884 * Hardware close routine.
1885 * Called by comx (upper) layer when the user wants to bring down the interface
1887 * We also call it from MUNICH_open, if the open fails.
1888 * Brings down hardware, frees resources, stops receiver
1889 * Returns 0 on OK, or standard error value on error.
1892 static int MUNICH_close(struct net_device *dev)
1894 struct comx_channel *ch = netdev_priv(dev);
1895 struct slicecom_privdata *hw = ch->HW_privdata;
1896 struct proc_dir_entry *procfile = ch->procdir->subdir;
1897 munich_board_t *board;
1901 u32 timeslots = hw->timeslots;
1902 int stat, i, channel = hw->channel;
1903 unsigned long jiffs;
1905 board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
1911 del_timer((struct timer_list *)&board->modemline_timer);
1913 spin_lock_irqsave(&mister_lock, flags);
1915 set_current_state(TASK_UNINTERRUPTIBLE);
1916 schedule_timeout(1);
1918 /* Disable receiver for the channel: */
1920 for (i = 0; i < 32; i++)
1921 if ((1 << i) & timeslots)
1923 ccb->timeslot_spec[i].tti = 1;
1924 ccb->timeslot_spec[i].txfillmask = 0; /* just to be double-sure :) */
1926 ccb->timeslot_spec[i].rti = 1;
1927 ccb->timeslot_spec[i].rxfillmask = 0;
1930 if (!board->isx21) rework_idle_channels(dev);
1932 ccb->channel_spec[channel].ti = 0; /* Receive off, Transmit off */
1933 ccb->channel_spec[channel].to = 1;
1934 ccb->channel_spec[channel].ta = 0;
1935 ccb->channel_spec[channel].th = 1;
1937 ccb->channel_spec[channel].ri = 0;
1938 ccb->channel_spec[channel].ro = 1;
1939 ccb->channel_spec[channel].ra = 0;
1941 board->twins[channel] = NULL;
1943 ccb->action_spec = CCB_ACTIONSPEC_IN | (channel << 8);
1944 writel(CMD_ARPCM, MUNICH_VIRT(CMD));
1945 set_current_state(TASK_UNINTERRUPTIBLE);
1946 schedule_timeout(1);
1948 spin_unlock_irqrestore(&mister_lock, flags);
1952 while (!((stat = readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCMF)) && time_before(jiffies, jiffs + HZ))
1954 set_current_state(TASK_UNINTERRUPTIBLE);
1955 schedule_timeout(1);
1958 if (stat & STAT_PCMF)
1961 "MUNICH_close: %s: FATAL: channel off ARPCM failed, not closing!\n",
1963 writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT));
1964 /* If we return success, the privdata (and the descriptor list) will be freed */
1967 else if (!(stat & STAT_PCMA))
1968 printk(KERN_ERR "MUNICH_close: %s: channel off ARPCM timeout\n",
1971 writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT));
1972 // printk("MUNICH_close: %s: channel off took %ld jiffies\n", board->devname, jiffies-jiffs);
1974 spin_lock_irqsave(&mister_lock, flags);
1976 if (board->use_count) board->use_count--;
1978 if (!board->use_count) /* we were the last user of the board */
1980 printk("MUNICH_close: bringing down board %s\n", board->devname);
1982 /* program down the board: */
1984 writel(0x0000FF7F, MUNICH_VIRT(IMASK)); /* do not send any interrupts */
1985 writel(0, MUNICH_VIRT(CMD)); /* stop the timer if someone started it */
1986 writel(~0U, MUNICH_VIRT(STAT)); /* if an interrupt came between the cli()-sti(), quiet it */
1987 if (ch->hardware == &pcicomhw)
1988 writel(0x1400, MUNICH_VIRT(GPDATA));
1990 /* Put the board into 'reset' state: */
1991 pci_write_config_dword(board->pci, MUNICH_PCI_PCIRES, 0xe0000);
1993 /* Free irq and other resources: */
1995 free_irq(board->irq, (void *)board); /* Ha nem inicializalta magat, akkor meg nincs irq */
1998 /* Free CCB and the interrupt queues */
1999 if (board->ccb) kfree((void *)board->ccb);
2000 if (board->tiq) kfree((void *)board->tiq);
2001 if (board->riq) kfree((void *)board->riq);
2002 if (board->piq) kfree((void *)board->piq);
2004 board->tiq = board->riq = board->piq = NULL;
2007 /* Enable setting of hw parameters */
2008 for (; procfile; procfile = procfile->next)
2009 if (strcmp(procfile->name, FILENAME_BOARDNUM) == 0 ||
2010 strcmp(procfile->name, FILENAME_TIMESLOTS) == 0)
2011 procfile->mode = S_IFREG | 0644;
2013 /* We're not open anymore */
2014 ch->init_status &= ~HW_OPEN;
2016 spin_unlock_irqrestore(&mister_lock, flags);
2022 * Give (textual) status information.
2023 * The text it returns will be a part of what appears when the user does a
2024 * cat /proc/comx/comx[n]/status
2025 * Don't write more than PAGESIZE.
2026 * Return value: number of bytes written (length of the string, incl. 0)
2029 static int MUNICH_minden(struct net_device *dev, char *page)
2031 struct comx_channel *ch = netdev_priv(dev);
2032 struct slicecom_privdata *hw = ch->HW_privdata;
2033 munich_board_t *board;
2034 struct net_device *devp;
2037 e1_stats_t *curr_int, *prev_int;
2038 e1_stats_t last4, last96; /* sum of last 4, resp. last 96 intervals */
2039 unsigned *sump, /* running pointer for the sum data */
2040 *p; /* running pointer for the interval data */
2048 board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
2051 curr_int = &board->intervals[board->current_interval];
2054 intervals[(board->current_interval + SLICECOM_BOARD_INTERVALS_SIZE -
2055 1) % SLICECOM_BOARD_INTERVALS_SIZE];
2059 frs0 = readb(lbi + FRS0);
2060 fmr2 = readb(lbi + FMR2);
2061 len += scnprintf(page + len, PAGE_SIZE - len, "Controller status:\n");
2063 len += scnprintf(page + len, PAGE_SIZE - len, "\tNo alarms\n");
2066 if (frs0 & FRS0_LOS)
2067 len += scnprintf(page + len, PAGE_SIZE - len, "\tLoss Of Signal\n");
2070 if (frs0 & FRS0_AIS)
2071 len += scnprintf(page + len, PAGE_SIZE - len,
2072 "\tAlarm Indication Signal\n");
2075 if (frs0 & FRS0_AUXP)
2076 len += scnprintf(page + len, PAGE_SIZE - len,
2077 "\tAuxiliary Pattern Indication\n");
2078 if (frs0 & FRS0_LFA)
2079 len += scnprintf(page + len, PAGE_SIZE - len,
2080 "\tLoss of Frame Alignment\n");
2083 if (frs0 & FRS0_RRA)
2084 len += scnprintf(page + len, PAGE_SIZE - len,
2085 "\tReceive Remote Alarm\n");
2087 /* You can't set this framing with the /proc interface, but it */
2088 /* may be good to have here this alarm if you set it by hand: */
2090 if ((board->framing == SLICECOM_FRAMING_CRC4) &&
2092 len += scnprintf(page + len, PAGE_SIZE - len,
2093 "\tLoss of CRC4 Multiframe Alignment\n");
2095 if (((fmr2 & 0xc0) == 0xc0) && (frs0 & FRS0_NMF))
2096 len += scnprintf(page + len, PAGE_SIZE - len,
2097 "\tNo CRC4 Multiframe alignment Found after 400 msec\n");
2103 frs1 = readb(lbi + FRS1);
2104 if (FRS1_XLS & frs1)
2105 len += scnprintf(page + len, PAGE_SIZE - len,
2106 "\tTransmit Line Short\n");
2108 /* debug Rx ring: DEL: - vagy meghagyni, de akkor legyen kicsit altalanosabb */
2111 len += scnprintf(page + len, PAGE_SIZE - len, "Rx ring:\n");
2112 len += scnprintf(page + len, PAGE_SIZE - len, "\trafutott: %d\n", hw->rafutott);
2113 len += scnprintf(page + len, PAGE_SIZE - len,
2114 "\tlastcheck: %ld, jiffies: %ld\n", board->lastcheck, jiffies);
2115 len += scnprintf(page + len, PAGE_SIZE - len, "\tbase: %08x\n",
2116 (u32) virt_to_phys(&hw->rx_desc[0]));
2117 len += scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %d\n",
2119 len += scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %08x\n",
2120 (u32) virt_to_phys(&hw->rx_desc[hw->rx_desc_ptr]));
2121 len += scnprintf(page + len, PAGE_SIZE - len, "\thw_curr_ptr: %08x\n",
2122 board->ccb->current_rx_desc[hw->channel]);
2124 for (i = 0; i < RX_DESC_MAX; i++)
2125 len += scnprintf(page + len, PAGE_SIZE - len, "\t%08x %08x %08x %08x\n",
2126 *((u32 *) & hw->rx_desc[i] + 0),
2127 *((u32 *) & hw->rx_desc[i] + 1),
2128 *((u32 *) & hw->rx_desc[i] + 2),
2129 *((u32 *) & hw->rx_desc[i] + 3));
2133 len += scnprintf(page + len, PAGE_SIZE - len,
2134 "Interfaces using this board: (channel-group, interface, timeslots)\n");
2135 for (i = 0; i < 32; i++)
2137 devp = board->twins[i];
2141 ((struct slicecom_privdata *)((struct comx_channel *)devp->
2142 priv)->HW_privdata)->
2144 len += scnprintf(page + len, PAGE_SIZE - len, "\t%2d %s: ", i,
2146 for (j = 0; j < 32; j++)
2147 if ((1 << j) & timeslots)
2148 len += scnprintf(page + len, PAGE_SIZE - len, "%d ", j);
2149 len += scnprintf(page + len, PAGE_SIZE - len, "\n");
2154 len += scnprintf(page + len, PAGE_SIZE - len, "Interrupt work histogram:\n");
2155 for (i = 0; i < MAX_WORK; i++)
2156 len += scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i,
2157 board->histogram[i], (i &&
2158 ((i + 1) % 4 == 0 ||
2159 i == MAX_WORK - 1)) ? '\n' : ' ');
2161 len += scnprintf(page + len, PAGE_SIZE - len, "Tx ring histogram:\n");
2162 for (i = 0; i < TX_DESC_MAX; i++)
2163 len += scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i,
2164 hw->tx_ring_hist[i], (i &&
2165 ((i + 1) % 4 == 0 ||
2167 TX_DESC_MAX - 1)) ? '\n' : ' ');
2172 memset((void *)&last4, 0, sizeof(last4));
2173 memset((void *)&last96, 0, sizeof(last96));
2175 /* Calculate the sum of last 4 intervals: */
2177 for (i = 1; i <= 4; i++)
2179 p = (unsigned *)&board->intervals[(board->current_interval +
2180 SLICECOM_BOARD_INTERVALS_SIZE -
2181 i) % SLICECOM_BOARD_INTERVALS_SIZE];
2182 sump = (unsigned *)&last4;
2183 for (j = 0; j < (sizeof(e1_stats_t) / sizeof(unsigned)); j++)
2187 /* Calculate the sum of last 96 intervals: */
2189 for (i = 1; i <= 96; i++)
2191 p = (unsigned *)&board->intervals[(board->current_interval +
2192 SLICECOM_BOARD_INTERVALS_SIZE -
2193 i) % SLICECOM_BOARD_INTERVALS_SIZE];
2194 sump = (unsigned *)&last96;
2195 for (j = 0; j < (sizeof(e1_stats_t) / sizeof(unsigned)); j++)
2199 len += scnprintf(page + len, PAGE_SIZE - len,
2200 "Data in current interval (%d seconds elapsed):\n",
2201 board->elapsed_seconds);
2202 len += scnprintf(page + len, PAGE_SIZE - len,
2203 " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
2204 curr_int->line_code_violations,
2205 curr_int->path_code_violations, curr_int->e_bit_errors);
2206 len += scnprintf(page + len, PAGE_SIZE - len,
2207 " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
2208 curr_int->slip_secs, curr_int->fr_loss_secs,
2209 curr_int->line_err_secs, curr_int->degraded_mins);
2210 len += scnprintf(page + len, PAGE_SIZE - len,
2211 " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
2212 curr_int->errored_secs, curr_int->bursty_err_secs,
2213 curr_int->severely_err_secs, curr_int->unavail_secs);
2215 len += scnprintf(page + len, PAGE_SIZE - len,
2216 "Data in Interval 1 (15 minutes):\n");
2217 len += scnprintf(page + len, PAGE_SIZE - len,
2218 " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
2219 prev_int->line_code_violations,
2220 prev_int->path_code_violations, prev_int->e_bit_errors);
2221 len += scnprintf(page + len, PAGE_SIZE - len,
2222 " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
2223 prev_int->slip_secs, prev_int->fr_loss_secs,
2224 prev_int->line_err_secs, prev_int->degraded_mins);
2225 len += scnprintf(page + len, PAGE_SIZE - len,
2226 " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
2227 prev_int->errored_secs, prev_int->bursty_err_secs,
2228 prev_int->severely_err_secs, prev_int->unavail_secs);
2230 len += scnprintf(page + len, PAGE_SIZE - len,
2231 "Data in last 4 intervals (1 hour):\n");
2232 len += scnprintf(page + len, PAGE_SIZE - len,
2233 " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
2234 last4.line_code_violations, last4.path_code_violations,
2235 last4.e_bit_errors);
2236 len += scnprintf(page + len, PAGE_SIZE - len,
2237 " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
2238 last4.slip_secs, last4.fr_loss_secs, last4.line_err_secs,
2239 last4.degraded_mins);
2240 len += scnprintf(page + len, PAGE_SIZE - len,
2241 " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
2242 last4.errored_secs, last4.bursty_err_secs,
2243 last4.severely_err_secs, last4.unavail_secs);
2245 len += scnprintf(page + len, PAGE_SIZE - len,
2246 "Data in last 96 intervals (24 hours):\n");
2247 len += scnprintf(page + len, PAGE_SIZE - len,
2248 " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
2249 last96.line_code_violations, last96.path_code_violations,
2250 last96.e_bit_errors);
2251 len += scnprintf(page + len, PAGE_SIZE - len,
2252 " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
2253 last96.slip_secs, last96.fr_loss_secs,
2254 last96.line_err_secs, last96.degraded_mins);
2255 len += scnprintf(page + len, PAGE_SIZE - len,
2256 " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
2257 last96.errored_secs, last96.bursty_err_secs,
2258 last96.severely_err_secs, last96.unavail_secs);
2262 // len +=scnprintf( page + len, PAGE_SIZE - len, "Special events:\n" );
2263 // len +=scnprintf( page + len, PAGE_SIZE - len, "\tstat_pri/missed: %u / %u\n", board->stat_pri_races, board->stat_pri_races_missed );
2264 // len +=scnprintf( page + len, PAGE_SIZE - len, "\tstat_pti/missed: %u / %u\n", board->stat_pti_races, board->stat_pti_races_missed );
2269 * Memory dump function. Not used currently.
2271 static int BOARD_dump(struct net_device *dev)
2274 ("BOARD_dump() requested. It is unimplemented, it should not be called\n");
2279 * /proc file read function for the files registered by this module.
2280 * This function is called by the procfs implementation when a user
2281 * wants to read from a file registered by this module.
2282 * page is the workspace, start should point to the real start of data,
2283 * off is the file offset, data points to the file's proc_dir_entry
2285 * Returns the number of bytes copied to the request buffer.
2288 static int munich_read_proc(char *page, char **start, off_t off, int count,
2289 int *eof, void *data)
2291 struct proc_dir_entry *file = (struct proc_dir_entry *)data;
2292 struct net_device *dev = file->parent->data;
2293 struct comx_channel *ch = netdev_priv(dev);
2294 struct slicecom_privdata *hw = ch->HW_privdata;
2295 munich_board_t *board;
2298 u32 timeslots = hw->timeslots;
2300 board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
2302 if (!strcmp(file->name, FILENAME_BOARDNUM))
2303 len = sprintf(page, "%d\n", hw->boardnum);
2304 else if (!strcmp(file->name, FILENAME_TIMESLOTS))
2306 for (i = 0; i < 32; i++)
2307 if ((1 << i) & timeslots)
2308 len += scnprintf(page + len, PAGE_SIZE - len, "%d ", i);
2309 len += scnprintf(page + len, PAGE_SIZE - len, "\n");
2311 else if (!strcmp(file->name, FILENAME_FRAMING))
2314 while (slicecom_framings[i].value &&
2315 slicecom_framings[i].value != board->framing)
2317 len += scnprintf(page + len, PAGE_SIZE - len, "%s\n",
2318 slicecom_framings[i].name);
2320 else if (!strcmp(file->name, FILENAME_LINECODE))
2323 while (slicecom_linecodes[i].value &&
2324 slicecom_linecodes[i].value != board->linecode)
2326 len += scnprintf(page + len, PAGE_SIZE - len, "%s\n",
2327 slicecom_linecodes[i].name);
2329 else if (!strcmp(file->name, FILENAME_CLOCK_SOURCE))
2332 while (slicecom_clock_sources[i].value &&
2333 slicecom_clock_sources[i].value != board->clock_source)
2336 scnprintf(page + len, PAGE_SIZE - len, "%s\n",
2337 slicecom_clock_sources[i].name);
2339 else if (!strcmp(file->name, FILENAME_LOOPBACK))
2342 while (slicecom_loopbacks[i].value &&
2343 slicecom_loopbacks[i].value != board->loopback)
2345 len += scnprintf(page + len, PAGE_SIZE - len, "%s\n",
2346 slicecom_loopbacks[i].name);
2348 /* We set permissions to write-only for REG and LBIREG, but root can read them anyway: */
2349 else if (!strcmp(file->name, FILENAME_REG))
2351 len += scnprintf(page + len, PAGE_SIZE - len,
2352 "%s: " FILENAME_REG ": write-only file\n", dev->name);
2354 else if (!strcmp(file->name, FILENAME_LBIREG))
2356 len += scnprintf(page + len, PAGE_SIZE - len,
2357 "%s: " FILENAME_LBIREG ": write-only file\n", dev->name);
2361 printk("slicecom_read_proc: internal error, filename %s\n", file->name);
2364 /* file handling administration: count eof status, offset, start address
2373 *start = page + off;
2374 if (count >= len - off)
2376 return min((off_t) count, (off_t) len - off);
2380 * Write function for /proc files registered by us.
2381 * See the comment on read function above.
2382 * Beware! buffer is in userspace!!!
2383 * Returns the number of bytes written
2386 static int munich_write_proc(struct file *file, const char *buffer,
2387 u_long count, void *data)
2389 struct proc_dir_entry *entry = (struct proc_dir_entry *)data;
2390 struct net_device *dev = (struct net_device *)entry->parent->data;
2391 struct comx_channel *ch = netdev_priv(dev);
2392 struct slicecom_privdata *hw = ch->HW_privdata;
2393 munich_board_t *board;
2395 unsigned long ts, tmp_boardnum;
2397 u32 tmp_timeslots = 0;
2401 board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
2403 /* Paranoia checking: */
2405 if (PDE(file->f_dentry->d_inode) != entry)
2407 printk(KERN_ERR "munich_write_proc: file <-> data internal error\n");
2411 /* Request tmp buffer */
2412 if (!(page = (char *)__get_free_page(GFP_KERNEL)))
2415 /* Copy user data and cut trailing \n */
2416 if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) {
2417 free_page((unsigned long)page);
2420 if (*(page + count - 1) == '\n')
2421 *(page + count - 1) = 0;
2422 *(page + PAGE_SIZE - 1) = 0;
2424 if (!strcmp(entry->name, FILENAME_BOARDNUM))
2426 tmp_boardnum = simple_strtoul(page, NULL, 0);
2427 if (0 <= tmp_boardnum && tmp_boardnum < MAX_BOARDS)
2428 hw->boardnum = tmp_boardnum;
2431 printk("%s: " FILENAME_BOARDNUM " range is 0...%d\n", dev->name,
2433 free_page((unsigned long)page);
2437 else if (!strcmp(entry->name, FILENAME_TIMESLOTS))
2446 ts = simple_strtoul(p, &p, 10); /* base = 10: Don't read 09 as an octal number */
2447 /* ts = 0 ha nem tudta beolvasni a stringet, erre egy kicsit epitek itt: */
2448 if (0 <= ts && ts < 32)
2450 tmp_timeslots |= (1 << ts);
2454 printk("%s: " FILENAME_TIMESLOTS " range is 1...31\n",
2456 free_page((unsigned long)page);
2461 hw->timeslots = tmp_timeslots;
2463 else if (!strcmp(entry->name, FILENAME_FRAMING))
2466 while (slicecom_framings[i].value &&
2467 strncmp(slicecom_framings[i].name, page,
2468 strlen(slicecom_framings[i].name)))
2470 if (!slicecom_framings[i].value)
2472 printk("slicecom: %s: Invalid " FILENAME_FRAMING " '%s'\n",
2474 free_page((unsigned long)page);
2481 * echo >framing no-crc4
2483 * - when the framing was set, hw->boardnum was 0, so it would set the framing for board 0
2484 * Workaround: allow to set it only if interface is administrative UP
2486 if (netif_running(dev))
2487 slicecom_set_framing(hw->boardnum, slicecom_framings[i].value);
2490 printk("%s: " FILENAME_FRAMING
2491 " can not be set while the interface is DOWN\n",
2493 free_page((unsigned long)page);
2498 else if (!strcmp(entry->name, FILENAME_LINECODE))
2501 while (slicecom_linecodes[i].value &&
2502 strncmp(slicecom_linecodes[i].name, page,
2503 strlen(slicecom_linecodes[i].name)))
2505 if (!slicecom_linecodes[i].value)
2507 printk("slicecom: %s: Invalid " FILENAME_LINECODE " '%s'\n",
2509 free_page((unsigned long)page);
2514 * Allow to set it only if interface is administrative UP,
2515 * for the same reason as FILENAME_FRAMING
2517 if (netif_running(dev))
2518 slicecom_set_linecode(hw->boardnum,
2519 slicecom_linecodes[i].value);
2522 printk("%s: " FILENAME_LINECODE
2523 " can not be set while the interface is DOWN\n",
2525 free_page((unsigned long)page);
2530 else if (!strcmp(entry->name, FILENAME_CLOCK_SOURCE))
2533 while (slicecom_clock_sources[i].value &&
2534 strncmp(slicecom_clock_sources[i].name, page,
2535 strlen(slicecom_clock_sources[i].name)))
2537 if (!slicecom_clock_sources[i].value)
2539 printk("%s: Invalid " FILENAME_CLOCK_SOURCE " '%s'\n", dev->name,
2541 free_page((unsigned long)page);
2546 * Allow to set it only if interface is administrative UP,
2547 * for the same reason as FILENAME_FRAMING
2549 if (netif_running(dev))
2550 slicecom_set_clock_source(hw->boardnum,
2551 slicecom_clock_sources[i].value);
2554 printk("%s: " FILENAME_CLOCK_SOURCE
2555 " can not be set while the interface is DOWN\n",
2557 free_page((unsigned long)page);
2562 else if (!strcmp(entry->name, FILENAME_LOOPBACK))
2565 while (slicecom_loopbacks[i].value &&
2566 strncmp(slicecom_loopbacks[i].name, page,
2567 strlen(slicecom_loopbacks[i].name)))
2569 if (!slicecom_loopbacks[i].value)
2571 printk("%s: Invalid " FILENAME_LOOPBACK " '%s'\n", dev->name, page);
2572 free_page((unsigned long)page);
2577 * Allow to set it only if interface is administrative UP,
2578 * for the same reason as FILENAME_FRAMING
2580 if (netif_running(dev))
2581 slicecom_set_loopback(hw->boardnum,
2582 slicecom_loopbacks[i].value);
2585 printk("%s: " FILENAME_LOOPBACK
2586 " can not be set while the interface is DOWN\n",
2588 free_page((unsigned long)page);
2593 else if (!strcmp(entry->name, FILENAME_REG))
2594 { /* DEL: 'reg' csak tmp */
2596 u32 *bar1 = board->bar1;
2598 reg = simple_strtoul(page, &p, 0);
2599 reg_ertek = simple_strtoul(p + 1, NULL, 0);
2603 printk("reg(0x%02x) := 0x%08x jiff: %lu\n", reg, reg_ertek, jiffies);
2604 writel(reg_ertek, MUNICH_VIRT(reg >> 2));
2608 printk("reg(0x%02x) is 0x%08x jiff: %lu\n", reg - 0x100,
2609 readl(MUNICH_VIRT((reg - 0x100) >> 2)), jiffies);
2612 else if (!strcmp(entry->name, FILENAME_LBIREG))
2613 { /* DEL: 'lbireg' csak tmp */
2615 u8 *lbi = board->lbi;
2617 lbireg = simple_strtoul(page, &p, 0);
2618 lbireg_ertek = simple_strtoul(p + 1, NULL, 0);
2622 printk("lbireg(0x%02x) := 0x%02x jiff: %lu\n", lbireg,
2623 lbireg_ertek, jiffies);
2624 writeb(lbireg_ertek, lbi + lbireg);
2627 printk("lbireg(0x%02x) is 0x%02x jiff: %lu\n", lbireg - 0x100,
2628 readb(lbi + lbireg - 0x100), jiffies);
2632 printk(KERN_ERR "munich_write_proc: internal error, filename %s\n",
2634 free_page((unsigned long)page);
2638 /* Don't forget to free the workspace */
2639 free_page((unsigned long)page);
2644 * Boardtype init function.
2645 * Called by the comx (upper) layer, when you set boardtype.
2646 * Allocates resources associated to using munich board for this device,
2647 * initializes ch_struct pointers etc.
2648 * Returns 0 on success and standard error codes on error.
2651 static int init_escape(struct comx_channel *ch)
2653 kfree(ch->HW_privdata);
2657 static int BOARD_init(struct net_device *dev)
2659 struct comx_channel *ch = netdev_priv(dev);
2660 struct slicecom_privdata *hw;
2661 struct proc_dir_entry *new_file;
2663 /* Alloc data for private structure */
2664 if ((ch->HW_privdata =
2665 kmalloc(sizeof(struct slicecom_privdata), GFP_KERNEL)) == NULL)
2668 memset(hw = ch->HW_privdata, 0, sizeof(struct slicecom_privdata));
2670 /* Register /proc files */
2671 if ((new_file = create_proc_entry(FILENAME_BOARDNUM, S_IFREG | 0644,
2672 ch->procdir)) == NULL)
2673 return init_escape(ch);
2674 new_file->data = (void *)new_file;
2675 new_file->read_proc = &munich_read_proc;
2676 new_file->write_proc = &munich_write_proc;
2677 // new_file->proc_iops = &comx_normal_inode_ops;
2678 new_file->nlink = 1;
2680 if (ch->hardware == &slicecomhw)
2682 if ((new_file = create_proc_entry(FILENAME_TIMESLOTS, S_IFREG | 0644,
2683 ch->procdir)) == NULL)
2684 return init_escape(ch);
2685 new_file->data = (void *)new_file;
2686 new_file->read_proc = &munich_read_proc;
2687 new_file->write_proc = &munich_write_proc;
2688 // new_file->proc_iops = &comx_normal_inode_ops;
2689 new_file->nlink = 1;
2691 if ((new_file = create_proc_entry(FILENAME_FRAMING, S_IFREG | 0644,
2692 ch->procdir)) == NULL)
2693 return init_escape(ch);
2694 new_file->data = (void *)new_file;
2695 new_file->read_proc = &munich_read_proc;
2696 new_file->write_proc = &munich_write_proc;
2697 // new_file->proc_iops = &comx_normal_inode_ops;
2698 new_file->nlink = 1;
2700 if ((new_file = create_proc_entry(FILENAME_LINECODE, S_IFREG | 0644,
2701 ch->procdir)) == NULL)
2702 return init_escape(ch);
2703 new_file->data = (void *)new_file;
2704 new_file->read_proc = &munich_read_proc;
2705 new_file->write_proc = &munich_write_proc;
2706 // new_file->proc_iops = &comx_normal_inode_ops;
2707 new_file->nlink = 1;
2709 if ((new_file = create_proc_entry(FILENAME_CLOCK_SOURCE, S_IFREG | 0644,
2710 ch->procdir)) == NULL)
2711 return init_escape(ch);
2712 new_file->data = (void *)new_file;
2713 new_file->read_proc = &munich_read_proc;
2714 new_file->write_proc = &munich_write_proc;
2715 // new_file->proc_iops = &comx_normal_inode_ops;
2716 new_file->nlink = 1;
2718 if ((new_file = create_proc_entry(FILENAME_LOOPBACK, S_IFREG | 0644,
2719 ch->procdir)) == NULL)
2720 return init_escape(ch);
2721 new_file->data = (void *)new_file;
2722 new_file->read_proc = &munich_read_proc;
2723 new_file->write_proc = &munich_write_proc;
2724 // new_file->proc_iops = &comx_normal_inode_ops;
2725 new_file->nlink = 1;
2728 /* DEL: ez itt csak fejlesztesi celokra!! */
2729 if ((new_file = create_proc_entry(FILENAME_REG, S_IFREG | 0200, ch->procdir)) == NULL)
2730 return init_escape(ch);
2731 new_file->data = (void *)new_file;
2732 new_file->read_proc = &munich_read_proc;
2733 new_file->write_proc = &munich_write_proc;
2734 // new_file->proc_iops = &comx_normal_inode_ops;
2735 new_file->nlink = 1;
2737 /* DEL: ez itt csak fejlesztesi celokra!! */
2738 if ((new_file = create_proc_entry(FILENAME_LBIREG, S_IFREG | 0200,
2739 ch->procdir)) == NULL)
2740 return init_escape(ch);
2741 new_file->data = (void *)new_file;
2742 new_file->read_proc = &munich_read_proc;
2743 new_file->write_proc = &munich_write_proc;
2744 // new_file->proc_iops = &comx_normal_inode_ops;
2745 new_file->nlink = 1;
2747 /* Fill in ch_struct hw specific pointers: */
2749 ch->HW_txe = MUNICH_txe;
2750 ch->HW_open = MUNICH_open;
2751 ch->HW_close = MUNICH_close;
2752 ch->HW_send_packet = MUNICH_send_packet;
2754 ch->HW_minden = MUNICH_minden;
2756 ch->HW_statistics = MUNICH_minden;
2759 hw->boardnum = SLICECOM_BOARDNUM_DEFAULT;
2760 hw->timeslots = ch->hardware == &pcicomhw ? 0xffffffff : 2;
2762 /* O.K. Count one more user on this module */
2768 * Boardtype exit function.
2769 * Called by the comx (upper) layer, when you clear boardtype from munich.
2770 * Frees resources associated to using munich board for this device,
2771 * resets ch_struct pointers etc.
2773 static int BOARD_exit(struct net_device *dev)
2775 struct comx_channel *ch = netdev_priv(dev);
2777 /* Free private data area */
2778 // board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
2780 kfree(ch->HW_privdata);
2781 /* Remove /proc files */
2782 remove_proc_entry(FILENAME_BOARDNUM, ch->procdir);
2783 if (ch->hardware == &slicecomhw)
2785 remove_proc_entry(FILENAME_TIMESLOTS, ch->procdir);
2786 remove_proc_entry(FILENAME_FRAMING, ch->procdir);
2787 remove_proc_entry(FILENAME_LINECODE, ch->procdir);
2788 remove_proc_entry(FILENAME_CLOCK_SOURCE, ch->procdir);
2789 remove_proc_entry(FILENAME_LOOPBACK, ch->procdir);
2791 remove_proc_entry(FILENAME_REG, ch->procdir);
2792 remove_proc_entry(FILENAME_LBIREG, ch->procdir);
2794 /* Minus one user for the module accounting */
2799 static struct comx_hardware slicecomhw =
2811 static struct comx_hardware pcicomhw =
2823 /* Module management */
2825 static int __init init_mister(void)
2828 comx_register_hardware(&slicecomhw);
2829 comx_register_hardware(&pcicomhw);
2830 return munich_probe();
2833 static void __exit cleanup_mister(void)
2837 comx_unregister_hardware("slicecom");
2838 comx_unregister_hardware("pcicom");
2840 for (i = 0; i < MAX_BOARDS; i++)
2842 if (slicecom_boards[i].bar1)
2843 iounmap((void *)slicecom_boards[i].bar1);
2844 if (slicecom_boards[i].lbi)
2845 iounmap((void *)slicecom_boards[i].lbi);
2846 if (pcicom_boards[i].bar1)
2847 iounmap((void *)pcicom_boards[i].bar1);
2848 if (pcicom_boards[i].lbi)
2849 iounmap((void *)pcicom_boards[i].lbi);
2853 module_init(init_mister);
2854 module_exit(cleanup_mister);