xref: /netbsd-src/sys/dev/pci/pci_subr.c (revision 7c7c171d130af9949261bc7dce2150a03c3d239c)
1 /*	$NetBSD: pci_subr.c,v 1.23 1998/04/20 14:16:26 drochner Exp $	*/
2 
3 /*
4  * Copyright (c) 1997 Zubin D. Dittia.  All rights reserved.
5  * Copyright (c) 1995, 1996 Christopher G. Demetriou.  All rights reserved.
6  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by Charles Hannum.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * PCI autoconfiguration support functions.
36  */
37 
38 #include "opt_pciverbose.h"
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 
44 #include <dev/pci/pcireg.h>
45 #include <dev/pci/pcivar.h>
46 #ifdef PCIVERBOSE
47 #include <dev/pci/pcidevs.h>
48 #endif
49 
50 /*
51  * Descriptions of known PCI classes and subclasses.
52  *
53  * Subclasses are described in the same way as classes, but have a
54  * NULL subclass pointer.
55  */
56 struct pci_class {
57 	char		*name;
58 	int		val;		/* as wide as pci_{,sub}class_t */
59 	struct pci_class *subclasses;
60 };
61 
62 struct pci_class pci_subclass_prehistoric[] = {
63 	{ "miscellaneous",	PCI_SUBCLASS_PREHISTORIC_MISC,		},
64 	{ "VGA",		PCI_SUBCLASS_PREHISTORIC_VGA,		},
65 	{ 0 }
66 };
67 
68 struct pci_class pci_subclass_mass_storage[] = {
69 	{ "SCSI",		PCI_SUBCLASS_MASS_STORAGE_SCSI,		},
70 	{ "IDE",		PCI_SUBCLASS_MASS_STORAGE_IDE,		},
71 	{ "floppy",		PCI_SUBCLASS_MASS_STORAGE_FLOPPY,	},
72 	{ "IPI",		PCI_SUBCLASS_MASS_STORAGE_IPI,		},
73 	{ "RAID",		PCI_SUBCLASS_MASS_STORAGE_RAID,		},
74 	{ "miscellaneous",	PCI_SUBCLASS_MASS_STORAGE_MISC,		},
75 	{ 0 },
76 };
77 
78 struct pci_class pci_subclass_network[] = {
79 	{ "ethernet",		PCI_SUBCLASS_NETWORK_ETHERNET,		},
80 	{ "token ring",		PCI_SUBCLASS_NETWORK_TOKENRING,		},
81 	{ "FDDI",		PCI_SUBCLASS_NETWORK_FDDI,		},
82 	{ "ATM",		PCI_SUBCLASS_NETWORK_ATM,		},
83 	{ "miscellaneous",	PCI_SUBCLASS_NETWORK_MISC,		},
84 	{ 0 },
85 };
86 
87 struct pci_class pci_subclass_display[] = {
88 	{ "VGA",		PCI_SUBCLASS_DISPLAY_VGA,		},
89 	{ "XGA",		PCI_SUBCLASS_DISPLAY_XGA,		},
90 	{ "miscellaneous",	PCI_SUBCLASS_DISPLAY_MISC,		},
91 	{ 0 },
92 };
93 
94 struct pci_class pci_subclass_multimedia[] = {
95 	{ "video",		PCI_SUBCLASS_MULTIMEDIA_VIDEO,		},
96 	{ "audio",		PCI_SUBCLASS_MULTIMEDIA_AUDIO,		},
97 	{ "miscellaneous",	PCI_SUBCLASS_MULTIMEDIA_MISC,		},
98 	{ 0 },
99 };
100 
101 struct pci_class pci_subclass_memory[] = {
102 	{ "RAM",		PCI_SUBCLASS_MEMORY_RAM,		},
103 	{ "flash",		PCI_SUBCLASS_MEMORY_FLASH,		},
104 	{ "miscellaneous",	PCI_SUBCLASS_MEMORY_MISC,		},
105 	{ 0 },
106 };
107 
108 struct pci_class pci_subclass_bridge[] = {
109 	{ "host",		PCI_SUBCLASS_BRIDGE_HOST,		},
110 	{ "ISA",		PCI_SUBCLASS_BRIDGE_ISA,		},
111 	{ "EISA",		PCI_SUBCLASS_BRIDGE_EISA,		},
112 	{ "MicroChannel",	PCI_SUBCLASS_BRIDGE_MC,			},
113 	{ "PCI",		PCI_SUBCLASS_BRIDGE_PCI,		},
114 	{ "PCMCIA",		PCI_SUBCLASS_BRIDGE_PCMCIA,		},
115 	{ "NuBus",		PCI_SUBCLASS_BRIDGE_NUBUS,		},
116 	{ "CardBus",		PCI_SUBCLASS_BRIDGE_CARDBUS,		},
117 	{ "miscellaneous",	PCI_SUBCLASS_BRIDGE_MISC,		},
118 	{ 0 },
119 };
120 
121 struct pci_class pci_subclass_communications[] = {
122 	{ "serial",		PCI_SUBCLASS_COMMUNICATIONS_SERIAL,	},
123 	{ "parallel",		PCI_SUBCLASS_COMMUNICATIONS_PARALLEL,	},
124 	{ "miscellaneous",	PCI_SUBCLASS_COMMUNICATIONS_MISC,	},
125 	{ 0 },
126 };
127 
128 struct pci_class pci_subclass_system[] = {
129 	{ "8259 PIC",		PCI_SUBCLASS_SYSTEM_PIC,		},
130 	{ "8237 DMA",		PCI_SUBCLASS_SYSTEM_DMA,		},
131 	{ "8254 timer",		PCI_SUBCLASS_SYSTEM_TIMER,		},
132 	{ "RTC",		PCI_SUBCLASS_SYSTEM_RTC,		},
133 	{ "miscellaneous",	PCI_SUBCLASS_SYSTEM_MISC,		},
134 	{ 0 },
135 };
136 
137 struct pci_class pci_subclass_input[] = {
138 	{ "keyboard",		PCI_SUBCLASS_INPUT_KEYBOARD,		},
139 	{ "digitizer",		PCI_SUBCLASS_INPUT_DIGITIZER,		},
140 	{ "mouse",		PCI_SUBCLASS_INPUT_MOUSE,		},
141 	{ "miscellaneous",	PCI_SUBCLASS_INPUT_MISC,		},
142 	{ 0 },
143 };
144 
145 struct pci_class pci_subclass_dock[] = {
146 	{ "generic",		PCI_SUBCLASS_DOCK_GENERIC,		},
147 	{ "miscellaneous",	PCI_SUBCLASS_DOCK_MISC,			},
148 	{ 0 },
149 };
150 
151 struct pci_class pci_subclass_processor[] = {
152 	{ "386",		PCI_SUBCLASS_PROCESSOR_386,		},
153 	{ "486",		PCI_SUBCLASS_PROCESSOR_486,		},
154 	{ "Pentium",		PCI_SUBCLASS_PROCESSOR_PENTIUM,		},
155 	{ "Alpha",		PCI_SUBCLASS_PROCESSOR_ALPHA,		},
156 	{ "PowerPC",		PCI_SUBCLASS_PROCESSOR_POWERPC,		},
157 	{ "Co-processor",	PCI_SUBCLASS_PROCESSOR_COPROC,		},
158 	{ 0 },
159 };
160 
161 struct pci_class pci_subclass_serialbus[] = {
162 	{ "Firewire",		PCI_SUBCLASS_SERIALBUS_FIREWIRE,	},
163 	{ "ACCESS.bus",		PCI_SUBCLASS_SERIALBUS_ACCESS,		},
164 	{ "SSA",		PCI_SUBCLASS_SERIALBUS_SSA,		},
165 	{ "USB",		PCI_SUBCLASS_SERIALBUS_USB,		},
166 	{ "Fiber Channel",	PCI_SUBCLASS_SERIALBUS_FIBER,		},
167 	{ 0 },
168 };
169 
170 struct pci_class pci_class[] = {
171 	{ "prehistoric",	PCI_CLASS_PREHISTORIC,
172 	    pci_subclass_prehistoric,				},
173 	{ "mass storage",	PCI_CLASS_MASS_STORAGE,
174 	    pci_subclass_mass_storage,				},
175 	{ "network",		PCI_CLASS_NETWORK,
176 	    pci_subclass_network,				},
177 	{ "display",		PCI_CLASS_DISPLAY,
178 	    pci_subclass_display,				},
179 	{ "multimedia",		PCI_CLASS_MULTIMEDIA,
180 	    pci_subclass_multimedia,				},
181 	{ "memory",		PCI_CLASS_MEMORY,
182 	    pci_subclass_memory,				},
183 	{ "bridge",		PCI_CLASS_BRIDGE,
184 	    pci_subclass_bridge,				},
185 	{ "communications",	PCI_CLASS_COMMUNICATIONS,
186 	    pci_subclass_communications,			},
187 	{ "system",		PCI_CLASS_SYSTEM,
188 	    pci_subclass_system,				},
189 	{ "input",		PCI_CLASS_INPUT,
190 	    pci_subclass_input,					},
191 	{ "dock",		PCI_CLASS_DOCK,
192 	    pci_subclass_dock,					},
193 	{ "processor",		PCI_CLASS_PROCESSOR,
194 	    pci_subclass_processor,				},
195 	{ "serial bus",		PCI_CLASS_SERIALBUS,
196 	    pci_subclass_serialbus,				},
197 	{ "undefined",		PCI_CLASS_UNDEFINED,
198 	    0,							},
199 	{ 0 },
200 };
201 
202 #ifdef PCIVERBOSE
203 /*
204  * Descriptions of of known vendors and devices ("products").
205  */
206 struct pci_knowndev {
207 	pci_vendor_id_t		vendor;
208 	pci_product_id_t	product;
209 	int			flags;
210 	char			*vendorname, *productname;
211 };
212 #define	PCI_KNOWNDEV_NOPROD	0x01		/* match on vendor only */
213 
214 #include <dev/pci/pcidevs_data.h>
215 #endif /* PCIVERBOSE */
216 
217 void
218 pci_devinfo(id_reg, class_reg, showclass, cp)
219 	pcireg_t id_reg, class_reg;
220 	int showclass;
221 	char *cp;
222 {
223 	pci_vendor_id_t vendor;
224 	pci_product_id_t product;
225 	pci_class_t class;
226 	pci_subclass_t subclass;
227 	pci_interface_t interface;
228 	pci_revision_t revision;
229 	char *vendor_namep, *product_namep;
230 	struct pci_class *classp, *subclassp;
231 #ifdef PCIVERBOSE
232 	struct pci_knowndev *kdp;
233 	const char *unmatched = "unknown ";
234 #else
235 	const char *unmatched = "";
236 #endif
237 
238 	vendor = PCI_VENDOR(id_reg);
239 	product = PCI_PRODUCT(id_reg);
240 
241 	class = PCI_CLASS(class_reg);
242 	subclass = PCI_SUBCLASS(class_reg);
243 	interface = PCI_INTERFACE(class_reg);
244 	revision = PCI_REVISION(class_reg);
245 
246 #ifdef PCIVERBOSE
247 	kdp = pci_knowndevs;
248         while (kdp->vendorname != NULL) {	/* all have vendor name */
249                 if (kdp->vendor == vendor && (kdp->product == product ||
250 		    (kdp->flags & PCI_KNOWNDEV_NOPROD) != 0))
251                         break;
252 		kdp++;
253 	}
254         if (kdp->vendorname == NULL)
255 		vendor_namep = product_namep = NULL;
256 	else {
257 		vendor_namep = kdp->vendorname;
258 		product_namep = (kdp->flags & PCI_KNOWNDEV_NOPROD) == 0 ?
259 		    kdp->productname : NULL;
260         }
261 #else /* PCIVERBOSE */
262 	vendor_namep = product_namep = NULL;
263 #endif /* PCIVERBOSE */
264 
265 	classp = pci_class;
266 	while (classp->name != NULL) {
267 		if (class == classp->val)
268 			break;
269 		classp++;
270 	}
271 
272 	subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
273 	while (subclassp && subclassp->name != NULL) {
274 		if (subclass == subclassp->val)
275 			break;
276 		subclassp++;
277 	}
278 
279 	if (vendor_namep == NULL)
280 		cp += sprintf(cp, "%svendor 0x%04x product 0x%04x",
281 		    unmatched, vendor, product);
282 	else if (product_namep != NULL)
283 		cp += sprintf(cp, "%s %s", vendor_namep, product_namep);
284 	else
285 		cp += sprintf(cp, "%s product 0x%04x",
286 		    vendor_namep, product);
287 	if (showclass) {
288 		cp += sprintf(cp, " (");
289 		if (classp->name == NULL)
290 			cp += sprintf(cp, "class 0x%02x, subclass 0x%02x",
291 			    class, subclass);
292 		else {
293 			if (subclassp == NULL || subclassp->name == NULL)
294 				cp += sprintf(cp,
295 				    "%s subclass 0x%02x",
296 				    classp->name, subclass);
297 			else
298 				cp += sprintf(cp, "%s %s",
299 				    subclassp->name, classp->name);
300 		}
301 		if (interface != 0)
302 			cp += sprintf(cp, ", interface 0x%02x", interface);
303 		if (revision != 0)
304 			cp += sprintf(cp, ", revision 0x%02x", revision);
305 		cp += sprintf(cp, ")");
306 	}
307 }
308 
309 /*
310  * Print out most of the PCI configuration registers.  Typically used
311  * in a device attach routine like this:
312  *
313  *	#ifdef MYDEV_DEBUG
314  *		printf("%s: ", sc->sc_dev.dv_xname);
315  *		pci_conf_print(pa->pa_pc, pa->pa_tag);
316  *	#endif
317  */
318 void
319 pci_conf_print(pc, tag)
320 	pci_chipset_tag_t pc;
321 	pcitag_t tag;
322 {
323 	pcireg_t rval;
324 	int reg;
325 #ifdef PCIVERBOSE
326 	struct pci_knowndev *kdp;
327 	static const char on_str[] = "ON", off_str[] = "OFF";
328 #endif
329 	struct pci_class *classp, *subclassp;
330 
331 	printf("PCI configuration registers:\n");
332 
333 	rval = pci_conf_read(pc, tag, PCI_ID_REG);
334 
335 #ifndef PCIVERBOSE
336 	printf("  Vendor ID: 0x%04x\n", PCI_VENDOR(rval));
337 	printf("  Device ID: 0x%04x\n", PCI_PRODUCT(rval));
338 #else
339 	for (kdp = pci_knowndevs; kdp->vendorname != NULL; kdp++) {
340 		if (kdp->vendor == PCI_VENDOR(rval) &&
341 		    (kdp->product == PCI_PRODUCT(rval) ||
342 		    (kdp->flags & PCI_KNOWNDEV_NOPROD) != 0)) {
343 			break;
344 		}
345 	}
346 	if (kdp->vendorname != NULL)
347 		printf("  Vendor Name: %s\n", kdp->vendorname);
348 	else
349 		printf("  Vendor ID: 0x%04x\n", PCI_VENDOR(rval));
350 
351 	if (kdp->productname != NULL && (kdp->flags & PCI_KNOWNDEV_NOPROD) == 0)
352 		printf("  Device Name: %s\n", kdp->productname);
353 	else
354 		printf("  Device ID: 0x%04x\n", PCI_PRODUCT(rval));
355 #endif /* PCIVERBOSE */
356 
357 	rval = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
358 
359 #ifndef PCIVERBOSE
360 	printf("  Command/Status Register: 0x%08x\n", rval);
361 #else
362 
363 #define	onoff(reg)	((rval & (reg)) ? on_str : off_str)
364 	printf("  Command Register:\n");
365 	printf("    I/O space accesses %s\n", onoff(PCI_COMMAND_IO_ENABLE));
366 	printf("    Mem space accesses %s\n", onoff(PCI_COMMAND_MEM_ENABLE));
367 	printf("    Bus mastering %s\n", onoff(PCI_COMMAND_MASTER_ENABLE));
368 	printf("    Special cycles %s\n", onoff(PCI_COMMAND_SPECIAL_ENABLE));
369 	printf("    MWI transactions %s\n",
370 	    onoff(PCI_COMMAND_INVALIDATE_ENABLE));
371 	printf("    Palette snooping %s\n", onoff(PCI_COMMAND_PALETTE_ENABLE));
372 	printf("    Parity error checking %s\n",
373 	    onoff(PCI_COMMAND_PARITY_ENABLE));
374 	printf("    Address/Data stepping %s\n",
375 	    onoff(PCI_COMMAND_STEPPING_ENABLE));
376 	printf("    System Error (SERR) %s\n", onoff(PCI_COMMAND_SERR_ENABLE));
377 	printf("    Fast back-to-back transactions %s\n",
378 	    onoff(PCI_COMMAND_BACKTOBACK_ENABLE));
379 	printf("  Status Register:\n");
380 	printf("    66 MHz capable %s\n", onoff(PCI_STATUS_66MHZ_SUPPORT));
381 	printf("    User Definable Features (UDF) support %s\n",
382 	    onoff(PCI_STATUS_UDF_SUPPORT));
383 	printf("    Fast back-to-back capable %s\n",
384 	    onoff(PCI_STATUS_BACKTOBACK_SUPPORT));
385 	printf("    Data parity error detected %s\n",
386 	    onoff(PCI_STATUS_PARITY_ERROR));
387 
388 	printf("    DEVSEL timing ");
389 	switch (rval & PCI_STATUS_DEVSEL_MASK) {
390 	case PCI_STATUS_DEVSEL_FAST:
391 		printf("fast");
392 		break;
393 	case PCI_STATUS_DEVSEL_MEDIUM:
394 		printf("medium");
395 		break;
396 	case PCI_STATUS_DEVSEL_SLOW:
397 		printf("slow");
398 		break;
399 	}
400 	printf("\n");
401 
402 	printf("    Slave signaled Target Abort %s\n",
403 	    onoff(PCI_STATUS_TARGET_TARGET_ABORT));
404 	printf("    Master received Target Abort %s\n",
405 	    onoff(PCI_STATUS_MASTER_TARGET_ABORT));
406 	printf("    Master received Master Abort %s\n",
407 	    onoff(PCI_STATUS_MASTER_ABORT));
408 	printf("    Asserted System Error (SERR) %s\n",
409 	    onoff(PCI_STATUS_SPECIAL_ERROR));
410 	printf("    Parity error detected %s\n",
411 	    onoff(PCI_STATUS_PARITY_DETECT));
412 #endif /* PCIVERBOSE */
413 
414 	rval = pci_conf_read(pc, tag, PCI_CLASS_REG);
415 
416 	for (classp = pci_class; classp->name != NULL; classp++) {
417 		if (PCI_CLASS(rval) == classp->val)
418 			break;
419 	}
420 	subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
421 	while (subclassp && subclassp->name != NULL) {
422 		if (PCI_SUBCLASS(rval) == subclassp->val)
423 			break;
424 		subclassp++;
425 	}
426 	if (classp->name != NULL) {
427 		printf("  Class Name: %s\n", classp->name);
428 		if (subclassp != NULL && subclassp->name != NULL)
429 			printf("  Subclass Name: %s\n", subclassp->name);
430 		else
431 			printf("  Subclass ID: 0x%02x\n", PCI_SUBCLASS(rval));
432 	} else {
433 		printf("  Class ID: 0x%02x\n", PCI_CLASS(rval));
434 		printf("  Subclass ID: 0x%02x\n", PCI_SUBCLASS(rval));
435 	}
436 	printf("  Interface: 0x%02x\n", PCI_INTERFACE(rval));
437 	printf("  Revision ID: 0x%02x\n", PCI_REVISION(rval));
438 
439 	rval = pci_conf_read(pc, tag, PCI_BHLC_REG);
440 
441 	printf("  BIST: 0x%02x\n", PCI_BIST(rval));
442 	printf("  Header Type: 0x%02x\n", PCI_HDRTYPE(rval));
443 	printf("  Latency Timer: 0x%02x\n", PCI_LATTIMER(rval));
444 	printf("  Cache Line Size: 0x%02x\n", PCI_CACHELINE(rval));
445 
446 	for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) {
447 		rval = pci_conf_read(pc, tag, reg);
448 		printf("  Mapping register 0x%02x\n", reg);
449 		if (PCI_MAPREG_TYPE(rval) == PCI_MAPREG_TYPE_MEM) {
450 			printf("    Base Address: 0x%08x, size 0x%08x, "
451 			    "type = mem", PCI_MAPREG_MEM_ADDR(rval),
452 			    PCI_MAPREG_MEM_SIZE(rval));
453 			switch (PCI_MAPREG_MEM_TYPE(rval)) {
454 			case PCI_MAPREG_MEM_TYPE_32BIT:
455 				printf(", 32-bit");
456 				break;
457 			case PCI_MAPREG_MEM_TYPE_32BIT_1M:
458 				printf(", 32-bit-1M");
459 				break;
460 			case PCI_MAPREG_MEM_TYPE_64BIT:
461 				printf(", 64-bit");
462 				break;
463 			}
464 			if (PCI_MAPREG_MEM_CACHEABLE(rval))
465 				printf(", cacheable");
466 			else
467 				printf(", not cacheable");
468 			printf("\n");
469 		} else {
470 			printf("    Base Address: 0x%08x, size 0x%08x, "
471 			    "type = i/o\n", PCI_MAPREG_IO_ADDR(rval),
472 			    PCI_MAPREG_IO_SIZE(rval));
473 		}
474 	}
475 
476 	rval = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
477 
478 	printf("  Maximum Latency: 0x%08x\n", (rval >> 24) & 0xff);
479 	printf("  Minimum Grant: 0x%08x\n", (rval >> 16) & 0xff);
480 	printf("  Interrupt pin: 0x%08x", PCI_INTERRUPT_PIN(rval));
481 	switch (PCI_INTERRUPT_PIN(rval)) {
482 	case PCI_INTERRUPT_PIN_NONE:
483 		printf(" (none)");
484 		break;
485 	case PCI_INTERRUPT_PIN_A:
486 		printf(" (pin A)");
487 		break;
488 	case PCI_INTERRUPT_PIN_B:
489 		printf(" (pin B)");
490 		break;
491 	case PCI_INTERRUPT_PIN_C:
492 		printf(" (pin C)");
493 		break;
494 	case PCI_INTERRUPT_PIN_D:
495 		printf(" (pin D)");
496 		break;
497 	}
498 	printf("\n");
499 	printf("  Interrupt line: 0x%08x\n", PCI_INTERRUPT_LINE(rval));
500 }
501