Booting the linux-ppc64 kernel & flattened device tree v0.4

2005-06-03 Thread David Gibson
On Thu, Jun 02, 2005 at 05:09:18PM +1000, David Gibson wrote:
> On Wed, Jun 01, 2005 at 06:26:30PM +1000, Benjamin Herrenschmidt wrote:
> > DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
> > 
> > Here's the fourth version of my document along with new kernel patches
> > for the new improved flattened format, and the first release of the
> > device-tree "compiler" tool. The patches will be posted as a reply to
> > this email. The compiler, dtc, can be downloaded, the URL is in the
> > document.
> 
> [snip]
> 
> > IV - "dtc", the device tree compiler
> > 
> 
> > 
> > dtc source code can be found at
> > 
> 
> I've just updated the dtc tarball with a new version.  Notable
> changes:
>   - Corrected comment parsing
>   - Corrected handling of #address-cells, #size-cells properties
>   - Input from device tree blobs should actually work now
>   - Corrected autogeneration of "name" properties in blob/asm
> output version < 0x10
>   - Added a TODO list

And yet another.  Notable changes:
- Basic generation of the reserve map in blob output, use -R
  command line option to leave space for a number of reserve
  map entries to be filled in by bootloader.
- Rewrite blob and assembler output to better share code, and
  produce more readable assembler output.


-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/people/dgibson



Booting the linux-ppc64 kernel & flattened device tree v0.4

2005-06-03 Thread Benjamin Herrenschmidt
On Wed, 2005-06-01 at 18:28 +1000, Benjamin Herrenschmidt wrote:
> Here is the kernel patch. It applies on top of the various prom_init.c
> bug fixes that I already posted today on the linuxppc-dev &
> linuxppc64-dev lists (those will be in the next -mm and maybe in
> 2.6.12).
> 
> This patch is intended to hit upstream by 2.6.13

Ok, the patch I posted with version 0.4 implementing version 0x10 of the
format was broken, here is a fixed version against current linus "git"
as of today:

Index: linux-work/arch/ppc64/kernel/prom_init.c
===
--- linux-work.orig/arch/ppc64/kernel/prom_init.c   2005-06-03 
16:52:28.0 +1000
+++ linux-work/arch/ppc64/kernel/prom_init.c2005-06-03 16:58:01.0 
+1000
@@ -1534,7 +1534,8 @@
  */
 #define MAX_PROPERTY_NAME 64
 
