1 /* dev.c - serialcp210x.device by Chris Hodges
6 #include "serialcp210x.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
)
54 struct NepClassSerial
*ncp
;
56 KPRINTF(10, ("devOpen ioreq: 0x%08lx unit: %ld flags: 0x%08lx base: 0x%08lx\n",
57 ioreq
, unit
, flags
, base
));
59 ++base
->np_Library
.lib_OpenCnt
;
60 base
->np_Library
.lib_Flags
&= ~LIBF_DELEXP
;
62 KPRINTF(10, ("devOpen: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
63 /* Damn f*cking programs which leave this field to zero! */
64 if(ioreq
->IOSer
.io_Message
.mn_Length
&& (ioreq
->IOSer
.io_Message
.mn_Length
< sizeof(struct IOExtSer
)))
66 KPRINTF(20, ("devOpen: invalid MN_LENGTH (%ld < %ld)!\n",
67 ioreq
->IOSer
.io_Message
.mn_Length
, sizeof(struct IOExtSer
)));
69 ioreq
->IOSer
.io_Error
= IOERR_BADLENGTH
;
71 /* Default to open failure. */
72 ioreq
->IOSer
.io_Error
= IOERR_OPENFAIL
;
74 ioreq
->IOSer
.io_Unit
= NULL
;
75 ncp
= (struct NepClassSerial
*) base
->np_ClsBase
->nh_Units
.lh_Head
;
76 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
78 if(ncp
->ncp_UnitNo
== unit
)
80 if(ncp
->ncp_Unit
.unit_OpenCnt
)
82 ioreq
->IOSer
.io_Error
= IOERR_UNITBUSY
;
84 ioreq
->IOSer
.io_Unit
= (struct Unit
*) ncp
;
88 ncp
= (struct NepClassSerial
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
91 if(!ioreq
->IOSer
.io_Unit
)
93 ioreq
->IOSer
.io_Error
= IOERR_OPENFAIL
;
94 KPRINTF(20, ("devOpen: could not open unit!\n"));
97 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
98 ioreq
->IOSer
.io_Error
= 0;
99 ioreq
->IOSer
.io_Unit
->unit_OpenCnt
++;
101 ioreq
->io_CtlChar
= SER_DEFAULT_CTLCHAR
;
102 ioreq
->io_RBufLen
= DEFREADBUFLEN
;
103 ioreq
->io_ExtFlags
= 0;
104 ioreq
->io_Baud
= 9600;
105 ioreq
->io_BrkTime
= 250000;
106 ioreq
->io_TermArray
.TermArray0
= 0;
107 ioreq
->io_TermArray
.TermArray1
= 0;
108 ioreq
->io_ReadLen
= 8;
109 ioreq
->io_WriteLen
= 8;
110 ioreq
->io_StopBits
= 1;
111 if(ioreq
->io_SerFlags
& SERF_RAD_BOOGIE
)
113 ioreq
->io_SerFlags
|= SERF_XDISABLED
;
114 ioreq
->io_SerFlags
&= ~SERF_PARTY_ON
|SERF_PARTY_ODD
;
118 ncp
->ncp_DenyRequests
= FALSE
;
120 /* initial settings */
121 ioreq
->IOSer
.io_Command
= SDCMD_SETPARAMS
;
122 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
123 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
124 while(!GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
))
126 WaitPort(&ncp
->ncp_Unit
.unit_MsgPort
);
133 ioreq
->IOSer
.io_Unit
= (APTR
) -1;
134 ioreq
->IOSer
.io_Device
= (APTR
) -1;
135 base
->np_Library
.lib_OpenCnt
--;
143 AROS_LH1(BPTR
, devClose
,
144 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
145 DEVBASETYPEPTR
, base
, 2, dev
)
150 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
152 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
156 /* Don't allow queuing */
157 ncp
->ncp_DenyRequests
= TRUE
;
159 ncp
->ncp_Unit
.unit_OpenCnt
--;
160 ioreq
->IOSer
.io_Unit
= (APTR
) -1;
161 ioreq
->IOSer
.io_Device
= (APTR
) -1;
163 if(--base
->np_Library
.lib_OpenCnt
== 0)
165 if(base
->np_Library
.lib_Flags
& LIBF_DELEXP
)
167 KPRINTF(5, ("devClose: calling expunge...\n"));
168 ret
= AROS_LC1(BPTR
, devExpunge
,
169 AROS_LCA(DEVBASETYPEPTR
, base
, D0
),
170 DEVBASETYPEPTR
, base
, 3, dev
);
174 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
182 AROS_LH1(BPTR
, devExpunge
,
183 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
184 DEVBASETYPEPTR
, base
, 3, dev
)
190 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
194 if(base
->np_Library
.lib_OpenCnt
== 0)
196 KPRINTF(5, ("devExpunge: Unloading...\n"));
198 CloseLibrary(base
->np_UtilityBase
);
200 ret
= base
->np_SegList
;
202 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
203 &base
->np_Library
.lib_Node
));
204 Remove(&base
->np_Library
.lib_Node
);
206 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
207 FreeMem((char *) base
- base
->np_Library
.lib_NegSize
,
208 (ULONG
) (base
->np_Library
.lib_NegSize
+ base
->np_Library
.lib_PosSize
));
210 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME
" expunged!\n\n"));
216 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
217 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
225 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
226 DEVBASETYPEPTR
, base
, 4, dev
)
233 AROS_LH1(void, devBeginIO
,
234 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
235 DEVBASETYPEPTR
, base
, 5, dev
)
239 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
240 WORD ret
= IOERR_NOCMD
;
242 //KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu\n", ioreq, base, ioreq->IOSer.io_Command));
244 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
245 ioreq
->IOSer
.io_Error
= 0;
247 if(ioreq
->IOSer
.io_Command
< NSCMD_DEVICEQUERY
)
249 switch (ioreq
->IOSer
.io_Command
)
252 if(ncp
->ncp_EPInStream
&& (!ncp
->ncp_DenyRequests
))
254 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
256 AddTail(&ncp
->ncp_ReadQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
259 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
269 if(!ncp
->ncp_DenyRequests
)
271 if(ioreq
->IOSer
.io_Length
== -1)
273 ioreq
->IOSer
.io_Length
= strlen(ioreq
->IOSer
.io_Data
);
275 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
277 AddTail(&ncp
->ncp_WriteQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
280 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
290 ncp
->ncp_DevSuspend
= FALSE
;
295 ncp
->ncp_DevSuspend
= TRUE
;
303 case SDCMD_SETPARAMS
:
305 if(!ncp
->ncp_DenyRequests
)
307 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
309 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
311 ioreq
->IOSer
.io_Actual
= 0;
321 switch(ioreq
->IOSer
.io_Command
)
323 case NSCMD_DEVICEQUERY
:
324 ret
= cmdNSDeviceQuery((struct IOStdReq
*) ioreq
, ncp
, base
);
333 if(ret
!= RC_DONTREPLY
)
335 KPRINTF(1, ("TermIO\n"));
340 ioreq
->IOSer
.io_Error
= ret
& 0xff;
342 /* Terminate the iorequest
350 AROS_LH1(LONG
, devAbortIO
,
351 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
352 DEVBASETYPEPTR
, base
, 6, dev
)
356 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
358 struct IOExtSer
*iocmp
;
360 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
365 if(ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
367 /* check if it's the writing pipe */
368 if(ioreq
== ncp
->ncp_WritePending
)
370 if(ncp
->ncp_AbortSignal
>= 0)
372 /* prod the subtask */
373 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_AbortSignal
);
378 iocmp
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
379 while(iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
383 Remove((struct Node
*) ioreq
);
384 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
385 ReplyMsg(&ioreq
->IOSer
.io_Message
);
389 iocmp
= (struct IOExtSer
*) iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
;
391 iocmp
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
392 while(iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
396 Remove((struct Node
*)ioreq
);
397 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
398 ReplyMsg(&ioreq
->IOSer
.io_Message
);
402 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
);