public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* PATCH: via audio 1.1.15-pre1
@ 2001-06-07 20:10 Jeff Garzik
  0 siblings, 0 replies; only message in thread
From: Jeff Garzik @ 2001-06-07 20:10 UTC (permalink / raw)
  To: Linux Kernel Mailing List, linux-via

[-- Attachment #1: Type: text/plain, Size: 447 bytes --]

Attached is a patch against kernel 2.4.6-pre1 which includes fixes for
via audio.  It -should- patch against kernel 2.4.3 or later, though.

I'm interested in feedback from people having via audio problems, if
this patch fixes them.  I am of course also interested in general
testing, to ensure I did not break anything in the process of fixing
things.  :)

-- 
Jeff Garzik      | Andre the Giant has a posse.
Building 1024    |
MandrakeSoft     |

[-- Attachment #2: via-pre1.patch --]
[-- Type: text/plain, Size: 16526 bytes --]

Index: linux_2_4/drivers/sound/via82cxxx_audio.c
diff -u linux_2_4/drivers/sound/via82cxxx_audio.c:1.1.1.19 linux_2_4/drivers/sound/via82cxxx_audio.c:1.1.1.19.2.2
--- linux_2_4/drivers/sound/via82cxxx_audio.c:1.1.1.19	Mon Jun  4 19:43:41 2001
+++ linux_2_4/drivers/sound/via82cxxx_audio.c	Thu Jun  7 13:04:28 2001
@@ -15,7 +15,7 @@
  */
 
 
-#define VIA_VERSION	"1.1.14b"
+#define VIA_VERSION	"1.1.15-pre1"
 
 
 #include <linux/config.h>
@@ -92,6 +92,7 @@
 #endif
 
 /* 82C686 function 5 (audio codec) PCI configuration registers */
+#define VIA_ACLINK_STATUS	0x40
 #define VIA_ACLINK_CTRL		0x41
 #define VIA_FUNC_ENABLE		0x42
 #define VIA_PNP_CONTROL		0x43
@@ -187,6 +188,7 @@
 /* controller base 0 register bitmasks */
 #define VIA_INT_DISABLE_MASK		(~(0x01|0x02))
 #define VIA_SGD_STOPPED			(1 << 2)
+#define VIA_SGD_PAUSED			(1 << 6)
 #define VIA_SGD_ACTIVE			(1 << 7)
 #define VIA_SGD_TERMINATE		(1 << 6)
 #define VIA_SGD_FLAG			(1 << 0)
@@ -381,7 +383,7 @@
  *
  */
 
-static inline void via_chan_stop (int iobase)
+static inline void via_chan_stop (long iobase)
 {
 	if (inb (iobase + VIA_PCM_STATUS) & VIA_SGD_ACTIVE)
 		outb (VIA_SGD_TERMINATE, iobase + VIA_PCM_CONTROL);
@@ -402,7 +404,7 @@
  *
  */
 
-static inline void via_chan_status_clear (int iobase)
+static inline void via_chan_status_clear (long iobase)
 {
 	u8 tmp = inb (iobase + VIA_PCM_STATUS);
 
@@ -425,6 +427,19 @@
 }
 
 
+static int sg_active (long iobase)
+{
+	u8 tmp = inb (iobase + VIA_PCM_STATUS);
+	if ((tmp & VIA_SGD_STOPPED) || (tmp & VIA_SGD_PAUSED)) {
+		printk(KERN_WARNING "via82cxxx warning: SG stopped or paused\n");
+		return 0;
+	}
+	if (tmp & VIA_SGD_ACTIVE)
+		return 1;
+	return 0;
+}
+
+
 /****************************************************************
  *
  * Miscellaneous debris
@@ -467,6 +482,8 @@
 
 static void via_stop_everything (struct via_info *card)
 {
+	u8 tmp, new_tmp;
+	
 	DPRINTK ("ENTER\n");
 
 	assert (card != NULL);
@@ -486,11 +503,32 @@
 	via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
 
 	/*
-	 * clear any enabled interrupt bits, reset to 8-bit mono PCM mode
+	 * clear any enabled interrupt bits
 	 */
-	outb (0, card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
-	outb (0, card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
-	outb (0, card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
+	tmp = inb (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
+	new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
+	if (tmp != new_tmp)
+		outb (0, card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
+
+	tmp = inb (card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
+	new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
+	if (tmp != new_tmp)
+		outb (0, card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
+
+	tmp = inb (card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
+	new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
+	if (tmp != new_tmp)
+		outb (0, card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
+
+	udelay(10);
+	
+	/*
+	 * clear any existing flags
+	 */
+	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
+	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
+	via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
+
 	DPRINTK ("EXIT\n");
 }
 
@@ -515,6 +553,8 @@
 
 	DPRINTK ("ENTER, rate = %d\n", rate);
 
+	if (chan->rate == rate)
+		goto out;
 	if (card->locked_rate) {
 		chan->rate = 48000;
 		goto out;
@@ -762,17 +802,17 @@
 {
 	DPRINTK ("ENTER\n");
 
-	synchronize_irq();
-
 	spin_lock_irq (&card->lock);
 
 	/* stop any existing channel output */
+	via_chan_status_clear (chan->iobase);
 	via_chan_stop (chan->iobase);
 	via_chan_status_clear (chan->iobase);
-	via_chan_pcm_fmt (chan, 1);
 
 	spin_unlock_irq (&card->lock);
 
+	synchronize_irq();
+
 	DPRINTK ("EXIT\n");
 }
 
@@ -840,7 +880,7 @@
 	/* if we are recording, enable recording fifo bit */
 	if (chan->is_record)
 		chan->pcm_fmt |= VIA_PCM_REC_FIFO;
-	/* set interrupt select bits where applicable (PCM & FM out channels) */
+	/* set interrupt select bits where applicable (PCM in & out channels) */
 	if (!chan->is_record)
 		chan->pcm_fmt |= VIA_CHAN_TYPE_INT_SELECT;
 
@@ -1142,6 +1182,8 @@
 
 static inline void via_chan_maybe_start (struct via_channel *chan)
 {
+	assert (chan->is_active == sg_active(chan->iobase));
+	
 	if (!chan->is_active && chan->is_enabled) {
 		chan->is_active = 1;
 		sg_begin (chan);
@@ -1405,20 +1447,43 @@
 #endif
 
         /*
-         * reset AC97 controller: enable, disable, enable
-         * pause after each command for good luck
+         * Reset AC97 controller: enable, disable, enable,
+         * pausing after each command for good luck.  Only
+	 * do this if the codec is not ready, because it causes
+	 * loud pops and such due to such a hard codec reset.
          */
-        pci_write_config_byte (pdev, VIA_ACLINK_CTRL, VIA_CR41_AC97_ENABLE |
-                               VIA_CR41_AC97_RESET | VIA_CR41_AC97_WAKEUP);
-        udelay (100);
-
-        pci_write_config_byte (pdev, VIA_ACLINK_CTRL, 0);
-        udelay (100);
-
-        pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
-			       VIA_CR41_AC97_ENABLE | VIA_CR41_PCM_ENABLE |
-                               VIA_CR41_VRA | VIA_CR41_AC97_RESET);
-        udelay (100);
+	pci_read_config_byte (pdev, VIA_ACLINK_STATUS, &tmp8);
+	if ((tmp8 & VIA_CR40_AC97_READY) == 0) {
+        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
+				       VIA_CR41_AC97_ENABLE |
+                		       VIA_CR41_AC97_RESET |
+				       VIA_CR41_AC97_WAKEUP);
+        	udelay (100);
+
+        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL, 0);
+        	udelay (100);
+
+        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
+				       VIA_CR41_AC97_ENABLE |
+				       VIA_CR41_PCM_ENABLE |
+                		       VIA_CR41_VRA | VIA_CR41_AC97_RESET);
+        	udelay (100);
+	}
+
+	/* Make sure VRA is enabled, in case we didn't do a
+	 * complete codec reset, above
+	 */
+	pci_read_config_byte (pdev, VIA_ACLINK_CTRL, &tmp8);
+	if (((tmp8 & VIA_CR41_VRA) == 0) ||
+	    ((tmp8 & VIA_CR41_AC97_ENABLE) == 0) ||
+	    ((tmp8 & VIA_CR41_PCM_ENABLE) == 0) ||
+	    ((tmp8 & VIA_CR41_AC97_RESET) == 0)) {
+        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
+				       VIA_CR41_AC97_ENABLE |
+				       VIA_CR41_PCM_ENABLE |
+                		       VIA_CR41_VRA | VIA_CR41_AC97_RESET);
+        	udelay (100);
+	}
 
 #if 0 /* this breaks on K7M */
 	/* disable legacy stuff */
@@ -1435,20 +1500,10 @@
 
 	/* WARNING: this line is magic.  Remove this
 	 * and things break. */
-	/* enable variable rate, variable rate MIC ADC */
- 	/*
- 	 * If we cannot enable VRA, we have a locked-rate codec.
- 	 * We try again to enable VRA before assuming so, however.
- 	 */
+	/* enable variable rate */
  	tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
- 	if ((tmp16 & 1) == 0) {
+ 	if ((tmp16 & 1) == 0)
  		via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
- 		tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
- 		if ((tmp16 & 1) == 0) {
- 			card->locked_rate = 1;
- 			printk (KERN_WARNING PFX "Codec rate locked at 48Khz\n");
- 		}
- 	}
 
 	DPRINTK ("EXIT, returning 0\n");
 	return 0;
@@ -1496,10 +1551,24 @@
 		goto err_out;
 	}
 
-	/* enable variable rate, variable rate MIC ADC */
+	/* enable variable rate */
 	tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
 	via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
 
+ 	/*
+ 	 * If we cannot enable VRA, we have a locked-rate codec.
+ 	 * We try again to enable VRA before assuming so, however.
+ 	 */
+ 	tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
+ 	if ((tmp16 & 1) == 0) {
+ 		via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
+ 		tmp16 = via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS);
+ 		if ((tmp16 & 1) == 0) {
+ 			card->locked_rate = 1;
+ 			printk (KERN_WARNING PFX "Codec rate locked at 48Khz\n");
+ 		}
+ 	}
+
 	DPRINTK ("EXIT, returning 0\n");
 	return 0;
 
@@ -1649,47 +1718,6 @@
 
 
 /**
- *	via_interrupt_disable - Disable all interrupt-generating sources
- *	@card: Private info for specified board
- *
- *	Disables all interrupt-generation flags in the Via
- *	audio hardware registers.
- */
-
-static void via_interrupt_disable (struct via_info *card)
-{
-	u8 tmp8;
-	unsigned long flags;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-
-	spin_lock_irqsave (&card->lock, flags);
-
-	pci_read_config_byte (card->pdev, VIA_FM_NMI_CTRL, &tmp8);
-	if ((tmp8 & VIA_CR48_FM_TRAP_TO_NMI) == 0) {
-		tmp8 |= VIA_CR48_FM_TRAP_TO_NMI;
-		pci_write_config_byte (card->pdev, VIA_FM_NMI_CTRL, tmp8);
-	}
-
-	outb (inb (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE) &
-	      VIA_INT_DISABLE_MASK,
-	      card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
-	outb (inb (card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE) &
-	      VIA_INT_DISABLE_MASK,
-	      card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
-	outb (inb (card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE) &
-	      VIA_INT_DISABLE_MASK,
-	      card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
-
-	spin_unlock_irqrestore (&card->lock, flags);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-/**
  *	via_interrupt_init - Initialize interrupt handling
  *	@card: Private info for specified board
  *
@@ -1700,6 +1728,8 @@
 
 static int via_interrupt_init (struct via_info *card)
 {
+	u8 tmp8;
+
 	DPRINTK ("ENTER\n");
 
 	assert (card != NULL);
@@ -1713,6 +1743,13 @@
 		return -EIO;
 	}
 
+	/* make sure FM irq is not routed to us */
+	pci_read_config_byte (card->pdev, VIA_FM_NMI_CTRL, &tmp8);
+	if ((tmp8 & VIA_CR48_FM_TRAP_TO_NMI) == 0) {
+		tmp8 |= VIA_CR48_FM_TRAP_TO_NMI;
+		pci_write_config_byte (card->pdev, VIA_FM_NMI_CTRL, tmp8);
+	}
+
 	if (request_irq (card->pdev->irq, via_interrupt, SA_SHIRQ, VIA_MODULE_NAME, card)) {
 		printk (KERN_ERR PFX "unable to obtain IRQ %d, aborting\n",
 			card->pdev->irq);
@@ -1720,38 +1757,11 @@
 		return -EBUSY;
 	}
 
-	/* we don't want interrupts until we're opened */
-	via_interrupt_disable (card);
-
 	DPRINTK ("EXIT, returning 0\n");
 	return 0;
 }
 
 
-/**
- *	via_interrupt_cleanup - Shutdown driver interrupt handling
- *	@card: Private info for specified board
- *
- *	Disable any potential interrupt sources in the Via audio
- *	hardware, and then release (un-reserve) the IRQ line
- *	in the kernel core.
- */
-
-static void via_interrupt_cleanup (struct via_info *card)
-{
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-	assert (card->pdev != NULL);
-
-	via_interrupt_disable (card);
-
-	free_irq (card->pdev->irq, card);
-
-	DPRINTK ("EXIT\n");
-}
-
-
 /****************************************************************
  *
  * OSS DSP device
@@ -1983,17 +1993,16 @@
 	tmp = atomic_read (&chan->n_frags);
 	assert (tmp >= 0);
 	assert (tmp <= chan->frag_number);
-	while (tmp == 0) {
+	if (tmp == 0) {
+	    	int ret;
 		if (nonblock || !chan->is_active)
 			return -EAGAIN;
 
 		DPRINTK ("Sleeping on block %d\n", n);
-		interruptible_sleep_on (&chan->wait);
-
-		if (signal_pending (current))
-			return -ERESTARTSYS;
-
-		tmp = atomic_read (&chan->n_frags);
+		ret = wait_event_interruptible(chan->wait,
+				(tmp = atomic_read(&chan->n_frags)));
+		if (ret < 0)
+			return ret;
 	}
 
 	/* Now that we have a buffer we can read from, send
@@ -2001,10 +2010,12 @@
 	 */
 	while ((count > 0) && (chan->slop_len < chan->frag_size)) {
 		size_t slop_left = chan->frag_size - chan->slop_len;
+		void *base = chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr;
+		unsigned ofs = n % (PAGE_SIZE / chan->frag_size);
 
 		size = (count < slop_left) ? count : slop_left;
 		if (copy_to_user (userbuf,
-				  chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr + n % (PAGE_SIZE / chan->frag_size) + chan->slop_len,
+				  base + ofs + chan->slop_len,
 				  size))
 			return -EFAULT;
 
@@ -2130,17 +2141,16 @@
 	tmp = atomic_read (&chan->n_frags);
 	assert (tmp >= 0);
 	assert (tmp <= chan->frag_number);
-	while (tmp == 0) {
+	if (tmp == 0) {
+	    	int ret;
 		if (nonblock || !chan->is_enabled)
 			return -EAGAIN;
 
 		DPRINTK ("Sleeping on page %d, tmp==%d, ir==%d\n", n, tmp, chan->is_record);
-		interruptible_sleep_on (&chan->wait);
-
-		if (signal_pending (current))
-			return -ERESTARTSYS;
-
-		tmp = atomic_read (&chan->n_frags);
+		ret = wait_event_interruptible(chan->wait,
+				(tmp = atomic_read(&chan->n_frags)));
+		if (ret < 0)
+		    	return ret;
 	}
 
 	/* Now that we have at least one fragment we can write to, fill the buffer
@@ -2263,36 +2273,30 @@
 static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wait)
 {
 	struct via_info *card;
-	unsigned int mask = 0, rd, wr;
+	struct via_channel *chan;
+	unsigned int mask = 0;
 
 	DPRINTK ("ENTER\n");
 
 	assert (file != NULL);
 	card = file->private_data;
 	assert (card != NULL);
-
-	rd = (file->f_mode & FMODE_READ);
-	wr = (file->f_mode & FMODE_WRITE);
 
-	if (wr && (atomic_read (&card->ch_out.n_frags) == 0)) {
-		assert (card->ch_out.is_active);
-                poll_wait(file, &card->ch_out.wait, wait);
-	}
-        if (rd) {
-		/* XXX is it ok, spec-wise, to start DMA here? */
-		if (!card->ch_in.is_active) {
-			via_chan_set_buffering(card, &card->ch_in, -1);
-			via_chan_buffer_init(card, &card->ch_in);
-		}
-		via_chan_maybe_start (&card->ch_in);
-		if (atomic_read (&card->ch_in.n_frags) == 0)
-	                poll_wait(file, &card->ch_in.wait, wait);
+	if (file->f_mode & FMODE_READ) {
+		chan = &card->ch_in;
+		if (sg_active (chan->iobase))
+	                poll_wait(file, &chan->wait, wait);
+		if (atomic_read (&chan->n_frags) > 0)
+			mask |= POLLIN | POLLRDNORM;
 	}
 
-	if (wr && ((atomic_read (&card->ch_out.n_frags) > 0) || !card->ch_out.is_active))
-		mask |= POLLOUT | POLLWRNORM;
-	if (rd && (atomic_read (&card->ch_in.n_frags) > 0))
-		mask |= POLLIN | POLLRDNORM;
+	if (file->f_mode & FMODE_WRITE) {
+		chan = &card->ch_out;
+		if (sg_active (chan->iobase))
+	                poll_wait(file, &chan->wait, wait);
+		if (atomic_read (&chan->n_frags) > 0)
+			mask |= POLLOUT | POLLWRNORM;
+	}
 
 	DPRINTK ("EXIT, returning %u\n", mask);
 	return mask;
@@ -2324,7 +2328,8 @@
 
 	via_chan_maybe_start (chan);
 
-	while (atomic_read (&chan->n_frags) < chan->frag_number) {
+	if (atomic_read (&chan->n_frags) < chan->frag_number) {
+	    	int ret;
 		if (nonblock) {
 			DPRINTK ("EXIT, returning -EAGAIN\n");
 			return -EAGAIN;
@@ -2357,11 +2362,11 @@
 #endif
 
 		DPRINTK ("sleeping, nbufs=%d\n", atomic_read (&chan->n_frags));
-		interruptible_sleep_on (&chan->wait);
-
-		if (signal_pending (current)) {
+		ret = wait_event_interruptible(chan->wait,
+			(atomic_read (&chan->n_frags) >= chan->frag_number));
+		if (ret < 0) {
 			DPRINTK ("EXIT, returning -ERESTARTSYS\n");
-			return -ERESTARTSYS;
+			return ret;
 		}
 	}
 
@@ -2950,7 +2955,7 @@
 				via_chan_pcm_fmt (chan, 0);
 				via_set_rate (&card->ac97, chan, 44100);
 			} else {
-				via_chan_pcm_fmt (chan, 0);
+				via_chan_pcm_fmt (chan, 1);
 				via_set_rate (&card->ac97, chan, 8000);
 			}
 		}
@@ -3020,25 +3024,19 @@
 	if (printed_version++ == 0)
 		printk (KERN_INFO "Via 686a audio driver " VIA_VERSION "\n");
 
-	if (pci_enable_device (pdev)) {
-		rc = -EIO;
-		goto err_out_none;
-	}
-
-	if (!request_region (pci_resource_start (pdev, 0),
-	    		     pci_resource_len (pdev, 0),
-			     VIA_MODULE_NAME)) {
-		printk (KERN_ERR PFX "unable to obtain I/O resources, aborting\n");
-		rc = -EBUSY;
+	rc = pci_enable_device (pdev);
+	if (rc)
 		goto err_out;
-	}
 
+	rc = pci_request_regions (pdev, "via82cxxx_audio");
+	if (rc)
+		goto err_out;
 
 	card = kmalloc (sizeof (*card), GFP_KERNEL);
 	if (!card) {
 		printk (KERN_ERR PFX "out of memory, aborting\n");
 		rc = -ENOMEM;
-		goto err_out_none;
+		goto err_out_res;
 	}
 
 	pci_set_drvdata (pdev, card);
@@ -3143,8 +3128,8 @@
 #endif
 	kfree (card);
 
-err_out_none:
-	release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));
+err_out_res:
+	pci_release_regions (pdev);
 err_out:
 	pci_set_drvdata (pdev, NULL);
 	DPRINTK ("EXIT - returning %d\n", rc);
@@ -3162,12 +3147,12 @@
 	card = pci_get_drvdata (pdev);
 	assert (card != NULL);
 
-	via_interrupt_cleanup (card);
+	free_irq (card->pdev->irq, card);
 	via_card_cleanup_proc (card);
 	via_dsp_cleanup (card);
 	via_ac97_cleanup (card);
 
-	release_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));
+	pci_release_regions (pdev);
 
 #ifndef VIA_NDEBUG
 	memset (card, 0xAB, sizeof (*card)); /* poison memory */

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2001-06-07 20:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-06-07 20:10 PATCH: via audio 1.1.15-pre1 Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox