1 /* dev.c - serialpl2303.device by Chris Hodges
6 #include "serialpl2303.class.h"
8 AROS_UFH3(DEVBASETYPEPTR
, devInit
,
9 AROS_UFHA(DEVBASETYPEPTR
, base
, D0
),
10 AROS_UFHA(BPTR
, seglist
, A0
),
11 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
15 KPRINTF(10, ("devInit base: 0x%08lx seglist: 0x%08lx SysBase: 0x%08lx\n",
16 base
, seglist
, SysBase
));
18 base
->np_Library
.lib_Node
.ln_Type
= NT_DEVICE
;
19 base
->np_Library
.lib_Node
.ln_Name
= DEVNAME
;
20 base
->np_Library
.lib_Flags
= LIBF_SUMUSED
|LIBF_CHANGED
;
21 base
->np_Library
.lib_Version
= VERSION_NUMBER
;
22 base
->np_Library
.lib_Revision
= REVISION_NUMBER
;
23 base
->np_Library
.lib_IdString
= VERSION_STRING
;
26 base
->np_SegList
= seglist
;
28 if((base
->np_UtilityBase
= OpenLibrary("utility.library", 0)))
30 KPRINTF(10, ("devInit: Ok\n"));
31 KPRINTF(10, ("devInit: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
44 #define UtilityBase base->np_UtilityBase
46 AROS_LH3(DEVBASETYPEPTR
, devOpen
,
47 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
48 AROS_LHA(ULONG
, unit
, D0
),
49 AROS_LHA(ULONG
, flags
, D1
),
50 DEVBASETYPEPTR
, base
, 1, dev
)
53 struct NepClassSerial
*ncp
;
55 KPRINTF(10, ("devOpen ioreq: 0x%08lx unit: %ld flags: 0x%08lx base: 0x%08lx\n",
56 ioreq
, unit
, flags
, base
));
58 ++base
->np_Library
.lib_OpenCnt
;
59 base
->np_Library
.lib_Flags
&= ~LIBF_DELEXP
;
61 KPRINTF(10, ("devOpen: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
62 /* Damn f*cking programs which leave this field to zero! */
63 if(ioreq
->IOSer
.io_Message
.mn_Length
&& (ioreq
->IOSer
.io_Message
.mn_Length
< sizeof(struct IOExtSer
)))
65 KPRINTF(20, ("devOpen: invalid MN_LENGTH (%ld < %ld)!\n",
66 ioreq
->IOSer
.io_Message
.mn_Length
, sizeof(struct IOExtSer
)));
68 ioreq
->IOSer
.io_Error
= IOERR_BADLENGTH
;
70 /* Default to open failure. */
71 ioreq
->IOSer
.io_Error
= IOERR_OPENFAIL
;
73 ioreq
->IOSer
.io_Unit
= NULL
;
74 ncp
= (struct NepClassSerial
*) base
->np_ClsBase
->nh_Units
.lh_Head
;
75 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
77 if(ncp
->ncp_UnitNo
== unit
)
79 if(ncp
->ncp_Unit
.unit_OpenCnt
)
81 ioreq
->IOSer
.io_Error
= IOERR_UNITBUSY
;
83 ioreq
->IOSer
.io_Unit
= (struct Unit
*) ncp
;
87 ncp
= (struct NepClassSerial
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
90 if(!ioreq
->IOSer
.io_Unit
)
92 ioreq
->IOSer
.io_Error
= IOERR_OPENFAIL
;
93 KPRINTF(20, ("devOpen: could not open unit!\n"));
96 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
97 ioreq
->IOSer
.io_Error
= 0;
98 ioreq
->IOSer
.io_Unit
->unit_OpenCnt
++;
100 ioreq
->io_CtlChar
= SER_DEFAULT_CTLCHAR
;
101 ioreq
->io_RBufLen
= DEFREADBUFLEN
;
102 ioreq
->io_ExtFlags
= 0;
103 ioreq
->io_Baud
= 9600;
104 ioreq
->io_BrkTime
= 250000;
105 ioreq
->io_TermArray
.TermArray0
= 0;
106 ioreq
->io_TermArray
.TermArray1
= 0;
107 ioreq
->io_ReadLen
= 8;
108 ioreq
->io_WriteLen
= 8;
109 ioreq
->io_StopBits
= 1;
110 if(ioreq
->io_SerFlags
& SERF_RAD_BOOGIE
)
112 ioreq
->io_SerFlags
|= SERF_XDISABLED
;
113 ioreq
->io_SerFlags
&= ~SERF_PARTY_ON
|SERF_PARTY_ODD
;
117 ncp
->ncp_DenyRequests
= FALSE
;
119 /* initial settings */
120 ioreq
->IOSer
.io_Command
= SDCMD_SETPARAMS
;
121 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
122 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
123 while(!GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
))
125 WaitPort(&ncp
->ncp_Unit
.unit_MsgPort
);
132 ioreq
->IOSer
.io_Unit
= (APTR
) -1;
133 ioreq
->IOSer
.io_Device
= (APTR
) -1;
134 base
->np_Library
.lib_OpenCnt
--;
142 AROS_LH1(BPTR
, devClose
,
143 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
144 DEVBASETYPEPTR
, base
, 2, dev
)
149 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
151 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
155 /* Don't allow queuing */
156 ncp
->ncp_DenyRequests
= TRUE
;
158 ncp
->ncp_Unit
.unit_OpenCnt
--;
159 ioreq
->IOSer
.io_Unit
= (APTR
) -1;
160 ioreq
->IOSer
.io_Device
= (APTR
) -1;
162 if(--base
->np_Library
.lib_OpenCnt
== 0)
164 if(base
->np_Library
.lib_Flags
& LIBF_DELEXP
)
166 KPRINTF(5, ("devClose: calling expunge...\n"));
167 ret
= AROS_LC1(BPTR
, devExpunge
,
168 AROS_LCA(DEVBASETYPEPTR
, base
, D0
),
169 DEVBASETYPEPTR
, base
, 3, dev
);
173 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
181 AROS_LH1(BPTR
, devExpunge
,
182 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
183 DEVBASETYPEPTR
, base
, 3, dev
)
189 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
193 if(base
->np_Library
.lib_OpenCnt
== 0)
195 KPRINTF(5, ("devExpunge: Unloading...\n"));
197 CloseLibrary(base
->np_UtilityBase
);
199 ret
= base
->np_SegList
;
201 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
202 &base
->np_Library
.lib_Node
));
203 Remove(&base
->np_Library
.lib_Node
);
205 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
206 FreeMem((char *) base
- base
->np_Library
.lib_NegSize
,
207 (ULONG
) (base
->np_Library
.lib_NegSize
+ base
->np_Library
.lib_PosSize
));
209 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME
" expunged!\n\n"));
215 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
216 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
224 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
225 DEVBASETYPEPTR
, base
, 4, dev
)
232 AROS_LH1(void, devBeginIO
,
233 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
234 DEVBASETYPEPTR
, base
, 5, dev
)
238 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
239 WORD ret
= IOERR_NOCMD
;
241 //KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu\n", ioreq, base, ioreq->IOSer.io_Command));
243 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
244 ioreq
->IOSer
.io_Error
= 0;
246 if(ioreq
->IOSer
.io_Command
< NSCMD_DEVICEQUERY
)
248 switch (ioreq
->IOSer
.io_Command
)
251 if(ncp
->ncp_EPInStream
&& (!ncp
->ncp_DenyRequests
))
253 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
255 AddTail(&ncp
->ncp_ReadQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
258 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
268 if(!ncp
->ncp_DenyRequests
)
270 if(ioreq
->IOSer
.io_Length
== -1)
272 ioreq
->IOSer
.io_Length
= strlen(ioreq
->IOSer
.io_Data
);
274 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
276 AddTail(&ncp
->ncp_WriteQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
279 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
289 ncp
->ncp_DevSuspend
= FALSE
;
294 ncp
->ncp_DevSuspend
= TRUE
;
302 case SDCMD_SETPARAMS
:
304 if(!ncp
->ncp_DenyRequests
)
306 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
308 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
310 ioreq
->IOSer
.io_Actual
= 0;
320 switch(ioreq
->IOSer
.io_Command
)
322 case NSCMD_DEVICEQUERY
:
323 ret
= cmdNSDeviceQuery((struct IOStdReq
*) ioreq
, ncp
, base
);
332 if(ret
!= RC_DONTREPLY
)
334 KPRINTF(1, ("TermIO\n"));
339 ioreq
->IOSer
.io_Error
= ret
& 0xff;
341 /* Terminate the iorequest
349 AROS_LH1(LONG
, devAbortIO
,
350 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
351 DEVBASETYPEPTR
, base
, 6, dev
)
355 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
357 struct IOExtSer
*iocmp
;
359 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
364 if(ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
366 /* check if it's the writing pipe */
367 if(ioreq
== ncp
->ncp_WritePending
)
369 if(ncp
->ncp_AbortSignal
>= 0)
371 /* prod the subtask */
372 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_AbortSignal
);
377 iocmp
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
378 while(iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
382 Remove((struct Node
*) ioreq
);
383 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
384 ReplyMsg(&ioreq
->IOSer
.io_Message
);
388 iocmp
= (struct IOExtSer
*) iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
;
390 iocmp
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
391 while(iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
395 Remove((struct Node
*)ioreq
);
396 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
397 ReplyMsg(&ioreq
->IOSer
.io_Message
);
401 iocmp
= (struct IOExtSer
*) iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
;
415 const UWORD NSDSupported
[] =
417 CMD_CLEAR
, CMD_RESET
,
419 CMD_WRITE
, CMD_START
,
420 CMD_STOP
, SDCMD_QUERY
,
426 WORD
cmdNSDeviceQuery(struct IOStdReq
*ioreq
,
427 struct NepClassSerial
*ncp
,
428 struct NepSerDevBase
*base
)
430 struct my_NSDeviceQueryResult
*query
;
432 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
434 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq
, query
));
441 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
442 (query
->DevQueryFormat
!= 0) ||
443 (query
->SizeAvailable
!= 0))
445 /* Return error. This is special handling, since iorequest is only
446 guaranteed to be sizeof(struct IOStdReq). If we'd let our
447 devBeginIO dispatcher return the error, it would trash some
448 memory past end of the iorequest (ios2_WireError field).
450 ioreq
->io_Error
= IOERR_NOCMD
;
451 TermIO((struct IOExtSer
*) ioreq
, base
);
453 /* Don't reply, we already did.
458 ioreq
->io_Actual
= query
->SizeAvailable
459 = sizeof(struct my_NSDeviceQueryResult
);
460 query
->DeviceType
= NSDEVTYPE_SERIAL
;
461 query
->DeviceSubType
= 0;
462 query
->SupportedCommands
= NSDSupported
;
464 /* Return success (note that this will NOT poke ios2_WireError).
470 *===========================================================
471 * TermIO(ioreq, base)
472 *===========================================================
474 * Return completed ioreq to sender.
478 void TermIO(struct IOExtSer
*ioreq
,
479 struct NepSerDevBase
*base
)
481 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
483 /* If not quick I/O, reply the message
485 if(!(ioreq
->IOSer
.io_Flags
& IOF_QUICK
))
487 ReplyMsg(&ioreq
->IOSer
.io_Message
);