2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
5 Desc: Amigastyle device for trackdisk
9 #include <devices/trackdisk.h>
10 #include <exec/resident.h>
11 #include <exec/errors.h>
12 #include <exec/memory.h>
13 #include <exec/lists.h>
14 #include <exec/alerts.h>
15 #include <exec/tasks.h>
16 #include <libraries/expansionbase.h>
17 #include <libraries/configvars.h>
18 #include <dos/filehandler.h>
19 #include <dos/dosextens.h>
20 #include <dos/dostags.h>
21 #include <clib/alib_protos.h>
22 #include <aros/symbolsets.h>
23 #include <aros/bootloader.h>
26 #include <proto/oop.h>
27 #include <proto/exec.h>
28 #include <proto/expansion.h>
29 #include <proto/utility.h>
30 #include <proto/bootloader.h>
31 #include <proto/dos.h>
35 #include "trackdisk_device.h"
36 #include "trackdisk_hw.h"
38 #include LC_LIBDEFS_FILE
41 #include <aros/debug.h>
45 void td_floppytimer(HIDDT_IRQ_Handler
*, HIDDT_IRQ_HwInfo
*);
46 void td_floppyint(HIDDT_IRQ_Handler
*, HIDDT_IRQ_HwInfo
*);
47 int td_getbyte(unsigned char *, struct TrackDiskBase
*);
48 int td_sendbyte(unsigned char, struct TrackDiskBase
*);
49 ULONG
TD_InitTask(struct TrackDiskBase
*);
50 static void TD_DevTask();
51 BOOL
TD_PerformIO( struct IOExtTD
*, struct TrackDiskBase
*);
53 struct TDU
*TD_InitUnit(ULONG num
, struct TrackDiskBase
*tdb
)
56 struct ExpansionBase
*ExpansionBase
= NULL
;
57 struct DeviceNode
*devnode
;
59 TEXT dosdevname
[4] = "DF0", *handler
= "afs.handler";
62 /* Try to get memory for structure */
63 unit
= AllocMem(sizeof(struct TDU
), MEMF_PUBLIC
| MEMF_CLEAR
);
66 ExpansionBase
= (struct ExpansionBase
*)OpenLibrary("expansion.library",40);
69 unit
->tdu_DiskIn
= TDU_NODISK
; /* Assume there is no floppy in there */
70 unit
->pub
.tdu_StepDelay
= 4; /* Standard values here */
71 unit
->pub
.tdu_SettleDelay
= 16;
72 unit
->pub
.tdu_RetryCnt
= 3;
73 unit
->pub
.tdu_CalibrateDelay
= 4;
74 unit
->tdu_UnitNum
=num
;
75 unit
->tdu_lastcyl
= -1;
76 unit
->tdu_lasthd
= -1;
77 NEWLIST(&unit
->tdu_Listeners
);
79 /* Alloc memory for track buffering */
80 unit
->td_DMABuffer
=AllocMem(DP_SECTORS
*512,MEMF_CLEAR
|MEMF_CHIP
);
82 if (!unit
->td_DMABuffer
)
84 Alert(AT_DeadEnd
| AO_TrackDiskDev
| AG_NoMemory
);
87 /* If buffer doesn't fit into DMA page realloc it */
88 if (( (((ULONG
)unit
->td_DMABuffer
+ DP_SECTORS
*512) & 0xffff0000) -
89 ((ULONG
)unit
->td_DMABuffer
&0xffff0000) ) != 0)
93 buffer
= AllocMem(DP_SECTORS
*512, MEMF_CLEAR
| MEMF_CHIP
);
96 Alert(AT_DeadEnd
| AO_TrackDiskDev
| AG_NoMemory
);
99 FreeMem(unit
->td_DMABuffer
, DP_SECTORS
*512);
100 unit
->td_DMABuffer
= buffer
;
102 /* Store the unit in TDBase */
103 tdb
->td_Units
[num
] = unit
;
107 D(bug("TD: Adding bootnode\n"));
108 pp
= (IPTR
*)AllocMem(sizeof(struct DosEnvec
)+sizeof(IPTR
)*4,MEMF_PUBLIC
|MEMF_CLEAR
);
112 dosdevname
[2] += num
;
113 pp
[0] = (IPTR
)dosdevname
;
114 pp
[1] = (IPTR
)MOD_NAME_STRING
;
116 pp
[DE_TABLESIZE
+ 4] = DE_BOOTBLOCKS
;
117 pp
[DE_SIZEBLOCK
+ 4] = 128;
118 pp
[DE_NUMHEADS
+ 4] = 2;
119 pp
[DE_SECSPERBLOCK
+ 4] = 1;
120 pp
[DE_BLKSPERTRACK
+ 4] = 18;
121 pp
[DE_RESERVEDBLKS
+ 4] = 2;
122 pp
[DE_LOWCYL
+ 4] = 0;
123 pp
[DE_HIGHCYL
+ 4] = 79;
124 pp
[DE_NUMBUFFERS
+ 4] = 10;
125 pp
[DE_BUFMEMTYPE
+ 4] = MEMF_PUBLIC
| MEMF_CHIP
;
126 pp
[DE_MAXTRANSFER
+ 4] = 0x00200000;
127 pp
[DE_MASK
+ 4] = 0x7FFFFFFE;
128 pp
[DE_BOOTPRI
+ 4] = 5;
129 pp
[DE_DOSTYPE
+ 4] = 0x444F5300;
130 pp
[DE_BOOTBLOCKS
+ 4] = 2;
131 devnode
= MakeDosNode(pp
);
135 len
= strlen(handler
);
136 devnode
->dn_Handler
= MKBADDR(AllocMem(
137 AROS_BSTR_MEMSIZE4LEN(len
), MEMF_PUBLIC
| MEMF_CLEAR
)
140 if (devnode
->dn_Name
!= NULL
)
142 CopyMem(handler
, AROS_BSTR_ADDR(devnode
->dn_Handler
),
144 AROS_BSTR_setstrlen(devnode
->dn_Handler
, len
);
145 AddBootNode(pp
[DE_BOOTPRI
+ 4], 0, devnode
, 0);
153 CloseLibrary((struct Library
*)ExpansionBase
);
158 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR TDBase
)
160 struct Library
*OOPBase
;
161 struct BootLoaderBase
*BootLoaderBase
;
165 D(bug("TD: Init\n"));
167 /* First thing, are we disabled from the bootloader? */
168 if ((BootLoaderBase
= OpenResource("bootloader.resource")))
173 list
= (struct List
*)GetBootInfo(BL_Args
);
176 ForeachNode(list
,node
)
178 if (0 == strncmp(node
->ln_Name
,"floppy=",5))
180 if (strstr(&node
->ln_Name
[7], "disabled"))
182 D(bug("[Floppy] Disabled with bootloader argument\n"));
185 TDBase
->td_nomount
= strstr(&node
->ln_Name
[7], "nomount");
191 /* First we check if there are any floppy drives configured in BIOS */
192 /* We do this by reading CMOS byte 0x10 */
193 /* It should really reside in battclock.resource */
199 /* No drives here. abort */
200 D(bug("TD: No drives defined in BIOS\n"));
204 for (i
=0; i
<TD_NUMUNITS
; i
++)
205 TDBase
->td_Units
[i
] = NULL
;
207 /* Set up the IRQ system */
208 OOPBase
= OpenLibrary(AROSOOP_NAME
, 0);
214 o
= OOP_NewObject(NULL
, CLID_Hidd_IRQ
, NULL
);
218 HIDDT_IRQ_Handler
*irq
;
220 irq
= AllocMem(sizeof(HIDDT_IRQ_Handler
), MEMF_CLEAR
|MEMF_PUBLIC
);
224 /* PANIC! No memory for trackdisk IntServer ! */
225 Alert(AT_DeadEnd
|AO_TrackDiskDev
|AN_IntrMem
);
227 irq
->h_Node
.ln_Pri
=127; /* Set the highest pri */
228 irq
->h_Node
.ln_Name
= (STRPTR
)MOD_NAME_STRING
;
229 irq
->h_Code
= td_floppyint
;
230 irq
->h_Data
= (APTR
)TDBase
;
232 HIDD_IRQ_AddHandler(o
, irq
, vHidd_IRQ_Floppy
);
234 irq
= AllocMem(sizeof(HIDDT_IRQ_Handler
), MEMF_CLEAR
|MEMF_PUBLIC
);
238 /* PANIC! No memory for trackdisk IntServer ! */
239 Alert(AT_DeadEnd
|AO_TrackDiskDev
|AN_IntrMem
);
241 irq
->h_Node
.ln_Pri
=10; /* Set the highest pri */
242 irq
->h_Node
.ln_Name
= (STRPTR
)MOD_NAME_STRING
;
243 irq
->h_Code
= td_floppytimer
;
244 irq
->h_Data
= (APTR
)TDBase
;
246 HIDD_IRQ_AddHandler(o
, irq
, vHidd_IRQ_Timer
);
248 OOP_DisposeObject(o
);
250 CloseLibrary(OOPBase
);
253 /* Swap drivebits around */
254 drives
= ( (drives
&0xf0)>>4 | (drives
&0x0f)<<4 );
256 for (i
=0;i
<TD_NUMUNITS
;i
++)
258 /* We only want 3.5" 1.44Mb drives */
259 if (((drives
>> (4*i
))&0x0f) == 4)
261 kprintf("[Floppy] Unit %d is a 1.44Mb drive\n",i
);
262 TD_InitUnit(i
,TDBase
);
266 /* Create the message processor task */
272 static int GM_UNIQUENAME(Open
)
274 LIBBASETYPEPTR TDBase
,
275 struct IOExtTD
*iotd
,
280 D(bug("TD: Open\n"));
281 iotd
->iotd_Req
.io_Error
= IOERR_OPENFAIL
;
283 /* Is the requested unitNumber valid? */
284 if (unitnum
< TD_NUMUNITS
)
288 iotd
->iotd_Req
.io_Device
= (struct Device
*)TDBase
;
290 /* Get TDU structure */
291 unit
= TDBase
->td_Units
[unitnum
];
292 if (unit
&& (unit
->tdu_Present
)) {
293 iotd
->iotd_Req
.io_Unit
= (struct Unit
*)unit
;
294 ((struct Unit
*)unit
)->unit_OpenCnt
++;
295 iotd
->iotd_Req
.io_Error
= 0;
299 return iotd
->iotd_Req
.io_Error
== 0;
303 static int GM_UNIQUENAME(Close
)
305 LIBBASETYPEPTR TDBase
,
309 iotd
->iotd_Req
.io_Unit
->unit_OpenCnt
--;
314 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
315 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
316 ADD2CLOSEDEV(GM_UNIQUENAME(Close
), 0)
317 ADD2LIBS("irq.hidd", 0, static struct Library
*, __irqhidd
)
319 AROS_LH1(void, beginio
,
320 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
321 struct TrackDiskBase
*, TDBase
, 5, TrackDisk
)
326 if (iotd
->iotd_Req
.io_Flags
& IOF_QUICK
)
328 switch(iotd
->iotd_Req
.io_Command
)
331 tdu
= (struct TDU
*)iotd
->iotd_Req
.io_Unit
;
332 if ((!(tdu
->pub
.tdu_PubFlags
& TDPF_NOCLICK
)) || (tdu
->tdu_DiskIn
== TDU_DISK
))
346 PutMsg(&TDBase
->td_TaskData
->td_Port
, &iotd
->iotd_Req
.io_Message
);
347 iotd
->iotd_Req
.io_Flags
&= ~IOF_QUICK
;
350 TD_PerformIO(iotd
,TDBase
);
355 /* Forward to devicetask */
356 PutMsg(&TDBase
->td_TaskData
->td_Port
, &iotd
->iotd_Req
.io_Message
);
358 iotd
->iotd_Req
.io_Flags
&= ~IOF_QUICK
;
364 AROS_LH1(LONG
, abortio
,
365 AROS_LHA(struct IOExtTD
*, iotd
, A1
),
366 struct TrackDiskBase
*, TDBase
, 6, TrackDisk
)
369 D(bug("TD: AbortIO\n"));
374 void TestInsert(struct TrackDiskBase
*tdb
, struct TDU
*tdu
)
377 struct IOExtTD
*iotd
;
379 td_rseek(tdu
->tdu_UnitNum
,tdu
->tdu_stepdir
,1,tdb
);
380 tdu
->tdu_stepdir
= !tdu
->tdu_stepdir
;
381 dir
= (inb(FDC_DIR
)>>7);
384 D(bug("[Floppy] Insertion detected\n"));
385 td_recalibrate(tdu
->tdu_UnitNum
,1,0,tdb
);
386 tdu
->tdu_DiskIn
= TDU_DISK
;
387 tdu
->pub
.tdu_Counter
++;
388 tdu
->tdu_ProtStatus
= td_getprotstatus(tdu
->tdu_UnitNum
,tdb
);
390 ForeachNode(&tdu
->tdu_Listeners
,iotd
)
392 Cause((struct Interrupt
*)((struct IOExtTD
*)iotd
->iotd_Req
.io_Data
));
398 BOOL
TD_PerformIO( struct IOExtTD
*iotd
, struct TrackDiskBase
*tdb
)
401 struct DriveGeometry
*geo
;
406 tdu
= (struct TDU
*)iotd
->iotd_Req
.io_Unit
;
407 switch(iotd
->iotd_Req
.io_Command
)
410 if (iotd
->iotd_Count
> tdu
->pub
.tdu_Counter
) {
411 iotd
->iotd_Req
.io_Error
= TDERR_DiskChanged
;
416 tdu
->tdu_lastcyl
= -1;
417 tdu
->tdu_lasthd
= -1;
418 iotd
->iotd_Req
.io_Error
= 0;
421 if (iotd
->iotd_Count
> tdu
->pub
.tdu_Counter
) {
422 iotd
->iotd_Req
.io_Error
= TDERR_DiskChanged
;
426 tdu
->tdu_Busy
= TRUE
;
427 iotd
->iotd_Req
.io_Error
= td_read(iotd
, tdb
);
428 tdu
->tdu_Busy
= FALSE
;
431 if (iotd
->iotd_Count
> tdu
->pub
.tdu_Counter
) {
432 iotd
->iotd_Req
.io_Error
= TDERR_DiskChanged
;
436 tdu
->tdu_Busy
= TRUE
;
437 iotd
->iotd_Req
.io_Error
= td_update(tdu
, tdb
);
438 tdu
->tdu_Busy
= FALSE
;
441 if (iotd
->iotd_Count
> tdu
->pub
.tdu_Counter
) {
442 iotd
->iotd_Req
.io_Error
= TDERR_DiskChanged
;
446 tdu
->tdu_Busy
= TRUE
;
447 iotd
->iotd_Req
.io_Error
= td_write(iotd
, tdb
);
448 tdu
->tdu_Busy
= FALSE
;
450 case TD_ADDCHANGEINT
:
452 AddTail(&tdu
->tdu_Listeners
,(struct Node
*)iotd
);
457 iotd
->iotd_Req
.io_Actual
= tdu
->pub
.tdu_Counter
;
458 iotd
->iotd_Req
.io_Error
=0;
461 if ((tdu
->pub
.tdu_PubFlags
& TDPF_NOCLICK
) && (tdu
->tdu_DiskIn
== TDU_NODISK
)) {
462 TestInsert(tdb
, tdu
);
463 if (!tdu
->tdu_MotorOn
)
464 td_motoroff(tdu
->tdu_UnitNum
, tdb
);
466 if (tdu
->tdu_DiskIn
== TDU_DISK
)
468 /* test if disk is still in there */
469 temp
= td_getDiskChange();
470 iotd
->iotd_Req
.io_Actual
= temp
;
471 tdu
->tdu_DiskIn
= temp
^ 1;
475 /* No disk in drive */
476 iotd
->iotd_Req
.io_Actual
= 1;
478 iotd
->iotd_Req
.io_Error
=0;
481 if (iotd
->iotd_Count
> tdu
->pub
.tdu_Counter
) {
482 iotd
->iotd_Req
.io_Error
= TDERR_DiskChanged
;
486 tdu
->tdu_Busy
= TRUE
;
487 iotd
->iotd_Req
.io_Error
= td_format(iotd
,tdb
);
488 tdu
->tdu_Busy
= FALSE
;
491 if (iotd
->iotd_Count
> tdu
->pub
.tdu_Counter
) {
492 iotd
->iotd_Req
.io_Error
= TDERR_DiskChanged
;
496 iotd
->iotd_Req
.io_Error
=0;
497 switch (iotd
->iotd_Req
.io_Length
)
500 tdu
->tdu_MotorOn
= 0;
501 td_motoroff(tdu
->tdu_UnitNum
,tdb
);
504 tdu
->tdu_MotorOn
= 1;
505 td_motoron(tdu
->tdu_UnitNum
,tdb
,TRUE
);
508 iotd
->iotd_Req
.io_Error
= TDERR_NotSpecified
;
513 iotd
->iotd_Req
.io_Actual
= tdu
->tdu_ProtStatus
;
514 iotd
->iotd_Req
.io_Error
=0;
516 case TD_REMCHANGEINT
:
518 Remove((struct Node
*)iotd
);
522 geo
= (struct DriveGeometry
*)iotd
->iotd_Req
.io_Data
;
523 geo
->dg_SectorSize
= 512;
524 geo
->dg_TotalSectors
= DP_STOTAL
;
525 geo
->dg_Cylinders
= DP_TRACKS
;
526 geo
->dg_CylSectors
= DP_SECTORS
*2;
528 geo
->dg_TrackSectors
= DP_SECTORS
;
529 geo
->dg_BufMemType
= MEMF_PUBLIC
;
530 geo
->dg_DeviceType
= DG_DIRECT_ACCESS
;
531 geo
->dg_Flags
= DGF_REMOVABLE
;
532 iotd
->iotd_Req
.io_Error
=0;
534 case TD_GETDRIVETYPE
:
535 iotd
->iotd_Req
.io_Actual
= DRIVE3_5
;
536 iotd
->iotd_Req
.io_Error
=0;
538 case TD_GETNUMTRACKS
:
539 iotd
->iotd_Req
.io_Actual
= DP_TRACKS
*2;
540 iotd
->iotd_Req
.io_Error
=0;
543 if (iotd
->iotd_Count
> tdu
->pub
.tdu_Counter
) {
544 iotd
->iotd_Req
.io_Error
= TDERR_DiskChanged
;
548 temp
= (iotd
->iotd_Req
.io_Offset
>> 10) / DP_SECTORS
;
549 tdu
->tdu_MotorOn
= 1;
550 iotd
->iotd_Req
.io_Error
= td_recalibrate(tdu
->tdu_UnitNum
, 0, temp
, tdb
);
554 D(bug("TD: Unknown command received\n"));
555 iotd
->iotd_Req
.io_Error
= IOERR_NOCMD
;
557 } /* switch(iotd->iotd_Req.io_Command) */
561 ULONG
TD_InitTask(struct TrackDiskBase
*tdb
)
567 /* Allocate Task Data structure */
568 t
= AllocMem(sizeof(struct TaskData
), MEMF_PUBLIC
|MEMF_CLEAR
);
569 /* Allocate Stack space */
570 if ((t
) && ((t
->td_Stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
|MEMF_CLEAR
)) == NULL
))
572 FreeMem(t
, sizeof(struct TaskData
));
575 /* Allocate MemEntry for this task */
576 ml
= (struct MemList
*)AllocMem(sizeof(struct MemList
), MEMF_PUBLIC
|MEMF_CLEAR
);
578 /* Find the current task */
583 D(bug("TD: Creating devicetask..."));
584 /* Save stack info into task structure */
585 t
->td_Task
.tc_SPLower
= t
->td_Stack
;
586 t
->td_Task
.tc_SPUpper
= (BYTE
*)t
->td_Stack
+ STACK_SIZE
;
587 t
->td_Task
.tc_SPReg
= (BYTE
*)t
->td_Task
.tc_SPUpper
- SP_OFFSET
- sizeof(APTR
);
590 NEWLIST(&t
->td_Port
.mp_MsgList
);
591 t
->td_Port
.mp_Node
.ln_Type
= NT_MSGPORT
;
592 t
->td_Port
.mp_Flags
= PA_SIGNAL
;
593 t
->td_Port
.mp_SigBit
= SIGBREAKB_CTRL_F
;
594 t
->td_Port
.mp_SigTask
= &t
->td_Task
;
595 t
->td_Port
.mp_Node
.ln_Name
= "trackdisk.device";
598 ml
->ml_NumEntries
= 1;
599 ml
->ml_ME
[0].me_Addr
= t
;
600 ml
->ml_ME
[0].me_Length
= sizeof(struct TaskData
);
601 NEWLIST(&t
->td_Task
.tc_MemEntry
);
602 AddHead(&t
->td_Task
.tc_MemEntry
, &ml
->ml_Node
);
604 /* Init Task structure */
605 t
->td_Task
.tc_Node
.ln_Name
= "trackdisk.task";
606 t
->td_Task
.tc_Node
.ln_Type
= NT_TASK
;
607 t
->td_Task
.tc_Node
.ln_Pri
= 5;
608 t
->td_Task
.tc_UserData
= me
;
610 tdb
->td_TaskData
= t
;
612 struct TagItem task_Tags
[] = {
613 { TASKTAG_ARG1
, tdb
},
616 /* Add task to system task list */
617 NewAddTask(&t
->td_Task
, &TD_DevTask
, NULL
, task_Tags
);
619 /* Wait until started */
620 Wait(SIGBREAKF_CTRL_F
);
630 if (t
->td_Stack
) FreeMem(t
->td_Stack
, STACK_SIZE
);
631 FreeMem(t
, sizeof(struct TaskData
));
633 if (ml
) FreeMem(ml
, sizeof(struct MemList
));
639 static void TD_DevTask(struct TrackDiskBase
*tdb
)
642 struct IOExtTD
*iotd
;
644 ULONG tasig
,tisig
,sigs
,i
;
647 D(bug("[TDTask] TD_DevTask(tdb=%p)\n", tdb
));
649 td
= tdb
->td_TaskData
;
651 D(bug("[TDTask] TD_DevTask: struct TaskData @ %p\n", td
));
653 tdb
->td_IntBit
= AllocSignal(-1);
654 tdb
->td_TmoBit
= AllocSignal(-1);
655 tdb
->td_TimerMP
= CreateMsgPort();
656 tdb
->td_TimerIO
= (struct timerequest
*) CreateIORequest(tdb
->td_TimerMP
, sizeof(struct timerequest
));
657 OpenDevice("timer.device", UNIT_VBLANK
, (struct IORequest
*)tdb
->td_TimerIO
, 0);
662 /* Initial check for floppies */
663 for (i
=0;i
<TD_NUMUNITS
;i
++)
667 td_rseek(i
, 0, 1, tdb
);
668 tdb
->td_Units
[i
]->tdu_Present
= !td_recalibrate(tdb
->td_Units
[i
]->tdu_UnitNum
,1,0,tdb
);
669 tdb
->td_Units
[i
]->pub
.tdu_CurrTrk
= 0;
670 tdb
->td_Units
[i
]->tdu_DiskIn
= (td_getDiskChange() ^ 1);
671 tdb
->td_Units
[i
]->tdu_ProtStatus
= td_getprotstatus(i
,tdb
);
672 tdb
->td_Units
[i
]->tdu_Busy
= FALSE
;
673 tdb
->td_Units
[i
]->tdu_stepdir
= 0;
674 if (((tdb
->td_Units
[i
]->pub
.tdu_PubFlags
& TDPF_NOCLICK
) && (tdb
->td_Units
[i
]->tdu_DiskIn
== TDU_NODISK
))
675 || (!tdb
->td_Units
[i
]->tdu_Present
))
677 D(bug("Drive %d presence: %ld\n", i
, tdb
->td_Units
[i
]->tdu_Present
));
681 tasig
= 1L << td
->td_Port
.mp_SigBit
;
682 tisig
= 1L << tdb
->td_TimerMP
->mp_SigBit
;
684 /* Reply to startup message */
685 Signal(td
->td_Task
.tc_UserData
,SIGBREAKF_CTRL_F
);
687 tdb
->td_TimerIO
->tr_node
.io_Command
= TR_ADDREQUEST
;
688 tdb
->td_TimerIO
->tr_time
.tv_secs
= 2;
689 tdb
->td_TimerIO
->tr_time
.tv_micro
= 500000;
690 SendIO((struct IORequest
*)tdb
->td_TimerIO
);
692 /* Endless task loop */
696 sigs
= Wait(tasig
| tisig
); /* Wait for a message */
697 /* If unit was not active process message */
700 /* We received a message. Deal with it */
701 while((iotd
= (struct IOExtTD
*)GetMsg(&td
->td_Port
)) != NULL
)
703 /* Execute command */
704 if (TD_PerformIO( iotd
, tdb
))
707 ReplyMsg((struct Message
*)iotd
);
713 /* We were woken up by the timer. */
714 WaitIO((struct IORequest
*)tdb
->td_TimerIO
);
715 for(i
=0;i
<TD_NUMUNITS
;i
++)
717 /* If there is no floppy in drive, scan for changes */
718 if (tdb
->td_Units
[i
])
720 tdu
= tdb
->td_Units
[i
];
721 switch (tdu
->tdu_DiskIn
)
725 Unfortunately "NoClick" technology which works on Amiga will not
726 work on PC because i82077 does not send step pulse when told to
727 seek to "-1" track and the drive can't recognize disk insertion.
728 Many thanks to Intel! :-(((
730 Here we use another technique: in NoClick mode we just do nothing
731 if the disk is not in drive. We can perform this test only once
732 inside TD_CHANGESTATE command which is invoked by DISKCHANGE
733 CLI command. This means that we'll have to issue DISKCHANGE command
734 manually after wi insert the disk, but this is probably better
737 if (tdu
->pub
.tdu_PubFlags
& TDPF_NOCLICK
) {
738 if (!tdu
->tdu_MotorOn
)
739 td_motoroff(tdu
->tdu_UnitNum
, tdb
);
741 TestInsert(tdb
, tdu
);
745 Fortunately this part is completely silent so we don't have to
746 do any extra mess here
750 if (!tdu
->tdu_MotorOn
)
751 td_motoron(tdu
->tdu_UnitNum
,tdb
,FALSE
);
752 dir
= (inb(FDC_DIR
)>>7);
753 if (!tdu
->tdu_MotorOn
)
754 td_motoroff(tdu
->tdu_UnitNum
,tdb
);
757 D(bug("[Floppy] Removal detected\n"));
758 /* Go to cylinder 0 */
759 td_recalibrate(tdu
->tdu_UnitNum
,1,0,tdb
);
760 tdu
->tdu_DiskIn
= TDU_NODISK
;
761 tdu
->pub
.tdu_Counter
++;
763 ForeachNode(&tdu
->tdu_Listeners
,iotd
)
765 Cause((struct Interrupt
*)((struct IOExtTD
*)iotd
->iotd_Req
.io_Data
));
768 tdu
->tdu_stepdir
= 0;
776 /* Reload the timer again */
777 GetMsg(tdb
->td_TimerMP
);
778 tdb
->td_TimerIO
->tr_node
.io_Command
= TR_ADDREQUEST
;
779 tdb
->td_TimerIO
->tr_time
.tv_secs
= 2;
780 tdb
->td_TimerIO
->tr_time
.tv_micro
= 500000;
781 SendIO((struct IORequest
*)tdb
->td_TimerIO
);
786 #define TDBase ((struct TrackDiskBase *)irq->h_Data)
787 void td_floppytimer(HIDDT_IRQ_Handler
*irq
, HIDDT_IRQ_HwInfo
*hw
)
789 // Does anyone wait for io?
790 if (TDBase
->td_inttmo
)
795 if (!TDBase
->td_inttmo
)
797 Signal(&TDBase
->td_TaskData
->td_Task
,(1L << TDBase
->td_TmoBit
));
802 void td_floppyint(HIDDT_IRQ_Handler
*irq
, HIDDT_IRQ_HwInfo
*hw
)
804 Signal(&TDBase
->td_TaskData
->td_Task
,(1L << TDBase
->td_IntBit
));