backport
[AROS.git] / workbench / devs / networks / ppp / init.c
blob6b6a3817515ffa5c318ccfea30e76a252facebfb
1 /*
2 * $Id$
3 */
5 #include <clib/alib_protos.h>
6 #include <exec/io.h>
7 #include <exec/ports.h>
8 #include <exec/errors.h>
9 #include <exec/lists.h>
11 #include <aros/io.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>
20 #include <stdlib.h>
21 #include <stdio.h>
23 #include "ppp.h"
24 #include "device_protos.h"
25 #include LC_LIBDEFS_FILE
28 BOOL SafePutToPort(struct PPPcontrolMsg *message, STRPTR portname)
30 struct MsgPort *port;
31 Forbid();
32 port = FindPort(portname);
33 if (port){
34 struct Message *M;
35 ForeachNode(&port->mp_MsgList,M){
36 if( (APTR)message == (APTR)M ){
37 // bug("SafePutToPort: message is already here !\n");
38 Permit();
39 return FALSE;
42 PutMsg(port,(struct Message *)message);
44 Permit();
45 return(port ? TRUE : FALSE);
48 #define TIMERVALUE 5
49 #define MAXINFOFAIL 10
51 VOID PPP_Process(VOID){
53 struct Process *proc;
54 struct IOExtSer *ioser;
55 struct IOSana2Req *ios2;
56 struct EasyTimer *timer=0;
57 ULONG waitmask,signals;
58 BYTE signalbit;
59 LIBBASETYPEPTR LIBBASE;
60 struct MsgPort *CtrlPort=0;
61 struct PPPcontrolMsg *CtrlMsg=0;
62 struct PPPcontrolMsg *InfoMsg=0;
63 ULONG oldin=0,oldout=0;
64 ULONG InfoFail=0;
66 UBYTE GUIPortName[PPP_MAXARGLEN];
67 BOOL UpdateInfo;
69 bug("PPP process hello!\n");
71 do{
72 LIBBASE = FindTask(NULL)->tc_UserData;
74 GUIPortName[0] = 0;
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;
97 for(;;){
99 // if Serial device is not ok, close it.
100 if(LIBBASE->ser ){
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 ) |
116 SIGBREAKF_CTRL_C ;
118 signals = Wait(waitmask);
120 UpdateInfo = FALSE;
122 // Time Out
123 if(GetMsg(timer->TimeMsg)){
124 // Calculate speed
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");
150 break;
153 // SANA2
154 while(ios2 = (struct IOSana2Req *)GetMsg((struct MsgPort *)LIBBASE->sd_Unit)){
155 PerformIO(LIBBASE,ios2);
158 // Serial handling
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 );
178 break;
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 ) ){
187 init_ppp( LIBBASE );
188 Set_phase( PPP_PHASE_CONFIGURATION );
189 QueueSerRequest(LIBBASE->ser, PPP_MAXBUFF );
190 if( ! LIBBASE->ser->Ok ){
191 CloseSerial(LIBBASE->ser);
194 break;
196 case PPP_CTRL_CLOSE_SERIAL:
197 CloseSerial( LIBBASE->ser );
198 Set_phase( PPP_PHASE_DEAD );
199 break;
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);
207 break;
209 default:
210 bug("ERROR unknow PPP_CTRL\n");
211 break;
214 UpdateInfo = TRUE;
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 );
242 InfoMsg->num++;
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 ) ){
249 InfoFail = 0;
250 }else{
251 bug("PPP: SendInfoMsg FAIL\n");
252 if( ++InfoFail > MAXINFOFAIL )GUIPortName[0]=0;
258 }while(0);
260 bug("PPP process: shut everything down..\n");
262 CloseSerial(LIBBASE->ser);
263 CloseTimer(timer);
265 if(CtrlPort){
266 Forbid();
267 while( CtrlMsg = (struct PPPcontrolMsg*)GetMsg(CtrlPort) ) ReplyMsg((struct Message *)CtrlMsg);
268 DeletePort(CtrlPort);
269 Permit();
272 if( InfoMsg ) FreeMem(InfoMsg,sizeof(struct PPPcontrolMsg));
273 if(signalbit) FreeSignal(signalbit);
275 bug("PPP process: shut down OK\n");
276 Forbid();
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,
307 NP_Priority, 1,
308 NP_UserData, LIBBASE,
309 NP_StackSize, 30000,
310 TAG_DONE))
313 while( ! LIBBASE->sdu_Proc_run ) Delay(5);
314 D(bug("...ok\n"));
315 }else{
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);
336 LIBBASE->ser = NULL;
337 LIBBASE->device_up = TRUE; // hmmm... why this is needed?
339 return TRUE;
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"));
350 return FALSE;
352 return TRUE;
357 static int GM_UNIQUENAME(Open)
359 LIBBASETYPEPTR LIBBASE,
360 struct IOSana2Req* req,
361 ULONG unitnum,
362 ULONG flags
364 struct PPP_DevUnit *sdu;
365 struct TagItem *bufftag;
367 BOOL status = FALSE;
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");
373 return FALSE;
377 ObtainSemaphore(&LIBBASE->sd_Lock);
379 LIBBASE->sd_OpenCnt++;
381 if(unitnum == 0 ){
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;
388 status = TRUE;
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. */
404 if(!status){
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);
413 return( status );
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"));
456 return TRUE;
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);
476 result = 0;
478 node = next;
480 return(result);
485 AROS_LH1(void, beginio,
486 AROS_LHA(struct IOSana2Req *, req, A1),
487 LIBBASETYPEPTR, LIBBASE, 5, PPPDev){
488 AROS_LIBFUNC_INIT
489 if( 0 ){
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;
493 TermIO(LIBBASE,req);
494 }else{
495 req->ios2_Req.io_Flags &= ~IOF_QUICK;
496 PutMsg( (struct MsgPort *) req->ios2_Req.io_Unit , (struct Message *)req );
499 AROS_LIBFUNC_EXIT
502 AROS_LH1(LONG, abortio,
503 AROS_LHA(struct IOSana2Req *, req, A1),
504 LIBBASETYPEPTR, LIBBASE, 6, PPPDev){
505 AROS_LIBFUNC_INIT
506 ULONG result = 0L;
508 D(bug("[PPP] AbortIO()\n"));
510 Disable();
511 if(req->ios2_Req.io_Message.mn_Node.ln_Type != NT_REPLYMSG){
512 switch (req->ios2_Req.io_Command){
513 case CMD_READ:
514 result=AbortReq(LIBBASE,&LIBBASE->Rx_List,req);
515 break;
517 case CMD_WRITE:
518 result=AbortReq(LIBBASE,&LIBBASE->Tx_List,req);
519 break;
521 default:
522 result=IOERR_NOCMD;
523 break;
526 Enable();
527 return result;
528 AROS_LIBFUNC_EXIT
532 ADD2INITLIB(GM_UNIQUENAME(Init),0)
533 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge),0)
534 ADD2OPENDEV(GM_UNIQUENAME(Open),0)
535 ADD2CLOSEDEV(GM_UNIQUENAME(Close),0)