2 * Copyright (C) 2012, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
7 * This file handles the creation of the per-unit driver task,
8 * and the creation of the per-unit 'struct PrinterData',
9 * and the pd_PWrite()/pd_PRead() etc IO functions.
12 #include <aros/debug.h>
13 #include <aros/printertag.h>
15 #include <exec/errors.h>
17 #include <proto/exec.h>
18 #include <proto/dos.h>
19 #include <proto/intuition.h>
21 #include <devices/printer.h>
22 #include <datatypes/datatypesclass.h>
24 #define CMD_OPENDEVICE (0x100)
25 #define CMD_CLOSEDEVICE (0x101)
27 #include LC_LIBDEFS_FILE
29 #include "printer_intern.h"
32 #define PDF_IOREQ (1 << 0) /* IORequest 0 or 1 */
33 #define PDF_NOIO (1 << 1) /* PRTA_NoIO was true */
34 #define PDF_CONVERT (1 << 2) /* PRTA_ConvertSource was true */
35 #define PDF_8BITGUNS (1 << 3) /* PRTA_8BitGuns was true */
37 const TEXT driverID
[] = "printer.driver";
39 const struct EasyStruct driverMisuse
= { \
40 .es_StructSize
= sizeof(struct EasyStruct
),
42 .es_Title
= "Improper use of printer.device",
43 .es_TextFormat
= "\"%s\" attempted to use the private\n"
44 "printer.driver method %s.\n"
45 "Only CMD_RAWWRITE is supported.\n",
46 .es_GadgetFormat
= "Ok",
49 #define TASK_PRINTERDATA(pd) \
50 struct PrinterData *pd =(struct PrinterData *)FindTask(NULL)->tc_UserData; \
52 pd->pd_Device.dd_Device.lib_Node.ln_Type != NT_DEVICE || \
53 pd->pd_Device.dd_Device.lib_IdString != driverID) { \
54 struct Library *IntuitionBase; \
55 if ((IntuitionBase = TaggedOpenLibrary(TAGGEDOPEN_INTUITION))) { \
56 IPTR args[] = { (IPTR)FindTask(NULL)->tc_Node.ln_Name, \
58 EasyRequestArgs(NULL, (struct EasyStruct *)&driverMisuse, \
60 CloseLibrary(IntuitionBase); \
66 static BOOL
initMsgPort(struct MsgPort
*port
)
68 BYTE sb
= AllocSignal(-1);
74 port
->mp_SigTask
= FindTask(NULL
);
75 port
->mp_Flags
= PA_SIGNAL
;
76 port
->mp_Node
.ln_Type
= NT_MSGPORT
;
77 NEWLIST(&port
->mp_MsgList
);
82 STATIC
AROS_LH3(LONG
, OpenDevice
,
83 AROS_LHA(struct IORequest
*, io
, A1
),
84 AROS_LHA(IPTR
, unitNumber
, D0
),
85 AROS_LHA(ULONG
, flags
, D1
),
86 struct PrinterUnit
*, pu
, 1, PrinterUnit
)
90 struct MsgPort
*reply
;
92 if ((reply
= CreateMsgPort())) {
93 struct IORequest ior
= *io
;
94 ior
.io_Message
.mn_ReplyPort
= reply
;
95 ior
.io_Command
= CMD_OPENDEVICE
;
99 return IOERR_OPENFAIL
;
104 STATIC
AROS_LH1(BPTR
, CloseDevice
,
105 AROS_LCA(struct IORequest
*,io
, A1
),
106 struct PrinterUnit
*, pu
, 2, PrinterUnit
)
110 struct MsgPort
*reply
;
112 if ((reply
= CreateMsgPort())) {
113 struct IORequest ior
= *io
;
114 ior
.io_Message
.mn_ReplyPort
= reply
;
115 ior
.io_Command
= CMD_CLOSEDEVICE
;
117 return AROS_LC1(BPTR
, Expunge
,
118 AROS_LCA(struct PrinterUnit
*, pu
, D0
),
119 struct PrinterUnit
*, pu
, 3, PrinterUnit
);
127 STATIC
AROS_LH1(BPTR
, Expunge
,
128 AROS_LHA(struct Library
*, extralib
, D0
),
129 struct PrinterUnit
*, pu
, 3, PrinterUnit
)
133 struct Library
*lib
= (struct Library
*)pu
;
135 if (lib
->lib_OpenCnt
== 0) {
136 BPTR seg
= pu
->pu_PrinterData
.pd_PrinterSegment
;
138 Remove((struct Node
*)lib
);
139 FreeMem((UBYTE
*)lib
- lib
->lib_NegSize
,
140 (ULONG
) (lib
->lib_NegSize
+
143 D(bug("%s: Return segment %p\n", __func__
, BADDR(seg
)));
147 lib
->lib_Flags
|= LIBF_DELEXP
;
155 STATIC
AROS_LH1(void, BeginIO
,
156 AROS_LHA(union printerIO
*, pio
, A1
),
157 struct PrinterUnit
*, pu
, 5, PrinterUnit
)
161 struct IOStdReq
*io
= &pio
->ios
;
162 struct PrinterData
*pd
= &pu
->pu_PrinterData
;
164 D(bug("BeginIO: io_Command = %d, Unit Port %p\n", io
->io_Command
, &pd
->pd_Unit
));
166 io
->io_Flags
&= ~IOF_QUICK
;
167 PutMsg(&pd
->pd_Unit
, &io
->io_Message
);
174 STATIC
AROS_LH1(LONG
, AbortIO
,
175 AROS_LHA(struct IORequest
*, pio
, A1
),
176 struct PrinterUnit
*, pd
, 6, PrinterUnit
)
183 /* These wrappers make sure that we don't
184 * make WaitIO() hang or corrupt memory
185 * if called on an already completed IO
187 static inline LONG
WaitIOStd(struct IOStdReq
*io
)
189 WaitIO((struct IORequest
*)io
);
190 io
->io_Message
.mn_Node
.ln_Type
= 0;
194 static inline LONG
DoIOStd(struct IOStdReq
*io
)
196 DoIO((struct IORequest
*)io
);
197 io
->io_Message
.mn_Node
.ln_Type
= 0;
201 static LONG
pd_PWrite(APTR data
, LONG len
)
204 TASK_PRINTERDATA(pd
);
206 if (pd
->pd_Flags
& PDF_NOIO
)
207 return IOERR_OPENFAIL
;
209 io
= (pd
->pd_Flags
& PDF_IOREQ
) ?
210 (struct IOStdReq
*)&pd
->pd_ior1
:
211 (struct IOStdReq
*)&pd
->pd_ior0
;
212 bug("%s: '%s'@%p (%d), io %d\n", __func__
, data
, data
, len
, pd
->pd_Flags
& PDF_IOREQ
);
214 /* TODO: Call error hook if there is an error */
215 io
->io_Command
= CMD_WRITE
;
221 io
->io_Message
.mn_Length
= sizeof(*io
);
222 SendIO((struct IORequest
*)io
);
224 pd
->pd_Flags
^= PDF_IOREQ
;
229 static LONG
pd_PBothReady(VOID
)
231 TASK_PRINTERDATA(pd
);
233 D(bug("%s:\n", __func__
));
234 if (pd
->pd_Flags
& PDF_NOIO
)
235 return IOERR_OPENFAIL
;
237 WaitIOStd((struct IOStdReq
*)&pd
->pd_ior0
);
238 WaitIOStd((struct IOStdReq
*)&pd
->pd_ior1
);
243 static LONG
pd_PRead(char * buffer
, LONG
*length
, struct timeval
*tv
)
248 TASK_PRINTERDATA(pd
);
250 if (pd
->pd_Flags
& PDF_NOIO
)
251 return IOERR_OPENFAIL
;
253 D(bug("%s:\n", __func__
));
254 io
= (pd
->pd_Flags
& PDF_IOREQ
) ?
255 (struct IOStdReq
*)&pd
->pd_ior1
:
256 (struct IOStdReq
*)&pd
->pd_ior0
;
258 /* TODO: Call error hook if there is an error */
259 pd
->pd_TIOR
.tr_node
.io_Command
= TR_ADDREQUEST
;
260 pd
->pd_TIOR
.tr_node
.io_Flags
= 0;
261 pd
->pd_TIOR
.tr_node
.io_Message
.mn_Length
= sizeof(pd
->pd_TIOR
);
262 pd
->pd_TIOR
.tr_time
= *tv
;
263 SendIO((struct IORequest
*)&pd
->pd_TIOR
);
265 io
->io_Command
= CMD_READ
;
268 io
->io_Length
= *length
;
269 io
->io_Data
= buffer
;
271 io
->io_Message
.mn_Length
= sizeof(*io
);
272 SendIO((struct IORequest
*)io
);
273 sigs
= Wait((1 << io
->io_Message
.mn_ReplyPort
->mp_SigBit
) |
274 (1 << pd
->pd_IORPort
.mp_SigBit
));
275 if (sigs
& (1 << pd
->pd_IORPort
.mp_SigBit
)) {
276 WaitIO((struct IORequest
*)&pd
->pd_TIOR
);
277 if (!CheckIO((struct IORequest
*)io
))
278 AbortIO((struct IORequest
*)io
);
283 *length
= io
->io_Actual
;
285 /* No need to swap units, as this one has been completed */
290 static LONG
pd_CallErrHook(struct Hook
*hook
, union printerIO
*ior
, struct PrtErrMsg
*pem
)
296 /* Only designed to work on the serial port. */
297 static LONG
pd_PQuery(LONG
*numofchars
)
302 TASK_PRINTERDATA(pd
);
304 if (pd
->pd_Flags
& PDF_NOIO
)
305 return IOERR_OPENFAIL
;
307 D(bug("%s:\n", __func__
));
308 io
= (pd
->pd_Flags
& PDF_IOREQ
) ?
309 (struct IOStdReq
*)&pd
->pd_ior1
:
310 (struct IOStdReq
*)&pd
->pd_ior0
;
312 /* TODO: Call error hook if there is an error */
313 io
->io_Command
= SDCMD_QUERY
;
319 io
->io_Message
.mn_Length
= sizeof(*io
);
322 *numofchars
= io
->io_Actual
;
326 /* No need to swap units, as this one has been completed */
331 /* Only designed to work on the serial and parallel port. */
332 static LONG
pd_Query(struct IOStdReq
*sio
)
337 TASK_PRINTERDATA(pd
);
339 D(bug("%s:\n", __func__
));
340 if (pd
->pd_PUnit
->pu_Prefs
.pp_Unit
.pu_DeviceName
[0] != 0 ||
341 (pd
->pd_Flags
& PDF_NOIO
)) {
343 return IOERR_OPENFAIL
;
346 io
= (pd
->pd_Flags
& PDF_IOREQ
) ?
347 (struct IOStdReq
*)&pd
->pd_ior1
:
348 (struct IOStdReq
*)&pd
->pd_ior0
;
350 /* TODO: Call error hook if there is an error */
351 io
->io_Command
= SDCMD_QUERY
;
357 io
->io_Message
.mn_Length
= sizeof(*io
);
360 UBYTE
*data
= sio
->io_Data
;
364 switch (pd
->pd_PUnit
->pu_Prefs
.pp_Txt
.pt_Port
) {
366 status
= ((struct IOExtSer
*)io
)->io_Status
;
369 status
= ((struct IOExtPar
*)io
)->io_Status
;
375 data
[0] = (status
>> 0) & 0xff;
376 data
[1] = (status
>> 8) & 0xff;
378 sio
->io_Actual
= pd
->pd_PUnit
->pu_Prefs
.pp_Txt
.pt_Port
+ 1;
381 /* No need to swap units, as this one has been completed */
386 static LONG
pd_Init(struct PrinterData
*pd
)
388 struct PrinterExtendedData
*ped
= &pd
->pd_SegmentData
->ps_PED
;
389 TEXT devname
[sizeof(pd
->pd_Preferences
.PrtDevName
) + 7 + 1];
391 /* Initialize the unit */
392 strcpy(devname
, pd
->pd_Preferences
.PrtDevName
);
393 strcat(devname
, ".device");
395 D(bug("%s: create msgport %p\n", __func__
, &pd
->pd_Unit
));
396 if (initMsgPort(&pd
->pd_Unit
)) {
397 D(bug("%s: Call ped_Init => %p\n", __func__
, pd
->pd_SegmentData
->ps_PED
.ped_Init
));
398 if (0 == pd
->pd_SegmentData
->ps_PED
.ped_Init(pd
)) {
399 if (pd
->pd_Flags
& PDF_NOIO
)
402 if ((pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_ReplyPort
=CreateMsgPort())) {
403 pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_Length
= sizeof(pd
->pd_ior0
);
404 if (0 == OpenDevice(devname
,
405 pd
->pd_Preferences
.DefaultPrtUnit
,
406 (struct IORequest
*)&pd
->pd_ior0
, 0)) {
407 D(bug("%s: open %s %d for io 0\n", __func__
, devname
, pd
->pd_Preferences
.DefaultPrtUnit
));
408 pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_Node
.ln_Type
= 0;
409 if ((pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_ReplyPort
=CreateMsgPort())) {
410 pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_Length
= sizeof(pd
->pd_ior1
);
411 if (0 == OpenDevice(devname
,
412 pd
->pd_Preferences
.DefaultPrtUnit
,
413 (struct IORequest
*)&pd
->pd_ior1
, 0)) {
414 pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_Node
.ln_Type
= 0;
415 D(bug("%s: open %s %d for io 1\n", __func__
, devname
, pd
->pd_Preferences
.DefaultPrtUnit
));
416 if (initMsgPort(&pd
->pd_IORPort
)) {
417 pd
->pd_TIOR
.tr_node
.io_Message
.mn_ReplyPort
=&pd
->pd_IORPort
;
418 pd
->pd_TIOR
.tr_node
.io_Message
.mn_Length
= sizeof(pd
->pd_TIOR
);
419 if (0 == OpenDevice("timer.device", UNIT_VBLANK
,
420 (struct IORequest
*)&pd
->pd_TIOR
, 0)) {
421 D(bug("%s: open timer.device %d\n", __func__
, UNIT_VBLANK
));
422 if (ped
->ped_Render
) {
423 LONG err
= ped
->ped_Render(0, 0, 0, PRS_PREINIT
);
430 FreeSignal(pd
->pd_IORPort
.mp_SigBit
);
432 CloseDevice((struct IORequest
*)&pd
->pd_ior1
);
434 DeleteMsgPort(pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_ReplyPort
);
436 CloseDevice((struct IORequest
*)&pd
->pd_ior0
);
438 DeleteMsgPort(pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_ReplyPort
);
440 pd
->pd_SegmentData
->ps_PED
.ped_Expunge();
442 FreeSignal(pd
->pd_Unit
.mp_SigBit
);
448 static VOID
pd_Close(struct PrinterData
*pd
, union printerIO
*pio
)
450 struct PrinterBase
*PrinterBase
= pd
->pd_PUnit
->pu_PrinterBase
;
451 struct PrinterExtendedData
*ped
= &pd
->pd_SegmentData
->ps_PED
;
452 LONG unitnum
= pd
->pd_PUnit
->pu_Prefs
.pp_DeviceUnit
.pd_UnitNum
;
456 if (!(pd
->pd_Flags
& PDF_NOIO
)) {
457 CloseDevice((struct IORequest
*)&pd
->pd_TIOR
);
458 FreeSignal(pd
->pd_IORPort
.mp_SigBit
);
459 CloseDevice((struct IORequest
*)&pd
->pd_ior1
);
460 DeleteMsgPort(pd
->pd_ior1
.pd_p1
.IOPar
.io_Message
.mn_ReplyPort
);
461 CloseDevice((struct IORequest
*)&pd
->pd_ior0
);
462 DeleteMsgPort(pd
->pd_ior0
.pd_p0
.IOPar
.io_Message
.mn_ReplyPort
);
464 FreeSignal(pd
->pd_Unit
.mp_SigBit
);
468 /* Remove from the parent printer.device */
469 ObtainSemaphore(&PrinterBase
->pb_UnitLock
[unitnum
]);
470 PrinterBase
->pb_Unit
[unitnum
] = NULL
;
472 PrinterBase
->pb_Device
.dd_Library
.lib_OpenCnt
--;
474 ReleaseSemaphore(&PrinterBase
->pb_UnitLock
[unitnum
]);
477 static LONG
pd_DoPreferences(const union printerIO
*pio
, LONG command
)
481 TASK_PRINTERDATA(pd
);
483 if (pd
->pd_SegmentData
->ps_Version
>= 44 &&
484 (pd
->pd_SegmentData
->ps_PED
.ped_PrinterClass
& PPCF_EXTENDED
) &&
485 pd
->pd_SegmentData
->ps_PED
.ped_DoPreferences
!= NULL
) {
486 err
= pd
->pd_SegmentData
->ps_PED
.ped_DoPreferences((union printerIO
*)pio
, command
);
505 /* A driver task is created on an OpenDevice() call,
506 * and is killed by a CloseDevice() call.
508 static LONG
pd_DriverTask(VOID
)
510 TASK_PRINTERDATA(pd
);
512 struct Process
*me
= (struct Process
*)FindTask(NULL
);
513 struct PrinterExtendedData
*ped
= &pd
->pd_SegmentData
->ps_PED
;
514 struct MagicMessage
*msg
= NULL
;
515 union printerIO
*pio
;
517 BOOL stopped
= FALSE
;
520 /* Wait for startup message -
521 * we use the DOS port because the
522 * pd_Unit has not been created yet
524 D(bug("%s: Waiting for startup. pd=%p\n", __func__
, pd
));
525 WaitPort(&me
->pr_MsgPort
);
526 msg
= (struct MagicMessage
*)GetMsg(&me
->pr_MsgPort
);
528 D(bug("%s: Initializing driver, Unit Port %p\n", __func__
, &pd
->pd_Unit
));
531 D(bug("%s: Replying with %d\n", __func__
, ret
));
532 msg
->mn_Version
= ret
;
533 ReplyMsg((struct Message
*)msg
);
538 /* Wait for unit messages on the pd_Unit */
542 D(bug("%s: Waiting for command on port %p\n", __func__
, &pd
->pd_Unit
));
543 WaitPort(&pd
->pd_Unit
);
544 pio
= (union printerIO
*)GetMsg(&pd
->pd_Unit
);
545 cmd
= pio
->ios
.io_Command
;
547 D(bug("%s: Command = %d\n", __func__
, cmd
));
550 err
= ped
->ped_Open(pio
);
552 Printer_Text_Write(pd
, "\033#1", 3); /* aRIN */
554 case CMD_CLOSEDEVICE
:
558 AbortIO((struct IORequest
*)&pd
->pd_ior0
);
559 WaitIOStd((struct IOStdReq
*)&pd
->pd_ior0
);
560 AbortIO((struct IORequest
*)&pd
->pd_ior1
);
561 WaitIOStd((struct IOStdReq
*)&pd
->pd_ior1
);
567 err
= Printer_Text_Command(pd
, aRIN
, 0, 0, 0, 0);
580 err
= Printer_Text_Write(pd
, pio
->ios
.io_Data
, pio
->ios
.io_Length
);
582 pio
->ios
.io_Actual
= pio
->ios
.io_Length
;
589 err
= pd_PWrite(pio
->ios
.io_Data
, pio
->ios
.io_Length
);
591 pio
->ios
.io_Actual
= pio
->ios
.io_Length
;
600 err
= pd_DoPreferences(pio
, pio
->ios
.io_Command
);
603 pd
->pd_PUnit
->pu_ErrHook
= ((struct IOPrtErrReq
*)pio
)->io_Hook
;
605 case PRD_DUMPRPORTTAGS
:
609 err
= Printer_Gfx_DumpRPort((struct IODRPReq
*)pio
, ((struct IODRPTagsReq
*)pio
)->io_TagList
);
615 err
= Printer_Gfx_DumpRPort((struct IODRPReq
*)pio
, NULL
);
618 err
= pd_Query(&pio
->ios
);
624 pio
->ios
.io_Error
= err
;
625 D(bug("%s: Command = %d, Result = %d\n", __func__
, cmd
, err
));
627 ReplyMsg((struct Message
*)pio
);
628 } while (cmd
!= CMD_CLOSEDEVICE
);
630 D(bug("%s: Shutting down\n", __func__
));
635 /* Synchronize old-style prefs with new style prefs
637 static void pd_SyncPrefs(struct PrinterData
*pd
)
639 struct Preferences
*dprefs
= &pd
->pd_Preferences
;
640 struct PrinterPrefs
*uprefs
= &pd
->pd_PUnit
->pu_Prefs
;
642 dprefs
->PrinterType
= pd
->pd_PrinterType
;
644 strncpy(dprefs
->PrinterFilename
, uprefs
->pp_Txt
.pt_Driver
,
645 sizeof(dprefs
->PrinterFilename
));
646 dprefs
->PrinterFilename
[sizeof(dprefs
->PrinterFilename
)-1] = 0;
648 dprefs
->PrintPitch
= uprefs
->pp_Txt
.pt_Pitch
;
649 dprefs
->PrintQuality
= uprefs
->pp_Txt
.pt_Quality
;
650 dprefs
->PrintSpacing
= uprefs
->pp_Txt
.pt_Spacing
;
651 dprefs
->PrintLeftMargin
= uprefs
->pp_Txt
.pt_LeftMargin
;
652 dprefs
->PrintRightMargin
= uprefs
->pp_Txt
.pt_RightMargin
;
653 dprefs
->PrintImage
= uprefs
->pp_Gfx
.pg_Image
;
654 dprefs
->PrintAspect
= uprefs
->pp_Gfx
.pg_Aspect
;
655 dprefs
->PrintShade
= uprefs
->pp_Gfx
.pg_Shade
;
656 dprefs
->PrintThreshold
= uprefs
->pp_Gfx
.pg_Threshold
;
657 dprefs
->PaperSize
= uprefs
->pp_Txt
.pt_PaperSize
;
658 dprefs
->PaperType
= uprefs
->pp_Txt
.pt_PaperType
;
659 dprefs
->PaperLength
= uprefs
->pp_Txt
.pt_PaperLength
;
661 if (uprefs
->pp_Unit
.pu_DeviceName
[0] == 0) {
662 if (uprefs
->pp_Txt
.pt_Port
== PP_PARALLEL
) {
663 strcpy(dprefs
->PrtDevName
, "parallel");
664 } else if (uprefs
->pp_Txt
.pt_Port
== PP_SERIAL
) {
665 strcpy(dprefs
->PrtDevName
, "serial");
667 strcpy(dprefs
->PrtDevName
, "printtofile");
670 strncpy(dprefs
->PrtDevName
, uprefs
->pp_Unit
.pu_DeviceName
, sizeof(dprefs
->PrtDevName
));
671 dprefs
->PrtDevName
[sizeof(dprefs
->PrtDevName
)-1]=0;
674 dprefs
->DefaultPrtUnit
= uprefs
->pp_Unit
.pu_UnitNum
;
675 dprefs
->PrintFlags
= uprefs
->pp_Gfx
.pg_GraphicFlags
;
676 dprefs
->PrintMaxWidth
= uprefs
->pp_Gfx
.pg_PrintMaxWidth
;
677 dprefs
->PrintMaxHeight
= uprefs
->pp_Gfx
.pg_PrintMaxHeight
;
678 dprefs
->PrintDensity
= uprefs
->pp_Gfx
.pg_PrintDensity
;
679 dprefs
->PrintXOffset
= uprefs
->pp_Gfx
.pg_PrintXOffset
;
682 /* Create a PrinterData plugin
684 struct PrinterUnit
*Printer_Unit(struct PrinterBase
*PrinterBase
, LONG unitnum
)
686 struct PrinterUnit
*pu
;
687 struct PrinterPrefs prefs
;
688 BPTR olddir
, dir
, driverseg
;
690 if (!Printer_LoadPrefs(PrinterBase
, unitnum
, &prefs
) || prefs
.pp_Txt
.pt_Driver
[0] == 0) {
691 D(bug("%s: No valid prefs for printer.device %d\n", __func__
, unitnum
));
695 if ((dir
= Lock("DEVS:Printers", SHARED_LOCK
)) != BNULL
) {
696 olddir
= CurrentDir(dir
);
697 driverseg
= LoadSeg(prefs
.pp_Txt
.pt_Driver
);
701 D(bug("%s: %s => %p\n", __func__
, prefs
.pp_Txt
.pt_Driver
, BADDR(driverseg
)));
704 struct PrinterSegment
*prtseg
= BADDR(driverseg
);
706 D(bug("%s: magic 0x%08x, expect 0x%08x\n", __func__
, prtseg
->ps_runAlert
, AROS_PRINTER_MAGIC
));
707 if (prtseg
->ps_runAlert
== AROS_PRINTER_MAGIC
) {
709 AROS_SLIB_ENTRY(OpenDevice
,PrinterUnit
,1),
710 AROS_SLIB_ENTRY(CloseDevice
,PrinterUnit
,2),
711 AROS_SLIB_ENTRY(Expunge
,PrinterUnit
,3),
713 AROS_SLIB_ENTRY(BeginIO
,PrinterUnit
,5),
714 AROS_SLIB_ENTRY(AbortIO
,PrinterUnit
,6),
718 if ((pu
= (struct PrinterUnit
*)MakeLibrary(funcs
, NULL
, NULL
, sizeof(*pu
), driverseg
))) {
719 struct Process
*proc
;
720 struct PrinterData
*pd
= &pu
->pu_PrinterData
;
721 struct Device
*dev
= (struct Device
*)pu
;
723 /* Loop back to self */
724 pu
->pu_PrinterBase
= PrinterBase
;
727 /* Duplicate the prefs */
728 CopyMem(&prefs
, &pu
->pu_Prefs
, sizeof(prefs
));
730 /* Update pd->pd_Preferences from pu->pu_Prefs */
733 dev
->dd_Library
.lib_Node
.ln_Name
= pu
->pu_Prefs
.pp_DeviceUnit
.pd_UnitName
;
734 dev
->dd_Library
.lib_Version
= prtseg
->ps_Version
;
735 dev
->dd_Library
.lib_Revision
= prtseg
->ps_Revision
;
736 /* Magic token for TASK_PRINTERDATA() macro */
737 dev
->dd_Library
.lib_IdString
= (APTR
)driverID
;
739 pd
->pd_Device
.dd_Segment
= BADDR(driverseg
);
740 pd
->pd_Device
.dd_ExecBase
= SysBase
;
741 pd
->pd_Device
.dd_CmdVectors
= prtseg
->ps_PED
.ped_Commands
;
742 pd
->pd_Device
.dd_CmdBytes
= NULL
;
743 pd
->pd_Device
.dd_NumCommands
= aRAW
+ 1;
744 pd
->pd_PrinterSegment
= driverseg
;
745 pd
->pd_PrinterType
= 0;
746 pd
->pd_SegmentData
= prtseg
;
747 pd
->pd_PWrite
= pd_PWrite
;
748 pd
->pd_PBothReady
= pd_PBothReady
;
749 pd
->pd_PRead
= pd_PRead
;
750 pd
->pd_CallErrHook
= (APTR
)pd_CallErrHook
;
751 pd
->pd_PQuery
= pd_PQuery
;
752 pd
->pd_UnitNumber
= unitnum
;
753 pd
->pd_DriverName
= &pd
->pd_Preferences
.PrinterFilename
[0];
755 /* Make RemDevice() and friends happy */
758 proc
= CreateNewProcTags(NP_Entry
, pd_DriverTask
,
759 NP_Name
, prefs
.pp_DeviceUnit
.pd_UnitName
,
764 D(bug("%s: Driver process %p\n", __func__
, proc
));
766 struct MsgPort
*port
;
768 /* Store the process here... */
769 pu
->pu_Process
= proc
;
772 if ((port
= CreateMsgPort())) {
773 struct MagicMessage startup
, *reply
;
775 D(bug("%s: Driver unit port %p\n", __func__
, port
));
776 startup
.mn_ReplyPort
=port
;
777 startup
.mn_Length
= sizeof(startup
);
778 startup
.mn_Magic
= AROS_MAKE_ID('p','r','u','n');
779 startup
.mn_Version
= 0;
780 PutMsg(&proc
->pr_MsgPort
, (struct Message
*)&startup
);
782 D(bug("%s: Driver replied\n", __func__
));
783 reply
= (struct MagicMessage
*)GetMsg(port
);
784 D(bug("%s: Driver reply = %p\n", __func__
, reply
));
786 D(bug("%s: Driver port %p gone\n", __func__
, port
));
787 if (reply
== &startup
&&
788 reply
->mn_Length
== sizeof(*reply
) &&
789 reply
->mn_Magic
== AROS_MAKE_ID('p','r','u','n') &&
790 reply
->mn_Version
== 0) {
792 D(bug("%s: Driver started\n", __func__
));
795 D(bug("%s: Driver startup failed\n", __func__
));
797 /* pd_DriverTask will kill itself on failure */
799 /* pd_Expunge() calls UnLoadSeg() automatically */
800 RemDevice((struct Device
*)pd
);
805 UnLoadSeg(driverseg
);