1 /* dev.c - usbparallel.device by Chris Hodges
6 #include "printer.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 IOExtPar
*, ioreq
, A1
),
48 AROS_LHA(ULONG
, unit
, D0
),
49 AROS_LHA(ULONG
, flags
, D1
),
50 DEVBASETYPEPTR
, base
, 1, dev
)
54 struct NepClassPrinter
*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 /* Turboprint has an illegal message length of 0 in its iorequests! */
64 if(ioreq
->IOPar
.io_Message
.mn_Length
&& (ioreq
->IOPar
.io_Message
.mn_Length
< sizeof(struct IOExtPar
)))
66 KPRINTF(20, ("devOpen: invalid MN_LENGTH (%ld < %ld)!\n",
67 ioreq
->IOPar
.io_Message
.mn_Length
, sizeof(struct IOExtPar
)));
69 ioreq
->IOPar
.io_Error
= IOERR_BADLENGTH
;
71 /* Default to open failure. */
72 ioreq
->IOPar
.io_Error
= IOERR_OPENFAIL
;
74 ioreq
->IOPar
.io_Unit
= NULL
;
75 ncp
= (struct NepClassPrinter
*) 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
->IOPar
.io_Error
= IOERR_UNITBUSY
;
84 ioreq
->IOPar
.io_Unit
= (struct Unit
*) ncp
;
88 ncp
= (struct NepClassPrinter
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
91 if(!ioreq
->IOPar
.io_Unit
)
93 ioreq
->IOPar
.io_Error
= IOERR_OPENFAIL
;
94 KPRINTF(20, ("devOpen: could not open unit!\n"));
97 ioreq
->IOPar
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
98 ioreq
->IOPar
.io_Error
= 0;
99 ioreq
->IOPar
.io_Unit
->unit_OpenCnt
++;
102 ncp
->ncp_FlushBuffer
= FALSE
;
103 ncp
->ncp_DenyRequests
= FALSE
;
109 ioreq
->IOPar
.io_Unit
= (APTR
) -1;
110 ioreq
->IOPar
.io_Device
= (APTR
) -1;
111 base
->np_Library
.lib_OpenCnt
--;
119 AROS_LH1(BPTR
, devClose
,
120 AROS_LHA(struct IOExtPar
*, ioreq
, A1
),
121 DEVBASETYPEPTR
, base
, 2, dev
)
126 struct NepClassPrinter
*ncp
= (struct NepClassPrinter
*) ioreq
->IOPar
.io_Unit
;
128 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
131 /* Try to flush the last buffer */
133 ncp
->ncp_FlushBuffer
= TRUE
;
134 if(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
)
136 Signal(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
, 1L<<(ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
141 ncp
->ncp_DenyRequests
= FALSE
;
143 ncp
->ncp_Unit
.unit_OpenCnt
--;
144 ioreq
->IOPar
.io_Unit
= (APTR
) -1;
145 ioreq
->IOPar
.io_Device
= (APTR
) -1;
147 if(--base
->np_Library
.lib_OpenCnt
== 0)
149 if(base
->np_Library
.lib_Flags
& LIBF_DELEXP
)
151 KPRINTF(5, ("devClose: calling expunge...\n"));
152 ret
= AROS_LC1(BPTR
, devExpunge
,
153 AROS_LCA(DEVBASETYPEPTR
, base
, D0
),
154 DEVBASETYPEPTR
, base
, 3, dev
);
158 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
166 AROS_LH1(BPTR
, devExpunge
,
167 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
168 DEVBASETYPEPTR
, base
, 3, dev
)
174 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
178 if(base
->np_Library
.lib_OpenCnt
== 0)
180 KPRINTF(5, ("devExpunge: Unloading...\n"));
182 CloseLibrary(base
->np_UtilityBase
);
184 ret
= base
->np_SegList
;
186 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
187 &base
->np_Library
.lib_Node
));
188 Remove(&base
->np_Library
.lib_Node
);
190 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
191 FreeMem((char *) base
- base
->np_Library
.lib_NegSize
,
192 (ULONG
) (base
->np_Library
.lib_NegSize
+ base
->np_Library
.lib_PosSize
));
194 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME
" expunged!\n\n"));
200 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
201 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
209 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
210 DEVBASETYPEPTR
, base
, 4, dev
)
217 AROS_LH1(void, devBeginIO
,
218 AROS_LHA(struct IOExtPar
*, ioreq
, A1
),
219 DEVBASETYPEPTR
, base
, 5, dev
)
223 struct NepClassPrinter
*ncp
= (struct NepClassPrinter
*) ioreq
->IOPar
.io_Unit
;
224 WORD ret
= IOERR_NOCMD
;
226 KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu\n", ioreq
, base
, ioreq
->IOPar
.io_Command
));
228 ioreq
->IOPar
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
229 ioreq
->IOPar
.io_Error
= 0;
231 if(ioreq
->IOPar
.io_Command
< NSCMD_DEVICEQUERY
)
233 switch (ioreq
->IOPar
.io_Command
)
236 if(ncp
->ncp_EPInStream
&& (!ncp
->ncp_DenyRequests
))
238 ioreq
->IOPar
.io_Flags
&= ~IOF_QUICK
;
240 AddTail(&ncp
->ncp_ReadQueue
, &ioreq
->IOPar
.io_Message
.mn_Node
);
243 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_TaskMsgPort
->mp_SigBit
);
253 if(!ncp
->ncp_DenyRequests
)
255 ioreq
->IOPar
.io_Flags
&= ~IOF_QUICK
;
257 AddTail(&ncp
->ncp_WriteQueue
, &ioreq
->IOPar
.io_Message
.mn_Node
);
260 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_TaskMsgPort
->mp_SigBit
);
270 ncp
->ncp_DevSuspend
= FALSE
;
275 ncp
->ncp_DevSuspend
= TRUE
;
276 case PDCMD_SETPARAMS
:
284 if(!ncp
->ncp_DenyRequests
)
286 ioreq
->IOPar
.io_Flags
&= ~IOF_QUICK
;
288 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
299 switch(ioreq
->IOPar
.io_Command
)
301 case NSCMD_DEVICEQUERY
:
302 ret
= cmdNSDeviceQuery((struct IOStdReq
*) ioreq
, ncp
, base
);
311 if(ret
!= RC_DONTREPLY
)
313 KPRINTF(1, ("TermIO\n"));
318 ioreq
->IOPar
.io_Error
= ret
& 0xff;
320 /* Terminate the iorequest
328 AROS_LH1(LONG
, devAbortIO
,
329 AROS_LHA(struct IOExtPar
*, ioreq
, A1
),
330 DEVBASETYPEPTR
, base
, 6, dev
)
334 struct NepClassPrinter
*ncp
= (struct NepClassPrinter
*) ioreq
->IOPar
.io_Unit
;
335 struct IOExtPar
*iocmp
;
337 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
342 if(ioreq
->IOPar
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
344 /* check if it's the writing pipe */
345 if(ioreq
== ncp
->ncp_WritePending
)
347 if(ncp
->ncp_AbortSignal
>= 0)
349 /* prod the subtask */
350 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_AbortSignal
);
355 iocmp
= (struct IOExtPar
*) ncp
->ncp_ReadQueue
.lh_Head
;
356 while(iocmp
->IOPar
.io_Message
.mn_Node
.ln_Succ
)
360 Remove((struct Node
*) ioreq
);
361 ioreq
->IOPar
.io_Error
= IOERR_ABORTED
;
362 ReplyMsg(&ioreq
->IOPar
.io_Message
);
366 iocmp
= (struct IOExtPar
*) iocmp
->IOPar
.io_Message
.mn_Node
.ln_Succ
;
368 iocmp
= (struct IOExtPar
*) ncp
->ncp_WriteQueue
.lh_Head
;
369 while(iocmp
->IOPar
.io_Message
.mn_Node
.ln_Succ
)
373 Remove((struct Node
*) ioreq
);
374 ioreq
->IOPar
.io_Error
= IOERR_ABORTED
;
375 ReplyMsg(&ioreq
->IOPar
.io_Message
);
379 iocmp
= (struct IOExtPar
*) iocmp
->IOPar
.io_Message
.mn_Node
.ln_Succ
;
392 const UWORD NSDSupported
[] =
394 CMD_CLEAR
, CMD_RESET
,
396 CMD_WRITE
, CMD_START
,
397 CMD_STOP
, PDCMD_QUERY
,
402 WORD
cmdNSDeviceQuery(struct IOStdReq
*ioreq
,
403 struct NepClassPrinter
*ncp
,
404 struct NepPrtDevBase
*base
)
406 struct my_NSDeviceQueryResult
*query
;
408 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
410 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq
, query
));
417 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
418 (query
->DevQueryFormat
!= 0) ||
419 (query
->SizeAvailable
!= 0))
421 /* Return error. This is special handling, since iorequest is only
422 guaranteed to be sizeof(struct IOStdReq). If we'd let our
423 devBeginIO dispatcher return the error, it would trash some
424 memory past end of the iorequest (ios2_WireError field).
426 ioreq
->io_Error
= IOERR_NOCMD
;
427 TermIO((struct IOExtPar
*) ioreq
, base
);
429 /* Don't reply, we already did.
434 ioreq
->io_Actual
= query
->SizeAvailable
435 = sizeof(struct my_NSDeviceQueryResult
);
436 query
->DeviceType
= NSDEVTYPE_PARALLEL
;
437 query
->DeviceSubType
= 0;
438 query
->SupportedCommands
= NSDSupported
;
440 /* Return success (note that this will NOT poke ios2_WireError).
446 *===========================================================
447 * TermIO(ioreq, base)
448 *===========================================================
450 * Return completed ioreq to sender.
454 void TermIO(struct IOExtPar
*ioreq
,
455 struct NepPrtDevBase
*base
)
457 ioreq
->IOPar
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
459 /* If not quick I/O, reply the message
461 if(!(ioreq
->IOPar
.io_Flags
& IOF_QUICK
))
463 ReplyMsg(&ioreq
->IOPar
.io_Message
);