From: Ted Bullock Subject: Re: Testing Radeon console fixes on sparc64 To: Pekka Niiranen Cc: tech@openbsd.org Date: Sun, 1 Nov 2026 11:50:30 -0500 Hi Pekka, Here is my Radeon DRM console patch. I think this should let the console actually render with that video card, because otherwise it's broken. This includes the DMA fix. I haven't compiled this version yet. Save the diff below in /usr/src as sparc64-radeon-console-7.9-stable.patch and apply it: cd /usr/src doas patch -C -p0 < sparc64-radeon-console-7.9-stable.patch doas patch -p0 < sparc64-radeon-console-7.9-stable.patch If that succeeds, rebuild your GENERIC.MP kernel as usual. It looks like you have radeondrm disabled. You'll need to enable it for this test. Boot the patched kernel with -c, then at the UKC prompt: enable radeondrm quit Keep your working kernel available so you can boot back into it. Give it a shot and let me know how it goes. To undo the source changes: cd /usr/src doas patch -R -p0 < sparc64-radeon-console-7.9-stable.patch Thanks, Ted --- sys/dev/pci/drm/radeon/radeon.h +++ sys/dev/pci/drm/radeon/radeon.h @@ -2326,6 +2326,7 @@ struct radeon_device { bus_space_tag_t memt; bus_dma_tag_t dmat; void *irqh; + bool dma_limited; void (*switchcb)(void *, int, int); void *switchcbarg; --- sys/dev/pci/drm/radeon/radeon_device.c +++ sys/dev/pci/drm/radeon/radeon_device.c @@ -1392,6 +1392,13 @@ int radeon_device_init(struct radeon_device *rdev, } rdev->need_swiotlb = drm_need_swiotlb(dma_bits); + /* disabling sparc64 iommu requires 64 bits */ +#ifdef __sparc64__ + rdev->dma_limited = true; +#else + rdev->dma_limited = dma_bits <= 32; +#endif + /* Registers mapping */ /* TODO: block userspace mapping of io register */ mtx_init(&rdev->mmio_idx_lock, IPL_TTY); --- sys/dev/pci/drm/radeon/radeon_ttm.c +++ sys/dev/pci/drm/radeon/radeon_ttm.c @@ -717,7 +717,7 @@ int radeon_ttm_init(struct radeon_device *rdev) /*rdev_to_drm(rdev)->anon_inode->i_mapping*/NULL, rdev_to_drm(rdev)->vma_offset_manager, rdev->need_swiotlb, - dma_addressing_limited(&rdev->pdev->dev)); + rdev->dma_limited); #endif if (r) { DRM_ERROR("failed initializing buffer object driver(%d).\n", r); --- sys/dev/pci/drm/radeon/radeon_display.c +++ sys/dev/pci/drm/radeon/radeon_display.c @@ -34,10 +34,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -626,6 +628,11 @@ struct drm_crtc *crtc; bool active = false; int ret; +#ifdef __sparc64__ + const unsigned char *p; + uint16_t *r, *g, *b; + int i; +#endif if (!set || !set->crtc) return -EINVAL; @@ -639,6 +646,26 @@ } ret = drm_crtc_helper_set_config(set, ctx); + +#ifdef __sparc64__ + /* When returning from X, we may need to restore the colour table. */ + if (ret == 0 && set->fb && + set->fb->format->format == DRM_FORMAT_C8) { + if (dev->fb_helper && set->fb == dev->fb_helper->fb) { + p = rasops_cmap; + r = set->crtc->gamma_store; + g = r + set->crtc->gamma_size; + b = g + set->crtc->gamma_size; + + for (i = 0; i < 256; i++) { + r[i] = *p++ << 8; + g[i] = *p++ << 8; + b[i] = *p++ << 8; + } + radeon_crtc_load_lut(set->crtc); + } + } +#endif list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) if (crtc->enabled) @@ -678,10 +705,69 @@ .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, }; +/* + * Sun firmware typically selects an indexed pixel format for its console. + * drm_crtc_init() advertises only 32-bit formats, so fbdev rejects C8 + * despite driver support. Add C8 for fbdev. + */ +#ifdef __sparc64__ +static const uint32_t sparc_fmt[3] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_C8 +}; + +/* + * The primary DRM plane scans out the framebuffer to the display. We will + * use this modesetting operation since we just need the 8bit C8 pixel + * format to be compatible with the Sun firmware. + */ +static const struct drm_plane_funcs sparc_plane_funcs = { + DRM_PLANE_NON_ATOMIC_FUNCS, +}; + +static int +radeon_crtc_init_indexed(struct drm_device *dev, struct drm_crtc *crtc) +{ + struct drm_plane *primary; + int ret; + + primary = __drm_universal_plane_alloc( + dev, + sizeof(*primary), + 0, + 0, + &sparc_plane_funcs, + sparc_fmt, + ARRAY_SIZE(sparc_fmt), + NULL, + DRM_PLANE_TYPE_PRIMARY, + NULL); + if (IS_ERR(primary)) + return PTR_ERR(primary); + + /* Incomplete pixel format list */ + primary->format_default = true; + ret = drm_crtc_init_with_planes( + dev, + crtc, + primary, + NULL, + &radeon_crtc_funcs, + NULL); + if (ret != 0) { + drm_plane_cleanup(primary); + kfree(primary); + } + return ret; +} +#endif + static void radeon_crtc_init(struct drm_device *dev, int index) { struct radeon_device *rdev = dev->dev_private; struct radeon_crtc *radeon_crtc; + int ret; radeon_crtc = kzalloc(sizeof(*radeon_crtc), GFP_KERNEL); if (radeon_crtc == NULL) @@ -693,7 +779,17 @@ return; } - drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs); + /* Advertise C8 for the SPARC console preference. */ +#ifdef __sparc64__ + ret = radeon_crtc_init_indexed(dev, &radeon_crtc->base); +#else + ret = drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs); +#endif + if (ret != 0) { + destroy_workqueue(radeon_crtc->flip_queue); + kfree(radeon_crtc); + return; + } drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); radeon_crtc->crtc_id = index; --- sys/dev/pci/drm/radeon/radeon_drv.c +++ sys/dev/pci/drm/radeon/radeon_drv.c @@ -742,9 +742,6 @@ void (*)(void *, int, int), void *); void radeondrm_doswitch(void *); void radeondrm_enter_ddb(void *, void *); -#ifdef __sparc64__ -void radeondrm_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); -#endif void radeondrm_setpal(struct radeon_device *, struct rasops_info *); struct wsscreen_descr radeondrm_stdscreen = { @@ -863,11 +860,7 @@ struct radeon_device *rdev = ri->ri_hw; rasops_show_screen(ri, rdev->switchcookie, 0, NULL, NULL); -#ifdef __sparc64__ - fbwscons_setcolormap(&rdev->sf, radeondrm_setcolor); -#else radeondrm_setpal(rdev, ri); -#endif drm_fb_helper_restore_fbdev_mode_unlocked(rdev_to_drm(rdev)->fb_helper); if (rdev->switchcb) @@ -887,25 +880,6 @@ rasops_show_screen(ri, cookie, 0, NULL, NULL); drm_fb_helper_debug_enter(fb_helper->info); } - -#ifdef __sparc64__ -void -radeondrm_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) -{ - struct sunfb *sf = v; - struct radeon_device *rdev = sf->sf_ro.ri_hw; - - /* see legacy_crtc_load_lut() */ - if (rdev->family < CHIP_RS600) { - WREG8(RADEON_PALETTE_INDEX, index); - WREG32(RADEON_PALETTE_30_DATA, - (r << 22) | (g << 12) | (b << 2)); - } else { - printf("%s: setcolor family %d not handled\n", - rdev->self.dv_xname, rdev->family); - } -} -#endif void radeondrm_setpal(struct radeon_device *rdev, struct rasops_info *ri) @@ -1167,7 +1141,10 @@ ri->ri_hw = rdev; ri->ri_updatecursor = NULL; - fbwscons_init(&rdev->sf, RI_VCONS | RI_WRONLY | RI_BSWAP, console); + /* + * Keep the early Sun firmware console until DRM allocates its own buffer. + */ + fbwscons_init(&rdev->sf, RI_BSWAP, console); if (console) fbwscons_console_init(&rdev->sf, -1); } @@ -1279,21 +1256,35 @@ else format = NULL; + /* + * If the firmware uses an 8bit console, keep that pixel format when + * setting up the new KMS framebuffer. + */ +#ifdef __sparc64__ + if (rdev->sf.sf_depth == 8) + format = drm_format_info(DRM_FORMAT_C8); +#endif + drm_client_setup(dev, format); if (ri->ri_bits == NULL) return; -#ifdef __sparc64__ - fbwscons_setcolormap(&rdev->sf, radeondrm_setcolor); - ri = &rdev->sf.sf_ro; -#else radeondrm_setpal(rdev, ri); ri->ri_flg = RI_CENTER | RI_VCONS | RI_WRONLY; + /* + * Centre the firmware text geometry in the new KMS mode. Avoid + * RI_FULLCLEAR during normal operation so erases stay inside the + * text area; clear the margins once below with the console colour. + */ +#ifdef __sparc64__ + ri->ri_flg |= RI_BSWAP; + rasops_init(ri, rdev->sf.sf_ro.ri_rows, rdev->sf.sf_ro.ri_cols); +#else rasops_init(ri, 160, 160); +#endif ri->ri_hw = rdev; -#endif radeondrm_stdscreen.capabilities = ri->ri_caps; radeondrm_stdscreen.nrows = ri->ri_rows; @@ -1313,6 +1304,15 @@ uint32_t defattr; ri->ri_ops.pack_attr(ri->ri_active, 0, 0, 0, &defattr); +#ifdef __sparc64__ + /* + * Rasops has no full framebuffer clear, so use this workaround + * to clear the margins too. + */ + ri->ri_flg |= RI_FULLCLEAR; + ri->ri_ops.eraserows(ri->ri_active, 0, ri->ri_rows, defattr); + ri->ri_flg &= ~RI_FULLCLEAR; +#endif wsdisplay_cnattach(&radeondrm_stdscreen, ri->ri_active, ri->ri_ccol, ri->ri_crow, defattr); } --- sys/dev/rasops/rasops8.c +++ sys/dev/rasops/rasops8.c @@ -50,6 +50,7 @@ */ static int32_t stamp[16]; static uint32_t stamp_attr; +static struct rasops_info *stamp_ri; static int stamp_mutex; /* XXX see note in README */ #endif @@ -170,6 +171,7 @@ fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff; bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff; stamp_attr = attr; + stamp_ri = ri; for (i = 0; i < 16; i++) { #if BYTE_ORDER == LITTLE_ENDIAN @@ -222,7 +224,7 @@ #endif /* Recompute stamp? */ - if (attr != stamp_attr) + if (ri != stamp_ri || attr != stamp_attr) rasops8_makestamp(ri, attr); rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); @@ -290,7 +292,7 @@ #endif /* Recompute stamp? */ - if (attr != stamp_attr) + if (ri != stamp_ri || attr != stamp_attr) rasops8_makestamp(ri, attr); rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); @@ -361,7 +363,7 @@ #endif /* Recompute stamp? */ - if (attr != stamp_attr) + if (ri != stamp_ri || attr != stamp_attr) rasops8_makestamp(ri, attr); rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale); On Sat, 31 Oct 2026 20:11:09 +0200, Pekka Niiranen wrote: > Hi, > > I saw that long discussion in openbsd.tech after your previous email > and decided to wait for the consensus. > > The server is currently running v7.9 with all 40 official patches installed. > > -pekka- > > On 27.10.2026 3.29, Ted Bullock wrote: > > Hi Pekka, > > > > I've attached an updated console patch against current OpenBSD head, > > 3da5d7fe. This covers the Radeon console setup and the rasops8 fix. The DMA > > allocation fix for the CAFEDEAD problem is already in current OpenBSD, so > > that isn't duplicated here. > > > > Are you still running 7.9 on the Ultra 45? Please send uname -a and a current > > dmesg. The attached patch is for current source, so please don't apply it > > to 7.9 or on top of the earlier patches. > > > > I can prepare a version for your source tree, or a kernel for you to try, > > once we have the exact version. > > > > Thanks, > > Ted