Port-atari archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Revive Milan support



I wrote:
> Current status:
> - only 16MB RAM is works; see the original leo@'s post back in 2001:
>   http://mail-index.netbsd.org/port-atari/2001/06/07/0000.html
 :
> TODO:
> - probe whole RAM on all four SIMMs
>   (needs info about physcal address mappings)

After investigating MMU and page table settings by the Milan's bootloader,
it turns out that each bank in each SIMM slot has the following
physical address retions:

0x00000000- : SLOT 0 BANK 0
0x04000000- : SLOT 1 BANK 0
0x08000000- : SLOT 2 BANK 0
0x0C000000- : SLOT 3 BANK 0
0x10000000- : SLOT 0 BANK 1
0x14000000- : SLOT 1 BANK 1
0x18000000- : SLOT 2 BANK 1
0x1C000000- : SLOT 3 BANK 1

Milan's ROM bootloader also stores SIMM info at 0x00000714 like:

32MB x4:  00000710: 00 df e0 00 33 33 33 33
128MB x1: 00000710: 00 df e0 00 50 00 50 00
128MB x3: 00000710: 00 df e0 00 55 50 55 50

Each nibble may indicate 4MB=1, 8MB=2, 16MB=3, 32MB=4, 64MB=5.
(Note 0x00dfe000 is an address of %srp and %urp, i.e. MMU L1 table)

However, to use SIMMs info set by ROM bootloader we have to change
both kernel and NetBSD bootloader to pass it.
Instead, I write dumb memory probe routines for Milan to avoid
API changes, and it seems working with multiple SIMMs, 128MBx3 and
16MBx4 settings.

Not 128MBx4 SIMMs causes TOS loading errors on ROM bootloader.
128MBx3 work fine.

I'm not sure how many Milan users in the world, but I'll commit
the changes soon.

Index: atari/atari_init.c
===================================================================
RCS file: /cvsroot/src/sys/arch/atari/atari/atari_init.c,v
retrieving revision 1.100
diff -u -p -d -r1.100 atari_init.c
--- atari/atari_init.c	10 Aug 2012 17:43:32 -0000	1.100
+++ atari/atari_init.c	9 Feb 2018 15:40:13 -0000
@@ -91,9 +91,26 @@ static void set_machtype(void);
 static void mmu040_setup(paddr_t, u_int, paddr_t, psize_t, paddr_t, paddr_t);
 #endif
 
+#if defined(_MILANHW_)
+static u_int milan_probe_bank_1(paddr_t paddr);
+static u_int milan_probe_bank(paddr_t paddr);
+
+#define NBANK	2
+#define NSLOT	4
+
+#define MB(n)		((n) * 1024 * 1024)
+#define MB_END(n)	(MB(n) - 1)
+#define MAGIC_4M	(4 - 1)
+#define MAGIC_4M_INV	((uint8_t)~MAGIC_4M)
+#define MAGIC_8M	(8 - 1)
+#define MAGIC_16M	(16 - 1)
+#define MAGIC_32M	(32 - 1)
+#define MAGIC_64M	(64 - 1)
+#endif
+
 /*
  * Extent maps to manage all memory space, including I/O ranges.  Allocate
- * storage for 8 regions in each, initially.  Later, iomem_malloc_safe
+ * storage for 16 regions in each, initially.  Later, iomem_malloc_safe
  * will indicate that it's safe to use malloc() to dynamically allocate
  * region descriptors.
  * This means that the fixed static storage is only used for registrating
@@ -102,7 +119,7 @@ static void mmu040_setup(paddr_t, u_int,
  * The extent maps are not static!  They are used for bus address space
  * allocation.
  */
-static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
+static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)];
 struct extent *iomem_ex;
 int iomem_malloc_safe;
 
@@ -204,23 +221,67 @@ start_c(int id, u_int ttphystart, u_int 
 	paddr_t		kbase;
 	u_int		kstsize;
 	paddr_t		Sysptmap_pa;
-
 #if defined(_MILANHW_)
-	/* XXX
-	 * XXX The right place todo this is probably the booter (Leo)
-	 * XXX More than 16MB memory is not yet supported on the Milan!
+	/*
 	 * The Milan Lies about the presence of TT-RAM. If you insert
 	 * 16MB it is split in 14MB ST starting at address 0 and 2MB TT RAM,
-	 * starting at address 16MB. 
+	 * starting at address 16MB as the BIOS remapping memory using MMU.
+	 *
+	 * Milan actually has four SIMM slots and each slot has two banks,
+	 * so it could have up to 8 memory segment regions.
 	 */
-	stphysize += ttphysize;
-	ttphysize  = ttphystart = 0;
-#endif
+	const paddr_t simm_base[NBANK][NSLOT] = {
+		/* slot 0-3, bank 0 */
+		{ 0x00000000, 0x04000000, 0x08000000, 0x0c000000 },
+		/* slot 0-3, bank 1 */
+		{ 0x10000000, 0x14000000, 0x18000000, 0x1c000000 }
+	};
+	int slot, bank, seg;
+	u_int mb;
+
+	/* On Milan, all RAMs are fast 32 bit so no need to reloc kernel */
+	reloc_kernel = 0;
+
+	/* probe memory region in all SIMM slots and banks */
+	seg = 0;
+	ttphysize = 0;
+	for (bank = 0; bank < 2; bank++) {
+		for (slot = 0; slot < 4; slot++) {
+			if (bank == 0 && slot == 0) {
+				/*
+				 * The first bank has at least 16MB because
+				 * the Milan's ROM bootloader requires it
+				 * to allocate ST RAM.
+				 */
+				mb = milan_probe_bank_1(simm_base[bank][slot]);
+				boot_segs[0].start = 0;
+				boot_segs[0].end   = MB(mb);
+				stphysize          = MB(mb);
+				seg++;
+			} else {
+				/*
+				 * The rest banks could be empty or
+				 * have 4, 8, 16, 32, or 64MB.
+				 */
+				mb = milan_probe_bank(simm_base[bank][slot]);
+				if (mb > 0) {
+					boot_segs[seg].start =
+					    simm_base[bank][slot];
+					boot_segs[seg].end   =
+					    simm_base[bank][slot] + MB(mb);
+					ttphysize += MB(mb);
+					seg++;
+				}
+			}
+		}
+	}
+#else /* _MILANHW_ */
 	boot_segs[0].start       = 0;
 	boot_segs[0].end         = stphysize;
 	boot_segs[1].start       = ttphystart;
 	boot_segs[1].end         = ttphystart + ttphysize;
 	boot_segs[2].start = boot_segs[2].end = 0; /* End of segments! */
+#endif
 
 	/*
 	 * The following is a hack. We do not know how much ST memory we
@@ -484,10 +545,21 @@ start_c(int id, u_int ttphystart, u_int 
 	usable_segs[0].start = 0;
 	usable_segs[0].end   = stphysize;
 	usable_segs[0].free_list = VM_FREELIST_STRAM;
+#if defined(_MILANHW_)
+	for (i = 1; i < seg; i++) {
+		usable_segs[i].start = boot_segs[i].start;
+		usable_segs[i].end   = boot_segs[i].end;
+		usable_segs[i].free_list = VM_FREELIST_TTRAM;
+	}
+	for (; i < NMEM_SEGS; i++) {
+		usable_segs[i].start = usable_segs[i].end = 0;
+	}
+#else
 	usable_segs[1].start = ttphystart;
 	usable_segs[1].end   = ttphystart + ttphysize;
 	usable_segs[1].free_list = VM_FREELIST_TTRAM;
 	usable_segs[2].start = usable_segs[2].end = 0; /* End of segments! */
+#endif
 
 	if (kbase) {
 		/*
@@ -506,7 +578,7 @@ start_c(int id, u_int ttphystart, u_int 
 	 * available physical memory.
 	 */
 	usable_segs[0].first_page = 0;
-	for (i = 1; usable_segs[i].start; i++) {
+	for (i = 1; i < NMEM_SEGS && usable_segs[i].start; i++) {
 		usable_segs[i].first_page  = usable_segs[i-1].first_page;
 		usable_segs[i].first_page +=
 		    (usable_segs[i-1].end - usable_segs[i-1].start) / PAGE_SIZE;
@@ -609,7 +681,7 @@ start_c(int id, u_int ttphystart, u_int 
 	/*
 	 * Allocate the physical RAM from the extent map
 	 */
-	for (i = 0; boot_segs[i].end != 0; i++) {
+	for (i = 0; i < NMEM_SEGS && boot_segs[i].end != 0; i++) {
 		if (extent_alloc_region(iomem_ex, boot_segs[i].start,
 		    boot_segs[i].end - boot_segs[i].start, EX_NOWAIT)) {
 			/* XXX: Ahum, should not happen ;-) */
@@ -624,6 +696,151 @@ start_c(int id, u_int ttphystart, u_int 
 	intr_init();
 }
 
+#if defined(_MILANHW_)
+/*
+ * Probe and return available memory size in MB at specfied address.
+ * The first slot SIMM have at least 16MB, so check if it has 32 or 64 MB.
+ *
+ * Note it seems Milan does not generate bus errors on accesses against
+ * address regions where memory doesn't exist, but it returns memory images
+ * of lower address of the bank.
+ */
+static u_int
+milan_probe_bank_1(paddr_t start_paddr)
+{
+	volatile uint8_t *base;
+	u_int mb;
+	uint8_t save_16, save_32, save_64;
+
+	/* Assume that this bank has at least 16MB */
+	mb = 16;
+
+	base = (uint8_t *)start_paddr;
+
+	/* save and write a MAGIC at the end of 16MB region */
+	save_16 = base[MB_END(16)];
+	base[MB_END(16)] = MAGIC_16M;
+
+	/* check bus error at the end of 32MB region */
+	if (badbaddr(__UNVOLATILE(base + MB_END(32)), sizeof(uint8_t))) {
+		/* bus error; assume no memory there */
+		goto out16;
+	}
+
+	/* check if the 32MB region is not image of the prior 16MB region */
+	save_32 = base[MB_END(32)];
+	base[MB_END(32)] = MAGIC_32M;
+	if (base[MB_END(32)] != MAGIC_32M || base[MB_END(16)] != MAGIC_16M) {
+		/* no memory or image at the 32MB region */
+		goto out16;
+	}
+	/* we have at least 32MB */
+	mb = 32;
+
+	/* check bus error at the end of 64MB region */
+	if (badbaddr(__UNVOLATILE(base + MB_END(64)), sizeof(uint8_t))) {
+		/* bus error; assume no memory there */
+		goto out32;
+	}
+
+	/* check if the 64MB region is not image of the prior 32MB region */
+	save_64 = base[MB_END(64)];
+	base[MB_END(64)] = MAGIC_64M;
+	if (base[MB_END(64)] != MAGIC_64M || base[MB_END(32)] != MAGIC_32M) {
+		/* no memory or image at the 64MB region */
+		goto out32;
+	}
+	/* we have 64MB */
+	mb = 64;
+	base[MB_END(64)] = save_64;
+ out32:
+	base[MB_END(32)] = save_32;
+ out16:
+	base[MB_END(16)] = save_16;
+
+	return mb;
+}
+
+/*
+ * Probe and return available memory size in MB at specfied address.
+ * The rest slot could be empty so check all possible size.
+ */
+static u_int
+milan_probe_bank(paddr_t start_paddr)
+{
+	volatile uint8_t *base;
+	u_int mb;
+	uint8_t save_4, save_8, save_16;
+
+	/* The rest banks might have no memory */
+	mb = 0;
+
+	base = (uint8_t *)start_paddr;
+
+	/* check bus error at the end of 4MB region */
+	if (badbaddr(__UNVOLATILE(base + MB_END(4)), sizeof(uint8_t))) {
+		/* bus error; assume no memory there */
+		goto out;
+	}
+
+	/* check if the 4MB region has memory */
+	save_4 = base[MB_END(4)];
+	base[MB_END(4)] = MAGIC_4M_INV;
+	if (base[MB_END(4)] != MAGIC_4M_INV) {
+		/* no memory */
+		goto out;
+	}
+	base[MB_END(4)] = MAGIC_4M;
+	if (base[MB_END(4)] != MAGIC_4M) {
+		/* no memory */
+		goto out;
+	}
+	/* we have at least 4MB */
+	mb = 4;
+
+	/* check bus error at the end of 8MB region */
+	if (badbaddr(__UNVOLATILE(base + MB_END(8)), sizeof(uint8_t))) {
+		/* bus error; assume no memory there */
+		goto out4;
+	}
+
+	/* check if the 8MB region is not image of the prior 4MB region */
+	save_8 = base[MB_END(8)];
+	base[MB_END(8)] = MAGIC_8M;
+	if (base[MB_END(8)] != MAGIC_8M || base[MB_END(4)] != MAGIC_4M) {
+		/* no memory or image at the 8MB region */
+		goto out4;
+	}
+	/* we have at least 8MB */
+	mb = 8;
+
+	/* check bus error at the end of 16MB region */
+	if (badbaddr(__UNVOLATILE(base + MB_END(16)), sizeof(uint8_t))) {
+		/* bus error; assume no memory there */
+		goto out8;
+	}
+
+	/* check if the 16MB region is not image of the prior 8MB region */
+	save_16 = base[MB_END(16)];
+	base[MB_END(16)] = MAGIC_16M;
+	if (base[MB_END(16)] != MAGIC_16M || base[MB_END(8)] != MAGIC_8M) {
+		/* no memory or image at the 32MB region */
+		goto out8;
+	}
+	/* we have at least 16MB, so check more region as the first bank */
+	mb = milan_probe_bank_1(start_paddr);
+
+	base[MB_END(16)] = save_16;
+ out8:
+	base[MB_END(8)] = save_8;
+ out4:
+	base[MB_END(4)] = save_4;
+ out:
+
+	return mb;
+}
+#endif	/* _MILANHW_ */
+
 /*
  * Try to figure out on what type of machine we are running
  * Note: This module runs *before* the io-mapping is setup!
Index: include/vmparam.h
===================================================================
RCS file: /cvsroot/src/sys/arch/atari/include/vmparam.h,v
retrieving revision 1.31
diff -u -p -d -r1.31 vmparam.h
--- include/vmparam.h	2 Feb 2017 21:53:54 -0000	1.31
+++ include/vmparam.h	9 Feb 2018 15:40:13 -0000
@@ -104,8 +104,10 @@
 
 /*
  * Our bootloader currently passes up to 2 segments (ST and TT ram).
+ * On the other hand, Milan has four SIMM slots with 2 banks
+ * so it could have upto 8 segments.
  */
-#define VM_PHYSSEG_MAX		(2)
+#define VM_PHYSSEG_MAX		(8)
 #define VM_PHYSSEG_STRAT	VM_PSTRAT_RANDOM
 
 #define	VM_NFREELIST		2


---

(serial console output with debug printfs)
---
NetBSD/Atari tertiary bootloader ($Revision: 1.8 $)

tc:          0x0000c000
srp:         0x00dfde00
urp:         0x00dfde00
stmem_size:  0x00dec000
ttmem_start: 0x01000000
ttmem_size:  0x07180000
start_c: setup ser console
start_c: SIMM slot 0 bank 0: 16 MB
start_c: SIMM slot 1 bank 0: 16 MB
start_c: SIMM slot 2 bank 0: 16 MB
start_c: SIMM slot 3 bank 0: 16 MB
start_c: SIMM slot 0 bank 1: 16 MB
start_c: SIMM slot 1 bank 1: 16 MB
start_c: SIMM slot 2 bank 1: 16 MB
start_c: SIMM slot 3 bank 1: 16 MB
start_c: stphysize = 16777216, ttpysize = 117440512
start_c: boot_segs[0].start = 00000000, boot_segs[0].end = 01000000
start_c: boot_segs[1].start = 04000000, boot_segs[1].end = 05000000
start_c: boot_segs[2].start = 08000000, boot_segs[2].end = 09000000
start_c: boot_segs[3].start = 0c000000, boot_segs[3].end = 0d000000
start_c: boot_segs[4].start = 10000000, boot_segs[4].end = 11000000
start_c: boot_segs[5].start = 14000000, boot_segs[5].end = 15000000
start_c: boot_segs[6].start = 18000000, boot_segs[6].end = 19000000
start_c: boot_segs[7].start = 1c000000, boot_segs[7].end = 1d000000
start_c: usable_segs[1].start = 04000000, usable_segs[1].end = 05000000
start_c: usable_segs[2].start = 08000000, usable_segs[2].end = 09000000
start_c: usable_segs[3].start = 0c000000, usable_segs[3].end = 0d000000
start_c: usable_segs[4].start = 10000000, usable_segs[4].end = 11000000
start_c: usable_segs[5].start = 14000000, usable_segs[5].end = 15000000
start_c: usable_segs[6].start = 18000000, usable_segs[6].end = 19000000
start_c: usable_segs[7].start = 1c000000, usable_segs[7].end = 1d000000
start_c: calling pmap_bootstrap()
start_c: pmap_bootstrap() done
start_c: turning on MMU
start_c: pmap_bootstrap_finalize()
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 8.0_BETA (MILANP) #73: Mon Feb  5 23:51:47 JST 2018
	tsutsui@mirage:/r/work/netbsd-8/src/sys/arch/atari/compile/MILANP
Atari Milan (m68040 CPU/MMU/FPU)
total memory = 128 MB
avail memory = 122 MB
mainbus0 (root)

 :

---
Izumi Tsutsui


Home | Main Index | Thread Index | Old Index