5 #include <clib/alib_protos.h>
7 #include <exec/ports.h>
8 #include <exec/errors.h>
9 #include <exec/lists.h>
12 #include <aros/libcall.h>
13 #include <aros/symbolsets.h>
15 #include <utility/utility.h>
16 #include <utility/tagitem.h>
17 #include <utility/hooks.h>
18 #include <proto/utility.h>
24 #include "device_protos.h"
25 #include LC_LIBDEFS_FILE
28 BOOL
SafePutToPort(struct PPPcontrolMsg
*message
, STRPTR portname
)
32 port
= FindPort(portname
);
35 ForeachNode(&port
->mp_MsgList
,M
){
36 if( (APTR
)message
== (APTR
)M
){
37 // bug("SafePutToPort: message is already here !\n");
42 PutMsg(port
,(struct Message
*)message
);
45 return(port
? TRUE
: FALSE
);
49 #define MAXINFOFAIL 10
51 VOID
PPP_Process(VOID
){
54 struct IOExtSer
*ioser
;
55 struct IOSana2Req
*ios2
;
56 struct EasyTimer
*timer
=0;
57 ULONG waitmask
,signals
;
59 LIBBASETYPEPTR LIBBASE
;
60 struct MsgPort
*CtrlPort
=0;
61 struct PPPcontrolMsg
*CtrlMsg
=0;
62 struct PPPcontrolMsg
*InfoMsg
=0;
63 ULONG oldin
=0,oldout
=0;
66 UBYTE GUIPortName
[PPP_MAXARGLEN
];
69 bug("PPP process hello!\n");
72 LIBBASE
= FindTask(NULL
)->tc_UserData
;
76 NEWLIST((struct List
*)&LIBBASE
->Rx_List
);
77 NEWLIST((struct List
*)&LIBBASE
->Tx_List
);
78 InitSemaphore(&LIBBASE
->sdu_ListLock
);
80 proc
= (struct Process
*)FindTask(0L);
81 signalbit
= AllocSignal(-1L);
82 if(signalbit
== -1) break;
83 LIBBASE
->sd_Unit
->unit_MsgPort
.mp_SigBit
= signalbit
;
84 LIBBASE
->sd_Unit
->unit_MsgPort
.mp_SigTask
= (struct Task
*)proc
;
85 LIBBASE
->sd_Unit
->unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
87 if( !( CtrlPort
= CreatePort("ppp-control",0) ) ) break;
88 if( !(InfoMsg
= AllocMem(sizeof(struct PPPcontrolMsg
),MEMF_PUBLIC
| MEMF_CLEAR
))) break;
90 if( ! (timer
=OpenTimer())) break;
92 bug("PPP process: for ever loop...\n");
94 SetTimer(timer
,TIMERVALUE
);
95 LIBBASE
->sdu_Proc_run
= TRUE
;
99 // if Serial device is not ok, close it.
101 if( ! LIBBASE
->ser
->Ok
){
102 CloseSerial(LIBBASE
->ser
);
106 // device is down, close serial
107 if( Phase() == PPP_PHASE_DEAD
){
108 CloseSerial(LIBBASE
->ser
);
111 waitmask
= (1L<< signalbit
) |
112 ( LIBBASE
->ser
? (1L<< LIBBASE
->ser
->RxPort
->mp_SigBit
) : 0 ) |
113 ( LIBBASE
->ser
? (1L<< LIBBASE
->ser
->TxPort
->mp_SigBit
) : 0 ) |
114 (1L<< timer
->TimeMsg
->mp_SigBit
) |
115 (1L<< CtrlPort
->mp_SigBit
) |
118 signals
= Wait(waitmask
);
123 if(GetMsg(timer
->TimeMsg
)){
125 LIBBASE
->SpeedIn
= ( LIBBASE
->BytesIn
- oldin
) / TIMERVALUE
;
126 LIBBASE
->SpeedOut
= ( LIBBASE
->BytesOut
- oldout
) / TIMERVALUE
;
127 LIBBASE
->UpTime
+= TIMERVALUE
;
128 oldin
= LIBBASE
->BytesIn
;
129 oldout
= LIBBASE
->BytesOut
;
131 if( GUIPortName
[0] && (
132 InfoMsg
->BytesIn
!= LIBBASE
->BytesIn
||
133 InfoMsg
->BytesOut
!= LIBBASE
->BytesOut
||
134 InfoMsg
->SpeedIn
!= LIBBASE
->SpeedIn
||
135 InfoMsg
->SpeedOut
!= LIBBASE
->SpeedOut
136 )) UpdateInfo
= TRUE
;
138 if(LIBBASE
->device_up
&& LIBBASE
->ser
){
139 ppp_timer(TIMERVALUE
);
142 SetTimer(timer
,TIMERVALUE
);
147 // Have we been signaled to shut down?
148 if(signals
& SIGBREAKF_CTRL_C
){
149 bug("PPP process: received SIGBREAKF_CTRL_C\n");
154 while(ios2
= (struct IOSana2Req
*)GetMsg((struct MsgPort
*)LIBBASE
->sd_Unit
)){
155 PerformIO(LIBBASE
,ios2
);
159 if( LIBBASE
->ser
&& Phase() != PPP_PHASE_DEAD
){
160 if(ioser
= (struct IOExtSer
*)GetMsg(LIBBASE
->ser
->RxPort
)) {
161 CMD_READ_Ready(LIBBASE
,ioser
);
163 if(ioser
= (struct IOExtSer
*)GetMsg(LIBBASE
->ser
->TxPort
)){
164 CMD_WRITE_Ready(LIBBASE
);
169 // Control Port handling
170 while( CtrlMsg
= (struct PPPcontrolMsg
*)GetMsg(CtrlPort
) ){
171 bug("PPP process: received Control message\n");
172 if( CtrlMsg
->Msg
.mn_Length
== sizeof(struct PPPcontrolMsg
) ){
174 switch(CtrlMsg
->Command
){
176 case PPP_CTRL_SETPHASE
:
177 Set_phase( (ULONG
)CtrlMsg
->Arg
);
180 case PPP_CTRL_OPEN_SERIAL
:
181 strlcpy( LIBBASE
->DeviceName
, CtrlMsg
->DeviceName
, PPP_MAXARGLEN
);
182 strlcpy( LIBBASE
->username
, CtrlMsg
->username
, PPP_MAXARGLEN
);
183 strlcpy( LIBBASE
->password
, CtrlMsg
->password
, PPP_MAXARGLEN
);
184 LIBBASE
->SerUnitNum
= CtrlMsg
->UnitNum
;
185 if( LIBBASE
->ser
) CloseSerial( LIBBASE
->ser
);
186 if( LIBBASE
->ser
= OpenSerial( LIBBASE
->DeviceName
, LIBBASE
->SerUnitNum
) ){
188 Set_phase( PPP_PHASE_CONFIGURATION
);
189 QueueSerRequest(LIBBASE
->ser
, PPP_MAXBUFF
);
190 if( ! LIBBASE
->ser
->Ok
){
191 CloseSerial(LIBBASE
->ser
);
196 case PPP_CTRL_CLOSE_SERIAL
:
197 CloseSerial( LIBBASE
->ser
);
198 Set_phase( PPP_PHASE_DEAD
);
201 case PPP_CTRL_INFO_REQUEST
:
202 bug("PPP: INFO requester received\n");
203 if( strlen( (APTR
)CtrlMsg
->Arg
) < PPP_MAXARGLEN
){
204 strcpy( GUIPortName
, (APTR
)CtrlMsg
->Arg
);
205 bug("PPP:portname is %s\n",GUIPortName
);
210 bug("ERROR unknow PPP_CTRL\n");
216 ReplyMsg((struct Message
*)CtrlMsg
);
220 if( GUIPortName
[0] && (
221 InfoMsg
->Ser
!= (LIBBASE
->ser
? TRUE
:FALSE
) ||
222 InfoMsg
->Up
!= LIBBASE
->device_up
||
223 InfoMsg
->Phase
!= Phase()
224 )) UpdateInfo
= TRUE
;
226 if( GUIPortName
[0] && UpdateInfo
){
227 //bug("PPP: INFO reply\n");
228 InfoMsg
->Ser
= LIBBASE
->ser
? TRUE
:FALSE
;
229 InfoMsg
->Up
= LIBBASE
->device_up
;
230 InfoMsg
->Phase
= Phase();
231 InfoMsg
->BytesIn
= LIBBASE
->BytesIn
;
232 InfoMsg
->BytesOut
= LIBBASE
->BytesOut
;
233 InfoMsg
->SpeedIn
= LIBBASE
->SpeedIn
;
234 InfoMsg
->SpeedOut
= LIBBASE
->SpeedOut
;
235 InfoMsg
->UpTime
= LIBBASE
->UpTime
;
237 memcpy( InfoMsg
->LocalIP
, LIBBASE
->LocalIP
, 4 );
238 memcpy( InfoMsg
->RemoteIP
, LIBBASE
->RemoteIP
, 4 );
239 memcpy( InfoMsg
->PrimaryDNS
, LIBBASE
->PrimaryDNS
, 4 );
240 memcpy( InfoMsg
->SecondaryDNS
, LIBBASE
->SecondaryDNS
, 4 );
243 InfoMsg
->Command
= PPP_CTRL_INFO
;
244 InfoMsg
->Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
245 InfoMsg
->Msg
.mn_Length
= sizeof(struct PPPcontrolMsg
);
246 InfoMsg
->Msg
.mn_ReplyPort
= 0;
247 // bug("PPP: SendInfoMsg num %d -> %s\n",InfoMsg->num,GUIPortName);
248 if( SafePutToPort( InfoMsg
, GUIPortName
) ){
251 bug("PPP: SendInfoMsg FAIL\n");
252 if( ++InfoFail
> MAXINFOFAIL
)GUIPortName
[0]=0;
260 bug("PPP process: shut everything down..\n");
262 CloseSerial(LIBBASE
->ser
);
267 while( CtrlMsg
= (struct PPPcontrolMsg
*)GetMsg(CtrlPort
) ) ReplyMsg((struct Message
*)CtrlMsg
);
268 DeletePort(CtrlPort
);
272 if( InfoMsg
) FreeMem(InfoMsg
,sizeof(struct PPPcontrolMsg
));
273 if(signalbit
) FreeSignal(signalbit
);
275 bug("PPP process: shut down OK\n");
277 LIBBASE
->sdu_Proc_run
= FALSE
;
281 struct PPP_DevUnit
*InitPPPUnit(LIBBASETYPEPTR LIBBASE
,ULONG s2unit
){
283 struct PPP_DevUnit
*sdu
;
284 D(bug("InitPPPUnit\n"));
286 if(!LIBBASE
->sd_Unit
){
288 /* Allocate a new Unit structure */
289 if(sdu
= AllocMem(sizeof(struct Unit
), MEMF_CLEAR
|MEMF_PUBLIC
)){
291 LIBBASE
->sd_Unit
= (struct Unit
*)sdu
;
293 /* Do some initialization on the Unit structure */
295 NEWLIST(&LIBBASE
->sd_Unit
->unit_MsgPort
.mp_MsgList
);
296 LIBBASE
->sd_Unit
->unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
297 LIBBASE
->sd_Unit
->unit_MsgPort
.mp_Flags
= PA_IGNORE
;
298 LIBBASE
->sd_Unit
->unit_MsgPort
.mp_Node
.ln_Name
= "PPP";
300 LIBBASE
->sdu_Proc_run
= FALSE
;
302 D(bug("New ppp process:\n"));
303 if(LIBBASE
->sdu_Proc
= CreateNewProcTags(
304 NP_Entry
, PPP_Process
,
305 NP_Name
, "PPP process",
306 NP_Synchronous
, FALSE
,
308 NP_UserData
, LIBBASE
,
313 while( ! LIBBASE
->sdu_Proc_run
) Delay(5);
316 D(bug("New process:FAILL !!!\n"));
321 if(!LIBBASE
->sdu_Proc
){
322 /* The Unit process couldn't start for some reason, so free the Unit structure. */
323 FreeMem(sdu
,sizeof(struct Unit
));
324 LIBBASE
->sd_Unit
= NULL
;
328 return((struct PPP_DevUnit
*)LIBBASE
->sd_Unit
);
332 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR LIBBASE
){
333 D(bug("[PPP] Init()\n"));
335 InitSemaphore(&LIBBASE
->sd_Lock
);
337 LIBBASE
->device_up
= TRUE
; // hmmm... why this is needed?
343 static int GM_UNIQUENAME(Expunge
)(LIBBASETYPEPTR LIBBASE
){
345 D(bug("[PPP] Expunge()\n"));
347 if(LIBBASE
->sd_OpenCnt
){ // Sorry, we're busy. We'll expunge later on if we can.
348 LIBBASE
->sd_Flags
|= LIBF_DELEXP
;
349 D(bug("[PPP] Expunge,busy\n"));
357 static int GM_UNIQUENAME(Open
)
359 LIBBASETYPEPTR LIBBASE
,
360 struct IOSana2Req
* req
,
364 struct PPP_DevUnit
*sdu
;
365 struct TagItem
*bufftag
;
369 D(bug("[PPP] Open unit %d\n",unitnum
));
371 if(req
->ios2_Req
.io_Message
.mn_Length
< sizeof(struct IOSana2Req
)){
372 bug("[PPP] ERROR wrong ios2_Req lenght\n");
377 ObtainSemaphore(&LIBBASE
->sd_Lock
);
379 LIBBASE
->sd_OpenCnt
++;
382 if(sdu
= InitPPPUnit(LIBBASE
,unitnum
)){
383 if(bufftag
= FindTagItem(S2_CopyToBuff
, (struct TagItem
*)req
->ios2_BufferManagement
)){
384 LIBBASE
->CopyToBuffer
= (APTR
)bufftag
->ti_Data
;
385 if(bufftag
= FindTagItem(S2_CopyFromBuff
, (struct TagItem
*)req
->ios2_BufferManagement
)){
386 LIBBASE
->CopyFromBuffer
= (APTR
)bufftag
->ti_Data
;
390 LIBBASE
->sd_Flags
&=~LIBF_DELEXP
;
391 LIBBASE
->sd_Unit
->unit_OpenCnt
++;
393 //req->ios2_BufferManagement = (VOID *)bm;
394 req
->ios2_Req
.io_Error
= 0;
395 req
->ios2_Req
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
396 req
->ios2_Req
.io_Unit
=(APTR
)sdu
;
397 req
->ios2_Req
.io_Device
=(APTR
)LIBBASE
;
403 /* See if something went wrong. */
405 req
->ios2_Req
.io_Error
= IOERR_OPENFAIL
;
406 req
->ios2_Req
.io_Unit
= (struct Unit
*) -1;
407 req
->ios2_Req
.io_Device
= (struct Device
*) -1;
408 LIBBASE
->sd_OpenCnt
--;
411 ReleaseSemaphore(&LIBBASE
->sd_Lock
);
417 VOID
ExpungeUnit(LIBBASETYPEPTR LIBBASE
){
419 D(bug("[PPP] ExpungeUnit \n"));
421 D(bug("[PPP] ExpungeUnit Signal\n"));
422 Signal( (struct Task
*)LIBBASE
->sdu_Proc
, SIGBREAKF_CTRL_C
);
423 D(bug("[PPP] ExpungeUnit Wait\n"));
424 while( LIBBASE
->sdu_Proc_run
) Delay(5);
426 D(bug("[PPP] ExpungeUnit FreeMem\n"));
427 LIBBASE
->sd_Unit
= NULL
;
428 FreeMem(LIBBASE
->sd_Unit
, sizeof(struct Unit
));
429 D(bug("[PPP] ExpungeUnit ok\n"));
433 static int GM_UNIQUENAME(Close
)
435 LIBBASETYPEPTR LIBBASE
,
436 struct IOSana2Req
* req
439 D(bug("[PPP] Close\n"));
440 ObtainSemaphore(&LIBBASE
->sd_Lock
);
442 CloseSerial(LIBBASE
->ser
);
444 req
->ios2_Req
.io_Device
= (struct Device
*) -1;
445 req
->ios2_Req
.io_Unit
= (struct Unit
*) -1;
447 LIBBASE
->sd_Unit
->unit_OpenCnt
--;
448 if(!LIBBASE
->sd_Unit
->unit_OpenCnt
){
449 // ExpungeUnit(LIBBASE);
452 LIBBASE
->sd_OpenCnt
--;
453 ReleaseSemaphore(&LIBBASE
->sd_Lock
);
455 D(bug("[PPP] Close OK\n"));
461 ** This function is used to locate an IO request in a linked
462 ** list and abort it if found.
464 ULONG
AbortReq(LIBBASETYPEPTR LIBBASE
,struct MinList
*minlist
, struct IOSana2Req
*ios2
){
465 struct Node
*node
, *next
;
466 ULONG result
=IOERR_NOCMD
;
468 node
= (struct Node
*)minlist
->mlh_Head
;
470 while(node
->ln_Succ
){
471 next
= node
->ln_Succ
;
472 if(node
== (struct Node
*)ios2
){
473 Remove((struct Node
*)ios2
);
474 ios2
->ios2_Req
.io_Error
= IOERR_ABORTED
;
475 TermIO(LIBBASE
,ios2
);
485 AROS_LH1(void, beginio
,
486 AROS_LHA(struct IOSana2Req
*, req
, A1
),
487 LIBBASETYPEPTR
, LIBBASE
, 5, PPPDev
){
490 //if( ( ! LIBBASE->ser->RxPort ) && LIBBASE->ser->TxPort ){ // PPP_process is busy because openserial wait and wait...
491 req
->ios2_Req
.io_Error
= S2ERR_OUTOFSERVICE
;
492 req
->ios2_WireError
= S2WERR_UNIT_OFFLINE
;
495 req
->ios2_Req
.io_Flags
&= ~IOF_QUICK
;
496 PutMsg( (struct MsgPort
*) req
->ios2_Req
.io_Unit
, (struct Message
*)req
);
502 AROS_LH1(LONG
, abortio
,
503 AROS_LHA(struct IOSana2Req
*, req
, A1
),
504 LIBBASETYPEPTR
, LIBBASE
, 6, PPPDev
){
508 D(bug("[PPP] AbortIO()\n"));
511 if(req
->ios2_Req
.io_Message
.mn_Node
.ln_Type
!= NT_REPLYMSG
){
512 switch (req
->ios2_Req
.io_Command
){
514 result
=AbortReq(LIBBASE
,&LIBBASE
->Rx_List
,req
);
518 result
=AbortReq(LIBBASE
,&LIBBASE
->Tx_List
,req
);
532 ADD2INITLIB(GM_UNIQUENAME(Init
),0)
533 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge
),0)
534 ADD2OPENDEV(GM_UNIQUENAME(Open
),0)
535 ADD2CLOSEDEV(GM_UNIQUENAME(Close
),0)