diff --git a/drivers/isdn/hardware/mISDN/core.c b/drivers/isdn/hardware/mISDN/core.c index 8aba7f5..35ccf8c 100644 --- a/drivers/isdn/hardware/mISDN/core.c +++ b/drivers/isdn/hardware/mISDN/core.c @@ -172,6 +172,25 @@ disconnect_if(hisaxinstance_t *inst, u_int prim, hisaxif_t *hif) { return(err); } +static int +add_if(hisaxinstance_t *inst, u_int prim, hisaxif_t *hif) { + hisaxif_t *myif; + + if (!inst) + return(-EINVAL); + if (!hif) + return(-EINVAL); + if (hif->stat & IF_UP) { + myif = &inst->down; + } else if (hif->stat & IF_DOWN) { + myif = &inst->up; + } else + return(-EINVAL); + APPEND_TO_LIST(hif, myif); + inst->obj->own_ctrl(inst, prim, hif); + return(0); +} + static char tmpbuf[4096]; static int debugout(hisaxinstance_t *inst, logdata_t *log) @@ -217,6 +236,8 @@ static int central_manager(void *data, u_int prim, void *arg) { case MGR_DISCONNECT | REQUEST: case MGR_DISCONNECT | INDICATION: return(disconnect_if(data, prim, arg)); + case MGR_ADDIF | REQUEST: + return(add_if(data, prim, arg)); case MGR_CONNECT | REQUEST: return(ConnectIF(data, arg)); case MGR_LOADFIRM | REQUEST: diff --git a/drivers/isdn/hardware/mISDN/layer2.c b/drivers/isdn/hardware/mISDN/layer2.c index 2883fd3..a14194c 100644 --- a/drivers/isdn/hardware/mISDN/layer2.c +++ b/drivers/isdn/hardware/mISDN/layer2.c @@ -131,6 +131,12 @@ l2down(layer2_t *l2, u_int prim, int dinfo, int len, void *arg) { return(err); } +static int +l2_chain_down(hisaxif_t *hif, u_int prim, int dinfo, int len, void *arg) { + if (!hif || !hif->fdata) + return(-EINVAL); + return(l2down(hif->fdata, prim, dinfo, len, arg)); +} static int l2down_phd(layer2_t *l2, struct sk_buff *skb) { @@ -2090,6 +2096,19 @@ l2_manager(void *data, u_int prim, void *arg) { } return(SetIF(inst, arg, prim, l2from_up, l2from_down, l2l)); break; + case MGR_ADDIF | REQUEST: + if (!l2l) { + printk(KERN_WARNING "l2_manager addif l2 no instance\n"); + return(-EINVAL); + } + if (arg) { + hisaxif_t *hif = arg; + if (hif->stat & IF_UP) { + hif->fdata = l2l; + hif->func = l2_chain_down; + } + } + break; case MGR_DISCONNECT | REQUEST: case MGR_DISCONNECT | INDICATION: if (!l2l) { diff --git a/drivers/isdn/hardware/mISDN/udevice.c b/drivers/isdn/hardware/mISDN/udevice.c index 1fc1c1d..c06d96c 100644 --- a/drivers/isdn/hardware/mISDN/udevice.c +++ b/drivers/isdn/hardware/mISDN/udevice.c @@ -13,7 +13,7 @@ #define MAX_HEADER_LEN 4 #define FLG_MGR_SETSTACK 1 -#define FLG_DOWN_BUSY 2 +#define FLG_MGR_OWNSTACK 2 typedef struct _hisaxdevice { struct _hisaxdevice *prev; @@ -35,9 +35,8 @@ typedef struct _devicelayer { hisaxdevice_t *dev; hisaxinstance_t inst; hisaxinstance_t *slave; - hisaxif_t sif; - struct sk_buff_head queue; - struct sk_buff *last_skb; + hisaxif_t s_up; + hisaxif_t s_down; int iaddr; int lm_st; int Flags; @@ -53,8 +52,8 @@ static u_char stbuf[1000]; static int device_debug = 0; static int from_up_down(hisaxif_t *, u_int, int, int, void *); -static int from_peer(hisaxif_t *, u_int, int, int, void *); -static int to_peer(hisaxif_t *, u_int, int, int, void *); +// static int from_peer(hisaxif_t *, u_int, int, int, void *); +// static int to_peer(hisaxif_t *, u_int, int, int, void *); static int @@ -117,8 +116,30 @@ stack_inst_flg(hisaxdevice_t *dev, hisaxstack_t *st, int bit, int clear) return(ret); } +static hisaxstack_t * +clone_stack(int addr) +{ + int err; + hisaxstack_t *st; + hisaxinstance_t inst; + + memset(&inst, 0, sizeof(hisaxinstance_t)); + st = get_stack4id(addr); + if (!st) + return(NULL); + err = udev_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &inst); + if (err) + return(NULL); + memcpy(&inst.st->pid, &st->pid, sizeof(hisax_pid_t)); + inst.st->child = st->child; + inst.st->mgr = NULL; + return(st); +} + static int -create_layer(hisaxdevice_t *dev, hisaxstack_t *st, layer_info_t *linfo, int *adr) { +create_layer(hisaxdevice_t *dev, hisaxstack_t *st, layer_info_t *linfo, + int *adr, int mgr) +{ hisaxlayer_t *layer; int i, ret; devicelayer_t *nl; @@ -177,6 +198,10 @@ create_layer(hisaxdevice_t *dev, hisaxstack_t *st, layer_info_t *linfo, int *adr } } } + if (mgr) { + st->mgr = &nl->inst; + test_and_set_bit(FLG_MGR_OWNSTACK, &nl->Flags); + } nl->inst.down.owner = &nl->inst; nl->inst.up.owner = &nl->inst; nl->inst.obj = &udev_obj; @@ -186,7 +211,6 @@ create_layer(hisaxdevice_t *dev, hisaxstack_t *st, layer_info_t *linfo, int *adr nl->iaddr = nl->inst.id | IADDR_BIT; *adr++ = nl->iaddr; if (inst) { - skb_queue_head_init(&nl->queue); nl->slave = inst; *adr = inst->id; } else @@ -195,31 +219,32 @@ create_layer(hisaxdevice_t *dev, hisaxstack_t *st, layer_info_t *linfo, int *adr } static int -reconnect(devicelayer_t *dl) -{ - hisaxinstance_t *peer; +remove_if(devicelayer_t *dl, int stat) { + hisaxif_t *hif,*phif,*shif; + int err; - if (dl->inst.down.owner != &dl->inst) { - peer = dl->inst.down.owner; - if (peer->down.fdata == dl) { - memcpy(&peer->down, &dl->inst.down, sizeof(hisaxif_t)); - memset(&dl->inst.down, 0, sizeof(hisaxif_t)); - } else if (peer->up.fdata == dl) { - memcpy(&peer->up, &dl->inst.down, sizeof(hisaxif_t)); - memset(&dl->inst.down, 0, sizeof(hisaxif_t)); - } + if (device_debug & DEBUG_MGR_FUNC) + printk(KERN_DEBUG __FUNCTION__":dl(%p) stat(%x)\n", dl, stat); + phif = NULL; + if (stat & IF_UP) { + hif = &dl->inst.up; + shif = &dl->s_up; + if (shif->owner) + phif = &shif->owner->down; + else if (stat & IF_DOWN) + hif = &dl->inst.down; + shif = &dl->s_down; + if (shif->owner) + phif = &shif->owner->up; + } else { + printk(KERN_WARNING __FUNCTION__": stat not UP/DOWN\n"); + return(-EINVAL); } - if (dl->inst.up.owner != &dl->inst) { - peer = dl->inst.up.owner; - if (peer->down.fdata == dl) { - memcpy(&peer->down, &dl->inst.up, sizeof(hisaxif_t)); - memset(&dl->inst.up, 0, sizeof(hisaxif_t)); - } else if (peer->up.fdata == dl) { - memcpy(&peer->up, &dl->inst.up, sizeof(hisaxif_t)); - memset(&dl->inst.up, 0, sizeof(hisaxif_t)); - } - } - return(0); + err = udev_obj.ctrl(hif->peer, MGR_DISCONNECT | REQUEST, hif); + if (phif) + memcpy(phif, shif, sizeof(hisaxif_t)); + REMOVE_FROM_LIST(hif); + return(err); } static int @@ -234,13 +259,9 @@ del_layer(devicelayer_t *dl) { printk(KERN_DEBUG __FUNCTION__": iaddr %x inst %s slave %p\n", dl->iaddr, inst->name, dl->slave); } - reconnect(dl); + remove_if(dl, IF_UP); + remove_if(dl, IF_DOWN); if (dl->slave) { - discard_queue(&dl->queue); - if (dl->last_skb) { - dev_kfree_skb(dl->last_skb); - dl->last_skb = NULL; - } dl->slave->obj->own_ctrl(dl->slave, MGR_UNREGLAYER | REQUEST, NULL); dl->slave = NULL; @@ -270,21 +291,22 @@ del_layer(devicelayer_t *dl) { dl->iaddr = 0; REMOVE_FROM_LISTBASE(dl, dev->layer); udev_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL); + if (test_and_clear_bit(FLG_MGR_OWNSTACK, &dl->Flags)) { + udev_obj.ctrl(inst->st, MGR_DELSTACK | REQUEST, NULL); + } kfree(dl); return(0); } static int connect_if_req(hisaxdevice_t *dev, iframe_t *iff) { - hisaxif_t *hif, *phif; devicelayer_t *dl; - int stat,err=-ENXIO; interface_info_t *ifi = (interface_info_t *)&iff->data.p; hisaxinstance_t *inst; hisaxinstance_t *peer; if (device_debug & DEBUG_MGR_FUNC) - printk(KERN_DEBUG __FUNCTION__": addr:%x own(%x) peer(%X)\n", + printk(KERN_DEBUG __FUNCTION__": addr:%x own(%x) peer(%x)\n", iff->addr, ifi->owner, ifi->peer); if (!(dl=get_devlayer(dev, iff->addr))) return(-ENXIO); @@ -298,117 +320,104 @@ connect_if_req(hisaxdevice_t *dev, iframe_t *iff) { ifi->peer); return(-ENODEV); } - if (inst != &dl->inst) { - printk(KERN_WARNING __FUNCTION__": owner(%x) not our\n", + return(ConnectIF(inst, peer)); +} + +static int +set_if_req(hisaxdevice_t *dev, iframe_t *iff) { + hisaxif_t *hif,*phif,*shif; + int stat; + interface_info_t *ifi = (interface_info_t *)&iff->data.p; + devicelayer_t *dl; + hisaxinstance_t *inst, *peer; + + if (device_debug & DEBUG_MGR_FUNC) + printk(KERN_DEBUG __FUNCTION__": addr:%x own(%x) peer(%x)\n", + iff->addr, ifi->owner, ifi->peer); + if (!(dl=get_devlayer(dev, iff->addr))) + return(-ENXIO); + if (!(inst = get_instance4id(ifi->owner))) { + printk(KERN_WARNING __FUNCTION__": owner(%x) not found\n", ifi->owner); - return(-EINVAL); + return(-ENODEV); } + if (!(peer = get_instance4id(ifi->peer))) { + printk(KERN_WARNING __FUNCTION__": peer(%x) not found\n", + ifi->peer); + return(-ENODEV); + } + if (ifi->stat == IF_UP) { hif = &dl->inst.up; phif = &peer->down; + shif = &dl->s_up; stat = IF_DOWN; } else if (ifi->stat == IF_DOWN) { hif = &dl->inst.down; + shif = &dl->s_down; phif = &peer->up; stat = IF_UP; } else { printk(KERN_WARNING __FUNCTION__": if not UP/DOWN\n"); return(-EINVAL); } - if (hif->stat != IF_NOACTIV) + + + if (shif->stat != IF_NOACTIV) { + printk(KERN_WARNING __FUNCTION__": save if busy\n"); return(-EBUSY); - if (phif->stat != IF_NOACTIV) { /* install splitter */ - if (!(inst = phif->peer)) - return(-EINVAL); - memcpy(&dl->inst.down, phif, sizeof(hisaxif_t)); - phif->func = from_peer; - phif->fdata = dl; - if (stat == IF_UP) { - stat = IF_DOWN; - phif = &inst->down; - } else { - stat = IF_UP; - phif = &inst->up; - } - memcpy(&dl->inst.up, phif, sizeof(hisaxif_t)); - phif->func = to_peer; - phif->fdata = dl; - err = 0; - if (dl->slave) { - - dl->sif.stat = stat; - dl->sif.owner = &dl->inst; - dl->sif.peer = dl->slave; - err = dl->slave->obj->own_ctrl(dl->slave, MGR_SETIF | - REQUEST, &dl->sif); - if (err) - dl->sif.stat = IF_NOACTIV; - - } - } else { - hif->stat = stat; - hif->peer = peer; - err = udev_obj.ctrl(&dl->inst, MGR_CONNECT | REQUEST, - hif->peer); - if (err) - hif->stat = IF_NOACTIV; } - return(err); + if (hif->stat != IF_NOACTIV) { + printk(KERN_WARNING __FUNCTION__": own if busy\n"); + return(-EBUSY); + } + hif->stat = stat; + hif->owner = inst; + memcpy(shif, phif, sizeof(hisaxif_t)); + memset(phif, 0, sizeof(hisaxif_t)); + return(peer->obj->own_ctrl(peer, iff->prim, hif)); } static int -set_if_req(hisaxdevice_t *dev, iframe_t *iff) { - hisaxif_t *hif = NULL; - devicelayer_t *dl; - int *ip, err=-ENXIO; +add_if_req(hisaxdevice_t *dev, iframe_t *iff) { + hisaxif_t *hif; + interface_info_t *ifi = (interface_info_t *)&iff->data.p; + hisaxinstance_t *inst, *peer; if (device_debug & DEBUG_MGR_FUNC) - printk(KERN_DEBUG __FUNCTION__": addr:%x\n", iff->addr); - if (iff->len != sizeof(int)) - return(-EINVAL); - if (!(dl=get_devlayer(dev, iff->addr))) - return(-ENXIO); - ip = &iff->data.i; - if (iff->addr & IF_UP) { - hif = &dl->inst.up; - if (hif->stat == IF_NOACTIV) { - hif->stat = IF_DOWN; - hif->extentions = *ip++; - err = udev_obj.ctrl(dl->inst.st, MGR_CONNECT | REQUEST, hif); - if (err) - hif->stat = IF_NOACTIV; - } else - err = -EBUSY; - } else if (iff->addr & IF_DOWN) { - hif = &dl->inst.down; - if (hif->stat == IF_NOACTIV) { - hif->stat = IF_UP; - - err = udev_obj.ctrl(dl->inst.st, MGR_CONNECT | REQUEST, hif); - if (err) - hif->stat = IF_NOACTIV; - } else - err = -EBUSY; + printk(KERN_DEBUG __FUNCTION__": addr:%x own(%x) peer(%x)\n", + iff->addr, ifi->owner, ifi->peer); + if (!(inst = get_instance4id(ifi->owner))) { + printk(KERN_WARNING __FUNCTION__": owner(%x) not found\n", + ifi->owner); + return(-ENODEV); } - return(err); + if (!(peer = get_instance4id(ifi->peer))) { + printk(KERN_WARNING __FUNCTION__": peer(%x) not found\n", + ifi->peer); + return(-ENODEV); + } + + if (ifi->stat == IF_DOWN) { + hif = &inst->up; + } else if (ifi->stat == IF_UP) { + hif = &inst->down; + } else { + printk(KERN_WARNING __FUNCTION__": if not UP/DOWN\n"); + return(-EINVAL); + } + return(peer->obj->ctrl(peer, iff->prim, hif)); } static int del_if_req(hisaxdevice_t *dev, iframe_t *iff) { devicelayer_t *dl; - int err=-ENXIO; if (device_debug & DEBUG_MGR_FUNC) printk(KERN_DEBUG __FUNCTION__": addr:%x\n", iff->addr); if (!(dl=get_devlayer(dev, iff->addr))) return(-ENXIO); - if (iff->addr & IF_UP) - err = udev_obj.ctrl(dl->inst.up.peer, MGR_DISCONNECT | REQUEST, - &dl->inst.up); - else if (iff->addr & IF_DOWN) - err = udev_obj.ctrl(dl->inst.down.peer, MGR_DISCONNECT | REQUEST, - &dl->inst.down); - return(err); + return(remove_if(dl, iff->addr)); } static int @@ -512,6 +521,56 @@ hisax_wdata(hisaxdevice_t *dev, void *dp, int len) { off.len = 0; hisax_rdata(dev, &off, err); break; + case (MGR_SETSTACK | REQUEST): + used = head + sizeof(hisax_pid_t); + if (lenaddr; + off.dinfo = 0; + off.prim = MGR_SETSTACK | CONFIRM; + off.len = 0; + if ((st = get_stack4id(iff->addr))) { + stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 0); + err = udev_obj.ctrl(st, iff->prim, &iff->data.i); + if (err<0) + off.len = err; + } else + off.len = -ENODEV; + hisax_rdata(dev, &off, 1); + break; + case (MGR_NEWSTACK | REQUEST): + used = head + sizeof(layer_info_t); + if (lenaddr; + off.dinfo = 0; + off.prim = MGR_NEWSTACK | CONFIRM; + off.len = 8; + off.data.p = stbuf; + if ((st = clone_stack(iff->addr))) { + err = create_layer(dev, st, + (layer_info_t *)&iff->data.i, off.data.p, 1); + if (err<0) + off.len = err; + } else + off.len = -ENODEV; + hisax_rdata(dev, &off, 1); + break; + case (MGR_CLEARSTACK | REQUEST): + used = head; + off.addr = iff->addr; + off.prim = MGR_CLEARSTACK | CONFIRM; + off.dinfo = 0; + off.len = 0; + if ((st = get_stack4id(iff->addr))) { + stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 1); + err = udev_obj.ctrl(st, iff->prim, NULL); + if (err<0) + off.len = err; + } else + off.len = -ENODEV; + hisax_rdata(dev, &off, 1); + break; case (MGR_GETLAYER | REQUEST): used = head + sizeof(u_int); if (lenaddr))) { err = create_layer(dev, st, - (layer_info_t *)&iff->data.i, off.data.p); + (layer_info_t *)&iff->data.i, off.data.p, 0); if (err<0) off.len = err; } else @@ -656,6 +715,16 @@ hisax_wdata(hisaxdevice_t *dev, void *dp, int len) { off.len = set_if_req(dev, iff); hisax_rdata(dev, &off, 1); break; + case (MGR_ADDIF | REQUEST): + used = head + iff->len; + if (lenaddr; + off.prim = MGR_ADDIF | CONFIRM; + off.dinfo = 0; + off.len = add_if_req(dev, iff); + hisax_rdata(dev, &off, 1); + break; case (MGR_DISCONNECT | REQUEST): used = head; off.addr = iff->addr; @@ -664,38 +733,6 @@ hisax_wdata(hisaxdevice_t *dev, void *dp, int len) { off.len = del_if_req(dev, iff); hisax_rdata(dev, &off, 1); break; - case (MGR_SETSTACK | REQUEST): - used = head + sizeof(hisax_pid_t); - if (lenaddr; - off.dinfo = 0; - off.prim = MGR_SETSTACK | CONFIRM; - off.len = 0; - if ((st = get_stack4id(iff->addr))) { - stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 0); - err = udev_obj.ctrl(st, iff->prim, &iff->data.i); - if (err<0) - off.len = err; - } else - off.len = -ENODEV; - hisax_rdata(dev, &off, 1); - break; - case (MGR_CLEARSTACK | REQUEST): - used = head; - off.addr = iff->addr; - off.prim = MGR_CLEARSTACK | CONFIRM; - off.dinfo = 0; - off.len = 0; - if ((st = get_stack4id(iff->addr))) { - stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 1); - err = udev_obj.ctrl(st, iff->prim, NULL); - if (err<0) - off.len = err; - } else - off.len = -ENODEV; - hisax_rdata(dev, &off, 1); - break; default: used = head + iff->len; if (lenfdata; - if (!dl) - return(ret); - if (!dl->slave || !dl->sif.func) { - if (dl->inst.down.func) - ret = dl->inst.down.func(&dl->inst.down, prim, dinfo, len, - arg); - return(ret); - } - if (dinfo == DINFO_SKB) { - if (test_bit(FLG_DOWN_BUSY, &dl->Flags)) { - if (arg == dl->last_skb) { - if ((dl->last_skb = skb_dequeue(&dl->queue))) { - dl->inst.up.func(&dl->inst.up, - dl->last_skb->priority, - DINFO_SKB, 0, dl->last_skb); - } else - test_and_clear_bit(FLG_DOWN_BUSY, - &dl->Flags); - } - } - nskb = skb_clone(arg, GFP_ATOMIC); - ret = dl->sif.func(&dl->sif, prim, dinfo, len, arg); - if (ret) { - dev_kfree_skb(nskb); - if (dl->inst.down.func) - ret = dl->inst.down.func(&dl->inst.down, prim, - dinfo, len, arg); - } else { - if (dl->inst.down.func) - ret = dl->inst.down.func(&dl->inst.down, prim, - dinfo, len, nskb); - else - dev_kfree_skb(nskb); - if (ret) - dev_kfree_skb(nskb); - ret = 0; /* first delivery was OK */ - } - } else { - ret = dl->sif.func(&dl->sif, prim, dinfo, len, arg); - if (ret) { - if (dl->inst.down.func) - ret = dl->inst.down.func(&dl->inst.down, prim, - dinfo, len, arg); - } else { - if (dl->inst.down.func) - dl->inst.down.func(&dl->inst.down, prim, - dinfo, len, arg); - } - } - return(ret); -} - -static int -to_peer(hisaxif_t *hif, u_int prim, int dinfo, int len, void *arg) { - int ret = -EINVAL; - devicelayer_t *dl; - struct sk_buff *skb; - - printk(KERN_DEBUG __FUNCTION__ ": prim(%x) di(%x) l(%d) arg(%p)\n", - prim, dinfo, len, arg); - if (!hif) - return(-EINVAL); - dl = hif->fdata; - if (!dl) - return(ret); - if (!dl->slave) { - if (dl->inst.up.func) - ret = dl->inst.up.func(&dl->inst.up, prim, dinfo, - len, arg); - return(ret); - } - if (dinfo == DINFO_SKB) { - if (test_and_set_bit(FLG_DOWN_BUSY, &dl->Flags)) { - skb = arg; - skb->priority = prim; - skb_queue_tail(&dl->queue, skb); - return(0); - } - dl->last_skb = arg; - ret = dl->inst.up.func(&dl->inst.up, prim, dinfo, - len, arg); - } else { - ret = dl->inst.up.func(&dl->inst.up, prim, dinfo, - len, arg); - } - return(ret); -} static int set_if(devicelayer_t *dl, u_int prim, hisaxif_t *hif) { int err = 0; - - if (dl->slave && (hif->owner == dl->slave)) { - hif->peer = &dl->inst; - hif->fdata = dl; - hif->func = to_peer; - if ((prim & SUBCOMMAND_MASK) == REQUEST) { - if (dl->sif.stat == IF_NOACTIV) { - if (IF_TYPE(hif) == IF_UP) - dl->sif.stat = IF_DOWN; - else - dl->sif.stat = IF_UP; - dl->sif.owner = &dl->inst; - err = hif->owner->obj->own_ctrl(hif->owner, - MGR_SETIF | INDICATION, &dl->sif); - } else { - int_errtxt("REQ own stat(%x)", dl->sif.stat); - err= -EBUSY; - } - } - } else { - err = SetIF(&dl->inst, hif, prim, from_up_down, from_up_down, dl); - } + + err = SetIF(&dl->inst, hif, prim, from_up_down, from_up_down, dl); return(err); } diff --git a/include/linux/mISDNif.h b/include/linux/mISDNif.h index 7da3709..43d2fd4 100644 --- a/include/linux/mISDNif.h +++ b/include/linux/mISDNif.h @@ -43,6 +43,7 @@ #define MGR_CONNECT 0x0f3200 #define MGR_DISCONNECT 0x0f3300 #define MGR_SETIF 0x0f3400 +#define MGR_ADDIF 0x0f3500 #define MGR_RELEASE 0x0f4500 #define MGR_CONTROL 0x0fe100 #define MGR_STATUS 0x0fe200 @@ -219,7 +220,7 @@ #define IF_NOACTIV 0x00000000 #define IF_DOWN 0x01000000 #define IF_UP 0x02000000 -#define IF_LOG 0x04000000 +#define IF_CHAIN 0x04000000 #define IF_HANDSHAKE 0x08000000 #define IF_TYPEMASK 0x07000000 #define IF_ADDRMASK 0x00FFFFFF