2 * Core driver for Diva Server cards
3 * Implements the IDI interface
5 * Copyright (C) Eicon Technology Corporation, 2000.
7 * Eicon File Revision : 1.8
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
21 /* IDI request functions */
23 static void request(card_t *card, ENTITY *e);
25 static void req_0(ENTITY *e) { request(&DivasCards[ 0], e); }
26 static void req_1(ENTITY *e) { request(&DivasCards[ 1], e); }
27 static void req_2(ENTITY *e) { request(&DivasCards[ 2], e); }
28 static void req_3(ENTITY *e) { request(&DivasCards[ 3], e); }
29 static void req_4(ENTITY *e) { request(&DivasCards[ 4], e); }
30 static void req_5(ENTITY *e) { request(&DivasCards[ 5], e); }
31 static void req_6(ENTITY *e) { request(&DivasCards[ 6], e); }
32 static void req_7(ENTITY *e) { request(&DivasCards[ 7], e); }
33 static void req_8(ENTITY *e) { request(&DivasCards[ 8], e); }
34 static void req_9(ENTITY *e) { request(&DivasCards[ 9], e); }
35 static void req_10(ENTITY *e) { request(&DivasCards[10], e); }
36 static void req_11(ENTITY *e) { request(&DivasCards[11], e); }
37 static void req_12(ENTITY *e) { request(&DivasCards[12], e); }
38 static void req_13(ENTITY *e) { request(&DivasCards[13], e); }
39 static void req_14(ENTITY *e) { request(&DivasCards[14], e); }
40 static void req_15(ENTITY *e) { request(&DivasCards[15], e); }
42 IDI_CALL DivasIdiRequest[16] =
44 &req_0, &req_1, &req_2, &req_3,
45 &req_4, &req_5, &req_6, &req_7,
46 &req_8, &req_9, &req_10, &req_11,
47 &req_12, &req_13, &req_14, &req_15
50 #define PR_RAM ((struct pr_ram *)0)
51 #define RAM ((struct dual *)0)
53 /*------------------------------------------------------------------*/
54 /* local function prototypes */
55 /*------------------------------------------------------------------*/
57 static byte isdn_rc(ADAPTER *, byte, byte, byte, word);
58 static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
61 * IDI related functions
65 ENTITY *entity_ptr(ADAPTER *a, byte e_no)
71 return card->e_tbl[e_no].e;
75 void CALLBACK(ADAPTER *a, ENTITY *e)
79 if (card->log_types & DIVAS_LOG_IDI)
81 DivasLogIdi(card, e, FALSE);
88 void *PTR_P(ADAPTER *a, ENTITY *e, void *P)
94 void *PTR_R(ADAPTER *a, ENTITY *e)
100 void *PTR_X(ADAPTER *a, ENTITY *e)
106 void free_entity(ADAPTER *a, byte e_no)
113 ipl = UxCardLock(card->hw);
115 card->e_tbl[e_no].e = NULL;
118 UxCardUnlock(card->hw, ipl);
124 void assign_queue(ADAPTER * a, byte e_no, word ref)
131 ipl = UxCardLock(card->hw);
133 card->e_tbl[e_no].assign_ref = ref;
134 card->e_tbl[e_no].next = card->assign;
137 UxCardUnlock(card->hw, ipl);
143 byte get_assign(ADAPTER *a, word ref)
151 ipl = UxCardLock(card->hw);
153 e_no = (byte)card->assign;
156 if (card->e_tbl[e_no].assign_ref == ref)
160 e_no = card->e_tbl[e_no].next;
163 UxCardUnlock(card->hw, ipl);
169 void req_queue(ADAPTER * a, byte e_no)
176 ipl = UxCardLock(card->hw);
178 card->e_tbl[e_no].next = 0;
182 card->e_tbl[card->e_tail].next = e_no;
191 UxCardUnlock(card->hw, ipl);
197 byte look_req(ADAPTER * a)
203 return(card->e_head);
207 void next_req(ADAPTER * a)
215 ipl = UxCardLock(card->hw);
217 card->e_head = card->e_tbl[card->e_head].next;
223 UxCardUnlock(card->hw, ipl);
230 * IDI request function for active cards
233 void request(card_t *card, ENTITY *e)
240 if (card->log_types & DIVAS_LOG_IDI)
242 DivasLogIdi(card, e, TRUE);
247 special_req = (word *) e;
249 switch (*special_req)
255 for (i=0; i < DIM(card->cfg.name); i++)
257 ((struct get_name_s *) e)->name[i] = card->cfg.name[i];
263 DPRINTF(("IDI: attempted REQ_SERIAL or REQ_XLOG"));
271 ipl = UxCardLock(card->hw);
275 DPRINTF(("IDI: ASSIGN req"));
277 for (i = 1; i < card->e_max; i++)
279 if (!card->e_tbl[i].e)
285 if (i == card->e_max)
287 DPRINTF(("IDI: request all ids in use (IDI req ignored)"));
288 UxCardUnlock(card->hw, ipl);
289 e->Rc = OUT_OF_RESOURCES;
293 card->e_tbl[i].e = e;
307 DPRINTF(("IDI: request - entity is busy"));
308 UxCardUnlock(card->hw, ipl);
317 card->e_tbl[i].next = 0;
321 card->e_tbl[card->e_tail].next = i;
330 UxCardUnlock(card->hw, ipl);
332 DivasScheduleRequestDpc();
337 static byte pr_ready(ADAPTER * a)
341 ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
342 a->ram_in(a, &PR_RAM->ReqInput));
346 a->ram_inc(a, &PR_RAM->ReadyInt);
353 /*------------------------------------------------------------------*/
354 /* output function */
355 /*------------------------------------------------------------------*/
357 void DivasOut(ADAPTER * a)
360 ENTITY * this = NULL;
371 /* while a request is pending ... */
378 ReadyCount = pr_ready(a);
381 DPRINTF(("IDI: card not ready for next request"));
386 while(e_no && ReadyCount) {
390 this = entity_ptr(a, e_no);
392 #ifdef USE_EXTENDED_DEBUGS
395 ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
396 DBG_FTL(("!A%d ==> NULL entity ptr - try to ignore", (int)io->ANum))
402 ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
403 DPRINTF(("IDI: >A%d Id=0x%x Req=0x%x", io->ANum, this->Id, this->Req))
406 DPRINTF(("IDI: >REQ=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh));
409 /* get address of next available request buffer */
410 ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
412 /* now copy the data from the current data buffer into the */
413 /* adapters request buffer */
417 while(i<this->XNum && length<270) {
418 clength = (word)(270-length);
419 if (clength > X[i].PLength-this->XOffset)
420 clength = X[i].PLength-this->XOffset;
422 &ReqOut->XBuffer.P[length],
423 PTR_P(a,this,&X[i].P[this->XOffset]),
427 this->XOffset +=clength;
428 if(this->XOffset==X[i].PLength) {
429 this->XCurrent = (byte)++i;
434 a->ram_outw(a, &ReqOut->XBuffer.length, length);
435 a->ram_out(a, &ReqOut->ReqId, this->Id);
436 a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
438 /* if its a specific request (no ASSIGN) ... */
442 /* if buffers are left in the list of data buffers do */
443 /* do chaining (LL_MDATA, N_MDATA) */
446 if(i<this->XNum && this->MInd) {
447 a->ram_out(a, &ReqOut->Req, this->MInd);
452 a->ram_out(a, &ReqOut->Req, this->Req);
456 /* if we did chaining, this entity is put back into the */
460 req_queue(a,this->No);
464 /* else it's a ASSIGN */
468 /* save the request code used for buffer chaining */
471 if (this->Id==BLLC_ID) this->MInd = LL_MDATA;
472 if (this->Id==NL_ID ||
475 ) this->MInd = N_MDATA;
477 /* send the ASSIGN */
480 a->ram_out(a, &ReqOut->Req, this->Req);
482 /* save the reference of the ASSIGN */
484 assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
486 a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
493 /* send the filled request buffers to the ISDN adapter */
495 a->ram_out(a, &PR_RAM->ReqInput,
496 (byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
498 /* if it is a 'unreturncoded' UREMOVE request, remove the */
499 /* Id from our table after sending the request */
500 if(this->Req==UREMOVE && this->Id) {
502 e_no = a->IdTable[Id];
503 free_entity(a, e_no);
510 /*------------------------------------------------------------------*/
511 /* isdn interrupt handler */
512 /*------------------------------------------------------------------*/
514 byte DivasDpc(ADAPTER * a)
524 /* if return codes are available ... */
525 if((Count = a->ram_in(a, &PR_RAM->RcOutput))) {
527 DPRINTF(("IDI: #Rc=%x",Count));
529 /* get the buffer address of the first return code */
530 RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
532 /* for all return codes do ... */
535 if((Rc=a->ram_in(a, &RcIn->Rc))) {
537 /* call return code handler, if it is not our return code */
538 /* the handler returns 2 */
539 /* for all return codes we process, we clear the Rc field */
542 a->ram_in(a, &RcIn->RcId),
543 a->ram_in(a, &RcIn->RcCh),
544 a->ram_inw(a, &RcIn->Reference));
546 a->ram_out(a, &RcIn->Rc, 0);
549 /* get buffer address of next return code */
550 RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
553 /* clear all return codes (no chaining!) */
554 a->ram_out(a, &PR_RAM->RcOutput ,0);
556 /* call output function */
563 /* if indications are available ... */
564 if((Count = a->ram_in(a, &PR_RAM->IndOutput))) {
566 DPRINTF(("IDI: #Ind=%x",Count));
568 /* get the buffer address of the first indication */
569 IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
571 /* for all indications do ... */
574 /* if the application marks an indication as RNR, all */
575 /* indications from the same Id delivered in this interrupt */
577 if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) {
578 a->ram_out(a, &IndIn->Ind, 0);
579 a->ram_out(a, &IndIn->RNR, TRUE);
582 Ind = a->ram_in(a, &IndIn->Ind);
586 /* call indication handler, a return value of 2 means chain */
587 /* a return value of 1 means RNR */
588 /* for all indications we process, we clear the Ind field */
591 a->ram_in(a, &IndIn->IndId),
592 a->ram_in(a, &IndIn->IndCh),
594 a->ram_in(a, &IndIn->MInd),
595 a->ram_inw(a, &IndIn->MLength));
598 DPRINTF(("IDI: RNR"));
599 a->ram_out(a, &IndIn->Ind, 0);
600 RNRId = a->ram_in(a, &IndIn->IndId);
601 a->ram_out(a, &IndIn->RNR, TRUE);
606 /* get buffer address of next indication */
607 IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
610 a->ram_out(a, &PR_RAM->IndOutput, 0);
615 byte DivasTestInt(ADAPTER * a)
617 return a->ram_in(a,(void *)0x3fe);
620 void DivasClearInt(ADAPTER * a)
622 a->ram_out(a,(void *)0x3fe,0);
625 /*------------------------------------------------------------------*/
626 /* return code handler */
627 /*------------------------------------------------------------------*/
630 byte isdn_rc(ADAPTER * a,
639 #ifdef USE_EXTENDED_DEBUGS
641 ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
642 DPRINTF(("IDI: <A%d Id=0x%x Rc=0x%x", io->ANum, Id, Rc))
645 DPRINTF(("IDI: <RC(Rc=%x,Id=%x,Ch=%x)",Rc,Id,Ch));
648 /* check for ready interrupt */
657 /* if we know this Id ... */
658 e_no = a->IdTable[Id];
661 this = entity_ptr(a,e_no);
665 /* if it is a return code to a REMOVE request, remove the */
666 /* Id from our table */
667 if(this->Req==REMOVE && Rc==OK) {
668 free_entity(a, e_no);
671 /**************************************************************/
672 if ((this->More & XMOREC) > 1) {
673 this->More &= ~XMOREC;
675 DPRINTF(("isdn_rc, Id=%x, correct More on REMOVE", Id));
681 this->More = (this->More & (~XBUSY | XMOREC)) | 1;
682 this->complete = 0xFF;
686 if(this->More &XMOREC)
689 /* call the application callback function */
690 if(this->More &XMOREF && !(this->More &XMOREC)) {
699 /* if it's an ASSIGN return code check if it's a return */
700 /* code to an ASSIGN request from us */
701 if((Rc &0xf0)==ASSIGN_RC) {
703 e_no = get_assign(a, Ref);
707 this = entity_ptr(a,e_no);
711 /* call the application callback function */
718 a->IdTable[Id] = e_no;
722 free_entity(a, e_no);
732 /*------------------------------------------------------------------*/
733 /* indication handler */
734 /*------------------------------------------------------------------*/
737 byte isdn_ind(ADAPTER * a,
750 #ifdef USE_EXTENDED_DEBUGS
752 ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
753 DPRINTF(("IDI: <A%d Id=0x%x Ind=0x%x", io->ANum, Id, Ind))
756 DPRINTF(("IDI: <IND(Ind=%x,Id=%x,Ch=%x)",Ind,Id,Ch));
761 this = entity_ptr(a,a->IdTable[Id]);
765 /* if the Receive More flag is not yet set, this is the */
766 /* first buffer of the packet */
767 if(this->RCurrent==0xff) {
769 /* check for receive buffer chaining */
770 if(Ind==this->MInd) {
779 /* call the application callback function for the receive */
781 this->RLength = MLength;
783 a->ram_look_ahead(a, RBuffer, this);
788 /* map entity ptr, selector could be re-mapped by call to */
789 /* IDI from within callback */
790 this = entity_ptr(a,a->IdTable[Id]);
798 /* if no buffers are provided by the application, the */
799 /* application want to copy the data itself including */
800 /* N_MDATA/LL_MDATA chaining */
801 if(!this->RNR && !this->RNum) {
805 /* if there is no RNR, set the More flag */
811 if(Ind!=this->MInd) {
812 this->RCurrent = 0xff;
817 /* if we have received buffers from the application, copy */
818 /* the data into these buffers */
822 if(this->ROffset==R[this->RCurrent].PLength) {
826 clength = a->ram_inw(a, &RBuffer->length)-offset;
827 if (clength > R[this->RCurrent].PLength-this->ROffset)
828 clength = R[this->RCurrent].PLength-this->ROffset;
829 if(R[this->RCurrent].P) {
832 PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]),
836 this->ROffset +=clength;
837 } while(offset<(a->ram_inw(a, &RBuffer->length)));
839 /* if it's the last buffer of the packet, call the */
840 /* application callback function for the receive complete */
842 if(Ind!=this->MInd) {
843 R[this->RCurrent].PLength = this->ROffset;
844 if(this->ROffset) this->RCurrent++;
845 this->RNum = this->RCurrent;
846 this->RCurrent = 0xff;