From: "Noralf Trønnes" <noralf@tronnes.org>
To: dri-devel@lists.freedesktop.org
Cc: intel-gfx@lists.freedesktop.org
Subject: [RFC v4 08/25] drm/fb-helper: Use struct drm_client_display
Date: Sat, 14 Apr 2018 13:53:01 +0200 [thread overview]
Message-ID: <20180414115318.14500-9-noralf@tronnes.org> (raw)
In-Reply-To: <20180414115318.14500-1-noralf@tronnes.org>
Prepare to move the modeset committing code to drm_client.
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
drivers/gpu/drm/drm_fb_helper.c | 161 ++++++++++++++++++++--------------------
include/drm/drm_fb_helper.h | 8 ++
2 files changed, 89 insertions(+), 80 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 2eef24db21f8..bdb4b57d2c12 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <drm/drmP.h>
+#include <drm/drm_client.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
@@ -321,13 +322,14 @@ static bool drm_fb_helper_panel_rotation(struct drm_connector *connector,
return true;
}
-static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active)
+static int drm_client_display_restore_atomic(struct drm_client_display *display, bool active)
{
- struct drm_device *dev = fb_helper->dev;
+ struct drm_device *dev = display->dev;
struct drm_plane_state *plane_state;
+ struct drm_mode_set *mode_set;
struct drm_plane *plane;
struct drm_atomic_state *state;
- int i, ret;
+ int ret;
unsigned int plane_mask;
struct drm_modeset_acquire_ctx ctx;
@@ -363,8 +365,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
goto out_state;
}
- for (i = 0; i < fb_helper->crtc_count; i++) {
- struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+ drm_client_display_for_each_modeset(mode_set, display) {
struct drm_plane *primary = mode_set->crtc->primary;
unsigned int rotation;
@@ -412,13 +413,14 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
goto retry;
}
-static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
+static int drm_client_display_restore_legacy(struct drm_client_display *display)
{
- struct drm_device *dev = fb_helper->dev;
+ struct drm_device *dev = display->dev;
+ struct drm_mode_set *mode_set;
struct drm_plane *plane;
- int i, ret = 0;
+ int ret = 0;
- drm_modeset_lock_all(fb_helper->dev);
+ drm_modeset_lock_all(dev);
drm_for_each_plane(plane, dev) {
if (plane->type != DRM_PLANE_TYPE_PRIMARY)
drm_plane_force_disable(plane);
@@ -429,8 +431,7 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
DRM_MODE_ROTATE_0);
}
- for (i = 0; i < fb_helper->crtc_count; i++) {
- struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+ drm_client_display_for_each_modeset(mode_set, display) {
struct drm_crtc *crtc = mode_set->crtc;
if (crtc->funcs->cursor_set2) {
@@ -448,19 +449,17 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
goto out;
}
out:
- drm_modeset_unlock_all(fb_helper->dev);
+ drm_modeset_unlock_all(dev);
return ret;
}
-static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+static int drm_client_display_restore(struct drm_client_display *display)
{
- struct drm_device *dev = fb_helper->dev;
-
- if (drm_drv_uses_atomic_modeset(dev))
- return restore_fbdev_mode_atomic(fb_helper, true);
+ if (drm_drv_uses_atomic_modeset(display->dev))
+ return drm_client_display_restore_atomic(display, true);
else
- return restore_fbdev_mode_legacy(fb_helper);
+ return drm_client_display_restore_legacy(display);
}
/**
@@ -486,7 +485,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
return 0;
mutex_lock(&fb_helper->lock);
- ret = restore_fbdev_mode(fb_helper);
+ ret = drm_client_display_restore(fb_helper->display);
do_delayed = fb_helper->delayed_hotplug;
if (do_delayed)
@@ -548,7 +547,7 @@ static bool drm_fb_helper_force_kernel_mode(void)
continue;
mutex_lock(&helper->lock);
- ret = restore_fbdev_mode(helper);
+ ret = drm_client_display_restore(helper->display);
if (ret)
error = true;
mutex_unlock(&helper->lock);
@@ -580,22 +579,20 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
#endif
-static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
+static void drm_client_display_dpms_legacy(struct drm_client_display *display, int dpms_mode)
{
- struct drm_device *dev = fb_helper->dev;
+ struct drm_device *dev = display->dev;
struct drm_connector *connector;
struct drm_mode_set *modeset;
- int i, j;
+ int i;
drm_modeset_lock_all(dev);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- modeset = &fb_helper->crtc_info[i].mode_set;
-
+ drm_client_display_for_each_modeset(modeset, display) {
if (!modeset->crtc->enabled)
continue;
- for (j = 0; j < modeset->num_connectors; j++) {
- connector = modeset->connectors[j];
+ for (i = 0; i < modeset->num_connectors; i++) {
+ connector = modeset->connectors[i];
connector->funcs->dpms(connector, dpms_mode);
drm_object_property_set_value(&connector->base,
dev->mode_config.dpms_property, dpms_mode);
@@ -604,23 +601,21 @@ static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
drm_modeset_unlock_all(dev);
}
+static void drm_client_display_dpms(struct drm_client_display *display, int mode)
+{
+ if (drm_drv_uses_atomic_modeset(display->dev))
+ drm_client_display_restore_atomic(display, mode == DRM_MODE_DPMS_ON);
+ else
+ drm_client_display_dpms_legacy(display, mode);
+}
+
static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
{
struct drm_fb_helper *fb_helper = info->par;
- /*
- * For each CRTC in this fb, turn the connectors on/off.
- */
mutex_lock(&fb_helper->lock);
- if (!drm_fb_helper_is_bound(fb_helper)) {
- mutex_unlock(&fb_helper->lock);
- return;
- }
-
- if (drm_drv_uses_atomic_modeset(fb_helper->dev))
- restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON);
- else
- dpms_legacy(fb_helper, dpms_mode);
+ if (drm_fb_helper_is_bound(fb_helper))
+ drm_client_display_dpms(fb_helper->display, dpms_mode);
mutex_unlock(&fb_helper->lock);
}
@@ -811,6 +806,10 @@ int drm_fb_helper_init(struct drm_device *dev,
i++;
}
+ fb_helper->display = drm_client_display_create(dev);
+ if (IS_ERR(fb_helper->display))
+ goto out_free;
+
dev->fb_helper = fb_helper;
return 0;
@@ -919,6 +918,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
mutex_unlock(&kernel_fb_helper_lock);
mutex_destroy(&fb_helper->lock);
+ drm_client_display_free(fb_helper->display);
drm_fb_helper_crtc_free(fb_helper);
}
@@ -1265,13 +1265,14 @@ static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info)
static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
+ struct drm_mode_set *modeset;
struct drm_crtc *crtc;
u16 *r, *g, *b;
- int i, ret = 0;
+ int ret = 0;
drm_modeset_lock_all(fb_helper->dev);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
+ crtc = modeset->crtc;
if (!crtc->funcs->gamma_set || !crtc->gamma_size)
return -EINVAL;
@@ -1347,9 +1348,10 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
struct drm_modeset_acquire_ctx ctx;
struct drm_crtc_state *crtc_state;
struct drm_atomic_state *state;
+ struct drm_mode_set *modeset;
struct drm_crtc *crtc;
u16 *r, *g, *b;
- int i, ret = 0;
+ int ret = 0;
bool replaced;
drm_modeset_acquire_init(&ctx, 0);
@@ -1362,8 +1364,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
state->acquire_ctx = &ctx;
retry:
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
+ crtc = modeset->crtc;
if (!gamma_lut)
gamma_lut = setcmap_new_gamma_lut(crtc, cmap);
@@ -1391,8 +1393,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
if (ret)
goto out_state;
- for (i = 0; i < fb_helper->crtc_count; i++) {
- crtc = fb_helper->crtc_info[i].mode_set.crtc;
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
+ crtc = modeset->crtc;
r = crtc->gamma_store;
g = r + crtc->gamma_size;
@@ -1468,7 +1470,6 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
struct drm_fb_helper *fb_helper = info->par;
- struct drm_mode_set *mode_set;
struct drm_crtc *crtc;
int ret = 0;
@@ -1496,8 +1497,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
* make. If we're not smart enough here, one should
* just consider switch the userspace to KMS.
*/
- mode_set = &fb_helper->crtc_info[0].mode_set;
- crtc = mode_set->crtc;
+ crtc = fb_helper->display->modesets[0].crtc;
/*
* Only wait for a vblank event if the CRTC is
@@ -1651,13 +1651,9 @@ EXPORT_SYMBOL(drm_fb_helper_set_par);
static void pan_set(struct drm_fb_helper *fb_helper, int x, int y)
{
- int i;
-
- for (i = 0; i < fb_helper->crtc_count; i++) {
- struct drm_mode_set *mode_set;
-
- mode_set = &fb_helper->crtc_info[i].mode_set;
+ struct drm_mode_set *mode_set;
+ drm_client_display_for_each_modeset(mode_set, fb_helper->display) {
mode_set->x = x;
mode_set->y = y;
}
@@ -1671,7 +1667,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
pan_set(fb_helper, var->xoffset, var->yoffset);
- ret = restore_fbdev_mode_atomic(fb_helper, true);
+ ret = drm_client_display_restore(fb_helper->display);
if (!ret) {
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
@@ -1687,12 +1683,9 @@ static int pan_display_legacy(struct fb_var_screeninfo *var,
struct drm_fb_helper *fb_helper = info->par;
struct drm_mode_set *modeset;
int ret = 0;
- int i;
drm_modeset_lock_all(fb_helper->dev);
- for (i = 0; i < fb_helper->crtc_count; i++) {
- modeset = &fb_helper->crtc_info[i].mode_set;
-
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
modeset->x = var->xoffset;
modeset->y = var->yoffset;
@@ -1751,6 +1744,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
int crtc_count = 0;
int i;
struct drm_fb_helper_surface_size sizes;
+ struct drm_mode_set *mode_set;
int gamma_size = 0;
memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
@@ -1795,9 +1789,8 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
}
crtc_count = 0;
- for (i = 0; i < fb_helper->crtc_count; i++) {
+ drm_client_display_for_each_modeset(mode_set, fb_helper->display) {
struct drm_display_mode *desired_mode;
- struct drm_mode_set *mode_set;
int x, y, j;
/* in case of tile group, are we the last tile vert or horiz?
* If no tile group you are always the last one both vertically
@@ -1805,19 +1798,18 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
*/
bool lastv = true, lasth = true;
- desired_mode = fb_helper->crtc_info[i].desired_mode;
- mode_set = &fb_helper->crtc_info[i].mode_set;
+ desired_mode = mode_set->mode;
if (!desired_mode)
continue;
crtc_count++;
- x = fb_helper->crtc_info[i].x;
- y = fb_helper->crtc_info[i].y;
+ x = mode_set->x;
+ y = mode_set->y;
if (gamma_size == 0)
- gamma_size = fb_helper->crtc_info[i].mode_set.crtc->gamma_size;
+ gamma_size = mode_set->crtc->gamma_size;
sizes.surface_width = max_t(u32, desired_mode->hdisplay + x, sizes.surface_width);
sizes.surface_height = max_t(u32, desired_mode->vdisplay + y, sizes.surface_height);
@@ -1844,7 +1836,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
/* First time: disable all crtc's.. */
if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master))
- restore_fbdev_mode(fb_helper);
+ drm_client_display_restore(fb_helper->display);
return -EAGAIN;
}
@@ -2379,6 +2371,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
u32 width, u32 height)
{
struct drm_device *dev = fb_helper->dev;
+ struct drm_client_display *display;
struct drm_fb_helper_crtc **crtcs;
struct drm_display_mode **modes;
struct drm_fb_offset *offsets;
@@ -2402,6 +2395,10 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
goto out;
}
+ display = drm_client_display_create(dev);
+ if (IS_ERR(display))
+ goto out;
+
mutex_lock(&fb_helper->dev->mode_config.mutex);
if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0)
DRM_DEBUG_KMS("No connectors reported connected with modes\n");
@@ -2440,24 +2437,29 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
struct drm_fb_offset *offset = &offsets[i];
if (mode && fb_crtc) {
- struct drm_mode_set *modeset = &fb_crtc->mode_set;
struct drm_connector *connector =
fb_helper->connector_info[i]->connector;
+ struct drm_mode_set *modeset;
+
+ modeset = drm_client_display_find_modeset(display, fb_crtc->mode_set.crtc);
+ if (WARN_ON(!modeset)) {
+ drm_client_display_free(display);
+ goto out;
+ }
DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
- mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
+ mode->name, modeset->crtc->base.id, offset->x, offset->y);
- fb_crtc->desired_mode = mode;
- fb_crtc->x = offset->x;
- fb_crtc->y = offset->y;
- modeset->mode = drm_mode_duplicate(dev,
- fb_crtc->desired_mode);
+ modeset->mode = drm_mode_duplicate(dev, mode);
drm_connector_get(connector);
modeset->connectors[modeset->num_connectors++] = connector;
modeset->x = offset->x;
modeset->y = offset->y;
}
}
+
+ drm_client_display_free(fb_helper->display);
+ fb_helper->display = display;
out:
kfree(crtcs);
kfree(modes);
@@ -2476,11 +2478,10 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
{
struct fb_info *info = fb_helper->fbdev;
unsigned int rotation, sw_rotations = 0;
+ struct drm_mode_set *modeset;
int i;
- for (i = 0; i < fb_helper->crtc_count; i++) {
- struct drm_mode_set *modeset = &fb_helper->crtc_info[i].mode_set;
-
+ drm_client_display_for_each_modeset(modeset, fb_helper->display) {
if (!modeset->num_connectors)
continue;
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index d1e45c832cd5..e2df40ad5063 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -155,6 +155,14 @@ struct drm_fb_helper_connector {
struct drm_fb_helper {
struct drm_framebuffer *fb;
struct drm_device *dev;
+
+ /**
+ * @display:
+ *
+ * Display representation.
+ */
+ struct drm_client_display *display;
+
int crtc_count;
struct drm_fb_helper_crtc *crtc_info;
int connector_count;
--
2.15.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2018-04-14 11:53 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-14 11:52 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 01/25] drm: provide management functions for drm_file Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 02/25] drm/file: Don't set master on in-kernel clients Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 03/25] drm/fb-helper: No need to cache rotation and sw_rotations Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 04/25] drm/fb-helper: Remove drm_fb_helper_debug_enter/leave() Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 05/25] drm/fb-helper: dpms_legacy(): Only set on connectors in use Noralf Trønnes
2018-04-14 11:52 ` [RFC v4 06/25] drm/atomic: Move __drm_atomic_helper_disable_plane/set_config() Noralf Trønnes
2018-04-16 8:30 ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 07/25] drm: Begin an API for in-kernel clients Noralf Trønnes
2018-04-14 11:53 ` Noralf Trønnes [this message]
2018-04-14 11:53 ` [RFC v4 09/25] drm/fb-helper: Move modeset commit code to drm_client Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 10/25] drm/connector: Add drm_connector_has_preferred_mode/pick_cmdline_mode() Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 11/25] drm/connector: Add connector array functions Noralf Trønnes
2018-04-16 8:33 ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 12/25] drm/i915: Add drm_driver->initial_client_display callback Noralf Trønnes
2018-04-16 8:38 ` Daniel Vetter
2019-03-01 11:46 ` [Intel-gfx] " Noralf Trønnes
2019-03-01 11:51 ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 13/25] drm/fb-helper: Remove struct drm_fb_helper_crtc Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 14/25] drm/fb-helper: Remove struct drm_fb_helper_connector Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 15/25] drm/fb-helper: Move modeset config code to drm_client Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 16/25] drm: Make ioctls available for in-kernel clients Noralf Trønnes
2018-04-16 9:04 ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 17/25] drm/client: Bail out if there's a DRM master Noralf Trønnes
2018-04-16 8:45 ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 18/25] drm/client: Make the display modes available to clients Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 19/25] drm/client: Finish the in-kernel client API Noralf Trønnes
2018-04-16 8:27 ` [Intel-gfx] " Daniel Vetter
2018-04-16 15:58 ` Noralf Trønnes
2018-04-17 8:08 ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 20/25] drm/prime: Don't pin module on export for in-kernel clients Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 21/25] drm/fb-helper: Add drm_fb_helper_fb_open/release() Noralf Trønnes
2018-04-16 8:46 ` Daniel Vetter
2018-04-16 16:10 ` Noralf Trønnes
2018-04-17 8:14 ` [Intel-gfx] " Daniel Vetter
2018-04-14 11:53 ` [RFC v4 22/25] drm/fb-helper: Add generic fbdev emulation Noralf Trønnes
2018-04-16 8:52 ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 23/25] drm: Add DRM device registered notifier Noralf Trønnes
2018-04-17 10:16 ` Daniel Vetter
2018-04-14 11:53 ` [RFC v4 24/25] drm/client: Hack: Add bootsplash Noralf Trønnes
2018-04-14 11:53 ` [RFC v4 25/25] drm/client: Hack: Add DRM VT console client Noralf Trønnes
2018-04-16 8:21 ` [RFC v4 00/25] drm: Add generic fbdev emulation Daniel Vetter
2018-04-16 18:49 ` Noralf Trønnes
2018-04-17 8:10 ` [Intel-gfx] " Daniel Vetter
-- strict thread matches above, loose matches on Subject: below --
2018-04-13 16:53 Noralf Trønnes
2018-04-13 16:53 ` [RFC v4 08/25] drm/fb-helper: Use struct drm_client_display Noralf Trønnes
2018-04-12 13:17 [RFC v4 00/25] drm: Add generic fbdev emulation Noralf Trønnes
2018-04-12 13:17 ` [RFC v4 08/25] drm/fb-helper: Use struct drm_client_display Noralf Trønnes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180414115318.14500-9-noralf@tronnes.org \
--to=noralf@tronnes.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).