Index: sio.c =================================================================== RCS file: /home/ncvs/src/sys/i386/isa/sio.c,v retrieving revision 1.188 diff -c -r1.188 sio.c *** sio.c 1997/11/02 21:26:14 1.188 --- sio.c 1997/11/30 11:05:40 *************** *** 132,137 **** --- 132,138 ---- #define COM_ISMULTIPORT(dev) ((dev)->id_flags & 0x01) #define COM_MPMASTER(dev) (((dev)->id_flags >> 8) & 0x0ff) #define COM_NOTAST4(dev) ((dev)->id_flags & 0x04) + #define COM_SECMAST(dev) ((dev)->id_flags & 0x40000) #endif /* COM_MULTIPORT */ #define COM_CONSOLE(dev) ((dev)->id_flags & 0x10) *************** *** 208,213 **** --- 209,226 ---- bool_t l_queued; /* nonzero if queued */ }; + /* list of irqs and their clear port */ + Port_t ast4_sicr[] = { + -1, + -1, + 0x2f2, + 0x2f3, + 0x2f4, + 0x2f5, + 0x2f6, + 0x2f7, + }; + /* com device structure */ struct com_s { u_char state; /* miscellaneous flag bits */ *************** *** 224,229 **** --- 237,245 ---- u_char mcr_image; /* copy of value written to MCR */ #ifdef COM_MULTIPORT bool_t multiport; /* is this unit part of a multiport device? */ + bool_t isast4; /* is this unit ast/4 compatible */ + struct com_s *secondmast; /* minor of the secondary master */ + struct com_s *subports[4]; /* ports that apply to this master */ #endif /* COM_MULTIPORT */ bool_t no_irq; /* nonzero if irq is not attached */ bool_t gone; /* hardware disappeared */ *************** *** 261,266 **** --- 277,284 ---- Port_t modem_ctl_port; Port_t line_status_port; Port_t modem_status_port; + Port_t scr_port; + Port_t sicr_port; struct tty *tp; /* cross reference */ *************** *** 874,879 **** --- 892,898 ---- com->mcr_image = inb(com->modem_ctl_port); com->line_status_port = iobase + com_lsr; com->modem_status_port = iobase + com_msr; + com->scr_port = iobase + com_scr; /* * We don't use all the flags from since they *************** *** 1005,1015 **** if (COM_ISMULTIPORT(isdp)) { com->multiport = TRUE; printf(" (multiport"); ! if (unit == COM_MPMASTER(isdp)) printf(" master"); printf(")"); com->no_irq = find_isadev(isa_devtab_tty, &siodriver, COM_MPMASTER(isdp))->id_irq == 0; } #endif /* COM_MULTIPORT */ if (unit == comconsole) --- 1024,1065 ---- if (COM_ISMULTIPORT(isdp)) { com->multiport = TRUE; printf(" (multiport"); ! if (COM_SECMAST(isdp)) { ! int i, n; ! struct isa_device *prt; ! ! if (COM_MPMASTER(isdp) != unit) ! printf(" secondary"); ! else ! if (isdp->id_irq > 7 || isdp->id_irq < 2) ! com->sicr_port = ast4_sicr[7]; ! else ! com->sicr_port = ! ast4_sicr[isdp->id_irq]; ! ! for (n = 0, i = 0; i < NSIO; i++) { ! prt = find_isadev(isa_devtab_tty, &siodriver, ! i); ! /* ! * The i == unit is so that it will include ! * the secondary master as it's "master" ! * isn't itself, and we wouldn't be this ! * far if unit isn't a port :) ! */ ! if (COM_MPMASTER(prt) == unit || i == unit) ! com->subports[n++] = com_addr(i); ! if (COM_MPMASTER(prt) == unit && i != unit && ! COM_SECMAST(prt)) ! com->secondmast = com_addr(i); ! } ! } ! if (unit == COM_MPMASTER(isdp) || COM_SECMAST(isdp)) printf(" master"); printf(")"); com->no_irq = find_isadev(isa_devtab_tty, &siodriver, COM_MPMASTER(isdp))->id_irq == 0; + if (!COM_NOTAST4(isdp)) + com->isast4 = TRUE; } #endif /* COM_MULTIPORT */ if (unit == comconsole) *************** *** 1418,1423 **** --- 1468,1474 ---- struct com_s *com; bool_t possibly_more_intrs; + com = com_addr(unit); /* * Loop until there is no activity on any port. This is necessary * to get an interrupt edge more than to avoid another interrupt. *************** *** 1426,1449 **** * on. */ COM_LOCK(); ! do { ! possibly_more_intrs = FALSE; ! for (unit = 0; unit < NSIOTOT; ++unit) { ! com = com_addr(unit); /* ! * XXX COM_LOCK(); ! * would it work here, or be counter-productive? */ ! if (com != NULL ! && !com->gone ! && (inb(com->int_id_port) & IIR_IMASK) ! != IIR_NOPEND) { ! siointr1(com); ! possibly_more_intrs = TRUE; ! } ! /* XXX COM_UNLOCK(); */ } ! } while (possibly_more_intrs); COM_UNLOCK(); #endif /* COM_MULTIPORT */ } --- 1477,1532 ---- * on. */ COM_LOCK(); ! if (com->isast4 == TRUE) { ! int i, j; ! struct com_s *scom; ! struct com_s *h; ! ! scom = com->secondmast; ! ! /* ! * we have an AST/4 compatible status register ! */ ! while (((i = inb(com->scr_port)) & 0xf) != 0 || (scom != NULL && ! ((i = inb(scom->scr_port) | 0x100) & 0xf) != 0)) { ! if (i & 0x100) ! h = scom; ! else ! h = com; /* ! * a binary search could reduce this loop of 4 to ! * 2, would it really be worth it? */ ! for (j = 0; j < 4; j++) ! if (i & (1 << j)) { ! siointr1(h->subports[i]); ! break; ! } } ! /* ! * We are now done servicing interrupts, clear 'em out ! */ ! outb(com->sicr_port, 0); ! } else ! do { ! possibly_more_intrs = FALSE; ! for (unit = 0; unit < NSIOTOT; ++unit) { ! com = com_addr(unit); ! /* ! * XXX COM_LOCK(); ! * would it work here, or be ! * counter-productive? ! */ ! if (com != NULL ! && !com->gone ! && (inb(com->int_id_port) & IIR_IMASK) ! != IIR_NOPEND) { ! siointr1(com); ! possibly_more_intrs = TRUE; ! } ! /* XXX COM_UNLOCK(); */ ! } ! } while (possibly_more_intrs); COM_UNLOCK(); #endif /* COM_MULTIPORT */ }