Home | History | Annotate | Line # | Download | only in xxboot
      1  1.13    isaki | $NetBSD: boot.S,v 1.13 2020/08/16 06:43:43 isaki Exp $
      2   1.7    isaki 
      3   1.7    isaki |
      4   1.7    isaki | (1) IPL (or previous stage loader) loads first 1KB of this primary
      5   1.7    isaki |     bootloader to (*).  (*) is 0x2000 (from FD) or 0x2400 (from SASI/SCSI).
      6   1.7    isaki |
      7   1.7    isaki | (2) The first 1KB loads full primary bootloader (including first 1KB) from
      8   1.9    isaki |     the boot partition to 0x3000.  And jump to there.
      9   1.7    isaki |
     10   1.7    isaki | (3) The full primary bootloader loads the secondary bootloader known as
     11   1.7    isaki |     /boot from its filesystem to 0x6000.  And jump to there.
     12   1.7    isaki |
     13   1.7    isaki |       (1)         ->        (2)         ->        (3)
     14   1.7    isaki |  +------------+        +------------+        +------------+    0x000000
     15   1.7    isaki |  :            :        :            :        :            :
     16   1.7    isaki |  +------------+        +------------+        +------------+    (*)
     17   1.7    isaki |  | first 1KB  |        | first 1KB  |        | first 1KB  |
     18   1.7    isaki |  +------------+        +------------+        +------------+    (*)+0x400
     19   1.7    isaki |  :            :        :            :        :            :
     20   1.9    isaki |  :            :        +------------+        +------------+    0x003000
     21   1.9    isaki |  :            :        |full primary|        |full primary|
     22   1.9    isaki |  :            :        |boot loader |        |boot loader |
     23  1.11    isaki |  :            :        |(text+data) |        |(text+data) |
     24  1.11    isaki |  :            :        +------------+        +------------+    0x005000
     25  1.13    isaki |  :            :        |(startregs) |        |(startregs) |
     26  1.11    isaki |  :            :        |(bss)       |        |(bss)       |
     27  1.11    isaki |  :            :        +------------+        +------------+    0x006000
     28   1.7    isaki |  :            :        :            :        | /boot      |
     29   1.7    isaki |  :            :        :            :        +------------+
     30   1.7    isaki |  :            :        :            :        :            :
     31   1.7    isaki |  ~            ~        ~            ~        ~            ~
     32   1.7    isaki |  :            :        :            :<-SP    :            :<-SP
     33   1.9    isaki |  + - - - - - -+        + - - - - - -+        + - - - - - -+    0x100000
     34  1.12    isaki |  :            :        :(heap)      :        :(heap)      :
     35   1.7    isaki |  :            :        :            :        :            :
     36   1.7    isaki |
     37  1.13    isaki | The program code before first_kbyte
     38  1.13    isaki | - must not access any text/data labels after first_kbyte
     39  1.13    isaki |   (because it may not be loaded yet).
     40  1.13    isaki | - must access any labels before first_kbyte by PC relative addressing
     41  1.13    isaki |   (because this loader is assembled as starting from 0x3000 but is loaded
     42  1.13    isaki |   at 0x2000 or 0x2400).
     43  1.13    isaki | - must use RELOC() macro to access bss section (and first_kbyte as a jump
     44  1.13    isaki |   destination address).
     45  1.13    isaki |
     46  1.13    isaki | The program code after first_kbyte can access any labels in all sections
     47  1.13    isaki | directly.
     48   1.1  minoura 
     49   1.1  minoura #include <machine/asm.h>
     50   1.1  minoura #include "iocscall.h"
     51   1.1  minoura 
     52  1.13    isaki #define RELOC(var)	%a5@(((var)-top):W)
     53   1.1  minoura 
     54  1.13    isaki #define BOOT_ERROR(s)	jbsr boot_error; .asciz s; .even
     55   1.1  minoura 
     56  1.13    isaki #define minN	(0)
     57  1.13    isaki #define minC	(1)
     58  1.13    isaki #define minH	(2)
     59  1.13    isaki #define minR	(3)
     60  1.13    isaki #define maxN	(4)
     61  1.13    isaki #define maxC	(5)
     62  1.13    isaki #define maxH	(6)
     63  1.13    isaki #define maxR	(7)
     64  1.13    isaki 
     65  1.13    isaki 		.globl	_C_LABEL(bootmain)
     66  1.13    isaki 		.globl	_C_LABEL(startregs)
     67  1.13    isaki 		.text
     68   1.1  minoura 
     69   1.1  minoura ASENTRY_NOPROFILE(start)
     70   1.1  minoura ASENTRY_NOPROFILE(top)
     71  1.13    isaki 		bras	entry
     72   1.1  minoura 		.ascii	"SHARP/"
     73   1.1  minoura 		.ascii	"X680x0"
     74   1.1  minoura 		.word	0x8199,0x94e6,0x82ea,0x82bd
     75   1.1  minoura 		.word	0x8e9e,0x82c9,0x82cd,0x8cbb
     76   1.1  minoura 		.word	0x8ec0,0x93a6,0x94f0,0x8149
     77  1.13    isaki msg_progname:
     78  1.13    isaki 		| This will be printed on boot_error.  And it also roles
     79  1.13    isaki 		| a signature in binary dump.
     80  1.13    isaki 		| Max length of PROG(without \0) is 14 ("fdboot_ustarfs").
     81  1.13    isaki 		.ascii	"\r\n\n"		| 3
     82  1.13    isaki 		.ascii	PROG			| 14
     83  1.13    isaki 		.asciz	": "			| 2+1
     84  1.13    isaki 		.org	msg_progname + 20
     85  1.13    isaki entry:
     86  1.13    isaki 		jbra	disklabel_end
     87  1.13    isaki 
     88  1.13    isaki 		| Disklabel must be placed at 0x40 and the size is 404 bytes.
     89  1.13    isaki 		| (See LABELOFFSET in <machine/disklabel.h>)
     90   1.5    isaki 		.org	0x40
     91   1.1  minoura disklabel:
     92   1.1  minoura 		.space	404
     93  1.13    isaki disklabel_end:
     94  1.13    isaki 		| At first save all initial registers for observing traces
     95  1.13    isaki 		| of the IPL (or the previous bootloader).  At this point
     96  1.13    isaki 		| we cannot use RELOC() yet so that use absolute addressing.
     97  1.13    isaki 		| To prevent startregs from being cleared by subsequent bss
     98  1.13    isaki 		| initialization, we place it out of bss area.
     99  1.13    isaki 		moveml	%d0-%d7/%a0-%a7,startregs:W
    100  1.13    isaki 
    101  1.13    isaki 		| Initialize the screen.  Some IPL (060turbo ROM or genuine
    102  1.13    isaki 		| boot selector) don't initialize the screen.  It should be
    103  1.13    isaki 		| done as early as possible.
    104  1.13    isaki 		moveql	#0x10,%d1
    105  1.13    isaki 		IOCS(__CRTMOD)
    106   1.1  minoura 
    107  1.13    isaki 		| Set system stack
    108  1.13    isaki 		swap	%d1			| %d1 = 0x0010_0000
    109  1.13    isaki 		moveal	%d1,%sp
    110  1.13    isaki 
    111  1.13    isaki 		| Set base pointer.  Now we can use RELOC() macro.
    112  1.13    isaki 		leal	TEXTADDR:W,%a5
    113  1.13    isaki 
    114  1.13    isaki 		| Initialize bss.
    115  1.13    isaki 		| This code limits bss less than 64KB but it's no matter.
    116  1.13    isaki 		| The bss cannot grow more than 4KB.  See xxboot.ldscript.
    117  1.13    isaki 		leal	RELOC(__bss_start),%a1
    118  1.13    isaki 		movew	#_end - 1,%d0		| bss end
    119  1.13    isaki 
    120  1.13    isaki 		subw	%a1,%d0			| don't change this op!!
    121  1.13    isaki clrbss:						|  see chkmpu below
    122  1.13    isaki 		clrb	%a1@+
    123   1.1  minoura 		dbra	%d0,clrbss
    124   1.1  minoura 
    125  1.13    isaki 		| If it boots from SCSI, %d4 has SCSI ID.
    126  1.13    isaki 		movel	%d4,RELOC(SCSI_ID)
    127   1.1  minoura 
    128  1.13    isaki chkmpu:
    129  1.13    isaki 		| Check MPU beforehand since we want to use 68020 instructions.
    130  1.13    isaki 		| Here the above "subw %a1,%d0" = 0x9049 and %d0.w = -1 at this
    131  1.13    isaki 		| point, so that subsequent moveb loads
    132  1.13    isaki 		|   0x49 if MPU <= 010 (clrbss + %d0.w)
    133  1.13    isaki 		|   0x90 if MPU >= 020 (clrbss + %d0.w*2).
    134  1.13    isaki 		| This is a MOVE op, not a TST op because TST with pc-relative
    135  1.13    isaki 		| is not available on 000/010.
    136  1.13    isaki 		moveb	%pc@(clrbss-chkmpu-2:B,%d0:W:2),%d0
    137  1.13    isaki 		jmi	mpuok
    138  1.13    isaki 		BOOT_ERROR("MPU 68000?");
    139  1.13    isaki mpuok:
    140  1.13    isaki 		|
    141  1.13    isaki 		| Check where did I boot from.
    142  1.13    isaki 		|
    143  1.13    isaki 		IOCS(__BOOTINF)
    144  1.13    isaki 		movel	%d0,RELOC(BOOT_INFO)	| save whole result
    145   1.1  minoura 
    146  1.13    isaki 		| %d0 = 0xHHWWWWWW
    147   1.1  minoura 		|
    148  1.13    isaki 		| HH:     how did I boot (powersw or alarm etc)
    149  1.13    isaki 		| WWWWWW: where did I boot from
    150  1.13    isaki 		|  0x80...0x8f		SASI
    151  1.13    isaki 		|  0x90...0x93		Floppy
    152  1.13    isaki 		|  0xed0000...0xed3ffe	SRAM
    153  1.13    isaki 		|  others		ROM (maybe SCSI)
    154  1.13    isaki 
    155  1.13    isaki 		bfextu	%d0{#8:#8},%d1
    156  1.13    isaki 		jne	boot_rom_ram		| ROM or SRAM
    157  1.13    isaki 		| FALLTHROUGH			| SASI or Floppy
    158  1.13    isaki 
    159  1.13    isaki boot_sasi_floppy:
    160  1.13    isaki 		| Floppy or SASI
    161  1.13    isaki 		cmpiw	#0x90,%d0
    162  1.13    isaki 		jlt	boot_dev_not_supp	| SASI
    163  1.13    isaki 
    164  1.13    isaki 		|
    165  1.13    isaki 		| Boot from floppy
    166  1.13    isaki 		|
    167  1.13    isaki boot_floppy:
    168  1.13    isaki 		| Make PDA+MODE
    169  1.13    isaki 		lslw	#8,%d0			| %d0=$00009X00 (X is unit#)
    170  1.13    isaki 		moveql	#0x70,%d1
    171  1.13    isaki 		orw	%d0,%d1			| %d1=$00009X70 = (PDA<<8)+MODE
    172  1.13    isaki 		movel	%d1,RELOC(FDMODE)
    173  1.13    isaki check_fd_format:
    174  1.13    isaki 		| Check fd format.
    175  1.13    isaki 		| Obtain min & max sector # of track(cylinder) 0.
    176  1.13    isaki 		| On x68k, we can consider only double-sided floppy.
    177  1.13    isaki 		moveql	#0,%d2
    178  1.13    isaki init_loop:
    179  1.13    isaki 		| On 1st time, clear %d3-%d5 with zero.
    180  1.13    isaki 		| On 2nd time, initialize %d3-%d5 with first %d2.
    181  1.13    isaki 		movel	%d2,%d3			| %d3: initial NCHR
    182  1.13    isaki 		movel	%d2,%d4			| %d4: minimum NCHR
    183  1.13    isaki 		movel	%d2,%d5			| %d5: maximum NCHR
    184  1.13    isaki loop:
    185  1.13    isaki 		| B_READID with MSB of %d2 set obtains detected CHRN to %d2.
    186  1.13    isaki 		moveql	#1,%d2			| %d2 = 0x00000001
    187  1.13    isaki 		rorl	#1,%d2			| %d2 = 0x80000000
    188  1.13    isaki 		IOCS(__B_READID)
    189  1.13    isaki 						| %d2 = 0xCCHHRRNN
    190  1.13    isaki 		rorl	#8,%d2			| %d2 = 0xNNCCHHRR
    191  1.13    isaki 
    192  1.13    isaki 		| On 1st time, goto init_loop with %d2 (%d2 is not zero).
    193  1.13    isaki 		| On 2nd time, fall through because %d3 is not zero.
    194  1.13    isaki 		tstl	%d3
    195  1.13    isaki 		jeq	init_loop
    196  1.13    isaki 
    197  1.13    isaki 		cmpl	%d4,%d2			| if (%d2 < %d4)
    198  1.13    isaki 		jge	1f			|
    199  1.13    isaki 		movel	%d2,%d4			|  min = %d2
    200  1.13    isaki 1:
    201  1.13    isaki 		cmpl	%d5,%d2			| if (%d2 > %d5)
    202  1.13    isaki 		jle	1f			|
    203  1.13    isaki 		movel	%d2,%d5			|  max = %d2
    204  1.13    isaki 1:
    205  1.13    isaki 		cmpl	%d3,%d2			| if (%d2 == %d3) break
    206  1.13    isaki 		jne	loop
    207  1.13    isaki 
    208  1.13    isaki 		| Assume 2HD
    209  1.13    isaki 		oriw	#0x0100,%d5		| FDSEC.maxsec.H = 1
    210  1.13    isaki 		moveml	%d4-%d5,RELOC(FDSEC)	| Store
    211  1.13    isaki 		| end of check_fd_format
    212  1.13    isaki 
    213  1.13    isaki 		| read 8KB myself from floppy
    214  1.13    isaki 						| %d1: (PDA<<8)+MODE already
    215  1.13    isaki 		movel	%d4,%d2			| %d2: read pos = first sector
    216  1.13    isaki 		moveql	#0x20,%d3		| %d3: read bytes = (0x20 << 8)
    217  1.13    isaki 		lsll	#8,%d3			|  = 0x2000 = 8192
    218  1.13    isaki 		leal	%a5@,%a1		| %a1: dest buffer
    219  1.13    isaki 		IOCS(__B_READ)
    220   1.1  minoura 
    221  1.13    isaki 		| Jump to full parimary loader
    222  1.13    isaki 		jmp	RELOC(first_kbyte)
    223  1.13    isaki 
    224  1.13    isaki boot_rom_ram:
    225  1.13    isaki 		| ROM(SCSI) or SRAM
    226  1.13    isaki 		cmpib	#0xed,%d1
    227  1.13    isaki 		jeq	boot_dev_not_supp	| SRAM
    228   1.1  minoura 
    229   1.1  minoura 		|
    230  1.13    isaki 		| Boot from SCSI
    231   1.1  minoura 		|
    232  1.13    isaki boot_scsi:
    233  1.13    isaki 		| get block length of the SCSI disk
    234  1.13    isaki 		leal	RELOC(SCSI_CAP),%a1
    235  1.13    isaki 		SCSIIOCS(__S_READCAP)
    236  1.13    isaki 		tstl	%d0
    237  1.13    isaki 		jeq	boot_scsi1
    238  1.13    isaki 		BOOT_ERROR("READCAP failed")
    239  1.13    isaki boot_scsi1:
    240  1.13    isaki 		movel	RELOC(SCSI_CAP+4),%d0	| %d0 = blocksize in bytes
    241  1.13    isaki 		lsrl	#2,%d0			| %d0 = blocksize in longword
    242  1.13    isaki 		moveql	#25,%d5
    243  1.13    isaki 		bfffo	%d0{#0:#32},%d1		| 25:256 24:512 23:1024 22:2048
    244  1.13    isaki 		subl	%d1,%d5			|  0:256  1:512  2:1024  3:2048
    245  1.13    isaki 		movel	%d5,RELOC(SCSI_BLKLEN)	| %d5 = sector length index
    246  1.13    isaki 
    247  1.13    isaki 		| Find out the start position of the boot partition.
    248  1.13    isaki 		| There seems to be no interface or consensus about this and
    249  1.13    isaki 		| so that we would have to do it heuristicly.
    250   1.1  minoura 		|
    251  1.13    isaki 		| ROM firmware:
    252  1.13    isaki 		|	pass read pos (in block #, aka sector #) in %d2.
    253  1.13    isaki 		|	Human68k-style partition table does not exist.
    254  1.13    isaki 		|	%d2 is 4 at the maximum.
    255  1.13    isaki 		| SCSI IPLs (genuine and SxSI):
    256  1.13    isaki 		|	pass read pos (in kilobytes) in %d2.
    257  1.13    isaki 		|	%d2 is bigger than 0x20.
    258  1.13    isaki 		|	partition table on the memory is destroyed.
    259  1.13    isaki 		| BOOT MENU Ver.2.22:
    260  1.13    isaki 		|	passes partition table entry address in %a0.
    261  1.13    isaki 		|	%d2 is cleared to zero
    262  1.13    isaki 		| No other IPLs are supported.
    263  1.13    isaki 
    264  1.13    isaki 		tstl	%d2
    265  1.13    isaki 		jne	1f
    266  1.13    isaki 		| If no information in %d2, probably from BOOT MENU.
    267  1.13    isaki 		| %a0 points the on-memory partition table entry.
    268  1.13    isaki 		movel	%a0@(0x0008),%d2	| %d2 = pos in kbyte
    269  1.13    isaki 1:
    270  1.13    isaki 		moveql	#0x20,%d3
    271  1.13    isaki 		cmpl	%d3,%d2
    272  1.13    isaki 		jcs	1f			| jump if %d2 > 0x20
    273  1.13    isaki 		| SCSI IPL or BOOT MENU.
    274  1.13    isaki 		| At this point, %d2 is pos in kbyte in all cases.
    275  1.13    isaki 		lsll	#8,%d2			| %d2 = pos in longword
    276  1.13    isaki 		divul	%d0,%d2			| %d2 = pos in sector
    277  1.13    isaki 1:
    278  1.13    isaki 		| At this point, %d2 is pos in sector in all cases.
    279  1.13    isaki 		| TDSIZE = 8192, TDSIZE / 4 = 0x800 = (0x20 << 6).
    280  1.13    isaki 		lsll	#6,%d3			| %d3 = TDSIZE in longword
    281  1.13    isaki 		divul	%d0,%d3			| %d0 = TDSIZE in sector
    282  1.13    isaki 		| Read full primary bootloader
    283  1.13    isaki 		moveal	%a5,%a1			| %a1 = dest buffer
    284  1.13    isaki 		jbsr	scsiread
    285  1.13    isaki 
    286  1.13    isaki 		| Selected start sector should not <= 4.  There should be
    287  1.13    isaki 		| partition table.  If so, repoints to zero(?).
    288  1.13    isaki 		moveql	#5,%d0
    289  1.13    isaki 		cmpl	%d0,%d2
    290  1.13    isaki 		bcc	1f
    291  1.13    isaki 		moveql	#0,%d2
    292  1.13    isaki 1:
    293  1.13    isaki 		movel	%d2,RELOC(SCSI_PARTTOP)
    294  1.13    isaki 
    295  1.13    isaki 		| Jump to full parimary loader
    296  1.13    isaki 		jmp	RELOC(first_kbyte)
    297  1.13    isaki 
    298  1.13    isaki |
    299  1.13    isaki | scsiread
    300  1.13    isaki |	Read SCSI disk using __S_READ as possible.  If __S_READ cannot be
    301  1.13    isaki |	used (due to read length or offset), use __S_READEXT instead.
    302  1.13    isaki | input:
    303  1.13    isaki |	%d2.l: pos in sector
    304  1.13    isaki |	%d3.l: len in sector (must be < 65536)
    305  1.13    isaki |	%d4.l: target SCSI ID
    306  1.13    isaki |	%d5.l: sector length index (0:256, 1:512, 2:1024, 3:2048, ...)
    307  1.13    isaki |	%a1.l: buffer address
    308  1.13    isaki | destroy:
    309  1.13    isaki |	%d0,%d1
    310  1.13    isaki scsiread:
    311  1.13    isaki 		| if (len >= 256 || pos + len >= 0x200000)
    312  1.13    isaki 		|   use READEXT
    313  1.13    isaki 		| else
    314  1.13    isaki 		|   use READ
    315  1.13    isaki 
    316  1.13    isaki 		moveql	#__S_READEXT,%d1
    317   1.1  minoura 
    318  1.13    isaki 		cmpiw	#256,%d3
    319  1.13    isaki 		jge	scsiread_core		| if (d3 >= 256) use READEXT
    320   1.1  minoura 
    321  1.13    isaki 		movel	%d2,%d0
    322  1.13    isaki 		addl	%d3,%d0			| %d0 = pos + len
    323  1.13    isaki 		jcs	scsiread_core		| if overflow, use READEXT
    324  1.13    isaki 		bftst	%d0{#0:#11}		| if (pos + len >= 0x200000)
    325  1.13    isaki 		jne	scsiread_core		|  use REAEXT
    326  1.13    isaki 
    327  1.13    isaki 		moveql	#__S_READ,%d1		| else use READ
    328  1.13    isaki scsiread_core:
    329  1.13    isaki 		IOCS(__SCSIDRV)
    330  1.13    isaki 		rts
    331   1.1  minoura 
    332  1.13    isaki boot_dev_not_supp:
    333  1.13    isaki 		BOOT_ERROR("not supported device");
    334   1.1  minoura 
    335   1.1  minoura |
    336  1.13    isaki | void __dead BOOT_ERROR(const char *msg);
    337  1.13    isaki |	Print an error message, wait for key press, and reboot.
    338  1.13    isaki |	Called from C.
    339  1.13    isaki ENTRY_NOPROFILE(BOOT_ERROR)
    340  1.13    isaki 		addql	#4,%sp			| throw away return address
    341  1.13    isaki 		| FALLTHROUGH
    342   1.1  minoura |
    343  1.13    isaki | BOOT_ERROR(msg)
    344  1.13    isaki |	Print an error message, wait for key press, and reboot.
    345  1.13    isaki |	Called from asm.
    346  1.13    isaki boot_error:
    347  1.13    isaki 		leal	%pc@(msg_progname),%a1
    348   1.1  minoura 		IOCS(__B_PRINT)
    349   1.1  minoura 		moveal	%sp@+,%a1
    350   1.1  minoura 		IOCS(__B_PRINT)
    351   1.1  minoura ENTRY_NOPROFILE(exit)
    352   1.1  minoura ENTRY_NOPROFILE(_rtt)
    353  1.13    isaki 		leal	%pc@(msg_reboot),%a1
    354   1.1  minoura 		IOCS(__B_PRINT)
    355   1.1  minoura 
    356   1.1  minoura 		| wait for a key press (or release of a modifier)
    357   1.1  minoura 		IOCS(__B_KEYINP)
    358   1.1  minoura 
    359   1.1  minoura 		| issue software reset
    360   1.1  minoura 		trap	#10
    361   1.1  minoura 		| NOTREACHED
    362  1.13    isaki msg_reboot:
    363  1.13    isaki 		.asciz	"\r\n[Hit key to reboot]"
    364  1.13    isaki 		.even
    365   1.1  minoura 
    366   1.1  minoura 		.globl	first_kbyte
    367   1.1  minoura first_kbyte:
    368   1.1  minoura |--------------------------------------------------------------------------
    369   1.1  minoura |
    370  1.13    isaki #if defined(SELFTEST)
    371  1.13    isaki 		jbsr	selftest_ashldi3
    372  1.13    isaki 		jbsr	selftest_ashrdi3
    373  1.13    isaki 		jbsr	selftest_memcmp
    374  1.13    isaki 		jbsr	selftest_memmove
    375  1.13    isaki 		jbsr	selftest_memset
    376  1.13    isaki #endif
    377   1.6    isaki 
    378  1.13    isaki 		jmp	_C_LABEL(bootmain)
    379  1.13    isaki 		| NOTREACHED
    380   1.1  minoura 
    381  1.13    isaki |
    382  1.13    isaki | uint32_t badbadd(void *addr)
    383  1.13    isaki |	returns 1 if reading addr occurs bus error.  Otherwise it returns 0.
    384   1.1  minoura ENTRY_NOPROFILE(badbaddr)
    385  1.13    isaki 		leal	0x0008:W,%a1		| bus error vector
    386  1.13    isaki 		moveql	#1,%d0
    387  1.13    isaki 		leal	%pc@(badbaddr1),%a0
    388   1.1  minoura 		movew	%sr,%sp@-
    389   1.1  minoura 		oriw	#0x0700,%sr		| keep out interrupts
    390   1.1  minoura 		movel	%a1@,%sp@-
    391   1.1  minoura 		movel	%a0,%a1@		| set bus error vector
    392   1.1  minoura 		movel	%sp,%d1			| save sp
    393   1.1  minoura 		moveal	%sp@(10),%a0
    394   1.1  minoura 		tstb	%a0@			| try read...
    395  1.13    isaki 		moveql	#0,%d0			| this is skipped on bus error
    396  1.13    isaki badbaddr1:
    397  1.13    isaki 		moveal	%d1,%sp			| restore sp
    398   1.1  minoura 		movel	%sp@+,%a1@
    399   1.1  minoura 		movew	%sp@+,%sr
    400   1.1  minoura 		rts
    401   1.1  minoura 
    402  1.13    isaki |
    403  1.13    isaki | int raw_read(uint32_t blkpos, uint32_t bytelen, void *buf)
    404  1.13    isaki |	blkpos:  read start position in 512 byte block unit (always?).
    405  1.13    isaki |	bytelen: read length in bytes.
    406  1.13    isaki |	         caller already avoids bytelen == 0 so that no checks here.
    407  1.13    isaki |	         must be a multiple of sector size on scsi.
    408  1.13    isaki |	buf:     destination buffer address
    409  1.13    isaki |
    410  1.13    isaki ENTRY_NOPROFILE(raw_read)
    411  1.13    isaki 		moveal	%sp,%a1
    412   1.1  minoura 		moveml	%d2-%d7/%a2-%a6,%sp@-
    413  1.13    isaki 		moveml	%a1@,%d0/%d2-%d3/%a1	| %d0 (return address)
    414  1.13    isaki 						| %d2 blkpos
    415  1.13    isaki 						| %d3 bytelen
    416  1.13    isaki 						| %a1 buf
    417  1.13    isaki 		| At this point boot device is either floppy or SCSI.
    418  1.13    isaki 		tstb	%pc@(BOOT_INFO+1)
    419  1.13    isaki 		jeq	raw_read_floppy
    420  1.13    isaki 		| FALLTHROUGH
    421   1.1  minoura 
    422   1.1  minoura raw_read_scsi:
    423  1.13    isaki 						| %d2 = pos from device top
    424  1.13    isaki 						|  in 512 bytes/block
    425  1.13    isaki 		lsll	#1,%d2			| %d2 = in 256 bytes/block
    426  1.13    isaki 		movel	%pc@(SCSI_BLKLEN),%d5	| %d5 = sector length index
    427  1.13    isaki 		lsrl	%d5,%d2			| %d2 = pos from device top
    428  1.13    isaki 						|  in media sector size
    429   1.1  minoura 
    430  1.13    isaki 		divull	%pc@(SCSI_CAP+4),%d0:%d3| %d3 = bytelen / sectsize
    431  1.13    isaki 						| %d0 = bytelen % sectsize
    432  1.13    isaki 		tstl	%d0
    433  1.13    isaki 		jeq	.Lraw1
    434  1.13    isaki 		BOOT_ERROR("Err1")		| ASSERT(bytelen%sectsize==0)
    435  1.13    isaki .Lraw1:
    436  1.13    isaki 		movel	%pc@(SCSI_ID),%d4	| %d4 = SCSI ID
    437   1.1  minoura 		jbsr	scsiread
    438  1.13    isaki 
    439  1.13    isaki raw_read_exit:
    440  1.13    isaki 		moveml	%sp@+,%d2-%d7/%a2-%a6
    441  1.13    isaki 		rts
    442   1.1  minoura 
    443   1.1  minoura raw_read_floppy:
    444  1.13    isaki 		| nhead = FDSEC.maxsec.H - FDSEC.minsec.H + 1
    445  1.13    isaki 		|       = 2;
    446  1.13    isaki 		| nsect = FDSEC.maxsec.R - FDSEC.minsec.R + 1;
    447  1.13    isaki 		|
    448  1.13    isaki 		| sect = (blkpos % nsect) + FDSEC.minsec.R;
    449  1.13    isaki 		| head = ((blkpos / nsect) % nhead) + FDSEC.minsec.H;
    450  1.13    isaki 		| cyl  = ((blkpos / nsect) / nhead) + FDSEC.minsec.C;
    451  1.13    isaki 		|
    452  1.13    isaki 		| NCHR = (FDSEC.minsec.N << 24) |
    453  1.13    isaki 		|      (cyl << 16) |
    454  1.13    isaki 		|      (head << 8) |
    455  1.13    isaki 		|      sect;
    456  1.13    isaki 
    457  1.13    isaki 		| calc nsect.
    458  1.13    isaki 		moveql	#1,%d0			| %d0 = 1
    459  1.13    isaki 		addb	%pc@(FDSEC+maxR),%d0	| %d0 = 1 + maxsec.R
    460  1.13    isaki 		subb	%pc@(FDSEC+minR),%d0	| %d0 = 1 + maxsec.R - minsec.R
    461  1.13    isaki 						|     = nsect
    462  1.13    isaki 
    463  1.13    isaki 		| Convert blkpos to N/C/H/R.
    464  1.13    isaki 		divuw	%d0,%d2			| %d2.hw = blkpos % nsect
    465  1.13    isaki 						| %d2.lw = blkpos / nsect
    466  1.13    isaki 		| Here, %d2.hw becomes sector number and .lw becomes cyl+head.
    467  1.13    isaki 		| %d2.lw = %0000_0000_CCCC_CCCH in binary form.  LSB of
    468  1.13    isaki 		| (blkpos / nsect) is head number because we support only
    469  1.13    isaki 		| double-sided floppy here.
    470  1.13    isaki 						| %d2.w = %0000_0000_CCCC_CCCH
    471  1.13    isaki 		lslw	#7,%d2			| %d2.w = %0CCC_CCCC_H000_0000
    472  1.13    isaki 		lsrb	#7,%d2			| %d2.w = %0CCC_CCCC_0000_000H
    473  1.13    isaki 						| i.e,
    474  1.13    isaki 						| %d2 = $00rrCCHH
    475  1.13    isaki 		swap	%d2			| %d2 = $CCHH00rr
    476  1.13    isaki 		lslw	#8,%d2			| %d2 = $CCHHrr00
    477  1.13    isaki 		| two bytes from odd FDSEC+minR is (minR << 8 | maxN) and
    478  1.13    isaki 		| minN == maxN always.
    479  1.13    isaki 		addw	%pc@(FDSEC+minR),%d2	| %d2 = $CCHHRRNN
    480  1.13    isaki 		rorl	#8,%d2			| %d2 = $NNCCHHRR
    481   1.1  minoura 
    482  1.13    isaki 		movel	%pc@(FDMODE),%d1	| %d1 = PDA+MODE
    483   1.1  minoura 		IOCS(__B_READ)
    484  1.13    isaki 		andil	#0xf8ffff00,%d0		| Check status (must be zero)
    485  1.13    isaki 		jeq	raw_read_exit
    486  1.13    isaki 		BOOT_ERROR("B_READ failed");
    487  1.13    isaki 
    488  1.13    isaki |
    489  1.13    isaki | BSS
    490  1.13    isaki |
    491  1.13    isaki 		BSS(BOOT_INFO, 4)	| whole result of IOCS BOOTINF
    492  1.13    isaki 
    493  1.13    isaki 		BSS(FDMODE, 4)
    494  1.13    isaki 		BSS(FDSEC, 8)		| +0: (minN) sector length
    495  1.13    isaki 					| +1: (minC) track number
    496  1.13    isaki 					| +2: (minH) head
    497  1.13    isaki 					| +3: (minR) sector number
    498  1.13    isaki 					| +4: (maxN) sector length
    499  1.13    isaki 					| +5: (maxC) track number
    500  1.13    isaki 					| +6: (maxH) head
    501  1.13    isaki 					| +7: (maxR) sector number
    502  1.13    isaki 
    503  1.13    isaki 		BSS(SCSI_ID, 4)		| SCSI ID, if booted from SCSI
    504  1.13    isaki 		BSS(SCSI_CAP, 8)	| result of SCSI READCAP
    505  1.13    isaki 					|  +0.L: total number of logical blocks
    506  1.13    isaki 					|  +4.L: block length in bytes
    507  1.13    isaki 		BSS(SCSI_PARTTOP, 4)	| top sector # of this partition
    508  1.13    isaki 		BSS(SCSI_BLKLEN ,4)	| sector length index
    509  1.13    isaki 					|  0:256, 1:512, 2:1024, 3:2048, ..
    510