View | Details | Raw Unified | Return to bug 20523
Collapse All | Expand All

(-)sio.c (-72 / +186 lines)
Lines 288-304 Link Here
288
	u_char	obuf2[256];
288
	u_char	obuf2[256];
289
};
289
};
290
290
291
#define MAXCHAN		8		/* up to 8 channels per multiport */
292
293
struct multicom {
294
	int		nchan;		/* channels per adapter */
295
	struct resource	*res;
296
	struct resource	*irq;
297
	void		*intrhand;
298
	struct com_s	com [MAXCHAN];
299
};
300
291
#ifdef COM_ESP
301
#ifdef COM_ESP
292
static	int	espattach	__P((struct com_s *com, Port_t esp_port));
302
static	int	espattach	__P((struct com_s *com, Port_t esp_port));
293
#endif
303
#endif
294
static	int	sioattach	__P((device_t dev, int rid));
304
static	int	sioattach	__P((device_t dev, int rid));
295
static	int	sio_isa_attach	__P((device_t dev));
305
static	int	sio_isa_attach	__P((device_t dev));
306
static	int	sio_attach_unit	__P((struct com_s *com, int unit, Port_t iobase, 
307
				    u_int flags, bool_t no_irq, 
308
				    bus_space_tag_t t, bus_space_handle_t h));
296
309
297
static	timeout_t siobusycheck;
310
static	timeout_t siobusycheck;
298
static	timeout_t siodtrwakeup;
311
static	timeout_t siodtrwakeup;
299
static	void	comhardclose	__P((struct com_s *com));
312
static	void	comhardclose	__P((struct com_s *com));
300
static	void	sioinput	__P((struct com_s *com));
313
static	void	sioinput	__P((struct com_s *com));
301
static	void	siointr1	__P((struct com_s *com));
314
static	void	siointr1	__P((struct com_s *com));
315
static	void	sio_pci_intr	__P((void *arg));
302
static	void	siointr		__P((void *arg));
316
static	void	siointr		__P((void *arg));
303
static	int	commctl		__P((struct com_s *com, int bits, int how));
317
static	int	commctl		__P((struct com_s *com, int bits, int how));
304
static	int	comparam	__P((struct tty *tp, struct termios *t));
318
static	int	comparam	__P((struct tty *tp, struct termios *t));
Lines 321-327 Link Here
321
335
322
#if NPCI > 0
336
#if NPCI > 0
323
static	int	sio_pci_attach __P((device_t dev));
337
static	int	sio_pci_attach __P((device_t dev));
324
static	void	sio_pci_kludge_unit __P((device_t dev));
325
static	int	sio_pci_probe __P((device_t dev));
338
static	int	sio_pci_probe __P((device_t dev));
326
#endif /* NPCI > 0 */
339
#endif /* NPCI > 0 */
327
340
Lines 329-336 Link Here
329
342
330
/* table and macro for fast conversion from a unit number to its com struct */
343
/* table and macro for fast conversion from a unit number to its com struct */
331
static	devclass_t	sio_devclass;
344
static	devclass_t	sio_devclass;
332
#define	com_addr(unit)	((struct com_s *) \
345
#define SIO_MAXUNITS	64		/* up to 64 ports */
333
			 devclass_get_softc(sio_devclass, unit))
346
#define	com_addr(unit)	(p_com_addr[unit])
347
static	struct com_s	*p_com_addr[SIO_MAXUNITS];
334
348
335
static device_method_t sio_isa_methods[] = {
349
static device_method_t sio_isa_methods[] = {
336
	/* Device interface */
350
	/* Device interface */
Lines 373-381 Link Here
373
};
387
};
374
388
375
static driver_t sio_pci_driver = {
389
static driver_t sio_pci_driver = {
376
	driver_name,
390
	"siopci",
377
	sio_pci_methods,
391
	sio_pci_methods,
378
	sizeof(struct com_s),
392
	sizeof(struct multicom),
379
};
393
};
380
#endif /* NPCI > 0 */
394
#endif /* NPCI > 0 */
381
395
Lines 419-424 Link Here
419
static	struct	callout_handle sio_timeout_handle
433
static	struct	callout_handle sio_timeout_handle
420
    = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
434
    = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
421
static	int	sio_numunits;
435
static	int	sio_numunits;
436
static	int	sio_pci_numunits = NSIO;
422
437
423
static	struct speedtab comspeedtab[] = {
438
static	struct speedtab comspeedtab[] = {
424
	{ 0,		0 },
439
	{ 0,		0 },
Lines 576-587 Link Here
576
struct pci_ids {
591
struct pci_ids {
577
	u_int32_t	type;
592
	u_int32_t	type;
578
	const char	*desc;
593
	const char	*desc;
579
	int		rid;
594
	int		rid;		/* pci base address register */
595
	int		nchan;		/* channels per adapter */
596
	int		iostep;		/* addresses per channel */
597
	int		fifo_size;	/* fifo size in bytes */
598
	int		hw_rts_cts;	/* hardware rts/cts support */
580
};
599
};
581
600
582
static struct pci_ids pci_ids[] = {
601
static struct pci_ids pci_ids[] = {
583
	{ 0x100812b9, "3COM PCI FaxModem", 0x10 },
602
	{ 0x100812b9, "3COM PCI FaxModem", 0x10 },
584
	{ 0x048011c1, "ActionTec 56k FAX PCI Modem", 0x14 },
603
	{ 0x048011c1, "ActionTec 56k FAX PCI Modem", 0x14 },
604
	{ 0xc00110b5, "Cronyx Omega-PCI Serial Adapter", 0x18, 8, 8, 64, 1 },
585
	{ 0x00000000, NULL, 0 }
605
	{ 0x00000000, NULL, 0 }
586
};
606
};
587
607
Lines 591-596 Link Here
591
{
611
{
592
	u_int32_t	type;
612
	u_int32_t	type;
593
	struct pci_ids	*id;
613
	struct pci_ids	*id;
614
	struct multicom	*d = device_get_softc(dev);
615
	struct com_s	*com;
616
	Port_t		iobase;
617
	bus_space_tag_t	bst;
618
	bus_space_handle_t bsh, bsh_port;
619
	int		rid, offset, s, err = 0;
594
620
595
	type = pci_get_devid(dev);
621
	type = pci_get_devid(dev);
596
	id = pci_ids;
622
	id = pci_ids;
Lines 598-634 Link Here
598
		id++;
624
		id++;
599
	if (id->desc == NULL)
625
	if (id->desc == NULL)
600
		return (ENXIO);
626
		return (ENXIO);
601
	sio_pci_kludge_unit(dev);
602
	return (sioattach(dev, id->rid));
603
}
604
627
605
/*
628
	bzero((char*)d, sizeof(*d));
606
 * Don't cut and paste this to other drivers.  It is a horrible kludge
629
	s = splimp();
607
 * which will fail to work and also be unnecessary in future versions.
630
	d->nchan = id->nchan > 1 ? id->nchan : 1;
608
 */
631
609
static void
632
	/* Allocate i/o region. */
610
sio_pci_kludge_unit(dev)
633
	rid = id->rid;
611
	device_t dev;
634
	d->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
612
{
635
		RF_ACTIVE);
613
	devclass_t	dc;
636
	if (! d->res) {
614
	int		err;
637
		printf("sio%d: couldn't map ports/memory\n", sio_pci_numunits);
615
	int		start;
638
		err = ENXIO;
616
	int		unit;
639
		goto fail;
640
	}
617
641
618
	unit = 0;
642
	/* Allocate interrupt. */
619
	start = 0;
643
	rid = 0;
620
	while (resource_int_value("sio", unit, "port", &start) == 0 && 
644
	d->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
621
	    start > 0)
645
		RF_SHAREABLE | RF_ACTIVE);
622
		unit++;
646
	if (! d->irq) {
623
	if (device_get_unit(dev) < unit) {
647
		printf("sio%d: couldn't map interrupt\n", sio_pci_numunits);
624
		dc = device_get_devclass(dev);
648
		err = ENXIO;
625
		while (devclass_get_device(dc, unit))
649
		goto fail;
626
			unit++;
650
	}
627
		device_printf(dev, "moving to sio%d\n", unit);
651
628
		err = device_set_unit(dev, unit);	/* EVIL DO NOT COPY */
652
	/* Register the interrupt handler. */
629
		if (err)
653
	err = bus_setup_intr(dev, d->irq, INTR_TYPE_TTY | INTR_TYPE_FAST,
630
			device_printf(dev, "error moving device %d\n", err);
654
		sio_pci_intr, d, &d->intrhand);
655
	if (err) {
656
		printf("sio%d: couldn't set up irq\n", sio_pci_numunits);
657
fail:		if (d->res)
658
			bus_release_resource(dev, SYS_RES_IOPORT,
659
				id->rid, d->res);
660
		if (d->irq)
661
			bus_release_resource(dev, SYS_RES_IRQ, 0, d->irq);
662
		goto done;
663
	}
664
665
	/* Attach sio ports. */
666
	bst = rman_get_bustag(d->res);
667
	bsh = rman_get_bushandle(d->res);
668
	iobase = rman_get_start(d->res);
669
	offset = 0;
670
	for (com=d->com; com<d->com+d->nchan; ++com, offset+=id->iostep) {
671
		/* Get a handle for a subregion of an already-mapped 
672
		 * area of bus space. */
673
#if waiting_for_somebody_to_implement_bus_space_subregion
674
		if (bus_space_subregion (bst, bsh, offset, 8, &bsh_port) != 0) {
675
			printf("sio%d: cannot get bus subregion\n", 
676
				sio_pci_numunits);
677
			continue;
631
	}
678
	}
679
#else
680
		bsh_port = bsh + offset;
681
#endif
682
		/* Interrupt enable, do it _before_ sio_attach_unit. */
683
		outb (iobase + offset + com_mcr, 
684
			d->nchan > 1 ? MCR_IENABLE : 0);
685
686
		if (sio_attach_unit(com, sio_pci_numunits++, iobase + offset,
687
		    id->fifo_size << 24, 0, bst, bsh_port) != 0)
688
			printf("sio%d: cannot attach\n", sio_pci_numunits);
689
690
		/* Must do this _after_ sio_attach_unit. */
691
		com->st16650a = id->hw_rts_cts;
692
	}
693
done:
694
	splx (s);
695
	return err;
632
}
696
}
633
697
634
static int
698
static int
Lines 645-651 Link Here
645
	if (id->desc == NULL)
709
	if (id->desc == NULL)
646
		return (ENXIO);
710
		return (ENXIO);
647
	device_set_desc(dev, id->desc);
711
	device_set_desc(dev, id->desc);
648
	return (sioprobe(dev, id->rid));
712
	return (0);
649
}
713
}
650
#endif /* NPCI > 0 */
714
#endif /* NPCI > 0 */
651
715
Lines 1096-1110 Link Here
1096
	int		xrid;
1160
	int		xrid;
1097
{
1161
{
1098
	struct com_s	*com;
1162
	struct com_s	*com;
1099
#ifdef COM_ESP
1100
	Port_t		*espp;
1101
#endif
1102
	Port_t		iobase;
1163
	Port_t		iobase;
1103
	int		unit;
1164
	int		unit;
1104
	u_int		flags;
1165
	u_int		flags;
1105
	int		rid;
1166
	int		rid;
1106
	struct resource *port;
1167
	struct resource *port;
1107
	int		ret;
1168
	int		ret;
1169
	int		no_irq;
1108
1170
1109
	rid = xrid;
1171
	rid = xrid;
1110
	port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1172
	port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
Lines 1117-1122 Link Here
1117
	com = device_get_softc(dev);
1179
	com = device_get_softc(dev);
1118
	flags = device_get_flags(dev);
1180
	flags = device_get_flags(dev);
1119
1181
1182
#ifdef COM_MULTIPORT
1183
	if (COM_ISMULTIPORT(flags)) {
1184
		device_t masterdev;
1185
1186
		masterdev = devclass_get_device(sio_devclass,
1187
		    COM_MPMASTER(flags));
1188
		no_irq = (masterdev == NULL || bus_get_resource(masterdev,
1189
		    SYS_RES_IRQ, 0, NULL, NULL) != 0);
1190
	 } else
1191
#endif /* COM_MULTIPORT */
1192
	no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0;
1193
1194
	ret = sio_attach_unit(com, unit, iobase, flags, no_irq,
1195
		rman_get_bustag(port), rman_get_bushandle(port));
1196
		
1197
	if (ret != 0) {
1198
		/* Leave i/o resources allocated if this is a `cn'-level
1199
		 * console, so that other devices can't snarf them. */
1200
		if (iobase != siocniobase)
1201
			bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1202
		return ret;
1203
	}
1204
1205
	rid = 0;
1206
	com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1,
1207
	    RF_ACTIVE);
1208
	if (com->irqres) {
1209
		ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres,
1210
				     INTR_TYPE_TTY | INTR_TYPE_FAST,
1211
				     siointr, com, &com->cookie);
1212
		if (ret) {
1213
			ret = BUS_SETUP_INTR(device_get_parent(dev), dev,
1214
					     com->irqres, INTR_TYPE_TTY,
1215
					     siointr, com, &com->cookie);
1216
			if (ret == 0)
1217
				device_printf(dev, "unable to activate interrupt in fast mode - using normal mode");
1218
		}
1219
		if (ret)
1220
			device_printf(dev, "could not activate interrupt\n");
1221
	}
1222
	com->ioportres = port;
1223
	return 0;
1224
}
1225
1226
int
1227
sio_attach_unit(com, unit, iobase, flags, no_irq, bst, bsh)
1228
 	struct com_s	*com;
1229
	int		unit;
1230
	Port_t		iobase;
1231
	u_int		flags;
1232
	bool_t		no_irq;
1233
	bus_space_tag_t	bst;
1234
	bus_space_handle_t bsh;
1235
{
1236
#ifdef COM_ESP
1237
	Port_t		*espp;
1238
#endif
1239
1240
	if (unit >= SIO_MAXUNITS)
1241
		return ENXIO;
1120
	if (unit >= sio_numunits)
1242
	if (unit >= sio_numunits)
1121
		sio_numunits = unit + 1;
1243
		sio_numunits = unit + 1;
1122
	/*
1244
	/*
Lines 1133-1145 Link Here
1133
	 */
1255
	 */
1134
	bzero(com, sizeof *com);
1256
	bzero(com, sizeof *com);
1135
	com->unit = unit;
1257
	com->unit = unit;
1136
	com->ioportres = port;
1258
	com->bst = bst;
1137
	com->bst = rman_get_bustag(port);
1259
	com->bsh = bsh;
1138
	com->bsh = rman_get_bushandle(port);
1139
	com->cfcr_image = CFCR_8BITS;
1260
	com->cfcr_image = CFCR_8BITS;
1140
	com->dtr_wait = 3 * hz;
1261
	com->dtr_wait = 3 * hz;
1141
	com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
1262
	com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
1142
	com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0;
1263
	com->no_irq = no_irq;
1143
	com->tx_fifo_size = 1;
1264
	com->tx_fifo_size = 1;
1144
	com->obufs[0].l_head = com->obuf1;
1265
	com->obufs[0].l_head = com->obuf1;
1145
	com->obufs[1].l_head = com->obuf2;
1266
	com->obufs[1].l_head = com->obuf2;
Lines 1175-1186 Link Here
1175
		com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
1296
		com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
1176
	if (siosetwater(com, com->it_in.c_ispeed) != 0) {
1297
	if (siosetwater(com, com->it_in.c_ispeed) != 0) {
1177
		enable_intr();
1298
		enable_intr();
1178
		/*
1179
		 * Leave i/o resources allocated if this is a `cn'-level
1180
		 * console, so that other devices can't snarf them.
1181
		 */
1182
		if (iobase != siocniobase)
1183
			bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1184
		return (ENOMEM);
1299
		return (ENOMEM);
1185
	}
1300
	}
1186
	enable_intr();
1301
	enable_intr();
Lines 1287-1303 Link Here
1287
1402
1288
#ifdef COM_MULTIPORT
1403
#ifdef COM_MULTIPORT
1289
	if (COM_ISMULTIPORT(flags)) {
1404
	if (COM_ISMULTIPORT(flags)) {
1290
		device_t masterdev;
1291
1292
		com->multiport = TRUE;
1405
		com->multiport = TRUE;
1293
		printf(" (multiport");
1406
		printf(" (multiport");
1294
		if (unit == COM_MPMASTER(flags))
1407
		if (unit == COM_MPMASTER(flags))
1295
			printf(" master");
1408
			printf(" master");
1296
		printf(")");
1409
		printf(")");
1297
		masterdev = devclass_get_device(sio_devclass,
1298
		    COM_MPMASTER(flags));
1299
		com->no_irq = (masterdev == NULL || bus_get_resource(masterdev,
1300
		    SYS_RES_IRQ, 0, NULL, NULL) != 0);
1301
	 }
1410
	 }
1302
#endif /* COM_MULTIPORT */
1411
#endif /* COM_MULTIPORT */
1303
	if (unit == comconsole)
1412
	if (unit == comconsole)
Lines 1306-1311 Link Here
1306
		printf(" with a bogus IIR_TXRDY register");
1415
		printf(" with a bogus IIR_TXRDY register");
1307
	printf("\n");
1416
	printf("\n");
1308
1417
1418
	com_addr(unit) = com;
1419
1309
	if (!sio_registered) {
1420
	if (!sio_registered) {
1310
		register_swi(SWI_TTY, siopoll);
1421
		register_swi(SWI_TTY, siopoll);
1311
		sio_registered = TRUE;
1422
		sio_registered = TRUE;
Lines 1326-1349 Link Here
1326
	com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
1437
	com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
1327
	pps_init(&com->pps);
1438
	pps_init(&com->pps);
1328
1439
1329
	rid = 0;
1330
	com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1,
1331
	    RF_ACTIVE);
1332
	if (com->irqres) {
1333
		ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres,
1334
				     INTR_TYPE_TTY | INTR_TYPE_FAST,
1335
				     siointr, com, &com->cookie);
1336
		if (ret) {
1337
			ret = BUS_SETUP_INTR(device_get_parent(dev), dev,
1338
					     com->irqres, INTR_TYPE_TTY,
1339
					     siointr, com, &com->cookie);
1340
			if (ret == 0)
1341
				device_printf(dev, "unable to activate interrupt in fast mode - using normal mode");
1342
		}
1343
		if (ret)
1344
			device_printf(dev, "could not activate interrupt\n");
1345
	}
1346
1347
	return (0);
1440
	return (0);
1348
}
1441
}
1349
1442
Lines 1830-1835 Link Here
1830
	} while (possibly_more_intrs);
1923
	} while (possibly_more_intrs);
1831
	COM_UNLOCK();
1924
	COM_UNLOCK();
1832
#endif /* COM_MULTIPORT */
1925
#endif /* COM_MULTIPORT */
1926
}
1927
1928
static void
1929
sio_pci_intr(arg)
1930
	void		*arg;
1931
{
1932
	struct multicom	*d = arg;
1933
	struct com_s	*com;
1934
	bool_t		possibly_more_intrs;
1935
1936
	disable_intr();
1937
	do {
1938
		possibly_more_intrs = FALSE;
1939
		for (com=d->com; com<d->com+d->nchan; ++com) {
1940
			if ((inb(com->int_id_port) & IIR_IMASK) != IIR_NOPEND) {
1941
				siointr1(com);
1942
				possibly_more_intrs = TRUE;
1943
			}
1944
		}
1945
	} while (possibly_more_intrs);
1946
	enable_intr();
1833
}
1947
}
1834
1948
1835
static void
1949
static void

Return to bug 20523