📄 x400p-ss7.c
字号:
if (chan) { /* specific channel indicated */ switch (cd->config.ifgtype) { case SDL_GTYPE_E1: if (chan < 1 || chan > 31) { ptrace(("%s: ERROR: invalid chan %d\n", DRV_NAME, chan)); goto lmi_badppa; } slot = xp_e1_chan_map[chan - 1]; if (sp->slots[slot]) { ptrace(("%s: ERROR: slot %d in use\n", DRV_NAME, slot)); goto lmi_badppa; } if ((err = lmi_ok_ack(q, xp, LMI_DISABLED, LMI_ATTACH_REQ))) return (err); /* commit attach */ printd(("%s: attaching card %d, span %d, chan %d, slot %d\n", DRV_NAME, card, span, chan, slot)); spin_lock_irqsave(&xp->lock, flags); { sp->slots[slot] = ts_get(xp_alloc_ts(xp, sp, slot)); xp->sp = sp_get(sp); sp->config.iftype = SDL_TYPE_DS0; sp->config.ifrate = 64000; sp->config.ifmode = SDL_MODE_PEER; sp->config.ifblksize = 8; xp->i_state = LMI_DISABLED; xp->chan = chan; /* SDL configuration defaults */ xp->obj.sdl.statem.rx_state = SDL_STATE_IDLE; xp->obj.sdl.statem.tx_state = SDL_STATE_IDLE; /* inherit SDL configuration from span */ xp->obj.sdl.config = sp->config; xp->obj.sdl.config.ifflags = 0; } spin_unlock_irqrestore(&xp->lock, flags); return (QR_DONE); case SDL_GTYPE_T1: if (chan < 1 || chan > 24) { ptrace(("%s: ERROR: invalid chan %d\n", DRV_NAME, chan)); goto lmi_badppa; } slot = xp_t1_chan_map[chan - 1]; if (sp->slots[slot]) { ptrace(("%s: ERROR: slot %d in use\n", DRV_NAME, slot)); goto lmi_badppa; } if ((err = lmi_ok_ack(q, xp, LMI_DISABLED, LMI_ATTACH_REQ))) return (err); /* commit attach */ printd(("%s: attaching card %d, span %d, chan %d, slot %d\n", DRV_NAME, card, span, chan, slot)); spin_lock_irqsave(&xp->lock, flags); { sp->slots[slot] = ts_get(xp_alloc_ts(xp, sp, slot)); xp->sp = sp_get(sp); sp->config.iftype = SDL_TYPE_DS0; sp->config.ifrate = 64000; sp->config.ifmode = SDL_MODE_PEER; sp->config.ifblksize = 8; xp->i_state = LMI_DISABLED; xp->chan = chan; /* SDL configuration defaults */ xp->obj.sdl.statem.rx_state = SDL_STATE_IDLE; xp->obj.sdl.statem.tx_state = SDL_STATE_IDLE; /* inherit SDL configuration from span */ xp->obj.sdl.config = sp->config; xp->obj.sdl.config.ifflags = 0; } spin_unlock_irqrestore(&xp->lock, flags); return (QR_DONE); } } else { int c; /* entire span indicated */ switch (cd->config.ifgtype) { case SDL_GTYPE_E1: for (c = 0; c < sizeof(xp_e1_chan_map) / sizeof(xp_e1_chan_map[0]); c++) if (sp->slots[xp_e1_chan_map[c]]) { ptrace(("%s: ERROR: slot in use for chan %d\n", DRV_NAME, c)); goto lmi_badppa; } if ((err = lmi_ok_ack(q, xp, LMI_DISABLED, LMI_ATTACH_REQ))) return (err); /* commit attach */ printd(("%s: attaching card %d, entire span %d\n", DRV_NAME, card, span)); spin_lock_irqsave(&xp->lock, flags); { for (c = 0; c < sizeof(xp_e1_chan_map) / sizeof(xp_e1_chan_map[0]); c++) { slot = xp_e1_chan_map[c]; sp->slots[slot] = ts_get(xp_alloc_ts(xp, sp, slot)); } xp->sp = sp_get(sp); sp->config.iftype = SDL_TYPE_E1; sp->config.ifrate = 2048000; sp->config.ifmode = SDL_MODE_PEER; sp->config.ifblksize = 64; xp->i_state = LMI_DISABLED; xp->chan = chan; /* SDL configuration defaults */ xp->obj.sdl.statem.rx_state = SDL_STATE_IDLE; xp->obj.sdl.statem.tx_state = SDL_STATE_IDLE; /* inherit SDL configuration from span */ xp->obj.sdl.config = sp->config; xp->obj.sdl.config.ifflags = 0; } spin_unlock_irqrestore(&xp->lock, flags); return (QR_DONE); case SDL_GTYPE_T1: for (c = 0; c < (sizeof(xp_t1_chan_map) / sizeof(xp_t1_chan_map[0])); c++) if (sp->slots[xp_t1_chan_map[c]]) { ptrace(("%s: ERROR: slot in use for chan %d\n", DRV_NAME, c)); goto lmi_badppa; } if ((err = lmi_ok_ack(q, xp, LMI_DISABLED, LMI_ATTACH_REQ))) return (err); /* commit attach */ spin_lock_irqsave(&xp->lock, flags); { printd(("%s: attaching card %d, entire span %d\n", DRV_NAME, card, span)); for (c = 0; c < (sizeof(xp_t1_chan_map) / sizeof(xp_t1_chan_map[0])); c++) { slot = xp_t1_chan_map[c]; sp->slots[slot] = ts_get(xp_alloc_ts(xp, sp, slot)); } xp->sp = sp_get(sp); sp->config.iftype = SDL_TYPE_T1; sp->config.ifrate = 1544000; sp->config.ifmode = SDL_MODE_PEER; sp->config.ifblksize = 64; xp->i_state = LMI_DISABLED; xp->chan = chan; /* SDL configuration defaults */ xp->obj.sdl.statem.rx_state = SDL_STATE_IDLE; xp->obj.sdl.statem.tx_state = SDL_STATE_IDLE; /* inherit SDL configuration from span */ xp->obj.sdl.config = sp->config; xp->obj.sdl.config.ifflags = 0; } spin_unlock_irqrestore(&xp->lock, flags); return (QR_DONE); } } swerr(); { int errno, reason; efault: errno = EFAULT; reason = LMI_SYSERR; goto error_out; lmi_outstate: errno = 0; reason = LMI_OUTSTATE; goto error_out; lmi_badprim: errno = 0; reason = LMI_BADPRIM; goto error_out; lmi_badppa: errno = 0; reason = LMI_BADPPA; goto error_out; error_out: return lmi_error_ack(q, xp, LMI_UNATTACHED, LMI_ATTACH_REQ, errno, reason); }}/* * LMI_DETACH_REQ * ----------------------------------- */STATIC intlmi_detach_req(queue_t *q, mblk_t *mp){ struct xp *xp = XP_PRIV(q); struct sp *sp; struct cd *cd; int err, slot; psw_t flags = 0; /* validate detach */ if (xp->i_state != LMI_DISABLED) return lmi_error_ack(q, xp, xp->i_state, LMI_DETACH_REQ, 0, LMI_OUTSTATE); if (!(sp = xp->sp) || !(cd = sp->cd)) { swerr(); return m_error(q, xp, EFAULT); } xp->i_state = LMI_DETACH_PENDING; if ((err = lmi_ok_ack(q, xp, LMI_UNATTACHED, LMI_DETACH_REQ))) return (err); /* commit detach */ spin_lock_irqsave(&xp->lock, flags); { for (slot = 0; slot < 32; slot++) if (sp->slots[slot] && sp->slots[slot]->xp == xp) xp_free_ts(xchg(&sp->slots[slot], NULL)); sp_put(xchg(&xp->sp, NULL)); xp->chan = 0; } spin_unlock_irqrestore(&xp->lock, flags); return (QR_DONE);}/* * LMI_ENABLE_REQ * ----------------------------------- */STATIC intlmi_enable_req(queue_t *q, mblk_t *mp){ int err, offset; struct xp *xp = XP_PRIV(q); struct cd *cd; struct sp *sp; /* validate enable */ if (xp->i_state != LMI_DISABLED) { ptrace(("%s: ERROR: out of state: state = %ld\n", DRV_NAME, xp->i_state)); goto lmi_outstate; } if (!(sp = xp->sp)) { ptrace(("%s: ERROR: out of state: no span pointer\n", DRV_NAME)); goto lmi_outstate; } if (!(cd = sp->cd)) { ptrace(("%s: ERROR: out of state: no card pointer\n", DRV_NAME)); goto lmi_outstate; }#ifdef _DEBUG if (cd->config.ifgtype != SDL_GTYPE_E1 && cd->config.ifgtype != SDL_GTYPE_T1) { ptrace(("%s: ERROR: card group type = %lu\n", DRV_NAME, cd->config.ifgtype)); return m_error(q, xp, EFAULT); }#endif if (xp->obj.sdl.config.ifflags & SDL_IF_UP) { ptrace(("%s: ERROR: out of state: device already up\n", DRV_NAME)); goto lmi_outstate; } if ((err = lmi_enable_con(q, xp))) return (err); /* commit enable */ printd(("%s: performing enable\n", DRV_NAME)); xp->i_state = LMI_ENABLE_PENDING; xp->obj.sdl.config.ifname = sp->config.ifname; xp->obj.sdl.config.ifflags |= SDL_IF_UP; xp->obj.sdl.config.iftype = xp->obj.sdl.config.iftype; switch (xp->obj.sdl.config.iftype) { case SDL_TYPE_E1: xp->obj.sdl.config.ifrate = 2048000; xp->obj.sdl.config.ifblksize = 64; break; case SDL_TYPE_T1: xp->obj.sdl.config.ifrate = 1544000; xp->obj.sdl.config.ifblksize = 64; break; case SDL_TYPE_DS0: xp->obj.sdl.config.ifrate = 64000; xp->obj.sdl.config.ifblksize = 8; break; case SDL_TYPE_DS0A: xp->obj.sdl.config.ifrate = 56000; xp->obj.sdl.config.ifblksize = 8; break; } xp->obj.sdl.config.ifgtype = sp->config.ifgtype; xp->obj.sdl.config.ifgrate = sp->config.ifgrate; xp->obj.sdl.config.ifmode = sp->config.ifmode; xp->obj.sdl.config.ifgmode = sp->config.ifgmode; xp->obj.sdl.config.ifgcrc = sp->config.ifgcrc; xp->obj.sdl.config.ifclock = sp->config.ifclock; xp->obj.sdl.config.ifcoding = sp->config.ifcoding; xp->obj.sdl.config.ifframing = sp->config.ifframing; xp->obj.sdl.config.ifblksize = xp->obj.sdl.config.ifblksize; xp->obj.sdl.config.ifleads = sp->config.ifleads; xp->obj.sdl.config.ifbpv = sp->config.ifbpv; xp->obj.sdl.config.ifalarms = sp->config.ifalarms; xp->obj.sdl.config.ifrxlevel = sp->config.ifrxlevel; xp->obj.sdl.config.iftxlevel = sp->config.iftxlevel; xp->obj.sdl.config.ifsync = cd->config.ifsync; xp->i_state = LMI_ENABLED; if (!(sp->config.ifflags & SDL_IF_UP)) { /* need to bring up span */ int span = sp->span; int base = span << 8; uint8_t ccr1 = 0, tcr1 = 0; unsigned long timeout; switch (cd->config.ifgtype) { case SDL_GTYPE_E1: { psw_t flags = 0; printd(("%s: performing enable on E1 span %d\n", DRV_NAME, span)); spin_lock_irqsave(&cd->lock, flags); // cd->xlb[SYNREG] = SYNCSELF; /* NO, NO, NO */ /* Tell ISR to re-evaluate the sync source */ cd->eval_syncsrc = 1; cd->xlb[CTLREG] = (E1DIV); cd->xlb[LEDREG] = 0xff; /* zero all span registers */ for (offset = 0; offset < 192; offset++) cd->xlb[base + offset] = 0x00; /* Set up for interleaved serial bus operation, byte mode */ if (span == 0) cd->xlb[base + 0xb5] = 0x09; else cd->xlb[base + 0xb5] = 0x08; cd->xlb[base + 0x1a] = 0x04; /* CCR2: set LOTCMC */ for (offset = 0; offset <= 8; offset++) cd->xlb[base + offset] = 0x00; for (offset = 0x10; offset <= 0x4f; offset++) if (offset != 0x1a) cd->xlb[base + offset] = 0x00; cd->xlb[base + 0x10] = 0x20; /* RCR1: Rsync as input */ cd->xlb[base + 0x11] = 0x06; /* RCR2: Sysclk = 2.048 Mhz */ cd->xlb[base + 0x12] = 0x09; /* TCR1: TSiS mode */ tcr1 = 0x09; /* TCR1: TSiS mode */ switch (sp->config.ifframing) { default: case SDL_FRAMING_CCS: ccr1 |= 0x08; break; case SDL_FRAMING_CAS: tcr1 |= 0x20; break; } switch (sp->config.ifcoding) { default: case SDL_CODING_HDB3: ccr1 |= 0x44; break; case SDL_CODING_AMI: ccr1 |= 0x00; break; } switch (sp->config.ifgcrc) { case SDL_GCRC_CRC4: ccr1 |= 0x11; break; default: ccr1 |= 0x00; break; } cd->xlb[base + 0x12] = tcr1; cd->xlb[base + 0x14] = ccr1; cd->xlb[base + 0x18] = 0x20; /* 120 Ohm, Normal */ cd->xlb[base + 0x1b] = 0x8a; /* CRC3: LIRST & TSCLKM */ cd->xlb[base + 0x20] = 0x1b; /* TAFR */ cd->xlb[base + 0x21] = 0x5f; /* TNAFR */ cd->xlb[base + 0x40] = 0x0b; /* TSR1 */ for (offset = 0x41; offset <= 0x4f; offset++) cd->xlb[base + offset] = 0x55; for (offset = 0x22; offset <= 0x25; offset++) cd->xlb[base + offset] = 0xff; timeout = jiffies + 100 * HZ / 1000; spin_unlock_irqrestore(&cd->lock, flags); while (jiffies < timeout) ; spin_lock_irqsave(&cd->lock, flags); cd->xlb[base + 0x1b] = 0x9a; /* CRC3: set ESR as well */ cd->xlb[base + 0x1b] = 0x82; /* CRC3: TSCLKM only */ sp->config.ifflags |= (SDL_IF_UP | SDL_IF_TX_RUNNING | SDL_IF_RX_RUNNING); /* enable interrupts */ cd->xlb[CTLREG] = (INTENA | E1DIV); spin_unlock_irqrestore(&cd->lock, flags); break; } case SDL_GTYPE_T1: { int byte, val, c; unsigned short mask = 0; psw_t flags = 0; printd(("%s: performing enable on T1 span %d\n", DRV_NAME, span)); spin_lock_irqsave(&cd->lock, flags); // cd->xlb[SYNREG] = SYNCSELF; /* NO, NO, NO */ /* Tell ISR to re-evaluate the sync source */ cd->eval_syncsrc = 1; cd->xlb[CTLREG] = 0; cd->xlb[LEDREG] = 0xff; for (offset = 0; offset < 160; offset++) cd->xlb[base + offset] = 0x00; /* Set up for interleaved serial bus operation, byte mode */ if (span == 0) cd->xlb[base + 0x94] = 0x09; else cd->xlb[base + 0x94] = 0x08; cd->xlb[base + 0x2b] = 0x08; /* Full-on sync required (RCR1) */ cd->xlb[base + 0x2c] = 0x08; /* RSYNC is an input (RCR2) */ cd->xlb[base + 0x35] = 0x10; /* RBS enable (TCR1) */ cd->xlb[base + 0x36] = 0x04; /* TSYNC to be output (TCR2) */ cd->xlb[base + 0x37] = 0x9c; /* Tx & Rx Elastic stor, sysclk(s) = 2.048 mhz, loopback controls (CCR1) */ cd->xlb[base + 0x12] = 0x22; /* Set up received loopup and loopdown codes */ cd->xlb[base + 0x14] = 0x80; cd->xlb[base + 0x15] = 0x80; /* Enable F bits pattern */ switch (sp->config.ifframing) { default: case SDL_FRAMING_SF: val = 0x20; break; case SDL_FRAMING_ESF: val = 0x88; break; } switch (sp->config.ifcoding) { default: case SDL_CODING_AMI: break; case SDL_CODING_B8ZS: val |= 0x44; break; } cd->xlb[base + 0x38] = val; if (sp->config.ifcoding != SDL_CODING_B8ZS) cd->xlb[base + 0x7e] = 0x1c; /* Set FDL register to 0x1c */ cd->xlb[base + 0x7c] = sp->config.iftxlevel << 5; /* LBO */ cd->xlb[base + 0x0a] = 0x80; /* LIRST to reset line interface */ timeout = jiffies + 100 * HZ / 1000; spin_unlock_irqrestore(&cd->lock, flags); while (jiffies < timeout) ; spin_lock_irqsave(&cd->lock, flags); cd->xlb[base + 0x0a] = 0x30; /* LIRST bask to normal, Resetting elastic buffers */ sp->config.ifflags |= (SDL_IF_UP | SDL_IF_TX_RUNNING | SDL_IF_RX_RUNNING); /* enable interrupts */ cd->xlb[CTLREG] = (INTENA); spin_unlock_irqrestore(&cd->lock, flags); /* establish which channels are clear channel */ for (c = 0; c < 24; c++) { int slot = xp_t1_chan_map[c]; byte = c >> 3; if (!cd->spans[span]->slots[slot] || !cd->spans[span]->slots[slot]->xp || cd->spans[span]->slots[slot]->xp->obj.sdl.config.iftype != SDL_TYPE_DS0A) mask |= 1 << (c % 8); if ((c % 8) == 7) cd->xlb[base + 0x39 + byte] = mask; } break; } default: swerr(); break; } } return (QR_DONE); lmi_outstate: return lmi_error_ack(q, xp, xp->i_state, LMI_ENABLE_REQ, 0, LMI_OUTSTATE);}/* * LMI_DISABLE_REQ * ----------------------------------- */STATIC intlmi_disable_req(queue_t *q, mblk_t *mp){ struct xp *xp = XP_PRIV(q); int err; struct sp *sp; struct cd *cd; /* validate disable */ if (xp->i_state != LMI_ENABLED) goto lmi_outstate; xp->i_state = LMI_DISABLE_PENDING; /* perform disable */ if ((err = lmi_disable_con(q, xp))) return (err); /* commit disable */ if ((sp = xp->sp) && (cd = sp->cd)) { psw_t flags = 0; spin_lock_irqsave(&cd->lock, flags); { int slot, boff; uchar idle = (cd->config.ifgtype == SDL_GTYPE_T1) ? 0x7f : 0xff; uchar *base = (uchar *) cd->wbuf + span_to_byte(sp->span); for (slot = 0; slot < 32; slot++) if (sp->slots[slot] && sp->slots[slot]->xp == xp) for (boff = 0; boff < X400P_EBUFNO; boff++) *(base + (boff << 10) + (slot << 2)) = idle; /* stop transmitters and receivers */ xp->obj.sdl.config.ifflags = 0; xp->obj.sdl.statem.tx_state = SDL_STATE_IDLE; xp->obj.sdl.statem.rx_state = SDL_STATE_IDLE; } spin_unlock_irqrestore(&cd->lock, flags); } else swerr(); return (QR_DONE); lmi_outstate: return lmi_error_ack(q, xp, xp->i_state, LMI_DISABLE_REQ, 0, LMI_OUTSTATE);}/* * LMI_OPTMGMT_REQ * ----------------------------------- */STATIC intlmi_optmgmt_req(queue_t *q, mblk_t *mp){ (void) q; (void) mp; fixme(("FIXME: must check for options change\n")); return (QR_PASSALONG);}/* * M_DATA * ----------------------------------- */STATIC intch_m_data(queue_t *q, mblk_t *mp){ fixme(("Write this function\n")); return (-EFAULT);}/* * CH_DATA_REQ * ----------------------------------- * Non-preferred method for sending data. We should send just M_DATA blocks. */STATIC intch_data_req(queue_t *q, mblk_t *mp){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -