Пример #1
0
__initfunc(void auxio_probe(void))
{
	int node, auxio_nd;
	struct linux_prom_registers auxregs[1];

	switch (sparc_cpu_model) {
	case sun4d:
	case sun4:
		auxio_register = 0;
		return;
	default:
		break;
	}
	node = prom_getchild(prom_root_node);
	auxio_nd = prom_searchsiblings(node, "auxiliary-io");
	if(!auxio_nd) {
		node = prom_searchsiblings(node, "obio");
		node = prom_getchild(node);
		auxio_nd = prom_searchsiblings(node, "auxio");
		if(!auxio_nd) {
#ifdef CONFIG_PCI
			/* There may be auxio on Ebus */
			auxio_register = 0;
			return;
#else
			if(prom_searchsiblings(node, "leds")) {
				/* VME chassis sun4m machine, no auxio exists. */
				auxio_register = 0;
				return;
			}
			prom_printf("Cannot find auxio node, cannot continue...\n");
			prom_halt();
#endif
		}
	}
	prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs));
	prom_apply_obio_ranges(auxregs, 0x1);
	/* Map the register both read and write */
	auxio_register = (unsigned char *) sparc_alloc_io(auxregs[0].phys_addr, 0,
							  auxregs[0].reg_size,
							  "auxiliaryIO",
							  auxregs[0].which_io, 0x0);
	/* Fix the address on sun4m and sun4c. */
	if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 ||
	   sparc_cpu_model == sun4c)
		auxio_register = (unsigned char *) ((int)auxio_register | 3);

	TURN_ON_LED;
}
Пример #2
0
static volatile struct bpp_regs *map_bpp(struct linux_sbus_device *dev, int idx)
{
      volatile struct bpp_regs *regs;

      /*
       * PROM reports different numbers on Zebra and on DMA2.
       * We need to figure out when to apply parent ranges.
       * printk will show this on different machines.
       */

      /* IPC Zebra   1.fa200000[1c] i=2  */
      prom_apply_sbus_ranges(dev->my_bus, &dev->reg_addrs[0],
			     dev->num_registers, dev);

      regs = sparc_alloc_io(dev->reg_addrs[0].phys_addr, 0,
			    dev->reg_addrs[0].reg_size, "bpp",
			    dev->reg_addrs[0].which_io, 0x0);
      printk("bpp%d.map_bpp: 0x%x.%p[0x%x] i=%d\n", idx,
	     dev->reg_addrs[0].which_io, dev->reg_addrs[0].phys_addr,
	     dev->reg_addrs[0].reg_size, dev->irqs[0]);

      return regs;
}
Пример #3
0
__initfunc(void auxio_power_probe(void))
{
	struct linux_prom_registers regs;
	int node;

	/* Attempt to find the sun4m power control node. */
	node = prom_getchild(prom_root_node);
	node = prom_searchsiblings(node, "obio");
	node = prom_getchild(node);
	node = prom_searchsiblings(node, "power");
	if (node == 0 || node == -1)
		return;

	/* Map the power control register. */
	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
	prom_apply_obio_ranges(&regs, 1);
	auxio_power_register = (volatile unsigned char *)
		sparc_alloc_io(regs.phys_addr, 0, regs.reg_size,
			       "power off control", regs.which_io, 0);

	/* Display a quick message on the console. */
	if (auxio_power_register)
		printk(KERN_INFO "Power off control detected.\n");
}
Пример #4
0
int init_vfc_device(struct linux_sbus_device *sdev,struct vfc_dev *dev,
		    int instance) {
	if(!dev) {
		printk(KERN_ERR "VFC: Bogus pointer passed\n");
		return -ENOMEM;
	}
	printk("Initializing vfc%d\n",instance);
	dev->regs=NULL;
	prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], sdev->num_registers, sdev);
	dev->regs=sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
				 sizeof(struct vfc_regs), vfcstr, 
				 sdev->reg_addrs[0].which_io, 0x0);
	dev->which_io=sdev->reg_addrs[0].which_io;
	dev->phys_regs=(struct vfc_regs *)sdev->reg_addrs[0].phys_addr;
	if(!dev->regs) return -EIO;

	printk("vfc%d: registers mapped at phys_addr: 0x%lx\n    virt_addr: 0x%lx\n",
	       instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs);

	if(init_vfc_devstruct(dev,instance)) return -EINVAL;
	if(init_vfc_hw(dev)) return -EIO;

	return 0;
}
Пример #5
0
__initfunc(void pcic_probe(void))
{
	struct linux_prom_registers regs[PROMREG_MAX];
	struct linux_pbm_info* pbm;
	char namebuf[64];
	int node;
	int err;

	if (pcibios_present()) {
		prom_printf("PCIC: called twice!\n");
		prom_halt();
	}

	node = prom_getchild (prom_root_node);
	node = prom_searchsiblings (node, "pci");
	if (node == 0)
		return;
	/*
	 * Map in PCIC register set, config space, and IO base
	 */
	err = prom_getproperty(node, "reg", (char*)regs, sizeof(regs));
	if (err == 0 || err == -1) {
		prom_printf("PCIC: Error, cannot get PCIC registers "
			    "from PROM.\n");
		prom_halt();
	}
	
	pcic = &PCIC;

	pcic->pcic_regs = (unsigned long)sparc_alloc_io(regs[0].phys_addr, NULL,
					      regs[0].reg_size,
					      "PCIC Registers", 0, 0);
	if (!pcic->pcic_regs) {
		prom_printf("PCIC: Error, cannot map PCIC registers.\n");
		prom_halt();
	}

	pcic->pcic_io_phys = regs[1].phys_addr;
	pcic->pcic_io = (unsigned long)sparc_alloc_io(regs[1].phys_addr, NULL,
					    regs[1].reg_size,
					    "PCIC IO Base", 0, 0);
	if (pcic->pcic_io == 0UL) {
		prom_printf("PCIC: Error, cannot map PCIC IO Base.\n");
		prom_halt();
	}

	pcic->pcic_config_space_addr =
			(unsigned long)sparc_alloc_io (regs[2].phys_addr, NULL,
					     regs[2].reg_size * 2,
					     "PCI Config Space Address", 0, 0);
	if (pcic->pcic_config_space_addr == 0UL) {
		prom_printf("PCIC: Error, cannot map" 
			    "PCI Configuration Space Address.\n");
		prom_halt();
	}

	/*
	 * Docs say three least significant bits in address and data
	 * must be the same. Thus, we need adjust size of data.
	 */
	pcic->pcic_config_space_data =
			(unsigned long)sparc_alloc_io (regs[3].phys_addr, NULL,
					     regs[3].reg_size * 2,
					     "PCI Config Space Data", 0, 0);
	if (pcic->pcic_config_space_data == 0UL) {
		prom_printf("PCIC: Error, cannot map" 
			    "PCI Configuration Space Data.\n");
		prom_halt();
	}

	pbm = &pcic->pbm;
	pbm->prom_node = node;
	prom_getstring(node, "name", namebuf, sizeof(namebuf));
	strcpy(pbm->prom_name, namebuf);
}
Пример #6
0
__initfunc(void auxio_probe(void))
{
    struct linux_sbus *bus;
    struct linux_sbus_device *sdev = 0;
    struct linux_prom_registers auxregs[1];

    for_each_sbus(bus) {
        for_each_sbusdev(sdev, bus) {
            if(!strcmp(sdev->prom_name, "auxio")) {
                break;
            }
        }
    }

    if (!sdev) {
#ifdef CONFIG_PCI
        struct linux_ebus *ebus;
        struct linux_ebus_device *edev = 0;
        unsigned long led_auxio;

        for_each_ebus(ebus) {
            for_each_ebusdev(edev, ebus) {
                if (!strcmp(edev->prom_name, "auxio"))
                    goto ebus_done;
            }
        }
ebus_done:

        if (edev) {
            if (check_region(edev->base_address[0],
                             sizeof(unsigned int))) {
                prom_printf("%s: Can't get region %lx, %d\n",
                            __FUNCTION__, edev->base_address[0],
                            sizeof(unsigned int));
                prom_halt();
            }
            request_region(edev->base_address[0],
                           sizeof(unsigned int), "LED auxio");

            led_auxio = edev->base_address[0];
            outl(0x01, led_auxio);
            return;
        }
#endif
        if(central_bus) {
            auxio_register = NULL;
            return;
        }
        prom_printf("Cannot find auxio node, cannot continue...\n");
        prom_halt();
    }

    prom_getproperty(sdev->prom_node, "reg", (char *) auxregs, sizeof(auxregs));
    prom_apply_sbus_ranges(sdev->my_bus, auxregs, 0x1, sdev);
    /* Map the register both read and write */
    auxio_register = (unsigned char *) sparc_alloc_io(auxregs[0].phys_addr, 0,
                     auxregs[0].reg_size,
                     "auxiliaryIO",
                     auxregs[0].which_io, 0x0);
    TURN_ON_LED;
}
Пример #7
0
__initfunc(void sun4m_init_IRQ(void))
{
	int ie_node,i;
	struct linux_prom_registers int_regs[PROMREG_MAX];
	int num_regs;
    
	__cli();
	if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 ||
	   (ie_node = prom_getchild (ie_node)) == 0 ||
	   (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0) {
		prom_printf("Cannot find /obio/interrupt node\n");
		prom_halt();
	}
	num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs,
				    sizeof(int_regs));
	num_regs = (num_regs/sizeof(struct linux_prom_registers));
    
	/* Apply the obio ranges to these registers. */
	prom_apply_obio_ranges(int_regs, num_regs);
    
	int_regs[4].phys_addr = int_regs[num_regs-1].phys_addr;
	int_regs[4].reg_size = int_regs[num_regs-1].reg_size;
	int_regs[4].which_io = int_regs[num_regs-1].which_io;
	for(ie_node = 1; ie_node < 4; ie_node++) {
		int_regs[ie_node].phys_addr = int_regs[ie_node-1].phys_addr + PAGE_SIZE;
		int_regs[ie_node].reg_size = int_regs[ie_node-1].reg_size;
		int_regs[ie_node].which_io = int_regs[ie_node-1].which_io;
	}

	/* Map the interrupt registers for all possible cpus. */
	sun4m_interrupts = sparc_alloc_io(int_regs[0].phys_addr, 0,
					  PAGE_SIZE*NCPUS, "interrupts_percpu",
					  int_regs[0].which_io, 0x0);
    
	/* Map the system interrupt control registers. */
	sparc_alloc_io(int_regs[4].phys_addr, 0,
		       int_regs[4].reg_size, "interrupts_system",
		       int_regs[4].which_io, 0x0);
    
	sun4m_interrupts->set = ~SUN4M_INT_MASKALL;
	for (i=0; i<linux_num_cpus; i++)
		sun4m_interrupts->cpu_intregs[i].clear = ~0x17fff;
    
	if (linux_num_cpus > 1) {
		/* system wide interrupts go to cpu 0, this should always
		 * be safe because it is guaranteed to be fitted or OBP doesn't
		 * come up
		 *
		 * Not sure, but writing here on SLAVIO systems may puke
		 * so I don't do it unless there is more than 1 cpu.
		 */
		irq_rcvreg = (unsigned long *)
				&sun4m_interrupts->undirected_target;
		sun4m_interrupts->undirected_target = 0;
	}
	BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
	init_timers = sun4m_init_timers;
#ifdef __SMP__
	BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM);
#endif
	/* Cannot enable interrupts until OBP ticker is disabled. */
}
Пример #8
0
__initfunc(static void sun4m_init_timers(void (*counter_fn)(int, void *, struct pt_regs *)))
{
	int reg_count, irq, cpu;
	struct linux_prom_registers cnt_regs[PROMREG_MAX];
	int obio_node, cnt_node;

	cnt_node = 0;
	if((obio_node =
	    prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 ||
	   (obio_node = prom_getchild (obio_node)) == 0 ||
	   (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) {
		prom_printf("Cannot find /obio/counter node\n");
		prom_halt();
	}
	reg_count = prom_getproperty(cnt_node, "reg",
				     (void *) cnt_regs, sizeof(cnt_regs));
	reg_count = (reg_count/sizeof(struct linux_prom_registers));
    
	/* Apply the obio ranges to the timer registers. */
	prom_apply_obio_ranges(cnt_regs, reg_count);
    
	cnt_regs[4].phys_addr = cnt_regs[reg_count-1].phys_addr;
	cnt_regs[4].reg_size = cnt_regs[reg_count-1].reg_size;
	cnt_regs[4].which_io = cnt_regs[reg_count-1].which_io;
	for(obio_node = 1; obio_node < 4; obio_node++) {
		cnt_regs[obio_node].phys_addr =
			cnt_regs[obio_node-1].phys_addr + PAGE_SIZE;
		cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size;
		cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io;
	}
    
	/* Map the per-cpu Counter registers. */
	sun4m_timers = sparc_alloc_io(cnt_regs[0].phys_addr, 0,
				      PAGE_SIZE*NCPUS, "counters_percpu",
				      cnt_regs[0].which_io, 0x0);
    
	/* Map the system Counter register. */
	sparc_alloc_io(cnt_regs[4].phys_addr, 0,
		       cnt_regs[4].reg_size,
		       "counters_system",
		       cnt_regs[4].which_io, 0x0);
    
	sun4m_timers->l10_timer_limit =  (((1000000/HZ) + 1) << 10);
	master_l10_counter = &sun4m_timers->l10_cur_count;
	master_l10_limit = &sun4m_timers->l10_timer_limit;

	irq = request_irq(TIMER_IRQ,
			  counter_fn,
			  (SA_INTERRUPT | SA_STATIC_ALLOC),
			  "timer", NULL);
	if (irq) {
		prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ);
		prom_halt();
	}
    
	if(linux_num_cpus > 1) {
		for(cpu = 0; cpu < 4; cpu++)
			sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0;
		sun4m_interrupts->set = SUN4M_INT_E14;
	} else {
		sun4m_timers->cpu_timers[0].l14_timer_limit = 0;
	}
#ifdef __SMP__
	{
		unsigned long flags;
		extern unsigned long lvl14_save[4];
		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];

		/* For SMP we use the level 14 ticker, however the bootup code
		 * has copied the firmwares level 14 vector into boot cpu's
		 * trap table, we must fix this now or we get squashed.
		 */
		__save_and_cli(flags);
		trap_table->inst_one = lvl14_save[0];
		trap_table->inst_two = lvl14_save[1];
		trap_table->inst_three = lvl14_save[2];
		trap_table->inst_four = lvl14_save[3];
		local_flush_cache_all();
		__restore_flags(flags);
	}
#endif
}
Пример #9
0
__initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb))
{
	struct fb_fix_screeninfo *fix = &fb->fix;
	struct display *disp = &fb->disp;
	struct fbtype *type = &fb->type;
	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
	int lowdepth, i, j;

#ifndef FBCON_HAS_CFB8
	return NULL;
#endif

	lowdepth = prom_getbool (fb->prom_node, "tcx-8-bit");
	
	if (lowdepth) {
		strcpy(fb->info.modename, "TCX8");
		strcpy(fix->id, "TCX8");
	} else {
		strcpy(fb->info.modename, "TCX24");
		strcpy(fix->id, "TCX24");
	}
	fix->line_length = fb->var.xres_virtual;
	
	disp->scrollmode = SCROLL_YREDRAW;
	if (!disp->screen_base)
		disp->screen_base = (char *)sparc_alloc_io(phys, 0, 
			type->fb_size, "tcx_ram", fb->iospace, 0);
	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
	fb->s.tcx.tec = (struct tcx_tec *)sparc_alloc_io(fb->sbdp->reg_addrs[7].phys_addr, 0, 
			sizeof(struct tcx_tec), "tcx_tec", fb->iospace, 0);
	fb->s.tcx.thc = (struct tcx_thc *)sparc_alloc_io(fb->sbdp->reg_addrs[9].phys_addr, 0, 
			sizeof(struct tcx_thc), "tcx_thc", fb->iospace, 0);
	fb->s.tcx.bt = (struct bt_regs *)sparc_alloc_io(fb->sbdp->reg_addrs[8].phys_addr, 0, 
			sizeof(struct bt_regs), "tcx_dac", fb->iospace, 0);
	if (!lowdepth) {
		fb->s.tcx.cplane = (u32 *)sparc_alloc_io(fb->sbdp->reg_addrs[4].phys_addr, 0, 
				type->fb_size*4, "tcx_cplane", fb->iospace, 0);
		type->fb_depth = 24;
		fb->switch_from_graph = tcx_switch_from_graph;
	} else {
		/* As there can be one tcx in a machine only, we can write directly into
		   tcx_mmap_map */
		tcx_mmap_map[1].size = SBUS_MMAP_EMPTY;
		tcx_mmap_map[4].size = SBUS_MMAP_EMPTY;
		tcx_mmap_map[5].size = SBUS_MMAP_EMPTY;
		tcx_mmap_map[6].size = SBUS_MMAP_EMPTY;
	}
	fb->dispsw = fbcon_cfb8;

	fb->margins = tcx_margins;
	fb->loadcmap = tcx_loadcmap;
	if (prom_getbool (fb->prom_node, "hw-cursor")) {
		fb->setcursor = tcx_setcursor;
		fb->setcursormap = tcx_setcursormap;
		fb->setcurshape = tcx_setcurshape;
	}
	fb->restore_palette = tcx_restore_palette;
	fb->blank = tcx_blank;
	fb->unblank = tcx_unblank;
	fb->reset = tcx_reset;

	fb->physbase = 0;
	for (i = 0; i < 13; i++) {
		/* tcx_mmap_map has to be sorted by voff, while
		   order of phys registers from PROM differs a little
		   bit. Here is the correction */
		switch (i) {
		case 10: j = 12; break;
		case 11:
		case 12: j = i - 1; break;
		default: j = i; break;
		}
		tcx_mmap_map[i].poff = fb->sbdp->reg_addrs[j].phys_addr;
	}
	fb->mmap_map = tcx_mmap_map;

	/* Initialize Brooktree DAC */
	fb->s.tcx.bt->addr = 0x04 << 24;         /* color planes */
	fb->s.tcx.bt->control = 0xff << 24;
	fb->s.tcx.bt->addr = 0x05 << 24;
	fb->s.tcx.bt->control = 0x00 << 24;
	fb->s.tcx.bt->addr = 0x06 << 24;         /* overlay plane */
	fb->s.tcx.bt->control = 0x73 << 24;
	fb->s.tcx.bt->addr = 0x07 << 24;
	fb->s.tcx.bt->control = 0x00 << 24;

	sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s", fb->iospace, phys,
		    (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_REV_SHIFT) & TCX_THC_REV_REV_MASK,
                    (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_MINREV_SHIFT) & TCX_THC_REV_MINREV_MASK,
		    lowdepth ? "8-bit only" : "24-bit depth");
		    
	tcx_reset(fb);

	return idstring;
}
Пример #10
0
__initfunc(char *cgthreefb_init(struct fb_info_sbusfb *fb))
{
	struct fb_fix_screeninfo *fix = &fb->fix;
	struct display *disp = &fb->disp;
	struct fbtype *type = &fb->type;
	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
	int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL;

#ifndef FBCON_HAS_CFB8
	return NULL;
#endif

	if (!fb->s.cg3.regs) {
		fb->s.cg3.regs = (struct cg3_regs *)sparc_alloc_io(phys+CG3_REGS_OFFSET, 0, 
				sizeof(struct cg3_regs), "cg3_regs", fb->iospace, 0);
		if (cgRDI) {
			char buffer[40];
			char *p;
			int ww, hh;
		
			*buffer = 0;
			prom_getstring (fb->prom_node, "params", buffer, sizeof(buffer));
			if (*buffer) {
				ww = simple_strtoul (buffer, &p, 10);
				if (ww && *p == 'x') {
					hh = simple_strtoul (p + 1, &p, 10);
					if (hh && *p == '-') {
						if (type->fb_width != ww || type->fb_height != hh) {
							type->fb_width = ww;
							type->fb_height = hh;
							return SBUSFBINIT_SIZECHANGE;
						}
					}
				}
			}
		}
	}

	strcpy(fb->info.modename, "CGthree");
	strcpy(fix->id, "CGthree");
	fix->line_length = fb->var.xres_virtual;
	
	disp->scrollmode = SCROLL_YREDRAW;
	if (!disp->screen_base)
		disp->screen_base = (char *)sparc_alloc_io(phys+CG3_RAM_OFFSET, 0, 
			type->fb_size, "cg3_ram", fb->iospace, 0);
	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
	fb->dispsw = fbcon_cfb8;

	fb->margins = cg3_margins;
	fb->loadcmap = cg3_loadcmap;
	fb->blank = cg3_blank;
	fb->unblank = cg3_unblank;
	
	fb->physbase = phys;
	fb->mmap_map = cg3_mmap_map;
	
#ifdef __sparc_v9__	
	sprintf(idstring, "%s at %016lx", cgRDI ? "cgRDI" : "cgthree", phys);
#else
	sprintf(idstring, "%s at %x.%08lx", cgRDI ? "cgRDI" : "cgthree", fb->iospace, phys);
#endif
	
	if (!prom_getbool(fb->prom_node, "width")) {
		/* Ugh, broken PROM didn't initialize us.
		 * Let's deal with this ourselves.
		 */
		enum cg3_type type;
		u8 *p;

		if (cgRDI)
			type = CG3_RDI;
		else {
			u8 status = fb->s.cg3.regs->status, mon;
			if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) {
				mon = status & CG3_SR_RES_MASK;
				if (mon == CG3_SR_1152_900_76_A ||
				    mon == CG3_SR_1152_900_76_B)
					type = CG3_AT_76HZ;
				else
					type = CG3_AT_66HZ;
			} else {
				prom_printf("cgthree: can't handle SR %02x\n",
					    status);
				prom_halt();
				return NULL; /* fool gcc. */
			}
		}

		for (p = cg3_regvals[type]; *p; p += 2)
			((u8 *)fb->s.cg3.regs)[p[0]] = p[1];

		for (p = cg3_dacvals; *p; p += 2) {
			*(volatile u8 *)&fb->s.cg3.regs->cmap.addr = p[0];
			*(volatile u8 *)&fb->s.cg3.regs->cmap.control = p[1];
		}
	}

	return idstring;
}