English Amiga Board


Go Back   English Amiga Board > Coders > Coders. System

 
 
Thread Tools
Old 26 October 2018, 15:39   #1
Keir
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
Keir is offline  
Old 26 October 2018, 17:11   #2
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by kaffer View Post
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.
I've faced the same problem.
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.
ross is offline  
Old 27 October 2018, 07:58   #3
Keir
Registered User
 
Join Date: May 2011
Location: Cambridge
Posts: 682
Quote:
Originally Posted by ross View Post
I've faced the same problem.
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.
Bah I will try out some other options first... thank you!
Keir is offline  
Old 27 October 2018, 09:03   #4
Keir
Registered User
 
Join Date: May 2011
Location: Cambridge
Posts: 682
Quote:
Originally Posted by kaffer View Post
Bah I will try out some other options first... thank you!
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.
Keir is offline  
Old 27 October 2018, 09:31   #5
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by kaffer View Post
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.
Nice find

Quote:
This is a bit of a pain in the arse in asm but luckily I can wait until I'm in C.
This is the reason why I wrote that it is the easiest way I had found.
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
Sorry, I've not converted offsets to labels but sure you can find it in .i files.

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.
ross is offline  
Old 27 October 2018, 10:18   #6
Keir
Registered User
 
Join Date: May 2011
Location: Cambridge
Posts: 682
Quote:
Originally Posted by ross View Post
This is the reason why I wrote that it is the easiest way I had found.
Yes, is *bah* but works.
(I needed this in a multi-floppy multi-drives non-system compliant game, so a tag is anyway required )
Yes I think for handover to a custom loader your approach makes lots of sense, you just care about finding your boot disk in some drive. Filtered by available drives with a disk inserted is going to be typically fast.

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?
Keir is offline  
Old 27 October 2018, 11:26   #7
StingRay
move.l #$c0ff33,throat
 
StingRay's Avatar
 
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
Quote:
Originally Posted by kaffer View Post
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.

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
StingRay is offline  
Old 27 October 2018, 11:34   #8
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by StingRay View Post
Here's my quick and dirty 5 minutes code to test this:
Thanks StingRay, you preceded me, I was engaged in some sprites oddities
ross is offline  
Old 27 October 2018, 11:37   #9
StingRay
move.l #$c0ff33,throat
 
StingRay's Avatar
 
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.
StingRay is offline  
Old 27 October 2018, 11:39   #10
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by kaffer View Post
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?
*coff* old code *coff*
Sure works in every existing kickstart.
ross is offline  
Old 27 October 2018, 11:46   #11
Keir
Registered User
 
Join Date: May 2011
Location: Cambridge
Posts: 682
Quote:
Originally Posted by StingRay View Post
That does indeed seem to work, very nice. Here's my quick and dirty 5 minutes code to test this:
For production use, how much would you say this needs to be cleaned up? eg. my C code version is at least as many lines as this asm, but then it does everything the PRM-mandated way: allocates a signal for the port, initialises (more) port and ioreq fields, CloseDevice after successful OpenDevice (else the port and ioreq end up associated with multiple open device handles). This is what made this method seem such a pain. That said I bet your asm could be extended to do this stuff without as much pain as I first suspected...

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;
}
Keir is offline  
Old 27 October 2018, 12:01   #12
StingRay
move.l #$c0ff33,throat
 
StingRay's Avatar
 
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
Quote:
Originally Posted by kaffer View Post
For production use, how much would you say this needs to be cleaned up?

For bootblock use I think there only need to be CloseDevice() calls added, the rest should be fine.
StingRay is offline  
Old 27 October 2018, 12:09   #13
Keir
Registered User
 
Join Date: May 2011
Location: Cambridge
Posts: 682
Quote:
Originally Posted by StingRay View Post
For bootblock use I think there only need to be CloseDevice() calls added, the rest should be fine.
That's really not so bad then, and I agree that seems reasonable since no I/O gets issued on the IOReq.

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
Keir is offline  
Old 27 October 2018, 13:54   #14
StingRay
move.l #$c0ff33,throat
 
StingRay's Avatar
 
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
Quote:
It would be pretty simple to find valid drives by:
Or simply also use trackdisk for that as well. I have extended my code a bit, it now uses CloseDevice() and determines the boot disk, the number of available drives and which drives are available.

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
StingRay is offline  
Old 27 October 2018, 15:00   #15
Keir
Registered User
 
Join Date: May 2011
Location: Cambridge
Posts: 682
Quote:
Originally Posted by StingRay View Post
Or simply also use trackdisk for that as well. I have extended my code a bit, it now uses CloseDevice() and determines the boot disk, the number of available drives and which drives are available.
Very elegant sir. I'm going to squirrel this away for future reference.
Keir is offline  
Old 12 February 2023, 20:30   #16
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
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
Photon is offline  
Old 15 February 2023, 07:17   #17
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,215
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.
Thomas Richter is offline  
Old 15 February 2023, 12:33   #18
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,039
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
Preemptive: Don't use that code, it causes global warming and woke apocalypse.
a/b is offline  
Old 15 February 2023, 21:04   #19
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by a/b View Post
Preemptive: Don't use that code, it causes global warming and woke apocalypse.
You convinced me, next time I'll use it
ross is offline  
Old 15 February 2023, 23:52   #20
Photon
Moderator
 
Photon's Avatar
 
Join Date: Nov 2004
Location: Eksjö / Sweden
Posts: 5,602
Quote:
Originally Posted by a/b View Post
This is what I've been using
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.
Photon is offline  
 


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

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 05:54.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.12990 seconds with 13 queries