26 October 2018, 15:39 | #1 |
Registered User
Join Date: May 2011
Location: Cambridge
Posts: 682
|
Determining DFn: boot device in bootblock
Hi,
My problem is to write a custom bootblock which can determine which floppy unit number it was loaded from. Equivalently, to determine which floppy unit number the trackdisk.device IOReq passed in register a1 is associated with. Any ideas? Cheers! Keir |
26 October 2018, 17:11 | #2 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,480
|
Quote:
The easiest way I found is to use a long value in boot block (a unique tag) and then test in every attached drive for this tag. |
|
27 October 2018, 07:58 | #3 |
Registered User
Join Date: May 2011
Location: Cambridge
Posts: 682
|
|
27 October 2018, 09:03 | #4 |
Registered User
Join Date: May 2011
Location: Cambridge
Posts: 682
|
Answer: OpenDevice each trackdisk unit 0-3 in turn and check for a match on iotd_Req.io_Unit compared with the same field in the IOReq passed to the bootblock in A1.
This is a bit of a pain in the arse in asm but luckily I can wait until I'm in C. |
27 October 2018, 09:31 | #5 | ||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,480
|
Quote:
Quote:
Yes, is *bah* but works. (I needed this in a multi-floppy multi-drives non-system compliant game, so a tag is anyway required ) And is also fast if you check only into mapped drives: Code:
movea.l $14(a1),a1 movea.l $3c(a1),a1 now at $30(a1) you have four longword reporting attached drive EDIT: well, it can actually be mixed with your method but maybe the code would grow in size Last edited by ross; 27 October 2018 at 10:05. |
||
27 October 2018, 10:18 | #6 | |
Registered User
Join Date: May 2011
Location: Cambridge
Posts: 682
|
Quote:
By the way I tried following your asm code. It looks like it indirects via offset 0x3c in the Device structure. Isn't that off the end of the device structure, or is there extra public stuff there for trackdisk? |
|
27 October 2018, 11:26 | #7 | |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
Quote:
That does indeed seem to work, very nice. Here's my quick and dirty 5 minutes code to test this: Code:
_LVOOpenDevice = -444 INCDIR SOURCES:INCLUDE/ INCLUDE exec/io.i BOOT dc.l "DOS"<<8 dc.l 0 dc.l 0 FindBootDrive move.l a1,a5 moveq #4-1,d6 ; device number and loop counter .loop bsr.b OpenTrackdisk tst.l d0 bne.b .noDevice lea IOStdReq(pc),a0 move.l IO_UNIT(a0),d0 cmp.l IO_UNIT(a5),d0 beq.b .found .noDevice dbf d6,.loop .found move.w d6,d0 bra.b .found rts OpenTrackdisk lea TrackDiskName(pc),a0 lea IOStdReq(pc),a1 pea port(pc) move.l (a7)+,ReplyPort-IOStdReq(a1) pea ReplyPort(pc) move.l (a7)+,MN_REPLYPORT(a1) ;moveq #0,d0 ; unit number move.l d6,d0 moveq #0,d1 ; flags move.l $4.W,a6 jmp _LVOOpenDevice(a6) IOStdReq ds.b 56 ReplyPort dc.l 0 port ds.b 100 TrackDiskName dc.b 'trackdisk.device',0 ds.b 1024 |
|
27 October 2018, 11:34 | #8 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,480
|
|
27 October 2018, 11:37 | #9 |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
I was working on a crack intro, saw this thread and just had to quickly test this.
|
27 October 2018, 11:39 | #10 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,480
|
Quote:
Sure works in every existing kickstart. |
|
27 October 2018, 11:46 | #11 | |
Registered User
Join Date: May 2011
Location: Cambridge
Posts: 682
|
Quote:
EDIT: The C code (it's longer than it might otherwise be since I don't link with amiga.lib and have to hand roll a bunch of lib stuff, only NewList is allowable as it's inline): Code:
/* Allocate a message port (must be later initialised with InitPort()). */ static struct MsgPort *AllocPort(void) { int sig_bit; struct MsgPort *mp; if ((sig_bit = AllocSignal(-1L)) == -1) return NULL; mp = AllocMem(sizeof(*mp), MEMF_PUBLIC); if (mp == NULL) { FreeSignal(sig_bit); return NULL; } mp->mp_SigBit = sig_bit; mp->mp_SigTask = FindTask(0); return mp; } /* Initialise a previously-allocated but currently unused port. */ static void InitPort(struct MsgPort *mp) { UBYTE sig_bit = mp->mp_SigBit; void *sig_task = mp->mp_SigTask; memset(mp, 0, sizeof(*mp)); mp->mp_Node.ln_Type = NT_MSGPORT; mp->mp_Flags = PA_SIGNAL; mp->mp_SigBit = sig_bit; mp->mp_SigTask = sig_task; NewList(&mp->mp_MsgList); } /* Free a previously-allocated but currently unused port. */ static void FreePort(struct MsgPort *mp) { FreeSignal(mp->mp_SigBit); FreeMem(mp, sizeof(*mp)); } /* Boot-device IORequest structure. */ extern struct IOExtTD *TDIOReq; /* Search for the trackdisk boot device. The strategy is to open each * trackdisk unit in turn and test for a match on the io_Unit structure. */ static int trackdisk_get_boot_unit(void) { struct MsgPort *mp; struct IOExtTD *td; struct Unit *td_unit; int unit; BYTE rc; if ((mp = AllocPort()) == NULL) return 0; if ((td = AllocMem(sizeof(*td), MEMF_PUBLIC)) == NULL) { FreePort(mp); return 0; } for (unit = 0; unit < 4; unit++) { InitPort(mp); memset(td, 0, sizeof(*td)); td->iotd_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG; td->iotd_Req.io_Message.mn_ReplyPort = mp; td->iotd_Req.io_Message.mn_Length = sizeof(*td); rc = OpenDevice((unsigned char *)"trackdisk.device", unit, (struct IORequest *)td, 0); if (rc == 0) { td_unit = td->iotd_Req.io_Unit; CloseDevice((struct IORequest *)td); if (td_unit == TDIOReq->iotd_Req.io_Unit) break; } } FreeMem(td, sizeof(*td)); FreePort(mp); return unit & 3; } |
|
27 October 2018, 12:01 | #12 |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
|
27 October 2018, 12:09 | #13 | |
Registered User
Join Date: May 2011
Location: Cambridge
Posts: 682
|
Quote:
I also like ross's approach but would probably do direct hw access and ignore trackdisk rather than grubbing in its device structure. It would be pretty simple to find valid drives by: * All motors off * DF0: is valid if: select unit 0 and check CIAAPRA_CHNG=1 * DFn: (n!=0) is valid if: select unit n and check CIAAPRA_RDY=0, CIAAPRA_CHNG=1. Then check for disk tag on the filtered set of valid DFn. So that's two nice methods |
|
27 October 2018, 13:54 | #14 | |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
Quote:
Code:
_LVOOpenDevice = -444 _LVOCloseDevice = -450 INCDIR SOURCES:INCLUDE/ INCLUDE exec/io.i INCLUDE devices/trackdisk.i BOOT dc.l "DOS"<<8 dc.l 0 dc.l "STR!" ; find drive which was used to boot the disk and determine ; which drives are available bsr.b CheckDrives ; d3.w: bit mask for available drives ; d4.w: boot drive ; d5.w: number of available drives .wait bra.b .wait CheckDrives move.l a1,a5 moveq #0,d3 ; bit mask for available drives moveq #-1,d4 ; boot drive: default: unknown moveq #0,d5 ; number of available drives moveq #4-1,d6 ; device number and loop counter .loop bsr.b OpenTrackdisk tst.l d0 bne.b .noDevice addq.w #1,d5 ; drive available bset d6,d3 lea IOStdReq(pc),a1 move.l IO_UNIT(a1),d0 cmp.l IO_UNIT(a5),d0 bne.b .noBootDrive move.w d6,d4 .noBootDrive jsr _LVOCloseDevice(a6) .noDevice dbf d6,.loop rts OpenTrackdisk lea TrackDiskName(pc),a0 lea IOStdReq(pc),a1 pea port(pc) move.l (a7)+,ReplyPort-IOStdReq(a1) pea ReplyPort(pc) move.l (a7)+,MN_REPLYPORT(a1) move.l d6,d0 moveq #0,d1 ; flags ;move.l $4.W,a6 jmp _LVOOpenDevice(a6) IOStdReq ds.b IOTD_SIZE ReplyPort dc.l 0 port ds.b 100 TrackDiskName dc.b "trackdisk.device",0 ds.b 1024 |
|
27 October 2018, 15:00 | #15 |
Registered User
Join Date: May 2011
Location: Cambridge
Posts: 682
|
Very elegant sir. I'm going to squirrel this away for future reference.
|
12 February 2023, 20:30 | #16 |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,633
|
AmigaOS used OpenDevice() with the name of "trackdisk.device" to read the bootblock whose code is reached with the StdIOReq pointer in a1.
When it was opened, OpenDevice() stored the IO_DEVICE and IO_UNIT in this request, and set 1 of 4 pointers to accessed IO_UNITs, starting at offset 36 from the device base. (These are cleared when the number of accesses reaches 0 and CloseDevice() completes with no error.) More than one trackdisk.device unit may have been opened (say, to determine which disk to boot from), but only the unit used loaded the code that is reached for execution. Compare your unit pointer to the 4 in the device base, and you can get n=0..3. I'm glad I worked this out, very short and no memory usage |
15 February 2023, 07:17 | #17 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,251
|
Don't use that code above, this may likely cause a MuForce hit. Trouble is that the port is not properly initialized, the message list is not intialized properly.
|
15 February 2023, 12:33 | #18 |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,043
|
This is what I've been using (works for me, iirc also tested with ACA500+ to boot from df1):
Code:
; a1 = StdIOReq you receive in bootblock movem.l (20,a1),a0/a1 ; IO_DEVICE/IO_UNIT lea (34+2+4*4,a0),a0 ; internal TDU0-3 pointers (DD_SIZE+2) moveq #4-1,d0 ; NUMUNITS-1 .UnitLoop cmp.l -(a0),a1 dbeq d0,.UnitLoop ; d0 = boot device 0-3 |
15 February 2023, 21:04 | #19 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,480
|
|
15 February 2023, 23:52 | #20 |
Moderator
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,633
|
Apart from the first line (I load registers differently) this is exactly what I arrived at before adding some extra functionality.
The logical conclusion from not having to supply unit to IORequests was that the unit must be stored outside, since it wasn't in the unit in the request. So the device. Trackdisk.device was special in this regard, and by looking at ROM code I noticed how it stored the accessed units and where. I wrote my previous description so you shouldn't e.g. assume a unit being = 0L as indicator of not being "enabled" or "connected" or "disk in drive". Only if a unit has been accessed by OpenDevice with trackdisk.device, has it been stored there for requests until it's closed. |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Determining boot drive from custom bootblock | Keir | Coders. General | 0 | 15 July 2017 10:16 |
boot floppy w/o bootblock | emufan | request.UAE Wishlist | 0 | 12 March 2014 16:57 |
How to find Exec device name and unit number for boot drive | mark_k | Coders. System | 3 | 16 February 2013 19:52 |
uaehf.device and HDToolbox: Error 224 reading device description | Ebster | support.WinUAE | 3 | 16 September 2008 09:24 |
Using a partition as an Amiga Boot Device for UAE | JeffreyUS | support.WinUAE | 6 | 09 February 2006 01:36 |
|
|