static void init_spans(struct tor2 *tor)
{
int x, y, c;
for (x = 0; x <>spans[x].name, "Tor2/%d/%d", tor->num, x + 1);
snprintf(tor->spans[x].desc, sizeof(tor->spans[x].desc) - 1,
"Tormenta 2 (PCI) fQuad %s Card %d Span %d",
(tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1);
tor->spans[x].manufacturer = "Digium";
strncpy(tor->spans[x].devicetype, tor->type, sizeof(tor->spans[x].devicetype) - 1);
snprintf(tor->spans[x].location, sizeof(tor->spans[x].location) - 1,
"PCI Bus %02d Slot %02d", tor->pci->bus->number, PCI_SLOT(tor->pci->devfn) + 1);
tor->spans[x].spanconfig = tor2_spanconfig;
tor->spans[x].chanconfig = tor2_chanconfig;
tor->spans[x].startup = tor2_startup;
tor->spans[x].shutdown = tor2_shutdown;
tor->spans[x].rbsbits = tor2_rbsbits;
tor->spans[x].maint = tor2_maint;
tor->spans[x].open = tor2_open;
tor->spans[x].close = tor2_close;
if (tor->cardtype == TYPE_T1) {
tor->spans[x].channels = 24;
tor->spans[x].deflaw = ZT_LAW_MULAW;
tor->spans[x].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;
tor->spans[x].spantype = "T1";
} else {
tor->spans[x].channels = 31;
tor->spans[x].deflaw = ZT_LAW_ALAW;
tor->spans[x].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4;
tor->spans[x].spantype = "E1";
}
tor->spans[x].chans = tor->chans[x];
tor->spans[x].flags = ZT_FLAG_RBS;
tor->spans[x].ioctl = tor2_ioctl;
tor->spans[x].pvt = &tor->tspans[x];
tor->tspans[x].tor = tor;
tor->tspans[x].span = x;
init_waitqueue_head(&tor->spans[x].maintq);
for (y=0;yspans[x].channels;y++) {
struct zt_chan *mychans = tor->chans[x] + y;
sprintf(mychans->name, "Tor2/%d/%d/%d", tor->num, x + 1, y + 1);
mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS |
ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF | ZT_SIG_EM_E1;
c = (x * tor->spans[x].channels) + y;
mychans->pvt = &tor->tchans[c];
mychans->chanpos = y + 1;
tor->tchans[c].span = x;
tor->tchans[c].tor = tor;
}
}
}
These are the function assignments:
tor->spans[x].spanconfig = tor2_spanconfig;
tor->spans[x].chanconfig = tor2_chanconfig;
tor->spans[x].startup = tor2_startup;
tor->spans[x].shutdown = tor2_shutdown;
tor->spans[x].rbsbits = tor2_rbsbits;
tor->spans[x].maint = tor2_maint;
tor->spans[x].open = tor2_open;
tor->spans[x].close = tor2_close;
tor->spans[x].ioctl = tor2_ioctl;
The variable initialization
<snip what="name initialization">
tor->spans[x].channels = 24;
tor->spans[x].deflaw = ZT_LAW_MULAW;
tor->spans[x].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;
tor->spans[x].spantype = "T1";
Or
tor->spans[x].channels = 31;
tor->spans[x].deflaw = ZT_LAW_ALAW;
tor->spans[x].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4;
tor->spans[x].spantype = "E1";
tor->spans[x].chans = tor->chans[x];
tor->spans[x].flags = ZT_FLAG_RBS;
tor->spans[x].pvt = &tor->tspans[x];
My blog on Linux and programming. Covers Linux, VoIP, C, mysql, php and everything else that I come across while tinkering with my Linux boxes.
Monday, July 21, 2008
How span is populated
The function that configures a span is
tor2.c scratch pad
I am going to use this post as the scratch pad while reading through tor2.c
Init function: tor2_init
This function registers a pci driver. The driver structure is a global variable "tor2_driver". It has a probe function called "tor2_probe" and a function to remove the driver "tor2_remove".
Probe function: tor2_probe
This function populates the spans structure within tor structure.
Register with zaptel: tor2_launch
This function registers the spans with the zaptel driver.
And then... the action begins...
Init function: tor2_init
This function registers a pci driver. The driver structure is a global variable "tor2_driver". It has a probe function called "tor2_probe" and a function to remove the driver "tor2_remove".
Probe function: tor2_probe
- Does card specific PCI initialization
- Calls init_spans(tor);
- Calls tor2_launch(cards[x]);
This function populates the spans structure within tor structure.
Register with zaptel: tor2_launch
This function registers the spans with the zaptel driver.
And then... the action begins...
Saturday, July 19, 2008
case study
I am just starting the study of tor2.c. This will help me understand the device driver for a asterisk compatible card better. As I understand, this driver is registered as a pci driver. The interesting part is the probe function. It is through this function the drivers get registered in the zaptel. The details will follow.
A simpler key
Just the same structure from my previous post with all the optional components removed.
struct zt_span {
spinlock_t lock;
void *pvt; /* Private stuff */
char name[40]; /* Span name */
char desc[80]; /* Span description */
const char *spantype; /* span type in text form */
const char *manufacturer; /* span's device manufacturer */
char devicetype[80]; /* span's device type */
char location[40]; /* span device's location in system */
int deflaw; /* Default law (ZT_MULAW or ZT_ALAW) */
int alarms; /* Pending alarms on span */
int flags;
int irq; /* IRQ for this span's hardware */
int lbo; /* Span Line-Buildout */
int lineconfig; /* Span line configuration */
int linecompat; /* Span line compatibility */
int channels; /* Number of channels in span */
int txlevel; /* Tx level */
int rxlevel; /* Rx level */
int syncsrc; /* current sync src (gets copied here) */
unsigned int bpvcount; /* BPV counter */
unsigned int crc4count; /* CRC4 error counter */
unsigned int ebitcount; /* current E-bit error count */
unsigned int fascount; /* current FAS error count */
int maintstat; /* Maintenance state */
wait_queue_head_t maintq; /* Maintenance queue */
int mainttimer; /* Maintenance timer */
int irqmisses; /* Interrupt misses */
int timingslips; /* Clock slips */
struct zt_chan *chans; /* Member channel structures */
/* ==== Span Callback Operations ==== */
/* Req: Set the requested chunk size. This is the unit in which you must
report results for conferencing, etc */
int (*setchunksize)(struct zt_span *span, int chunksize);
/* ==== Channel Callback Operations ==== */
int (*echocan_with_params)(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p);
/* Okay, now we get to the signalling. You have several options: */
/* Option 1: If you're a T1 like interface, you can just provide a
rbsbits function and we'll assert robbed bits for you. Be sure to
set the ZT_FLAG_RBS in this case. */
/* Opt: If the span uses A/B bits, set them here */
int (*rbsbits)(struct zt_chan *chan, int bits);
/* Used by zaptel only -- no user servicable parts inside */
int spanno; /* Span number for zaptel */
int offset; /* Offset within a given card */
int lastalarms; /* Previous alarms */
#ifdef CONFIG_DEVFS_FS
devfs_handle_t dhandle; /* Directory name */
#endif
/* If the watchdog detects no received data, it will call the
watchdog routine */
int (*watchdog)(struct zt_span *span, int cause);
#ifdef CONFIG_ZAPTEL_WATCHDOG
int watchcounter;
int watchstate;
#endif
};
struct zt_span {
spinlock_t lock;
void *pvt; /* Private stuff */
char name[40]; /* Span name */
char desc[80]; /* Span description */
const char *spantype; /* span type in text form */
const char *manufacturer; /* span's device manufacturer */
char devicetype[80]; /* span's device type */
char location[40]; /* span device's location in system */
int deflaw; /* Default law (ZT_MULAW or ZT_ALAW) */
int alarms; /* Pending alarms on span */
int flags;
int irq; /* IRQ for this span's hardware */
int lbo; /* Span Line-Buildout */
int lineconfig; /* Span line configuration */
int linecompat; /* Span line compatibility */
int channels; /* Number of channels in span */
int txlevel; /* Tx level */
int rxlevel; /* Rx level */
int syncsrc; /* current sync src (gets copied here) */
unsigned int bpvcount; /* BPV counter */
unsigned int crc4count; /* CRC4 error counter */
unsigned int ebitcount; /* current E-bit error count */
unsigned int fascount; /* current FAS error count */
int maintstat; /* Maintenance state */
wait_queue_head_t maintq; /* Maintenance queue */
int mainttimer; /* Maintenance timer */
int irqmisses; /* Interrupt misses */
int timingslips; /* Clock slips */
struct zt_chan *chans; /* Member channel structures */
/* ==== Span Callback Operations ==== */
/* Req: Set the requested chunk size. This is the unit in which you must
report results for conferencing, etc */
int (*setchunksize)(struct zt_span *span, int chunksize);
/* ==== Channel Callback Operations ==== */
int (*echocan_with_params)(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p);
/* Okay, now we get to the signalling. You have several options: */
/* Option 1: If you're a T1 like interface, you can just provide a
rbsbits function and we'll assert robbed bits for you. Be sure to
set the ZT_FLAG_RBS in this case. */
/* Opt: If the span uses A/B bits, set them here */
int (*rbsbits)(struct zt_chan *chan, int bits);
/* Used by zaptel only -- no user servicable parts inside */
int spanno; /* Span number for zaptel */
int offset; /* Offset within a given card */
int lastalarms; /* Previous alarms */
#ifdef CONFIG_DEVFS_FS
devfs_handle_t dhandle; /* Directory name */
#endif
/* If the watchdog detects no received data, it will call the
watchdog routine */
int (*watchdog)(struct zt_span *span, int cause);
#ifdef CONFIG_ZAPTEL_WATCHDOG
int watchcounter;
int watchstate;
#endif
};
The key to zaptel
We need to have a deep understanding of the following structure to work with zaptel. This is the structure passed by individual driver to zaptel at the time of registration.
struct zt_span {
spinlock_t lock;
void *pvt; /* Private stuff */
char name[40]; /* Span name */
char desc[80]; /* Span description */
const char *spantype; /* span type in text form */
const char *manufacturer; /* span's device manufacturer */
char devicetype[80]; /* span's device type */
char location[40]; /* span device's location in system */
int deflaw; /* Default law (ZT_MULAW or ZT_ALAW) */
int alarms; /* Pending alarms on span */
int flags;
int irq; /* IRQ for this span's hardware */
int lbo; /* Span Line-Buildout */
int lineconfig; /* Span line configuration */
int linecompat; /* Span line compatibility */
int channels; /* Number of channels in span */
int txlevel; /* Tx level */
int rxlevel; /* Rx level */
int syncsrc; /* current sync src (gets copied here) */
unsigned int bpvcount; /* BPV counter */
unsigned int crc4count; /* CRC4 error counter */
unsigned int ebitcount; /* current E-bit error count */
unsigned int fascount; /* current FAS error count */
int maintstat; /* Maintenance state */
wait_queue_head_t maintq; /* Maintenance queue */
int mainttimer; /* Maintenance timer */
int irqmisses; /* Interrupt misses */
int timingslips; /* Clock slips */
struct zt_chan *chans; /* Member channel structures */
/* ==== Span Callback Operations ==== */
/* Req: Set the requested chunk size. This is the unit in which you must
report results for conferencing, etc */
int (*setchunksize)(struct zt_span *span, int chunksize);
/* Opt: Configure the span (if appropriate) */
int (*spanconfig)(struct zt_span *span, struct zt_lineconfig *lc);
/* Opt: Start the span */
int (*startup)(struct zt_span *span);
/* Opt: Shutdown the span */
int (*shutdown)(struct zt_span *span);
/* Opt: Enable maintenance modes */
int (*maint)(struct zt_span *span, int mode);
#ifdef ZAPTEL_SYNC_TICK
/* Opt: send sync to spans */
int (*sync_tick)(struct zt_span *span, int is_master);
#endif
/* ==== Channel Callback Operations ==== */
/* Opt: Set signalling type (if appropriate) */
int (*chanconfig)(struct zt_chan *chan, int sigtype);
/* Opt: Prepare a channel for I/O */
int (*open)(struct zt_chan *chan);
/* Opt: Close channel for I/O */
int (*close)(struct zt_chan *chan);
/* Opt: IOCTL */
int (*ioctl)(struct zt_chan *chan, unsigned int cmd, unsigned long data);
/* Opt: Native echo cancellation (simple) */
int (*echocan)(struct zt_chan *chan, int ecval);
int (*echocan_with_params)(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p);
/* Okay, now we get to the signalling. You have several options: */
/* Option 1: If you're a T1 like interface, you can just provide a
rbsbits function and we'll assert robbed bits for you. Be sure to
set the ZT_FLAG_RBS in this case. */
/* Opt: If the span uses A/B bits, set them here */
int (*rbsbits)(struct zt_chan *chan, int bits);
/* Option 2: If you don't know about sig bits, but do have their
equivalents (i.e. you can disconnect battery, detect off hook,
generate ring, etc directly) then you can just specify a
sethook function, and we'll call you with appropriate hook states
to set. Still set the ZT_FLAG_RBS in this case as well */
int (*hooksig)(struct zt_chan *chan, zt_txsig_t hookstate);
/* Option 3: If you can't use sig bits, you can write a function
which handles the individual hook states */
int (*sethook)(struct zt_chan *chan, int hookstate);
/* Opt: Dacs the contents of chan2 into chan1 if possible */
int (*dacs)(struct zt_chan *chan1, struct zt_chan *chan2);
/* Opt: Used to tell an onboard HDLC controller that there is data ready to transmit */
void (*hdlc_hard_xmit)(struct zt_chan *chan);
/* Used by zaptel only -- no user servicable parts inside */
int spanno; /* Span number for zaptel */
int offset; /* Offset within a given card */
int lastalarms; /* Previous alarms */
#ifdef CONFIG_DEVFS_FS
devfs_handle_t dhandle; /* Directory name */
#endif
/* If the watchdog detects no received data, it will call the
watchdog routine */
int (*watchdog)(struct zt_span *span, int cause);
#ifdef CONFIG_ZAPTEL_WATCHDOG
int watchcounter;
int watchstate;
#endif
};
struct zt_span {
spinlock_t lock;
void *pvt; /* Private stuff */
char name[40]; /* Span name */
char desc[80]; /* Span description */
const char *spantype; /* span type in text form */
const char *manufacturer; /* span's device manufacturer */
char devicetype[80]; /* span's device type */
char location[40]; /* span device's location in system */
int deflaw; /* Default law (ZT_MULAW or ZT_ALAW) */
int alarms; /* Pending alarms on span */
int flags;
int irq; /* IRQ for this span's hardware */
int lbo; /* Span Line-Buildout */
int lineconfig; /* Span line configuration */
int linecompat; /* Span line compatibility */
int channels; /* Number of channels in span */
int txlevel; /* Tx level */
int rxlevel; /* Rx level */
int syncsrc; /* current sync src (gets copied here) */
unsigned int bpvcount; /* BPV counter */
unsigned int crc4count; /* CRC4 error counter */
unsigned int ebitcount; /* current E-bit error count */
unsigned int fascount; /* current FAS error count */
int maintstat; /* Maintenance state */
wait_queue_head_t maintq; /* Maintenance queue */
int mainttimer; /* Maintenance timer */
int irqmisses; /* Interrupt misses */
int timingslips; /* Clock slips */
struct zt_chan *chans; /* Member channel structures */
/* ==== Span Callback Operations ==== */
/* Req: Set the requested chunk size. This is the unit in which you must
report results for conferencing, etc */
int (*setchunksize)(struct zt_span *span, int chunksize);
/* Opt: Configure the span (if appropriate) */
int (*spanconfig)(struct zt_span *span, struct zt_lineconfig *lc);
/* Opt: Start the span */
int (*startup)(struct zt_span *span);
/* Opt: Shutdown the span */
int (*shutdown)(struct zt_span *span);
/* Opt: Enable maintenance modes */
int (*maint)(struct zt_span *span, int mode);
#ifdef ZAPTEL_SYNC_TICK
/* Opt: send sync to spans */
int (*sync_tick)(struct zt_span *span, int is_master);
#endif
/* ==== Channel Callback Operations ==== */
/* Opt: Set signalling type (if appropriate) */
int (*chanconfig)(struct zt_chan *chan, int sigtype);
/* Opt: Prepare a channel for I/O */
int (*open)(struct zt_chan *chan);
/* Opt: Close channel for I/O */
int (*close)(struct zt_chan *chan);
/* Opt: IOCTL */
int (*ioctl)(struct zt_chan *chan, unsigned int cmd, unsigned long data);
/* Opt: Native echo cancellation (simple) */
int (*echocan)(struct zt_chan *chan, int ecval);
int (*echocan_with_params)(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p);
/* Okay, now we get to the signalling. You have several options: */
/* Option 1: If you're a T1 like interface, you can just provide a
rbsbits function and we'll assert robbed bits for you. Be sure to
set the ZT_FLAG_RBS in this case. */
/* Opt: If the span uses A/B bits, set them here */
int (*rbsbits)(struct zt_chan *chan, int bits);
/* Option 2: If you don't know about sig bits, but do have their
equivalents (i.e. you can disconnect battery, detect off hook,
generate ring, etc directly) then you can just specify a
sethook function, and we'll call you with appropriate hook states
to set. Still set the ZT_FLAG_RBS in this case as well */
int (*hooksig)(struct zt_chan *chan, zt_txsig_t hookstate);
/* Option 3: If you can't use sig bits, you can write a function
which handles the individual hook states */
int (*sethook)(struct zt_chan *chan, int hookstate);
/* Opt: Dacs the contents of chan2 into chan1 if possible */
int (*dacs)(struct zt_chan *chan1, struct zt_chan *chan2);
/* Opt: Used to tell an onboard HDLC controller that there is data ready to transmit */
void (*hdlc_hard_xmit)(struct zt_chan *chan);
/* Used by zaptel only -- no user servicable parts inside */
int spanno; /* Span number for zaptel */
int offset; /* Offset within a given card */
int lastalarms; /* Previous alarms */
#ifdef CONFIG_DEVFS_FS
devfs_handle_t dhandle; /* Directory name */
#endif
/* If the watchdog detects no received data, it will call the
watchdog routine */
int (*watchdog)(struct zt_span *span, int cause);
#ifdef CONFIG_ZAPTEL_WATCHDOG
int watchcounter;
int watchstate;
#endif
};
Subscribe to:
Posts (Atom)