-static void __init scan_dt_build_strings(phandle node, unsigned long 
*mem_start,
+static void __init scan_dt_build_strings(phandle node,
+unsigned long *mem_start,
 unsigned long *mem_end)
 {
unsigned long offset = reloc_offset();
@@ -1547,16 +1548,21 @@
/* get and store all property names */
prev_name = RELOC("");
for (;;) {
-   int rc;
-
/* 64 is max len of name including nul. */
namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
-   rc = call_prom("nextprop", 3, 1, node, prev_name, namep);
-   if (rc != 1) {
+   if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
/* No more nodes: unwind alloc */
*mem_start = (unsigned long)namep;
break;
}
+
+   /* skip "name" */
+   if (strcmp(namep, RELOC("name")) == 0) {
+   *mem_start = (unsigned long)namep;
+   prev_name = RELOC("name");
+   continue;
+   }
+   /* get/create string entry */
soff = dt_find_string(namep);
if (soff != 0) {
*mem_start = (unsigned long)namep;
@@ -1571,7 +1577,7 @@
 
/* do all our children */
child = call_prom("child", 1, 1, node);
-   while (child != (phandle)0) {
+   while (child != 0) {
scan_dt_build_strings(child, mem_start, mem_end);
child = call_prom("peer", 1, 1, child);
}
@@ -1580,16 +1586,13 @@
 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
unsigned long *mem_end)
 {
-   int l, align;
phandle child;
-   char *namep, *prev_name, *sstart, *p, *ep;
+   char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
unsigned long soff;
unsigned char *valp;
unsigned long offset = reloc_offset();
-   char pname[MAX_PROPERTY_NAME];
-   char *path;
-
-   path = RELOC(prom_scratch);
+   static char pname[MAX_PROPERTY_NAME];
+   int l;
 
dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
 
@@ -1599,23 +1602,33 @@
  namep, *mem_end - *mem_start);
if (l >= 0) {
/* Didn't fit?  Get more room. */
-   if (l+1 > *mem_end - *mem_start) {
+   if ((l+1) > (*mem_end - *mem_start)) {
namep = make_room(mem_start, mem_end, l+1, 1);
call_prom("package-to-path", 3, 1, node, namep, l);
}
namep[l] = '\0';
+
/* Fixup an Apple bug where they have bogus \0 chars in the
 * middle of the path in some properties
 */
for (p = namep, ep = namep + l; p < ep; p++)
if (*p == '\0') {
memmove(p, p+1, ep - p);
-   ep--; l--;
+   ep--; l--; p--;
}
-   *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 
1, 4);
+
+   /* now try to extract the unit name in that mess */
+   for (p = namep, lp = NULL; *p; p++)
+   if (*p == '/')
+   lp = p + 1;
+   if (lp != NULL)
+   memmove(namep, lp, strlen(lp) + 1);
+   *mem_start = _ALIGN(((unsigned long) namep) +
+   strlen(namep) + 1, 4);
}
 
/* get it again for debugging */
+   path = RELOC(prom_scratch);
memset(path, 0, PROM_SCRATCH_SIZE);
call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
 
@@ -1623,23 +1636,27 @@
prev_name = RELOC("");
sstart = (char *)RELOC(dt_string_start);
for (;;) {
-   int rc;
-
-   rc = call_prom("nextprop", 3, 1,

Booting the linux-ppc64 kernel & flattened device tree v0.4

2005-06-02 Thread David Gibson
On Wed, Jun 01, 2005 at 06:26:30PM +1000, Benjamin Herrenschmidt wrote:
> DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
> 
> Here's the fourth version of my document along with new kernel patches
> for the new improved flattened format, and the first release of the
> device-tree "compiler" tool. The patches will be posted as a reply to
> this email. The compiler, dtc, can be downloaded, the URL is in the
> document.

[snip]

> IV - "dtc", the device tree compiler
> 

> 
> dtc source code can be found at
> 

I've just updated the dtc tarball with a new version.  Notable
changes:
- Corrected comment parsing
- Corrected handling of #address-cells, #size-cells properties
- Input from device tree blobs should actually work now
- Corrected autogeneration of "name" properties in blob/asm
  output version < 0x10
- Added a TODO list

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/people/dgibson



Booting the linux-ppc64 kernel & flattened device tree v0.4

2005-06-02 Thread Benjamin Herrenschmidt
On Wed, 2005-06-01 at 14:54 -0500, Jon Loeliger wrote:
> On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
> > DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
> > 
> > Here's the fourth version of my document along with new kernel patches
> > for the new improved flattened format, and the first release of the
> > device-tree "compiler" tool. The patches will be posted as a reply to
> > this email. The compiler, dtc, can be downloaded, the URL is in the
> > document.
> > 
> > ---
> 
> > 
> > dtc source code can be found at 
> 
> Ben,
> 
> Here are diffs to:
> 
> - Fix multi-line C-style comments.
> 
> - Adjust the output of write_tree_source() such that it
>   separates properties and nodes a bit better.


Excellent, thanks. Please CC david next time.

Ben.





Booting the linux-ppc64 kernel & flattened device tree v0.4

2005-06-02 Thread Benjamin Herrenschmidt
On Wed, 2005-06-01 at 11:58 -0500, Jon Loeliger wrote:
> On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
> > Here's the fourth version of my document along with new kernel patches
> > for the new improved flattened format, and the first release of the
> > device-tree "compiler" tool. The patches will be posted as a reply to
> > this email. The compiler, dtc, can be downloaded, the URL is in the
> > document.
> 
> Ben,
> 
> Does it make sense to do this as well?

You mean include lsprop ? Well, I have another version of lsprop hacked
here that can generate a "source", but dtc can do it too now ... I think
we may just make dtc able to output in "lsprop" format too :) But I'll
talk to david (CC'd, he's the author of dtc).

Ben.





Booting the linux-ppc64 kernel & flattened device tree v0.4

2005-06-01 Thread Benjamin Herrenschmidt
Here is the kernel patch. It applies on top of the various prom_init.c
bug fixes that I already posted today on the linuxppc-dev &
linuxppc64-dev lists (those will be in the next -mm and maybe in
2.6.12).

This patch is intended to hit upstream by 2.6.13


Index: linux-work/arch/ppc64/kernel/prom_init.c
===
--- linux-work.orig/arch/ppc64/kernel/prom_init.c   2005-06-01 
16:02:28.0 +1000
+++ linux-work/arch/ppc64/kernel/prom_init.c2005-06-01 16:07:21.0 
+1000
@@ -1514,7 +1514,14 @@
return 0;
 }
 
-static void __init scan_dt_build_strings(phandle node, unsigned long 
*mem_start,
+/*
+ * The Open Firmware 1275 specification states properties must be 31 bytes or
+ * less, however not all firmwares obey this. Make it 64 bytes to be safe.
+ */
+#define MAX_PROPERTY_NAME 64
+
+static void __init scan_dt_build_strings(phandle node,
+unsigned long *mem_start,
 unsigned long *mem_end)
 {
unsigned long offset = reloc_offset();
@@ -1527,14 +1534,19 @@
/* get and store all property names */
prev_name = RELOC("");
for (;;) {
-   
-   /* 32 is max len of name including nul. */
-   namep = make_room(mem_start, mem_end, 32, 1);
+   namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
/* No more nodes: unwind alloc */
*mem_start = (unsigned long)namep;
break;
}
+
+   /* skip "name" */
+   if (strcmp(namep, RELOC("name")) == 0) {
+   *mem_start = (unsigned long)namep;
+   prev_name = RELOC("name");
+   continue;
+   }
soff = dt_find_string(namep);
if (soff != 0) {
*mem_start = (unsigned long)namep;
@@ -1555,72 +1567,83 @@
}
 }
 
-/*
- * The Open Firmware 1275 specification states properties must be 31 bytes or
- * less, however not all firmwares obey this. Make it 64 bytes to be safe.
- */
-#define MAX_PROPERTY_NAME 64
-
 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
unsigned long *mem_end)
 {
-   int l, align;
phandle child;
-   char *namep, *prev_name, *sstart, *p, *ep;
+   char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
unsigned long soff;
unsigned char *valp;
unsigned long offset = reloc_offset();
-   char pname[MAX_PROPERTY_NAME];
-   char *path;
-
-   path = RELOC(prom_scratch);
+   static char pname[MAX_PROPERTY_NAME] __initdata;
+   int l;
 
dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
 
-   /* get the node's full name */
+   /* get the node's full name for debugging */
+   path = RELOC(prom_scratch);
+   memset(path, 0, PROM_SCRATCH_SIZE);
+   call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
+   prom_debug("   %s\n", path);
+ 
+   /* get the node's full name for actual use */
namep = (char *)*mem_start;
l = call_prom("package-to-path", 3, 1, node,
  namep, *mem_end - *mem_start);
if (l >= 0) {
+   int had_fixup = 0;
+ 
/* Didn't fit?  Get more room. */
if (l+1 > *mem_end - *mem_start) {
namep = make_room(mem_start, mem_end, l+1, 1);
call_prom("package-to-path", 3, 1, node, namep, l);
}
-   namep[l] = '\0';
-   /* Fixup an Apple bug where they have bogus \0 chars in the
-* middle of the path in some properties
-*/
-   for (p = namep, ep = namep + l; p < ep; p++)
-   if (*p == '\0') {
-   memmove(p, p+1, ep - p);
-   ep--; l--;
-   }
-   *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 
1, 4);
+   ep = namep + l;
+   *ep = '\0';
+   /* now try to find the unit name in that mess */
+   for (p = namep, lp = NULL; p < ep; p++) {
+   if (*p == '/')
+   lp = p + 1;
+   /* bug fix: apple's OF has a funny bug where they have
+* a '\0' in the name/path string of some nodes.
+* We fix that up here
+*/
+   if (*p == '\0') {
+   memmove(p, p+1, ep - p);
+   ep--; l--;
+   had_fixup = 1;
+   }
+ 

Booting the linux-ppc64 kernel & flattened device tree v0.4

2005-06-01 Thread Benjamin Herrenschmidt
DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).

Here's the fourth version of my document along with new kernel patches
for the new improved flattened format, and the first release of the
device-tree "compiler" tool. The patches will be posted as a reply to
this email. The compiler, dtc, can be downloaded, the URL is in the
document.

---

   Booting the Linux/ppc64 kernel without Open Firmware
   


(c) 2005 Benjamin Herrenschmidt , IBM Corp.

   May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.

   May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or
   clarifies the fact that a lot of things are
   optional, the kernel only requires a very
   small device tree, though it is encouraged
   to provide an as complete one as possible.
 
   May 24, 2005: Rev 0.3 - Precise that DT block has to be in RAM
 - Misc fixes
 - Define version 3 and new format version 16
   for the DT block (version 16 needs kernel
   patches, will be fwd separately).
   String block now has a size, and full path
   is replaced by unit name for more
   compactness.
   linux,phandle is made optional, only nodes
   that are referenced by other nodes need it.
   "name" property is now automatically
   deduced from the unit name

   June 1, 2005: Rev 0.4 - Correct confusion between OF_DT_END and
   OF_DT_END_NODE in structure definition.
 - Change version 16 format to always align
   property data to 4 bytes. Since tokens are
   already aligned, that means no specific
   required alignement between property size
   and property data. The old style variable
   alignment would make it impossible to do
   "simple" insertion of properties using
   memove (thanks Milton for
   noticing). Updated kernel patch as well
 - Correct a few more alignement constraints
 - Add a chapter about the device-tree
   compiler and the textural representation of
   the tree that can be "compiled" by dtc.


 ToDo:

- Add some definitions of interrupt tree (simple/complex)
- Add some definitions for pci host bridges


I- Introduction
===


During the recent developpements of the Linux/ppc64 kernel, and more
specifically, the addition of new platform types outside of the old
IBM pSeries/iSeries pair, it was decided to enforce some strict rules
regarding the kernel entry and bootloader <-> kernel interfaces, in
order to avoid the degeneration that has become the ppc32 kernel entry
point and the way a new platform should be added to the kernel. The
legacy iSeries platform breaks those rules as it predates this scheme,
but no new board support will be accepted in the main tree that
doesn't follows them properly.

The main requirement that will be defined in more details below is
the presence of a device-tree whose format is defined after Open
Firmware specification. However, in order to make life easier
to embedded board vendors, the kernel doesn't require the device-tree
to represent every device in the system and only requires some nodes
and properties to be present. This will be described in details in
section III, but, for example, the kernel does not require you to
create a node for every PCI device in the system. It is a requirement
to have a node for PCI host bridges in order to provide interrupt
routing informations and memory/IO ranges, among others. It is also
recommended to define nodes for on chip devices and other busses that
doesn't specifically fit in an existing OF specification, like on chip
devices, this creates a great flexibility in the way the kernel can
them probe those and match drivers to device, without having to hard
code all sorts of tables. It also makes it more flexible for board
vendors to do minor hardware upgrades without impacting significantly
the kernel code or cluttering it with special cases.
 

1) Entry point
--

   There is one and one single entry point to the kernel, at the start
   of the kernel image. That entry point support two calling
   conventions:

a) Boot from Open Firmware. If your firmware is compatible
with Open Firmware (IEEE 1275) or provides an OF compatible
client interface API (support for "interpret" callback of
forth words isn't required), you can enter the

Booting the linux-ppc64 kernel & flattened device tree v0.4

2005-06-01 Thread Jon Loeliger
On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
> DO NOT REPLY TO ALL LISTS PLEASE ! (and CC me on replies).
> 
> Here's the fourth version of my document along with new kernel patches
> for the new improved flattened format, and the first release of the
> device-tree "compiler" tool. The patches will be posted as a reply to
> this email. The compiler, dtc, can be downloaded, the URL is in the
> document.
> 
> ---

> 
> dtc source code can be found at 

Ben,

Here are diffs to:

- Fix multi-line C-style comments.

- Adjust the output of write_tree_source() such that it
  separates properties and nodes a bit better.

Thanks,
jdl


diff -u dtc.orig/dtc-lexer.l dtc/dtc-lexer.l
--- dtc.orig/dtc-lexer.l2005-06-01 11:44:29.02000 -0500
+++ dtc/dtc-lexer.l 2005-06-01 13:39:56.01000 -0500
@@ -34,8 +34,6 @@
 
 #include "y.tab.h"
 
-#undef LEXDEBUG1
-
 %}
 
 \"[^"]*\"  {
@@ -102,7 +100,7 @@
 
 <*>{WS}+   /* eat whitespace */
 
-<*>\/\*[^*]*(\*[^/][^*])*\*\/  /* eat comments */
+<*>\/\*([^*]|\**[^*/])*\*+\/   /* eat C comments */
 
 <*>\/\/.*\n/* eat line comments */
 
diff -u dtc.orig/treesource.c dtc/treesource.c
--- dtc.orig/treesource.c   2005-06-01 11:44:29.02000 -0500
+++ dtc/treesource.c2005-06-01 13:58:33.01000 -0500
@@ -131,10 +131,16 @@
break;
}
}
-   fprintf(f, "\n");
+   if (tree->children) {
+   fprintf(f, "\n");
+   }
for_each_child(tree, child) {
write_tree_source(f, child, level+1);
}
write_prefix(f, level);
fprintf(f, "};\n");
+
+   if (tree->next_sibling) {
+   fprintf(f, "\n");
+   }
 }






Booting the linux-ppc64 kernel & flattened device tree v0.4

2005-06-01 Thread Jon Loeliger
On Wed, 2005-06-01 at 03:26, Benjamin Herrenschmidt wrote:
> Here's the fourth version of my document along with new kernel patches
> for the new improved flattened format, and the first release of the
> device-tree "compiler" tool. The patches will be posted as a reply to
> this email. The compiler, dtc, can be downloaded, the URL is in the
> document.

Ben,

Does it make sense to do this as well?

Thanks,
jdl


diff -Nur dtc.orig/lsprop.c dtc/lsprop.c
--- dtc.orig/lsprop.c   1969-12-31 18:00:00.0 -0600
+++ dtc/lsprop.c2005-06-01 11:43:01.02000 -0500
@@ -0,0 +1,221 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int recurse;
+int maxbytes = 128;
+int words_per_line = 0;
+char *buf;
+
+void lsprop(FILE *f, char *name);
+void lsdir(char *name);
+
+main(int ac, char **av)
+{
+FILE *f;
+int i;
+struct stat sb;
+char *endp;
+
+while ((i = getopt(ac, av, "Rm:w:")) != EOF) {
+   switch (i) {
+   case 'R':
+   recurse = 1;
+   break;
+   case 'm':
+   maxbytes = strtol(optarg, &endp, 0);
+   if (endp == optarg) {
+   fprintf(stderr, "%s: bad argument (%s) to -m option\n", av[0],
+   optarg);
+   exit(1);
+   }
+   maxbytes = (maxbytes + 15) & -16;
+   break;
+   case 'w':
+   words_per_line = strtol(optarg, &endp, 0);
+   if (endp == optarg) {
+   fprintf(stderr, "%s: bad argument (%s) to -w option\n",
+   av[0], optarg);
+   exit(1);
+   }
+   break;
+   }
+}
+
+buf = malloc(maxbytes);
+if (buf == 0) {
+   fprintf(stderr, "%s: virtual memory exhausted\n", av[0]);
+   exit(1);
+}
+
+if (optind == ac)
+   lsdir(".");
+else
+   for (i = optind; i < ac; ++i) {
+   if (stat(av[i], &sb) < 0) {
+   perror(av[i]);
+   continue;
+   }
+   if (S_ISREG(sb.st_mode)) {
+   f = fopen(av[i], "r");
+   if (f == NULL) {
+   perror(av[i]);
+   continue;
+   }
+   lsprop(f, av[i]);
+   fclose(f);
+   } else if (S_ISDIR(sb.st_mode)) {
+   lsdir(av[i]);
+   }
+   }
+exit(0);
+}
+
+void lsdir(char *name)
+{
+DIR *d;
+struct dirent *de;
+char *p, *q;
+struct stat sb;
+FILE *f;
+int np = 0;
+
+d = opendir(name);
+if (d == NULL) {
+   perror(name);
+   return;
+}
+
+p = malloc(strlen(name) + 520);
+if (p == 0) {
+   fprintf(stderr, "%s: virtual memory exhausted\n", name);
+   closedir(d);
+   return;
+}
+strcpy(p, name);
+q = p + strlen(p);
+while (q > p && q[-1] == '/')
+   --q;
+if (q == p + 1 && p[0] == '.')
+   q = p;
+else
+   *q++ = '/';
+
+while ((de = readdir(d)) != NULL) {
+   if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
+   continue;
+   strcpy(q, de->d_name);
+   if (stat(p, &sb) < 0) {
+   perror(p);
+   continue;
+   }
+   if (S_ISREG(sb.st_mode)) {
+   f = fopen(p, "r");
+   if (f == NULL) {
+   perror(p);
+   } else {
+   lsprop(f, de->d_name);
+   fclose(f);
+   ++np;
+   }
+   }
+}
+rewinddir(d);
+while ((de = readdir(d)) != NULL) {
+   if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
+   continue;
+   strcpy(q, de->d_name);
+   if (lstat(p, &sb) < 0) {
+   perror(p);
+   continue;
+   }
+   if (S_ISDIR(sb.st_mode)) {
+   if (np)
+   printf("\n");
+   printf("%s:\n", p);
+   lsdir(p);
+   ++np;
+   }
+}
+free(p);
+closedir(d);
+}
+
+void lsprop(FILE *f, char *name)
+{
+int n, nw, npl, i, j;
+
+n = fread(buf, 1, maxbytes, f);
+if (n < 0) {
+   printf("%s: read error\n", name);
+   return;
+}
+printf("%-16s", name);
+if (strlen(name) > 16)
+   printf("\n\t\t");
+for (i = 0; i < n; ++i)
+   if (buf[i] >= 0x7f ||
+   (buf[i] < 0x20 && buf[i] != '\r' && buf[i] != '\n'
+&& buf[i] != '\t' && buf[i] != 0))
+   break;
+if (i == n && n != 0 && (n == 1 || buf[0] != 0) && buf[n-1] == 0) {
+   printf(" \"");
+   for (i = 0; i < n - 1; ++i)
+   if (buf[i] == 0)
+   printf("\"\n\t\t \"");
+   else if (buf[i] == '\r' || buf[i] == '\n')
+   printf("\n\t\t ");
+   else
+   putchar(buf[i]);
+   putchar('"');
+} else if ((n & 3) == 0) {
+   nw = n >> 2;
+   if (nw == 1) {
+   i = *(int *)buf;
+   printf(" %.8x", i);
+   if (i > -0x1 && !(i >= 0 && i <= 9))
+   printf(" (%d)", i);
+   } else {