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