Home | History | Annotate | Line # | Download | only in cats
      1 /*	$NetBSD: cats_machdep.c,v 1.96 2024/10/21 13:37:07 skrll Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997,1998 Mark Brinicombe.
      5  * Copyright (c) 1997,1998 Causality Limited.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by Mark Brinicombe
     19  *	for the NetBSD Project.
     20  * 4. The name of the company nor the name of the author may be used to
     21  *    endorse or promote products derived from this software without specific
     22  *    prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     25  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     27  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     28  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     29  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  * Machine dependent functions for kernel setup for EBSA285 core architecture
     37  * using cyclone firmware
     38  *
     39  * Created      : 24/11/97
     40  */
     41 
     42 #include <sys/cdefs.h>
     43 __KERNEL_RCSID(0, "$NetBSD: cats_machdep.c,v 1.96 2024/10/21 13:37:07 skrll Exp $");
     44 
     45 #include "opt_arm_debug.h"
     46 #include "opt_cats.h"
     47 #include "opt_ddb.h"
     48 #include "opt_modular.h"
     49 
     50 #include "isadma.h"
     51 
     52 #include <sys/param.h>
     53 #include <sys/device.h>
     54 #include <sys/systm.h>
     55 #include <sys/kernel.h>
     56 #include <sys/exec.h>
     57 #include <sys/proc.h>
     58 #include <sys/msgbuf.h>
     59 #include <sys/reboot.h>
     60 #include <sys/termios.h>
     61 #include <sys/ksyms.h>
     62 #include <sys/cpu.h>
     63 #include <sys/intr.h>
     64 
     65 #include <dev/cons.h>
     66 
     67 #include <machine/db_machdep.h>
     68 #include <ddb/db_sym.h>
     69 #include <ddb/db_extern.h>
     70 
     71 #include <machine/bootconfig.h>
     72 #define	_ARM32_BUS_DMA_PRIVATE
     73 #include <sys/bus.h>
     74 #include <arm/locore.h>
     75 #include <arm/undefined.h>
     76 #include <arm/arm32/machdep.h>
     77 
     78 #include <machine/cyclone_boot.h>
     79 #include <arm/footbridge/dc21285mem.h>
     80 #include <arm/footbridge/dc21285reg.h>
     81 
     82 #include "ksyms.h"
     83 #include "opt_ableelf.h"
     84 
     85 #include "isa.h"
     86 #if NISA > 0
     87 #include <dev/isa/isareg.h>
     88 #include <dev/isa/isavar.h>
     89 #endif
     90 
     91 #ifdef VERBOSE_INIT_ARM
     92 #define VPRINTF(...)	printf(__VA_ARGS__)
     93 #else
     94 #define VPRINTF(...)	__nothing
     95 #endif
     96 
     97 /* Kernel text starts at the base of the kernel address space. */
     98 #define	KERNEL_TEXT_BASE	(KERNEL_BASE + 0x00000000)
     99 #define	KERNEL_VM_BASE		(KERNEL_BASE + 0x01000000)
    100 
    101 /*
    102  * The range 0xf1000000 - 0xfcffffff is available for kernel VM space
    103  * Footbridge registers and I/O mappings occupy 0xfd000000 - 0xffffffff
    104  */
    105 
    106 /*
    107  * Size of available KVM space, note that growkernel will grow into this.
    108  */
    109 #define KERNEL_VM_SIZE	0x0c000000
    110 
    111 /*
    112  * Address to call from cpu_reset() to reset the machine.
    113  * This is machine architecture dependent as it varies depending
    114  * on where the ROM appears when you turn the MMU off.
    115  */
    116 
    117 u_int dc21285_fclk = FCLK;
    118 
    119 struct ebsaboot ebsabootinfo;
    120 BootConfig bootconfig;		/* Boot config storage */
    121 static char bootargs[MAX_BOOT_STRING + 1];
    122 char *boot_args = NULL;
    123 char *boot_file = NULL;
    124 
    125 /* Prototypes */
    126 
    127 void consinit(void);
    128 
    129 int fcomcnattach(u_int iobase, int rate, tcflag_t cflag);
    130 int fcomcndetach(void);
    131 
    132 static void process_kernel_args(const char *);
    133 extern void configure(void);
    134 
    135 /* A load of console goo. */
    136 #include "vga.h"
    137 #if (NVGA > 0)
    138 #include <dev/ic/mc6845reg.h>
    139 #include <dev/ic/pcdisplayvar.h>
    140 #include <dev/ic/vgareg.h>
    141 #include <dev/ic/vgavar.h>
    142 #endif
    143 
    144 #include "pckbc.h"
    145 #if (NPCKBC > 0)
    146 #include <dev/ic/i8042reg.h>
    147 #include <dev/ic/pckbcvar.h>
    148 #endif
    149 
    150 #include "com.h"
    151 #if (NCOM > 0)
    152 #include <dev/ic/comreg.h>
    153 #include <dev/ic/comvar.h>
    154 #ifndef CONCOMADDR
    155 #define CONCOMADDR 0x3f8
    156 #endif
    157 #endif
    158 
    159 #ifndef CONSDEVNAME
    160 #define CONSDEVNAME "vga"
    161 #endif
    162 
    163 #define CONSPEED B38400
    164 #ifndef CONSPEED
    165 #define CONSPEED B9600	/* TTYDEF_SPEED */
    166 #endif
    167 #ifndef CONMODE
    168 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
    169 #endif
    170 
    171 int comcnspeed = CONSPEED;
    172 int comcnmode = CONMODE;
    173 
    174 static const struct pmap_devmap cats_devmap[] = {
    175 	/* Map 1MB for CSR space */
    176 	DEVMAP_ENTRY(DC21285_ARMCSR_VBASE,
    177 		     DC21285_ARMCSR_BASE,
    178 		     DC21285_ARMCSR_VSIZE),
    179 
    180 	/* Map 1MB for fast cache cleaning space */
    181 	DEVMAP_ENTRY(DC21285_CACHE_FLUSH_VBASE,
    182 		     DC21285_SA_CACHE_FLUSH_BASE,
    183 		     DC21285_CACHE_FLUSH_VSIZE),
    184 
    185 	/* Map 1MB for PCI IO space */
    186 	DEVMAP_ENTRY(DC21285_PCI_IO_VBASE,
    187 		     DC21285_PCI_IO_BASE,
    188 		     DC21285_PCI_IO_VSIZE),
    189 
    190 	/* Map 1MB for PCI IACK space */
    191 	DEVMAP_ENTRY(DC21285_PCI_IACK_VBASE,
    192 		     DC21285_PCI_IACK_SPECIAL,
    193 		     DC21285_PCI_IACK_VSIZE),
    194 
    195 	/* Map 16MB of type 1 PCI config access */
    196 	DEVMAP_ENTRY(DC21285_PCI_TYPE_1_CONFIG_VBASE,
    197 		     DC21285_PCI_TYPE_1_CONFIG,
    198 		     DC21285_PCI_TYPE_1_CONFIG_VSIZE),
    199 
    200 	/* Map 16MB of type 0 PCI config access */
    201 	DEVMAP_ENTRY(DC21285_PCI_TYPE_0_CONFIG_VBASE,
    202 		     DC21285_PCI_TYPE_0_CONFIG,
    203 		     DC21285_PCI_TYPE_0_CONFIG_VSIZE),
    204 
    205 	/* Map 1MB of 32 bit PCI address space for ISA MEM accesses via PCI */
    206 	DEVMAP_ENTRY(DC21285_PCI_ISA_MEM_VBASE,
    207 		     DC21285_PCI_MEM_BASE,
    208 		     DC21285_PCI_ISA_MEM_VSIZE),
    209 
    210 	DEVMAP_ENTRY_END
    211 };
    212 
    213 #define MAX_PHYSMEM 4
    214 static struct boot_physmem cats_physmem[MAX_PHYSMEM];
    215 int ncats_physmem = 0;
    216 
    217 extern struct bus_space footbridge_pci_io_bs_tag;
    218 extern struct bus_space footbridge_pci_mem_bs_tag;
    219 void footbridge_pci_bs_tag_init(void);
    220 
    221 /*
    222  * vaddr_t initarm(struct ebsaboot *bootinfo)
    223  *
    224  * Initial entry point on startup. This gets called before main() is
    225  * entered.
    226  * It should be responsible for setting up everything that must be
    227  * in place when main is called.
    228  * This includes
    229  *   Taking a copy of the boot configuration structure.
    230  *   Initialising the physical console so characters can be printed.
    231  *   Setting up page tables for the kernel
    232  *   Relocating the kernel to the bottom of physical memory
    233  */
    234 
    235 vaddr_t
    236 initarm(void *arm_bootargs)
    237 {
    238 	struct ebsaboot *bootinfo = arm_bootargs;
    239 	extern u_int cpu_get_control(void);
    240 
    241 	/*
    242 	 * Heads up ... Setup the CPU / MMU / TLB functions
    243 	 */
    244 	set_cpufuncs();
    245 
    246 	/* Copy the boot configuration structure */
    247 	ebsabootinfo = *bootinfo;
    248 
    249 	if (ebsabootinfo.bt_fclk >= 50000000
    250 	    && ebsabootinfo.bt_fclk <= 66000000)
    251 		dc21285_fclk = ebsabootinfo.bt_fclk;
    252 
    253 	/* Fake bootconfig structure for the benefit of pmap.c */
    254 	/* XXX must make the memory description h/w independent */
    255 	bootconfig.dramblocks = 1;
    256 	bootconfig.dram[0].address = ebsabootinfo.bt_memstart;
    257 	bootconfig.dram[0].pages = (ebsabootinfo.bt_memend
    258 	    - ebsabootinfo.bt_memstart) / PAGE_SIZE;
    259 
    260 	/*
    261 	 * Initialise the diagnostic serial console
    262 	 * This allows a means of generating output during initarm().
    263 	 * Once all the memory map changes are complete we can call consinit()
    264 	 * and not have to worry about things moving.
    265 	 */
    266 	pmap_devmap_bootstrap((vaddr_t)ebsabootinfo.bt_l1, cats_devmap);
    267 
    268 #ifdef FCOM_INIT_ARM
    269 	fcomcnattach(DC21285_ARMCSR_VBASE, comcnspeed, comcnmode);
    270 #endif
    271 
    272 	/* Talk to the user */
    273 	printf("NetBSD/cats booting ...\n");
    274 
    275 	if (ebsabootinfo.bt_magic != BT_MAGIC_NUMBER_EBSA
    276 	    && ebsabootinfo.bt_magic != BT_MAGIC_NUMBER_CATS)
    277 		panic("Incompatible magic number %#x passed in boot args",
    278 		    ebsabootinfo.bt_magic);
    279 
    280 	/* output the incoming bootinfo */
    281 	VPRINTF("bootinfo @ %p\n", arm_bootargs);
    282 	VPRINTF("bt_magic    = 0x%08x\n", ebsabootinfo.bt_magic);
    283 	VPRINTF("bt_vargp    = 0x%08x\n", ebsabootinfo.bt_vargp);
    284 	VPRINTF("bt_pargp    = 0x%08x\n", ebsabootinfo.bt_pargp);
    285 	VPRINTF("bt_args @ %p, contents = \"%s\"\n", ebsabootinfo.bt_args, ebsabootinfo.bt_args);
    286 	VPRINTF("bt_l1       = %p\n", ebsabootinfo.bt_l1);
    287 
    288 	VPRINTF("bt_memstart = 0x%08x\n", ebsabootinfo.bt_memstart);
    289 	VPRINTF("bt_memend   = 0x%08x\n", ebsabootinfo.bt_memend);
    290 	VPRINTF("bt_memavail = 0x%08x\n", ebsabootinfo.bt_memavail);
    291 	VPRINTF("bt_fclk     = 0x%08x\n", ebsabootinfo.bt_fclk);
    292 	VPRINTF("bt_pciclk   = 0x%08x\n", ebsabootinfo.bt_pciclk);
    293 	VPRINTF("bt_vers     = 0x%08x\n", ebsabootinfo.bt_vers);
    294 	VPRINTF("bt_features = 0x%08x\n", ebsabootinfo.bt_features);
    295 
    296 	/*
    297 	 * Examine the boot args string for options we need to know about
    298 	 * now.
    299 	 */
    300 	process_kernel_args(ebsabootinfo.bt_args);
    301 
    302 	psize_t ram_size = ebsabootinfo.bt_memend - ebsabootinfo.bt_memstart;
    303 	/*
    304 	 * If MEMSIZE specified less than what we really have, limit ourselves
    305 	 * to that.
    306 	*/
    307 #ifdef MEMSIZE
    308 	if (ram_size == 0 || ram_size > (unsigned)MEMSIZE * 1024 * 1024)
    309 		ram_size = (unsigned)MEMSIZE * 1024 * 1024;
    310 	VPRINTF("ram_size = 0x%x\n", (int)ram_size);
    311 #else
    312 	KASSERTMSG(ram_size > 0, "RAM size unknown and MEMSIZE undefined");
    313 #endif
    314 
    315 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
    316 	const bool mapallmem_p = true;
    317 
    318 	if (ram_size > KERNEL_VM_BASE - KERNEL_BASE) {
    319 		printf("%s: dropping RAM size from %luMB to %uMB\n",
    320 		    __func__, (unsigned long) (ram_size >> 20),
    321 		    (KERNEL_VM_BASE - KERNEL_BASE) >> 20);
    322 		ram_size = KERNEL_VM_BASE - KERNEL_BASE;
    323         }
    324 #else
    325         const bool mapallmem_p = false;
    326 #endif
    327 
    328 	printf("ram_size = 0x%08lx\n", ram_size);
    329 
    330 	arm32_bootmem_init(ebsabootinfo.bt_memstart, ram_size,
    331 	    ebsabootinfo.bt_memstart);
    332 
    333 	/*
    334 	 * The free block after the kernel from arm32_bootmem_init doesn't
    335 	 * account for bt_memavail.  Adjust for this.
    336 	 */
    337 	extern struct bootmem_info bootmem_info;
    338 	struct bootmem_info * const bmi = &bootmem_info;
    339 
    340 	pv_addr_t *pv0 = &bmi->bmi_freeblocks[0];
    341 	KASSERTMSG(pv0->pv_pa == bmi->bmi_kernelend,
    342 	    "pv_pa %#lx kernelend %#lx", pv0->pv_pa, bmi->bmi_kernelend);
    343 
    344 	pv0->pv_pa = ebsabootinfo.bt_memavail;
    345 	pv0->pv_va = KERN_PHYSTOV(pv0->pv_pa);
    346 	pv0->pv_size = bmi->bmi_end - pv0->pv_pa;
    347 
    348 	printf("First freeblock adjusted to: %lx -> %lx\n", pv0->pv_pa,
    349 	    pv0->pv_pa + pv0->pv_size - 1);
    350 
    351 	arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_LOW, 0, cats_devmap,
    352 	    mapallmem_p);
    353 
    354 	printf("init subsystems: patch ");
    355 
    356 	/*
    357 	 * PATCH PATCH ...
    358 	 *
    359 	 * Fixup the first word of the kernel to be the instruction
    360 	 * add pc, pc, #0x41000000
    361 	 *
    362 	 * This traps the case where the CPU core resets due to bus contention
    363 	 * on a prototype CATS system and will reboot into the firmware.
    364 	 */
    365 	*((u_int *)KERNEL_TEXT_BASE) = 0xe28ff441;
    366 
    367 #if NISA > 0
    368 	/* Initialise the ISA subsystem early ... */
    369 	isa_footbridge_init(DC21285_PCI_IO_VBASE, DC21285_PCI_ISA_MEM_VBASE);
    370 #endif
    371 
    372 	footbridge_pci_bs_tag_init();
    373 
    374 	printf("busses done.\n");
    375 
    376 	/* Map the boot arguments page */
    377 	if (ebsabootinfo.bt_vargp != vector_page) {
    378 		pmap_map_entry(kernel_l1pt.pv_va, ebsabootinfo.bt_vargp,
    379 		    ebsabootinfo.bt_pargp, VM_PROT_READ, PTE_CACHE);
    380 	}
    381 
    382 	printf("Doing freeblocks: %d\n", bmi->bmi_nfreeblocks);
    383 
    384 	for (size_t i = 0; i < bmi->bmi_nfreeblocks; i++) {
    385 		pv_addr_t * const pv = &bmi->bmi_freeblocks[i];
    386 		paddr_t start = pv->pv_pa;
    387 		paddr_t end = pv->pv_pa + pv->pv_size;
    388 		struct boot_physmem *bp;
    389 #if NISADMA > 0
    390 		paddr_t istart, isize;
    391 		extern struct arm32_dma_range *footbridge_isa_dma_ranges;
    392 		extern int footbridge_isa_dma_nranges;
    393 #endif
    394 
    395 		VPRINTF("%zu: 0x08%lx -> 0x08%lx\n", i, start, end - 1);
    396 
    397 #if NISADMA > 0
    398 		if (arm32_dma_range_intersect(footbridge_isa_dma_ranges,
    399 		   footbridge_isa_dma_nranges, start, end - start,
    400 		   &istart, &isize)) {
    401 			/*
    402 			 * Place the pages that intersect with the
    403 			 * ISA DMA range onto the ISA DMA free list.
    404 			 */
    405 			VPRINTF("    ISADMA 0x08%lx -> 0x%08lx\n", istart,
    406 			    istart + isize - 1);
    407 			bp = &cats_physmem[ncats_physmem++];
    408 			KASSERT(ncats_physmem < MAX_PHYSMEM);
    409 			bp->bp_start = atop(istart);
    410 			bp->bp_pages = atop(isize);
    411 			bp->bp_freelist = VM_FREELIST_ISADMA;
    412 
    413 			/*
    414 			 * Load the pieces that come before the
    415 			 * intersection onto the default free list.
    416 			 */
    417 			if (start < istart) {
    418 				VPRINTF("    BEFORE 0x08%lx -> 0x08%lx\n",
    419 				    start, istart - 1);
    420 				bp = &cats_physmem[ncats_physmem++];
    421 				KASSERT(ncats_physmem < MAX_PHYSMEM);
    422 				bp->bp_start = atop(start);
    423 				bp->bp_pages = atop(istart - start);
    424 				bp->bp_freelist = VM_FREELIST_DEFAULT;
    425 			}
    426 
    427 			/*
    428 			 * Load the pieces that come after the
    429 			 * intersection onto the default free list.
    430 			 */
    431 			if ((istart + isize) < end) {
    432 				VPRINTF("     AFTER 0x%08lx -> 0x%08lx\n",
    433 				    (istart + isize), end - 1);
    434 				bp = &cats_physmem[ncats_physmem++];
    435 				KASSERT(ncats_physmem < MAX_PHYSMEM);
    436 				bp->bp_start = atop(istart + isize);
    437 				bp->bp_pages = atop(end - (istart + isize));
    438 				bp->bp_freelist = VM_FREELIST_DEFAULT;
    439 			}
    440 		} else {
    441 			bp = &cats_physmem[ncats_physmem++];
    442 			KASSERT(ncats_physmem < MAX_PHYSMEM);
    443 			bp->bp_start = atop(start);
    444 			bp->bp_pages = atop(end - start);
    445 			bp->bp_freelist = VM_FREELIST_DEFAULT;
    446 		}
    447 #else /* NISADMA > 0 */
    448 		bp = &cats_physmem[ncats_physmem++];
    449 		KASSERT(ncats_physmem < MAX_PHYSMEM);
    450 		bp->bp_start = atop(start);
    451 		bp->bp_pages = atop(end - start);
    452 		bp->bp_freelist = VM_FREELIST_DEFAULT;
    453 #endif /* NISADMA > 0 */
    454 	}
    455 
    456 	cpu_reset_address_paddr = DC21285_ROM_BASE;
    457 
    458 	/* initarm_common returns the new stack pointer address */
    459 	vaddr_t sp;
    460 	sp = initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, cats_physmem,
    461 	    ncats_physmem);
    462 
    463 	/* Setup the IRQ system */
    464 	printf("init subsystems: irq ");
    465 	footbridge_intr_init();
    466 
    467 	printf("done.\n");
    468 
    469 #ifdef FCOM_INIT_ARM
    470 	fcomcndetach();
    471 #endif
    472 
    473 #ifdef DDB
    474 	if (boothowto & RB_KDB)
    475 		Debugger();
    476 #endif
    477 
    478 	/*
    479 	 * XXX this should only be done in main() but it useful to
    480 	 * have output earlier ...
    481 	 */
    482 	consinit();
    483 
    484 	return sp;
    485 }
    486 
    487 static void
    488 process_kernel_args(const char *loader_args)
    489 {
    490 	char *args;
    491 	boothowto = 0;
    492 
    493 	/* Make a local copy of the bootargs */
    494 	strncpy(bootargs, loader_args, MAX_BOOT_STRING);
    495 
    496 	args = bootargs;
    497 	boot_file = bootargs;
    498 
    499 	/* Skip the kernel image filename */
    500 	while (*args != ' ' && *args != 0)
    501 		++args;
    502 
    503 	if (*args != 0)
    504 		*args++ = 0;
    505 
    506 	while (*args == ' ')
    507 		++args;
    508 
    509 	boot_args = args;
    510 
    511 	printf("bootfile: %s\n", boot_file);
    512 	printf("bootargs: %s\n", boot_args);
    513 
    514 	parse_mi_bootargs(boot_args);
    515 }
    516 
    517 void
    518 consinit(void)
    519 {
    520 	static int consinit_called = 0;
    521 	const char *console = CONSDEVNAME;
    522 
    523 	if (consinit_called != 0)
    524 		return;
    525 
    526 	consinit_called = 1;
    527 
    528 	get_bootconf_option(boot_args, "console", BOOTOPT_TYPE_STRING,
    529 	    &console);
    530 
    531 	if (strncmp(console, "fcom", 4) == 0
    532 	    || strncmp(console, "diag", 4) == 0)
    533 		fcomcnattach(DC21285_ARMCSR_VBASE, comcnspeed, comcnmode);
    534 #if (NVGA > 0)
    535 	else if (strncmp(console, "vga", 3) == 0) {
    536 		vga_cnattach(&footbridge_pci_io_bs_tag,
    537 		    &footbridge_pci_mem_bs_tag, - 1, 0);
    538 #if (NPCKBC > 0)
    539 		pckbc_cnattach(&isa_io_bs_tag, IO_KBD, KBCMDP, PCKBC_KBD_SLOT,
    540 		    0);
    541 #endif	/* NPCKBC */
    542 	}
    543 #endif	/* NVGA */
    544 #if (NCOM > 0)
    545 	else if (strncmp(console, "com", 3) == 0) {
    546 		if (comcnattach(&isa_io_bs_tag, CONCOMADDR, comcnspeed,
    547 		    COM_FREQ, COM_TYPE_NORMAL, comcnmode))
    548 			panic("can't init serial console @%x", CONCOMADDR);
    549 	}
    550 #endif
    551 	/* Don't know what console was requested so use the fall back. */
    552 	else
    553 		fcomcnattach(DC21285_ARMCSR_VBASE, comcnspeed, comcnmode);
    554 }
    555 
    556 /* End of cats_machdep.c */
    557