Subject: Problems with NetBSD 1.5 on the DEC Multia Hardware
To: None <port-alpha@netbsd.org>
From: Juergen Weiss <weiss@Uni-Mainz.DE>
List: port-alpha
Date: 12/03/2000 22:35:56
Hello,

there are several problems with NetBSD 1.5 on Multias:

1. interrupt handling (port-alpha/11202), the serial ports do not work,
   in particular you can not use the serial console
2. when rebooting with serial console, the srm console crashes
3. the Xserver does not work (wrong screen geometry)
4. full duplex audio does not work (kern/11178)
5. pcmcia cards do not work (interrupt routing)
6. wavelan pcmcia cards do not work with alpha cpus (alignment problems)

The following patches fix the problems 3., 4. and 6.
and give at least hotfixes or `work arounds' for the
rest.

Some of the fixes are backports of 1.4 code (1., 3.).

Use the following configuration lines

wss*    at      isa? port 0x530 irq 9 drq 3 drq2 1 # Windows Sound System
audio*  at      wss?

pcic0   at      isa? port 0x3e0 iomem 0xd0000 iosiz 0x4000 1
#pcic1  at      isa? port 0x3e2 iomem 0xcc000 iosiz 0x10000
pcmcia* at      pcic? controller ? socket ?
options PCIC_ISA_ALLOC_IOBASE=0x300
options PCIC_ISA_ALLOC_IOSIZE=0x0ff
options PCIC_ISA_INTR_ALLOC_MASK=0x4000

diff -rc /usr/src.orig/sys/arch/alpha/pci/sio_pic.c /usr/src/sys/arch/alpha/pci/sio_pic.c
*** /usr/src.orig/sys/arch/alpha/pci/sio_pic.c	Tue Jun  6 05:10:13 2000
--- /usr/src/sys/arch/alpha/pci/sio_pic.c	Sun Dec  3 17:20:54 2000
***************
*** 121,128 ****
--- 121,135 ----
   * If prom console is broken, must remember the initial interrupt
   * settings and enforce them.  WHEE!
   */
+ #define       INITIALLY_ENABLED(irq) \
+           ((initial_ocw1[(irq) / 8] & (1 << ((irq) % 8))) == 0)
+ #define       INITIALLY_LEVEL_TRIGGERED(irq) \
+           ((initial_elcr[(irq) / 8] & (1 << ((irq) % 8))) != 0)
  u_int8_t initial_ocw1[2];
  u_int8_t initial_elcr[2];
+ #else
+ #define       INITIALLY_ENABLED(irq)          ((irq) == 2 ? 1 : 0)
+ #define       INITIALLY_LEVEL_TRIGGERED(irq)  0
  #endif
  
  void		sio_setirqstat __P((int, int, int));
***************
*** 384,390 ****
  			 * IRQs 0, 1, 8, and 13 must always be
  			 * edge-triggered.
  			 */
! 			sio_setirqstat(i, 0, IST_EDGE);
  			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
  			    IST_EDGE);
  			specific_eoi(i);
--- 391,399 ----
  			 * IRQs 0, 1, 8, and 13 must always be
  			 * edge-triggered.
  			 */
! 			if (INITIALLY_LEVEL_TRIGGERED(i))
! 				printf("sio_intr_setup: %d LT!\n", i);
! 			sio_setirqstat(i, INITIALLY_ENABLED(i), IST_EDGE);
  			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
  			    IST_EDGE);
  			specific_eoi(i);
***************
*** 405,413 ****
  			 * Otherwise, disable the IRQ and set its
  			 * type to (effectively) "unknown."
  			 */
! 			sio_setirqstat(i, 0, IST_NONE);
  			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
! 			    IST_NONE);
  			specific_eoi(i);
  			break;
  		}
--- 414,423 ----
  			 * Otherwise, disable the IRQ and set its
  			 * type to (effectively) "unknown."
  			 */
! 			sio_setirqstat(i, INITIALLY_ENABLED(i),
! 				       INITIALLY_LEVEL_TRIGGERED(i) ? IST_LEVEL : IST_NONE);
  			alpha_shared_intr_set_dfltsharetype(sio_intr, i,
! 							    INITIALLY_LEVEL_TRIGGERED(i) ? IST_LEVEL : IST_NONE);
  			specific_eoi(i);
  			break;
  		}
***************
*** 516,525 ****
  			break;
  
  		default:
! 			ist = IST_NONE;
  			break;
  		}
! 		sio_setirqstat(irq, 0, ist);
  		alpha_shared_intr_set_dfltsharetype(sio_intr, irq, ist);
  	}
  
--- 526,536 ----
  			break;
  
  		default:
! 			ist = INITIALLY_LEVEL_TRIGGERED(irq) ?
! 			    IST_LEVEL : IST_NONE;
  			break;
  		}
! 		sio_setirqstat(irq, INITIALLY_ENABLED(irq), ist);
  		alpha_shared_intr_set_dfltsharetype(sio_intr, irq, ist);
  	}
  
diff -rc /usr/src.orig/sys/dev/isa/ad1848_isa.c /usr/src/sys/dev/isa/ad1848_isa.c
*** /usr/src.orig/sys/dev/isa/ad1848_isa.c	Fri Jun 30 18:27:47 2000
--- /usr/src/sys/dev/isa/ad1848_isa.c	Sun Dec  3 20:40:57 2000
***************
*** 522,528 ****
  	ad1848_isa_halt_output(isc);
  	ad1848_isa_halt_input(isc);
  
! 	isc->sc_intr = 0;
  
  	if (isc->sc_playdrq != -1)
  		isa_dmamap_destroy(isc->sc_ic, isc->sc_playdrq);
--- 522,528 ----
  	ad1848_isa_halt_output(isc);
  	ad1848_isa_halt_input(isc);
  
! 	isc->sc_pintr = isc->sc_rintr = 0;
  
  	if (isc->sc_playdrq != -1)
  		isa_dmamap_destroy(isc->sc_ic, isc->sc_playdrq);
***************
*** 557,564 ****
  	    DMAMODE_READ | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
  
  	isc->sc_recrun = 1;
! 	isc->sc_intr = intr;
! 	isc->sc_arg = arg;
  
  	blksize = (blksize * 8) / (param->precision * param->factor * param->channels) - 1;
  
--- 557,569 ----
  	    DMAMODE_READ | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
  
  	isc->sc_recrun = 1;
! 	if (sc->mode == 2 && isc->sc_playdrq != isc->sc_recdrq) {
! 	    isc->sc_rintr = intr;
! 	    isc->sc_rarg = arg;
! 	} else {
! 	    isc->sc_pintr = intr;
! 	    isc->sc_parg = arg;
! 	}
  
  	blksize = (blksize * 8) / (param->precision * param->factor * param->channels) - 1;
  
***************
*** 594,601 ****
  	    DMAMODE_WRITE | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
  
  	isc->sc_playrun = 1;
! 	isc->sc_intr = intr;
! 	isc->sc_arg = arg;
  
  	blksize = (blksize * 8) / (param->precision * param->factor * param->channels) - 1;
  
--- 599,606 ----
  	    DMAMODE_WRITE | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
  
  	isc->sc_playrun = 1;
! 	isc->sc_pintr = intr;
! 	isc->sc_parg = arg;
  
  	blksize = (blksize * 8) / (param->precision * param->factor * param->channels) - 1;
  
***************
*** 665,679 ****
  	isc->sc_interrupts++;
  
  	/* Handle interrupt */
! 	if (isc->sc_intr && (status & INTERRUPT_STATUS)) {
! 		(*isc->sc_intr)(isc->sc_arg);
! 		retval = 1;
  	}
- 
- 	/* clear interrupt */
- 	if (status & INTERRUPT_STATUS)
- 		ADWRITE(sc, AD1848_STATUS, 0);
- 
  	return(retval);
  }
  
--- 670,695 ----
  	isc->sc_interrupts++;
  
  	/* Handle interrupt */
! 	if ((status & INTERRUPT_STATUS) != 0) {
! 	    if (sc->mode == 2 && isc->sc_playdrq != isc->sc_recdrq) {
! 		status = ad_read(sc, CS_IRQ_STATUS);
! 		if ((status & CS_IRQ_PI) && isc->sc_pintr) {
! 		    (*isc->sc_pintr)(isc->sc_parg);
! 		    retval = 1;
! 		}
! 		if ((status & CS_IRQ_CI) && isc->sc_rintr) {
! 		    (*isc->sc_rintr)(isc->sc_rarg);
! 		    retval = 1;
! 		}
! 	    } else {
! 		if (isc->sc_pintr) {
! 		    (*isc->sc_pintr)(isc->sc_parg);
! 		    retval = 1;
! 		}
! 	    }
! 	    /* clear interrupt */
! 	    ADWRITE(sc, AD1848_STATUS, 0);
  	}
  	return(retval);
  }
  
diff -rc /usr/src.orig/sys/dev/isa/ad1848var.h /usr/src/sys/dev/isa/ad1848var.h
*** /usr/src.orig/sys/dev/isa/ad1848var.h	Fri Jun 30 18:27:47 2000
--- /usr/src/sys/dev/isa/ad1848var.h	Sun Dec  3 20:37:02 2000
***************
*** 89,96 ****
  	bus_size_t sc_rec_maxsize;	/* record/capture DMA size */
  	
  	u_long	sc_interrupts;		/* number of interrupts taken */
! 	void	(*sc_intr)(void *);	/* dma completion intr handler */
! 	void	*sc_arg;		/* arg for sc_intr() */
  
  	/* Only used by pss XXX */
  	int	sc_iobase;
--- 89,98 ----
  	bus_size_t sc_rec_maxsize;	/* record/capture DMA size */
  	
  	u_long	sc_interrupts;		/* number of interrupts taken */
! 	void	(*sc_pintr)(void *);	/* dma completion intr handler */
! 	void	*sc_parg;		/* arg for sc_intr() */
! 	void	(*sc_rintr)(void *);	/* dma completion intr handler */
! 	void	*sc_rarg;		/* arg for sc_intr() */
  
  	/* Only used by pss XXX */
  	int	sc_iobase;
diff -rc /usr/src.orig/sys/dev/isa/i82365_isasubr.c /usr/src/sys/dev/isa/i82365_isasubr.c
*** /usr/src.orig/sys/dev/isa/i82365_isasubr.c	Tue May  9 19:59:39 2000
--- /usr/src/sys/dev/isa/i82365_isasubr.c	Sun Dec  3 17:28:35 2000
***************
*** 237,243 ****
  		/* Clear any pending interrupt. */
  		(void) pcic_read(h, PCIC_CSC);
  
! 		if ((sc->ih = isa_intr_establish(ic, irq, IST_EDGE, IPL_TTY,
  		    pcic_isa_count_intr, h)) == NULL)
  			panic("cant get interrupt");
  
--- 237,243 ----
  		/* Clear any pending interrupt. */
  		(void) pcic_read(h, PCIC_CSC);
  
! 		if ((sc->ih = isa_intr_establish(ic, irq, IST_LEVEL, IPL_TTY,
  		    pcic_isa_count_intr, h)) == NULL)
  			panic("cant get interrupt");
  
***************
*** 268,274 ****
  	}
  	sc->intr_mask[h->chip] = mask;
  
! 	printf("%s\n", sc->intr_mask ? "" : " none");
  }
  
  /*
--- 268,274 ----
  	}
  	sc->intr_mask[h->chip] = mask;
  
! 	printf("%s\n", sc->intr_mask[h->chip] ? "" : " none");
  }
  
  /*
***************
*** 339,345 ****
  				    "detected as available\n",
  				    sc->dev.dv_xname, sc->irq);
  		} else if (chipmask == 0 ||
! 		    isa_intr_alloc(ic, chipmask, IST_EDGE, &sc->irq)) {
  			printf("%s: no available irq; ", sc->dev.dv_xname);
  			sc->irq = IRQUNK;
  		} else if ((chipmask & ~(1 << sc->irq)) == 0 && chipuniq == 0) {
--- 339,345 ----
  				    "detected as available\n",
  				    sc->dev.dv_xname, sc->irq);
  		} else if (chipmask == 0 ||
! 		    isa_intr_alloc(ic, chipmask, IST_LEVEL, &sc->irq)) {
  			printf("%s: no available irq; ", sc->dev.dv_xname);
  			sc->irq = IRQUNK;
  		} else if ((chipmask & ~(1 << sc->irq)) == 0 && chipuniq == 0) {
***************
*** 353,359 ****
  	}
  
  	if (sc->irq != IRQUNK) {
! 		sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY,
  		    pcic_intr, sc);
  		if (sc->ih == NULL) {
  			printf("%s: can't establish interrupt",
--- 353,359 ----
  	}
  
  	if (sc->irq != IRQUNK) {
! 		sc->ih = isa_intr_establish(ic, sc->irq, IST_LEVEL, IPL_TTY,
  		    pcic_intr, sc);
  		if (sc->ih == NULL) {
  			printf("%s: can't establish interrupt",
***************
*** 478,484 ****
  	int reg;
  
  	if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
! 		ist = IST_EDGE;
  	else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
  		ist = IST_PULSE;
  	else
--- 478,484 ----
  	int reg;
  
  	if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
! 		ist = IST_LEVEL;
  	else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
  		ist = IST_PULSE;
  	else
diff -rc /usr/src.orig/sys/dev/pci/tga.c /usr/src/sys/dev/pci/tga.c
*** /usr/src.orig/sys/dev/pci/tga.c	Fri Jun 30 18:27:51 2000
--- /usr/src/sys/dev/pci/tga.c	Sun Dec  3 20:44:26 2000
***************
*** 264,269 ****
--- 264,284 ----
  	}
  
  	dc->dc_rowbytes = dc->dc_wid * (dc->dc_tgaconf->tgac_phys_depth / 8);
+ 
+ 
+         if ((TGARREG(dc, TGA_REG_VHCR) & 0x00000001) != 0 &&    /* XXX */
+             (TGARREG(dc, TGA_REG_VHCR) & 0x80000000) != 0) {    /* XXX */
+                 dc->dc_wid -= 4;
+                 /*
+                  * XXX XXX turning off 'odd' shouldn't be necesssary,
+                  * XXX XXX but i can't make X work with the weird size.
+                  */
+                 TGAWREG(dc, TGA_REG_VHCR, 
+ 			(TGARREG(dc, TGA_REG_VHCR) & ~0x80000001));
+                 dc->dc_rowbytes =
+                     dc->dc_wid * (dc->dc_tgaconf->tgac_phys_depth / 8);
+         }
+ 
  	dc->dc_ht = (TGARREG(dc, TGA_REG_VVCR) & 0x7ff);	/* XXX */
  
  	/* XXX this seems to be what DEC does */
diff -rc /usr/src.orig/sys/dev/pcmcia/if_wi.c /usr/src/sys/dev/pcmcia/if_wi.c
*** /usr/src.orig/sys/dev/pcmcia/if_wi.c	Tue Oct 17 02:56:32 2000
--- /usr/src/sys/dev/pcmcia/if_wi.c	Sun Dec  3 17:29:47 2000
***************
*** 498,510 ****
  		return;
  	}
  
  	eh = mtod(m, struct ether_header *);
  	m->m_pkthdr.rcvif = ifp;
  
  	if (rx_frame.wi_status == WI_STAT_1042 ||
  	    rx_frame.wi_status == WI_STAT_TUNNEL ||
  	    rx_frame.wi_status == WI_STAT_WMP_MSG) {
! 		if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES) {
  			printf("%s: oversized packet received "
  			    "(wi_dat_len=%d, wi_status=0x%x)\n",
  			    sc->sc_dev.dv_xname,
--- 498,511 ----
  		return;
  	}
  
+ 	m->m_data += 2;
  	eh = mtod(m, struct ether_header *);
  	m->m_pkthdr.rcvif = ifp;
  
  	if (rx_frame.wi_status == WI_STAT_1042 ||
  	    rx_frame.wi_status == WI_STAT_TUNNEL ||
  	    rx_frame.wi_status == WI_STAT_WMP_MSG) {
! 		if((rx_frame.wi_dat_len + WI_SNAPHDR_LEN) > MCLBYTES-2) {
  			printf("%s: oversized packet received "
  			    "(wi_dat_len=%d, wi_status=0x%x)\n",
  			    sc->sc_dev.dv_xname,
***************
*** 532,538 ****
  		}
  	} else {
  		if((rx_frame.wi_dat_len +
! 		    sizeof(struct ether_header)) > MCLBYTES) {
  			printf("%s: oversized packet received "
  			    "(wi_dat_len=%d, wi_status=0x%x)\n",
  			    sc->sc_dev.dv_xname,
--- 533,539 ----
  		}
  	} else {
  		if((rx_frame.wi_dat_len +
! 		    sizeof(struct ether_header)) > MCLBYTES-2) {
  			printf("%s: oversized packet received "
  			    "(wi_dat_len=%d, wi_status=0x%x)\n",
  			    sc->sc_dev.dv_xname,
diff -rc /usr/src.orig/sys/dev/pcmcia/if_wivar.h /usr/src/sys/dev/pcmcia/if_wivar.h
*** /usr/src.orig/sys/dev/pcmcia/if_wivar.h	Fri Jul 21 20:52:11 2000
--- /usr/src/sys/dev/pcmcia/if_wivar.h	Sun Dec  3 17:30:20 2000
***************
*** 76,82 ****
  	struct ieee80211_nwid	wi_netid;
  	struct ieee80211_nwid	wi_ibssid;
  
! 	u_int8_t		wi_txbuf[1596];
  	int                     wi_has_wep;
  	int                     wi_use_wep;
  	int                     wi_tx_key;
--- 76,82 ----
  	struct ieee80211_nwid	wi_netid;
  	struct ieee80211_nwid	wi_ibssid;
  
! 	u_int16_t		wi_txbuf[1596/2];
  	int                     wi_has_wep;
  	int                     wi_use_wep;
  	int                     wi_tx_key;


-- 
Juergen Weiss	      | Universitaet Mainz, Zentrum f"ur Datenverarbeitung,
weiss@uni-mainz.de    | 55099 Mainz, Tel: 06131/39-26361, FAX: 06131/39-26407