{"thread":{"id":"11607","subject":"Re: Digging through old vendor code","startedAt":"2008-01-13T16:28:06Z","lastAt":"2008-01-14T14:49:30Z","messageCount":5,"participants":["linux@horizon.com","Jon Smirl","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"65255","messageId":"20080113162806.13991.qmail@science.horizon.com","threadId":"11607","inReplyTo":null,"subject":"Re: Digging through old vendor code","fromName":"","fromEmail":"linux@horizon.com","sentAt":"2008-01-13T16:28:06Z","receivedAt":"2008-01-13T16:28:06Z","isPatch":false,"sender":{"key":"linux@horizon.com","avatar":null},"body":"> Heh. Maybe you could just use the rename logic?\n>\n> [How-to snipped]\n\nClever idea, but I think the real problem was to figure out what VERSION\nof the file was the base; i.e. to look through history.\n\nStill, it should be possible to adapt the technique...\n\n#!/bin/sh\n\n# List of files we are looking to copy from\nSRC=\"drivers/serial/\"\n# Temporary work directory\nDST=/tmp/work\ngit-clone -l -n -s . $DST\n{ cd $DST; git-symbolic-ref HEAD refs/heads/DELETEME; }\nfor i in `git-rev-list v2.6.20..v2.6.24-rc6 -- $SRC`; do\n        j=`git-describe $i`\n        git-archive --prefix=\"$j/\" $i -- $SRC | tar xf - -C $DST\n        # This is abusing the index, but it saves space...\n        { cd $DST; git add $j; rm -rf $j; }\ndone\n\n# And  now proceed as per Linus's idea...\n# Except we have it all in the index; no need\n# to actually make a commit...\n\ncd $DST\ncp $target_file $DST\n{ cd $DST; git-diff-files -M...; }\n\n\nMaybe a real git wizard will show me how to insert the index entries\ndirectly without ever doing anything as pedestrian as extracting, hashing,\nand then deleting the files, but it's still not that bad.\n\nAnd it's kind of a neat example of using the index as a staging area\nfor a commit.\n\n(Exercise for the reader: the above gets a complete copy of every file in\nthe directory for every commit in qhich ANY file in the directory changed.\nBetter would be to do the git-rev-list per-file, so you only add unique\nfile versions.  This requires an outer loop over file names and a more\ncareful pathname specification to git add in the inner loop.)\n"},{"id":"65258","messageId":"9e4733910801130904n7f311915tba4aa5b766c7a9bc@mail.gmail.com","threadId":"11607","inReplyTo":"20080113162806.13991.qmail@science.horizon.com","subject":"Re: Digging through old vendor code","fromName":"Jon Smirl","fromEmail":"jonsmirl@gmail.com","sentAt":"2008-01-13T17:04:17Z","receivedAt":"2008-01-13T17:04:17Z","isPatch":false,"sender":{"key":"jonsmirl@gmail.com","avatar":"https://gravatar.com/avatar/cff3bf5bfdfa6708b905712ff91f0f9b8aaca161659f38c02b787920d5d28b7e?d=mp&s=160"},"body":"The vendor gave me an edited file with support for their device. The\noriginal was copied from the kernel somewhere around 2.6.15 and then\nedited. Nobody remembers what the source file was but there are a\ncouple of fairly close matches.\n\nDiffing against the current kernel mixes the two sets of changes -\nwhat the vendor did and what changed in the core kernel. I'm sorting\nthis out by hand but it is 3,000 lines of diffs.\n\nIt is an interesting problem to use the git history to try and\ndiscover the original source file.\n\n-- \nJon Smirl\njonsmirl@gmail.com\n"},{"id":"65260","messageId":"9e4733910801130931y39a29ea2lf6bb3ebd216ed0ba@mail.gmail.com","threadId":"11607","inReplyTo":"20080113162806.13991.qmail@science.horizon.com","subject":"Re: Digging through old vendor code","fromName":"Jon Smirl","fromEmail":"jonsmirl@gmail.com","sentAt":"2008-01-13T17:31:35Z","receivedAt":"2008-01-13T17:31:35Z","isPatch":false,"sender":{"key":"jonsmirl@gmail.com","avatar":"https://gravatar.com/avatar/cff3bf5bfdfa6708b905712ff91f0f9b8aaca161659f38c02b787920d5d28b7e?d=mp&s=160"},"body":"On 13 Jan 2008 11:28:06 -0500, linux@horizon.com <linux@horizon.com> wrote:\n> > Heh. Maybe you could just use the rename logic?\n> >\n> > [How-to snipped]\n>\n> Clever idea, but I think the real problem was to figure out what VERSION\n> of the file was the base; i.e. to look through history.\n>\n> Still, it should be possible to adapt the technique...\n>\n> #!/bin/sh\n>\n> # List of files we are looking to copy from\n> SRC=\"drivers/serial/\"\n> # Temporary work directory\n> DST=/tmp/work\n> git-clone -l -n -s . $DST\n> { cd $DST; git-symbolic-ref HEAD refs/heads/DELETEME; }\n> for i in `git-rev-list v2.6.20..v2.6.24-rc6 -- $SRC`; do\n>         j=`git-describe $i`\n>         git-archive --prefix=\"$j/\" $i -- $SRC | tar xf - -C $DST\n>         # This is abusing the index, but it saves space...\n>         { cd $DST; git add $j; rm -rf $j; }\n> done\n>\n> # And  now proceed as per Linus's idea...\n> # Except we have it all in the index; no need\n> # to actually make a commit...\n>\n> cd $DST\n> cp $target_file $DST\n> { cd $DST; git-diff-files -M...; }\n\nI tried this using -M1%, it returned 53,575 files. Same thing for 10%.\n\nThe files don't seem to be in order by similarity, the first match\nreturned is not a good one.\n\nI attached the file if anyone wants to play with it. I'm 90% certain\nit was copied from amba-pl010.c in 2.6.15.\n\n\n>\n>\n> Maybe a real git wizard will show me how to insert the index entries\n> directly without ever doing anything as pedestrian as extracting, hashing,\n> and then deleting the files, but it's still not that bad.\n>\n> And it's kind of a neat example of using the index as a staging area\n> for a commit.\n>\n> (Exercise for the reader: the above gets a complete copy of every file in\n> the directory for every commit in qhich ANY file in the directory changed.\n> Better would be to do the git-rev-list per-file, so you only add unique\n> file versions.  This requires an outer loop over file names and a more\n> careful pathname specification to git add in the inner loop.)\n>\n\n\n-- \nJon Smirl\njonsmirl@gmail.com\n\n\n/*\n *  linux/drivers/serial/cs93xx.c\n *\n *  Driver for EP93xx serial ports\n *\n *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o,\n *  Deep Blue Solutions Ltd.\n *\n *  Copyright 1999 ARM Limited\n *  Copyright (C) 2000 Deep Blue Solutions Ltd.\n *  Copyright (c) 2003 Cirrus Logic, Inc.\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n *\n *  $Id: linux-2.6.21.5-ep9x.patch,v 1.8 2008/01/04 13:28:07 baustin Exp $\n *\n * The EP93xx serial ports are AMBA, but at different addresses from the\n * integrator.\n * This is a generic driver for ARM AMBA-type serial ports.  They\n * have a lot of 16550-like features, but are not register compatable.\n * Note that although they do have CTS, DCD and DSR inputs, they do\n * not have an RI input, nor do they have DTR or RTS outputs.  If\n * required, these have to be supplied via some other means (eg, GPIO)\n * and hooked into this driver.\n */\n#include <linux/module.h>\n#include <linux/tty.h>\n#include <linux/tty_flip.h>\n#include <linux/ioport.h>\n#include <linux/init.h>\n#include <linux/serial.h>\n#include <linux/console.h>\n#include <linux/sysrq.h>\n#include <linux/spinlock.h>\n//#include <linux/device.h>\n#include <linux/platform_device.h>\n\n#include <asm/hardware.h>\n#include <asm/io.h>\n//#include <asm/irqs.h>\n\n#if defined(CONFIG_SERIAL_EP93XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)\n#define SUPPORT_SYSRQ\n#endif\n\n\n#include <linux/serial_core.h>\n#include <linux/amba/bus.h>\n#include <linux/amba/serial.h>\n\n\n\n#if defined(CONFIG_ARCH_EP9301) || defined(CONFIG_ARCH_EP9302)\n#ifdef CONFIG_EP93XX_IRDA\n#define UART_NR\t\t1\n#else\n#define UART_NR\t\t2\n#endif\n#else\n#ifdef CONFIG_EP93XX_IRDA\n#define UART_NR\t\t2\n#else\n#define UART_NR\t\t3\n#endif\n#endif\n\n#define SERIAL_EP93XX_MAJOR\t204\n#define SERIAL_EP93XX_MINOR\t16\n#define SERIAL_EP93XX_NR\tUART_NR\n\n#define EP93XX_ISR_PASS_LIMIT\t256\n\n/*\n * Access macros for the AMBA UARTs\n */\n#define UART_GET_INT_STATUS(p)\t((readl((p)->membase + UARTIIR)) & 0xff)\n#define UART_PUT_ICR(p, c)\twritel((c), (p)->membase + UARTICR)\n#define UART_GET_FR(p)\t\t((readl((p)->membase + UARTFR)) & 0xff)\n#define UART_GET_CHAR(p)\t((readl((p)->membase + UARTDR)) & 0xff)\n#define UART_PUT_CHAR(p, c)\twritel((c), (p)->membase + UARTDR)\n#define UART_GET_RSR(p)\t\t((readl((p)->membase + UARTRSR)) & 0xff)\n#define UART_PUT_RSR(p, c)\twritel((c), (p)->membase + UARTRSR)\n#define UART_GET_CR(p)\t\t((readl((p)->membase + UARTCR)) & 0xff)\n#define UART_PUT_CR(p,c)\twritel((c), (p)->membase + UARTCR)\n#define UART_GET_LCRL(p)\t((readl((p)->membase + UARTCR_L)) & 0xff)\n#define UART_PUT_LCRL(p,c)\twritel((c), (p)->membase + UARTCR_L)\n#define UART_GET_LCRM(p)\t((readl((p)->membase + UARTCR_M)) & 0xff)\n#define UART_PUT_LCRM(p,c)\twritel((c), (p)->membase + UARTCR_M)\n#define UART_GET_LCRH(p)\t((readl((p)->membase + UARTCR_H)) & 0xff)\n#define UART_PUT_LCRH(p,c)\twritel((c), (p)->membase + UARTCR_H)\n#define UART_RX_DATA(s)\t\t(((s) & UARTFR_RXFE) == 0)\n#define UART_TX_READY(s)\t(((s) & UARTFR_TXFF) == 0)\n#define UART_TX_EMPTY(p)\t((UART_GET_FR(p) & UARTFR_TMSK) == 0)\n\n#define UART_GET_MCR(p)\t\treadl((p)->membase + UARTMCR)\n#define UART_PUT_MCR(c, p)\twritel((c), (p)->membase + UARTMCR)\n#define UART_CLEAR_ECR(p)\twritel( 0, (p)->membase + UARTECR)\n\n#define UART_DUMMY_RSR_RX\t256\n#define UART_PORT_SIZE\t\t65536\n\n/*\n * We wrap our port structure around the generic uart_port.\n */\nstruct uart_ep93xx_port {\n\tstruct uart_port\tport;\n\tunsigned int\t\told_status;\n};\n\n\nstatic void\nep93xxuart_enable_clocks(struct uart_port *port)\n{\n\tunsigned int uiSysDevCfg;\n\n\t/*\n\t * Enable the clocks to this UART in CSC_syscon\n\t * - Read DEVCFG\n\t * - OR in the correct uart enable bit\n\t * - Set the lock register\n\t * - Write back to DEVCFG\n\t */\n\tuiSysDevCfg = inl(SYSCON_DEVCFG);\n\n\tswitch ((unsigned long)port->membase) {\n\tcase UART1_BASE:\n\t\tuiSysDevCfg |= SYSCON_DEVCFG_U1EN;\n\t\tbreak;\n\n\tcase UART2_BASE:\n\t\tuiSysDevCfg |= SYSCON_DEVCFG_U2EN;\n\t\tbreak;\n\n\tcase UART3_BASE:\n\t\tuiSysDevCfg |= SYSCON_DEVCFG_U3EN;\n\t\tbreak;\n\t}\n\n\tSysconSetLocked( SYSCON_DEVCFG, uiSysDevCfg );\n}\n\nstatic void\nep93xxuart_disable_clocks(struct uart_port *port)\n{\n\tunsigned int uiSysDevCfg;\n\n\t/*\n\t * Disable the clocks to this UART in CSC_syscon\n\t * - Read DEVCFG\n\t * - AND to clear the correct uart enable bit\n\t * - Set the lock register\n\t * - Write back to DEVCFG\n\t */\n\tuiSysDevCfg = inl(SYSCON_DEVCFG);\n\n\tswitch ((unsigned long)port->membase) {\n\tcase UART1_BASE:\n\t\tuiSysDevCfg &= ~((unsigned int)SYSCON_DEVCFG_U1EN);\n\t\tbreak;\n\n\tcase UART2_BASE:\n\t\tuiSysDevCfg &= ~((unsigned int)SYSCON_DEVCFG_U2EN);\n\t\tbreak;\n\n\tcase UART3_BASE:\n\t\tuiSysDevCfg &= ~((unsigned int)SYSCON_DEVCFG_U3EN);\n\t\tbreak;\n\t}\n\n\tSysconSetLocked( SYSCON_DEVCFG, uiSysDevCfg );\n}\n\n#if 1\nstatic int\nep93xxuart_is_port_enabled(struct uart_port *port)\n{\n\tunsigned int uiSysDevCfg;\n\n\tuiSysDevCfg = inl(SYSCON_DEVCFG);\n\n\tswitch ((unsigned long)port->membase) {\n\tcase UART1_BASE:\n\t\tuiSysDevCfg &= (unsigned int)SYSCON_DEVCFG_U1EN;\n\t\tbreak;\n\n\tcase UART2_BASE:\n\t\tuiSysDevCfg &= (unsigned int)SYSCON_DEVCFG_U2EN;\n\t\tbreak;\n\n\tcase UART3_BASE:\n\t\tuiSysDevCfg &= (unsigned int)SYSCON_DEVCFG_U3EN;\n\t\tbreak;\n\t}\n\n\treturn( uiSysDevCfg != 0 );\n}\n#endif\n\nstatic void\nep93xxuart_stop_tx(struct uart_port *port)\n{\n\tunsigned int cr;\n\n\tcr = UART_GET_CR(port);\n\tcr &= ~UARTCR_TIE;\n\tUART_PUT_CR(port, cr);\n}\n\nstatic void\nep93xxuart_start_tx(struct uart_port *port)\n{\n\tunsigned int cr;\n\n\tcr = UART_GET_CR(port);\n\tcr |= UARTCR_TIE;\n\tUART_PUT_CR(port, cr);\n}\n\nstatic void\nep93xxuart_stop_rx(struct uart_port *port)\n{\n\tunsigned int cr;\n\n\tcr = UART_GET_CR(port);\n\tcr &= ~(UARTCR_RIE | UARTCR_RTIE);\n\tUART_PUT_CR(port, cr);\n}\n\nstatic void\nep93xxuart_enable_ms(struct uart_port *port)\n{\n\tunsigned int cr;\n\n\tcr = UART_GET_CR(port);\n\tcr |= UARTCR_MSIE;\n\tUART_PUT_CR(port, cr);\n}\n\nstatic void\n#ifdef SUPPORT_SYSRQ\nep93xxuart_rx_chars(struct uart_port *port, struct pt_regs *regs)\n#else\nep93xxuart_rx_chars(struct uart_port *port)\n#endif\n{\n\tstruct tty_struct *tty = port->info->tty;\n\tunsigned int status, ch, flag, rsr, max_count = 256;\n\nif(((unsigned long)port->membase)==UART2_BASE)\n{\nprintk(\"ep93 UART2 ep93xxuart_rx_chars\\n\");\n}\n\n\tflag = 0;\n\tstatus = UART_GET_FR(port);\n\twhile (UART_RX_DATA(status) && max_count--) {\n\t\t//if (tty->flip.count >= TTY_FLIPBUF_SIZE) {\n\t\t//\ttty->flip.work.func((void *)tty);\n\t\t//\tif (tty->flip.count >= TTY_FLIPBUF_SIZE) {\n\t\t//\t\tprintk(KERN_WARNING \"TTY_DONT_FLIP set\\n\");\n\t\t//\t\treturn;\n\t\t//\t}\n\t\t//}\n\t\t\n\t\tch = UART_GET_CHAR(port);\n\n\t\t//*tty->flip.char_buf_ptr = ch;\n\t\t//*tty->flip.flag_buf_ptr = TTY_NORMAL;\n\t\tport->icount.rx++;\n\n\t\t/*\n\t\t * Note that the error handling code is\n\t\t * out of the main execution path\n\t\t */\n\t\trsr = UART_GET_RSR(port) | UART_DUMMY_RSR_RX;\n\t\tUART_PUT_RSR(port, 0);\n\t\tif (rsr & UARTRSR_ANY) {\n\t\t\tif (rsr & UARTRSR_BE) {\n\t\t\t\trsr &= ~(UARTRSR_FE | UARTRSR_PE);\n\t\t\t\tport->icount.brk++;\n\t\t\t\tif (uart_handle_break(port))\n\t\t\t\t\tgoto ignore_char;\n\t\t\t} else if (rsr & UARTRSR_PE)\n\t\t\t\tport->icount.parity++;\n\t\t\telse if (rsr & UARTRSR_FE)\n\t\t\t\tport->icount.frame++;\n\t\t\tif (rsr & UARTRSR_OE)\n\t\t\t\tport->icount.overrun++;\n\n\t\t\trsr &= port->read_status_mask;\n\n\t\t\tif (rsr & UARTRSR_BE)\n\t\t\t\t//*tty->flip.flag_buf_ptr = TTY_BREAK;\n\t\t\t\tflag = TTY_BREAK;\n\t\t\telse if (rsr & UARTRSR_PE)\n\t\t\t\t//*tty->flip.flag_buf_ptr = TTY_PARITY;\n\t\t\t\tflag = TTY_PARITY;\n\t\t\telse if (rsr & UARTRSR_FE)\n\t\t\t\t//*tty->flip.flag_buf_ptr = TTY_FRAME;\n\t\t\t\tflag = TTY_FRAME;\n\t\t}\n\n\t\tif (uart_handle_sysrq_char(port, ch))\n\t\t\tgoto ignore_char;\n\n\t\t//if ((rsr & port->ignore_status_mask) == 0) {\n\t\t//\ttty->flip.flag_buf_ptr++;\n\t\t//\ttty->flip.char_buf_ptr++;\n\t\t//\ttty->flip.count++;\n\t\t//}\n\t\t//if ((rsr & UARTRSR_OE) &&\n\t\t//   tty->flip.count < TTY_FLIPBUF_SIZE) {\n\t\t\t/*\n\t\t\t * Overrun is special, since it's reported\n\t\t\t * immediately, and doesn't affect the current\n\t\t\t * character\n\t\t\t */\n\t\t//\t*tty->flip.char_buf_ptr++ = 0;\n\t\t//\t*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;\n\t\t//\ttty->flip.count++;\n\t\t//}\n\n\t\tuart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);\n\n\tignore_char:\n\t\tstatus = UART_GET_FR(port);\n\t}\n\ttty_flip_buffer_push(tty);\n\treturn;\n}\n\nstatic void\nep93xxuart_tx_chars(struct uart_port *port)\n{\n\tstruct circ_buf *xmit = &port->info->xmit;\n\tint count;\n\n\tif (port->x_char) {\n\t\tUART_PUT_CHAR(port, port->x_char);\n\t\tport->icount.tx++;\n\t\tport->x_char = 0;\n\t\treturn;\n\t}\n\tif (uart_circ_empty(xmit) || uart_tx_stopped(port)) {\n\t\tep93xxuart_stop_tx(port);\n\t\treturn;\n\t}\n\n\tcount = port->fifosize >> 1;\n\tdo {\n\t\tUART_PUT_CHAR(port, xmit->buf[xmit->tail]);\n\t\txmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);\n\t\tport->icount.tx++;\n\t\tif (uart_circ_empty(xmit))\n\t\t\tbreak;\n\t} while (--count > 0);\n\n\tif (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\n\t\tuart_write_wakeup(port);\n\n\tif (uart_circ_empty(xmit))\n\t\tep93xxuart_stop_tx(port);\n}\n\nstatic void\nep93xxuart_modem_status(struct uart_port *port)\n{\n\tstruct uart_ep93xx_port *uap = (struct uart_ep93xx_port *)port;\n\tunsigned int status, delta;\n\n\tUART_PUT_ICR(port, 0);\n\n\tstatus = UART_GET_FR(port) & UARTFR_MODEM_ANY;\n\n\tdelta = status ^ uap->old_status;\n\tuap->old_status = status;\n\n\tif (!delta)\n\t\treturn;\n\n\tif (delta & UARTFR_DCD)\n\t\tuart_handle_dcd_change(port, status & UARTFR_DCD);\n\n\tif (delta & UARTFR_DSR)\n\t\tport->icount.dsr++;\n\n\tif (delta & UARTFR_CTS)\n\t\tuart_handle_cts_change(port, status & UARTFR_CTS);\n\n\twake_up_interruptible(&port->info->delta_msr_wait);\n}\n\nstatic irqreturn_t\nep93xxuart_int(int irq, void *dev_id)\n{\n\tstruct uart_port *port = dev_id;\n\tunsigned int status, pass_counter = EP93XX_ISR_PASS_LIMIT;\n\n\nif(((unsigned long)port->membase)==UART2_BASE)\n{\nprintk(\"ep93 UART2 ep93xxuart_int\\n\");\n}\n\n\n\tspin_lock(&port->lock);\n\n\tstatus = UART_GET_INT_STATUS(port);\nif(((unsigned long)port->membase)==UART2_BASE)\n{\nprintk(\"status=%x\\n\",status);\n}\n\tdo {\n\t\tif (status & (UARTIIR_RTIS | UARTIIR_RIS))\n#ifdef SUPPORT_SYSRQ\n\t\t\tep93xxuart_rx_chars(port, regs);\n#else\n\t\t\tep93xxuart_rx_chars(port);\n#endif\n\t\tif (status & UARTIIR_TIS)\n\t\t\tep93xxuart_tx_chars(port);\n\t\tif (status & UARTIIR_MIS)\n\t\t\tep93xxuart_modem_status(port);\n\n\t\tif (pass_counter-- == 0)\n\t\t\tbreak;\n\n\t\tstatus = UART_GET_INT_STATUS(port);\n\t} while (status & (UARTIIR_RTIS | UARTIIR_RIS | UARTIIR_TIS));\n\n\tspin_unlock(&port->lock);\n\n\treturn IRQ_HANDLED;\n}\n\nstatic unsigned int\nep93xxuart_tx_empty(struct uart_port *port)\n{\n\treturn UART_GET_FR(port) & UARTFR_BUSY ? 0 : TIOCSER_TEMT;\n}\n\nstatic unsigned int\nep93xxuart_get_mctrl(struct uart_port *port)\n{\n\tunsigned int result = 0;\n\tunsigned int status;\n\n\tstatus = UART_GET_FR(port);\n\tif (status & UARTFR_DCD)\n\t\tresult |= TIOCM_CAR;\n\tif (status & UARTFR_DSR)\n\t\tresult |= TIOCM_DSR;\n\tif (status & UARTFR_CTS)\n\t\tresult |= TIOCM_CTS;\n\n\treturn result;\n}\n\nstatic void\nep93xxuart_set_mctrl(struct uart_port *port, unsigned int mctrl)\n{\n\tunsigned int ctrl = 0;\n\n\tctrl = UART_GET_MCR(port);\n\n#define BIT93(tiocmbit, uartbit)\t\t\\\n\tif (mctrl & tiocmbit)\t\t\\\n\t\tctrl |= uartbit;\t\\\n\telse\t\t\t\t\\\n\t\tctrl &= ~uartbit\n\n\tBIT93(TIOCM_RTS, UARTMCR_RTS);\n\tBIT93(TIOCM_DTR, UARTMCR_DTR);\n\tBIT93(TIOCM_OUT1, UARTMCR_OUT1);\n\tBIT93(TIOCM_OUT2, UARTMCR_OUT2);\n\tBIT93(TIOCM_LOOP, UARTMCR_LOOP);\n#undef BIT93\n\n\tUART_PUT_MCR(ctrl, port);\n}\n\nstatic void\nep93xxuart_break_ctl(struct uart_port *port, int break_state)\n{\n\tunsigned long flags;\n\tunsigned int lcr_h;\n\n\tspin_lock_irqsave(&port->lock, flags);\n\tlcr_h = UART_GET_LCRH(port);\n\tif (break_state == -1)\n\t\tlcr_h |= UARTLCR_H_BRK;\n\telse\n\t\tlcr_h &= ~UARTLCR_H_BRK;\n\tUART_PUT_LCRH(port, lcr_h);\n\tspin_unlock_irqrestore(&port->lock, flags);\n}\n\nstatic int\nep93xxuart_startup(struct uart_port *port)\n{\n\tstruct uart_ep93xx_port *uap = (struct uart_ep93xx_port *)port;\n\tint retval = -EINVAL;\n\tchar *name = 0;\n\n\t/*\n\t * Enable the clocks for this port.\n\t */\n\tep93xxuart_enable_clocks(port);\n\n\t/*\n\t * Get the name of this port (used only for resource allocations).\n\t */\n\tswitch ((unsigned long)port->membase) {\n\tcase UART1_BASE:\n\t\tname = \"ttyAM0\";\n\t\tbreak;\n\tcase UART2_BASE:\n\t\tname = \"ttyAM1\";\n\t\tbreak;\n\tcase UART3_BASE:\n\t\tname = \"ttyAM2\";\n\t\tbreak;\n\t}\nprintk(\"EP93XX UART--%s irq=%d\\n\",name,port->irq);\n\t/*\n\t * Allocate the IRQ\n\t */\n\tretval = request_irq(port->irq, ep93xxuart_int, 0 , name, port);\nprintk(\"irq is ok %d\\n\",retval);\n\tif (retval) {\n\t\tep93xxuart_disable_clocks(port);\n\t\treturn retval;\n\t}\n\n\t/*\n\t * Allocate the memory region.\n\t */\n\tif(request_mem_region(port->mapbase, UART_PORT_SIZE, name) == NULL) {\n\t\tprintk(\"mem region fail\\n\");\n\t\tfree_irq(port->irq, port);\n\t\tep93xxuart_disable_clocks(port);\n\t\treturn 1;\n\t}\n\n\t/*\n\t * initialise the old status of the modem signals\n\t */\n\tuap->old_status = UART_GET_FR(port) & UARTFR_MODEM_ANY;\n\nprintk(\"old status %x\\n\",uap->old_status);\n\t/*\n\t * Finally, enable interrupts\n\t */\n\tspin_lock_irq(&port->lock);\n\tUART_PUT_CR(port, UARTCR_UARTEN | UARTCR_RIE | UARTCR_RTIE|0x2);\n\tspin_unlock_irq(&port->lock);\n\t\n\t{\n\tunsigned int cr;\n\n\tcr = UART_GET_CR(port);\n\tprintk(\"cr=%x\\n\",cr);\n\t}\n\t/*\n\t * Success.\n\t */\n\treturn 0;\n}\n\nstatic void\nep93xxuart_shutdown(struct uart_port *port)\n{\n\t/*\n\t * disable all interrupts, disable the port\n\t */\n\tUART_PUT_CR(port, 0);\n\n\t/*\n\t * disable break condition and fifos\n\t */\n\tUART_PUT_LCRH(port, UART_GET_LCRH(port) &\n\t\t      ~(UARTLCR_H_BRK | UARTLCR_H_FEN));\n\n\t/*\n\t * Free the interrupt\n\t */\n\tfree_irq(port->irq, port);\n\n\t/*\n\t * Release the memory region.\n\t */\n\trelease_mem_region(port->mapbase, UART_PORT_SIZE);\n\n\t/*\n\t * Disable the clock.\n\t */\n\tep93xxuart_disable_clocks( port );\n}\n\nstatic void\nep93xxuart_set_termios(struct uart_port *port, struct ktermios *termios,\n\t\t       struct ktermios *old)\n{\n\tunsigned int lcr_h, baud, quot;\n\tunsigned long flags;\n\n\t/*\n\t * Ask the core to calculate the divisor for us.\n\t */\n\tbaud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);\n\tquot = uart_get_divisor(port, baud) - 1;\n\t\n\t/* byte size and parity */\n\tswitch (termios->c_cflag & CSIZE) {\n\tcase CS5:\n\t\tlcr_h = UARTLCR_H_WLEN_5;\n\t\tbreak;\n\tcase CS6:\n\t\tlcr_h = UARTLCR_H_WLEN_6;\n\t\tbreak;\n\tcase CS7:\n\t\tlcr_h = UARTLCR_H_WLEN_7;\n\t\tbreak;\n\tdefault: // CS8\n\t\tlcr_h = UARTLCR_H_WLEN_8;\n\t\tbreak;\n\t}\n\tif (termios->c_cflag & CSTOPB)\n\t\tlcr_h |= UARTLCR_H_STP2;\n\tif (termios->c_cflag & PARENB) {\n\t\tlcr_h |= UARTLCR_H_PEN;\n\t\tif (!(termios->c_cflag & PARODD))\n\t\t\tlcr_h |= UARTLCR_H_EPS;\n\t}\n\tif (port->fifosize > 1)\n\t\tlcr_h |= UARTLCR_H_FEN;\n\n\tspin_lock_irqsave(&port->lock, flags);\n\n\t/*\n\t * Update the per-port timeout.\n\t */\n\tuart_update_timeout(port, termios->c_cflag, baud);\n\n\tport->read_status_mask = UARTRSR_OE;\n\tif (termios->c_iflag & INPCK)\n\t\tport->read_status_mask |= UARTRSR_FE | UARTRSR_PE;\n\tif (termios->c_iflag & (BRKINT | PARMRK))\n\t\tport->read_status_mask |= UARTRSR_BE;\n\n\t/*\n\t * Characters to ignore\n\t */\n\tport->ignore_status_mask = 0;\n\tif (termios->c_iflag & IGNPAR)\n\t\tport->ignore_status_mask |= UARTRSR_FE | UARTRSR_PE;\n\tif (termios->c_iflag & IGNBRK) {\n\t\tport->ignore_status_mask |= UARTRSR_BE;\n\t\t/*\n\t\t * If we're ignoring parity and break indicators,\n\t\t * ignore overruns too (for real raw support).\n\t\t */\n\t\tif (termios->c_iflag & IGNPAR)\n\t\t\tport->ignore_status_mask |= UARTRSR_OE;\n\t}\n\n\t/*\n\t * Ignore all characters if CREAD is not set.\n\t */\n\tif ((termios->c_cflag & CREAD) == 0)\n\t\tport->ignore_status_mask |= UART_DUMMY_RSR_RX;\n\n\tif (UART_ENABLE_MS(port, termios->c_cflag))\n\t\tep93xxuart_enable_ms(port);\n\n\tUART_PUT_LCRL(port, quot & 0xff);\n\tUART_PUT_LCRM(port, (quot >> 8) & 0xff);\n\tUART_PUT_LCRH(port, lcr_h);\n\n\tspin_unlock_irqrestore(&port->lock, flags);\n}\n\nstatic const char *\nep93xxuart_type(struct uart_port *port)\n{\n\treturn port->type == PORT_AMBA ? \"EP93XX\" : NULL;\n}\n\n/*\n * Release the memory region(s) being used by 'port'\n */\nstatic void\nep93xxuart_release_port(struct uart_port *port)\n{\n}\n\n/*\n * Request the memory region(s) being used by 'port'\n */\nstatic int\nep93xxuart_request_port(struct uart_port *port)\n{\n\treturn 0;\n}\n\n/*\n * Configure/autoconfigure the port.\n */\nstatic void\nep93xxuart_config_port(struct uart_port *port, int flags)\n{\n\tif (flags & UART_CONFIG_TYPE)\n\t\tport->type = PORT_AMBA;\n}\n\n/*\n * verify the new serial_struct (for TIOCSSERIAL).\n */\nstatic int\nep93xxuart_verify_port(struct uart_port *port, struct serial_struct *ser)\n{\n\tint ret = 0;\n\tif (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)\n\t\tret = -EINVAL;\n\tif (ser->irq < 0 || ser->irq >= NR_IRQS)\n\t\tret = -EINVAL;\n\tif (ser->baud_base < 9600)\n\t\tret = -EINVAL;\n\treturn ret;\n}\n\nstatic struct uart_ops ep93xx_pops = {\n\t.tx_empty\t= ep93xxuart_tx_empty,\n\t.set_mctrl\t= ep93xxuart_set_mctrl,\n\t.get_mctrl\t= ep93xxuart_get_mctrl,\n\t.stop_tx\t= ep93xxuart_stop_tx,\n\t.start_tx\t= ep93xxuart_start_tx,\n\t.stop_rx\t= ep93xxuart_stop_rx,\n\t.enable_ms\t= ep93xxuart_enable_ms,\n\t.break_ctl\t= ep93xxuart_break_ctl,\n\t.startup\t= ep93xxuart_startup,\n\t.shutdown\t= ep93xxuart_shutdown,\n\t.set_termios\t= ep93xxuart_set_termios,\n\t.type\t\t= ep93xxuart_type,\n\t.release_port\t= ep93xxuart_release_port,\n\t.request_port\t= ep93xxuart_request_port,\n\t.config_port\t= ep93xxuart_config_port,\n\t.verify_port\t= ep93xxuart_verify_port,\n};\n\nstatic struct uart_ep93xx_port ep93xx_ports[UART_NR] = {\n\t{\n\t\t.port\t= {\n\t\t\t.membase\t= (void *)UART1_BASE,\n\t\t\t.mapbase\t= /*HwRegToPhys(UART1_BASE)*/UART1_BASE_VIRT,\n\t\t\t.iotype\t\t= UPIO_MEM,\n\t\t\t.irq\t\t= IRQ_EP93XX_UART1,\n\t\t\t.uartclk\t= 14745600,\n\t\t\t.fifosize\t= 16,\n\t\t\t.ops\t\t= &ep93xx_pops,\n\t\t\t.flags\t\t= UPF_BOOT_AUTOCONF,\n\t\t\t.line\t\t= 0,\n\t\t},\n\t},\n#if !defined(CONFIG_EP93XX_IRDA)\n\t{\n\t\t.port\t= {\n\t\t\t.membase\t= (void *)UART2_BASE,\n\t\t\t.mapbase\t= /*HwRegToPhys(UART2_BASE)*/UART2_BASE_VIRT,\n\t\t\t.iotype\t\t= UPIO_MEM,\n\t\t\t.irq\t\t= IRQ_EP93XX_UART2,\n\t\t\t.uartclk\t= 14745600,\n\t\t\t.fifosize\t= 16,\n\t\t\t.ops\t\t= &ep93xx_pops,\n\t\t\t.flags\t\t= UPF_BOOT_AUTOCONF,\n\t\t\t.line\t\t= 1,\n\t\t},\n\t},\n#endif\n#if !defined(CONFIG_ARCH_EP9301) && !defined(CONFIG_ARCH_EP9302)\n\t{\n\t\t.port\t= {\n\t\t\t.membase\t= (void *)UART3_BASE,\n\t\t\t.mapbase\t= /*HwRegToPhys(UART3_BASE)*/UART3_BASE_VIRT,\n\t\t\t.iotype\t\t= UPIO_MEM,\n\t\t\t.irq\t\t= IRQ_EP93XX_UART3,\n\t\t\t.uartclk\t= 14745600,\n\t\t\t.fifosize\t= 16,\n\t\t\t.ops\t\t= &ep93xx_pops,\n\t\t\t.flags\t\t= UPF_BOOT_AUTOCONF,\n#if !defined(CONFIG_EP93XX_IRDA)\n\t\t\t.line\t\t= 2,\n#else\n\t\t\t.line\t\t= 1,\n#endif\n\t\t},\n\t}\n#endif\n};\n\n#ifdef CONFIG_SERIAL_EP93XX_CONSOLE\n\nstatic void\nep93xxuart_console_write_char(struct uart_port *port, char ch)\n{\n\tunsigned int status;\n\n\tdo {\n\t\tstatus = UART_GET_FR(port);\n\t} while (!UART_TX_READY(status));\n\tUART_PUT_CHAR(port, ch);\n}\n\nstatic void\nep93xxuart_console_write(struct console *co, const char *s, unsigned int count)\n{\n\tstruct uart_port *port = &ep93xx_ports[co->index].port;\n\tunsigned int status, old_cr, old_power;\n\tint i;\n\n\told_power = ep93xxuart_is_port_enabled(port);\n\tif (!old_power)\n\t\tep93xxuart_enable_clocks(port);\n\n\t/*\n\t * First save the CR then disable the interrupts\n\t */\n\told_cr = UART_GET_CR(port);\n\tUART_PUT_CR(port, UARTCR_UARTEN);\n\n\t/*\n\t * Now, do each character\n\t */\n\tfor (i = 0; i < count; i++) {\n\t\tep93xxuart_console_write_char(port, s[i]);\n\t\tif (s[i] == '\\n')\n\t\t\tep93xxuart_console_write_char(port, '\\r');\n\t}\n\n\t/*\n\t * Finally, wait for transmitter to become empty\n\t * and restore the TCR\n\t */\n\tdo {\n\t\tstatus = UART_GET_FR(port);\n\t} while (status & UARTFR_BUSY);\n\tUART_PUT_CR(port, old_cr);\n\n\tif (!old_power)\n\t\tep93xxuart_disable_clocks(port);\n}\n\nstatic void __init\nep93xxuart_console_get_options(struct uart_port *port, int *baud, int *parity,\n\t\t\t       int *bits)\n{\n\tif (UART_GET_CR(port) & UARTCR_UARTEN) {\n\t\tunsigned int lcr_h, lcr_m, lcr_l;\n\n\t\tlcr_h = UART_GET_LCRH(port);\n\n\t\t*parity = 'n';\n\t\tif (lcr_h & UARTLCR_H_PEN) {\n\t\t\tif (lcr_h & UARTLCR_H_EPS)\n\t\t\t\t*parity = 'e';\n\t\t\telse\n\t\t\t\t*parity = 'o';\n\t\t}\n\n\t\tif ((lcr_h & 0x60) == UARTLCR_H_WLEN_7)\n\t\t\t*bits = 7;\n\t\telse\n\t\t\t*bits = 8;\n\n\t\tlcr_m = UART_GET_LCRM(port);\n\t\tlcr_l = UART_GET_LCRL(port);\n\n\t\t*baud = port->uartclk / (16 * ((lcr_m * 256) + lcr_l + 1));\n\t}\n}\n\nstatic int __init\nep93xxuart_console_setup(struct console *co, char *options)\n{\n\tstruct uart_port *port;\n\tint baud = 57600;\n\tint bits = 8;\n\tint parity = 'n';\n\tint flow = 'n';\n\n\t/*\n\t * Check whether an invalid uart number has been specified, and\n\t * if so, search for the first available port that does have\n\t * console support.\n\t */\n\tif (co->index >= UART_NR)\n\t\tco->index = 0;\n\tport = &ep93xx_ports[co->index].port;\n\n\tif (options)\n\t\tuart_parse_options(options, &baud, &parity, &bits, &flow);\n\telse\n\t\tep93xxuart_console_get_options(port, &baud, &parity, &bits);\n\n\treturn uart_set_options(port, co, baud, parity, bits, flow);\n}\n\nstatic struct console ep93xx_console;\n#define EP93XX_CONSOLE\t&ep93xx_console\n#else\n#define EP93XX_CONSOLE\tNULL\n#endif\n\nstatic struct uart_driver ep93xx_reg = {\n\t.driver_name\t\t= \"ttyAM\",\n\t.dev_name\t\t= \"ttyAM\",\n\t.major\t\t\t= SERIAL_EP93XX_MAJOR,\n\t.minor\t\t\t= SERIAL_EP93XX_MINOR,\n\t.nr\t\t\t= UART_NR,\n\t.cons\t\t\t= EP93XX_CONSOLE,\n};\n\n\n/*\n * The 'index' element of this field selects which UART to use for\n * console.  For ep93xx, valid values are 0, 1, and 2.  If you set\n * it to -1, then uart_get_console will search for the first UART\n * which is the same as setting it to 0.\n */\nstatic struct console ep93xx_console = {\n\t.name\t\t= \"ttyAM\",\n\t.write\t\t= ep93xxuart_console_write,\n\t.device\t\t= uart_console_device,\n\t.setup\t\t= ep93xxuart_console_setup,\n\t.flags\t\t= CON_PRINTBUFFER,\n\t.index\t\t= -1,\n\t.data\t\t= &ep93xx_reg,\n};\n\nstatic int __init\nep93xxuart_console_init(void)\n{\n\tregister_console(&ep93xx_console);\n\treturn 0;\n}\nconsole_initcall(ep93xxuart_console_init);\n\nstatic struct resource uarts[UART_NR] = {\n\t[0] = {\n\t\t.name\t\t= \"uart1\",\n\t\t.start\t\t= /*HwRegToPhys(UART1_BASE)*/UART1_BASE_VIRT,\n\t\t.end\t\t= /*HwRegToPhys(UART1_BASE)*/UART1_BASE_VIRT + 0x0000ffff,\n\t},\n#if !defined(CONFIG_EP93XX_IRDA)\n\t[1] = {\n\t\t.name\t\t= \"uart2\",\n\t\t.start\t\t= /*HwRegToPhys(UART2_BASE)*/UART2_BASE_VIRT,\n\t\t.end\t\t= /*HwRegToPhys(UART2_BASE)*/UART2_BASE_VIRT + 0x0000ffff,\n\t},\n#endif\n#if !defined(CONFIG_ARCH_EP9301) && !defined(CONFIG_ARCH_EP9302)\n\t[2] = {\n\t\t.name\t\t= \"uart3\",\n\t\t.start\t\t= /*HwRegToPhys(UART3_BASE)*/UART3_BASE_VIRT,\n\t\t.end\t\t= /*HwRegToPhys(UART3_BASE)*/UART3_BASE_VIRT + 0x0000ffff,\n\t},\n#endif\n};\n\nstatic int __init\nep93xxuart_init(void)\n{\n\tint ret, i;\n\n\tret = uart_register_driver(&ep93xx_reg);\n\tif (ret == 0) {\n\t\tfor (i = 0; i < UART_NR; i++) {\n\t\t\trequest_resource(&iomem_resource, &uarts[i]);\n\t\t\tuart_add_one_port(&ep93xx_reg, &ep93xx_ports[i].port);\n\t\t}\n\t}\n\treturn ret;\n}\n\nstatic void __exit ep93xxuart_exit(void)\n{\n\tint i;\n\n\tfor (i = 0; i < UART_NR; i++)\n\t\tuart_remove_one_port(&ep93xx_reg, &ep93xx_ports[i].port);\n\tuart_unregister_driver(&ep93xx_reg);\n}\n\nmodule_init(ep93xxuart_init);\nmodule_exit(ep93xxuart_exit);\n\nMODULE_AUTHOR(\"ARM Ltd/Deep Blue Solutions Ltd/Cirrus Logic, Inc.\");\nMODULE_DESCRIPTION(\"EP93xx ARM serial port driver\");\nMODULE_LICENSE(\"GPL\");\nMODULE_ALIAS_CHARDEV(SERIAL_EP93XX_MAJOR, SERIAL_EP93XX_MINOR);\n"},{"id":"65314","messageId":"20080114120807.GB12723@coredump.intra.peff.net","threadId":"11607","inReplyTo":"20080113162806.13991.qmail@science.horizon.com","subject":"Re: Digging through old vendor code","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-01-14T12:08:07Z","receivedAt":"2008-01-14T12:08:07Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Jan 13, 2008 at 11:28:06AM -0500, linux@horizon.com wrote:\n\n> Maybe a real git wizard will show me how to insert the index entries\n> directly without ever doing anything as pedestrian as extracting, hashing,\n> and then deleting the files, but it's still not that bad.\n\ngit-read-tree?  Unfortunately it has no option to insert only a subset\nof the tree. But you can make do with git-ls-tree piped to\ngit-update-index.\n\nUsing the script below, Jon's sample file seems to be\n\n  v2.6.15-rc6-81-g0b57ee9:drivers/serial/amba-pl010.c\n\nand it runs in about 8 seconds on v2.6.13..v2.6.15. I think it might be\nmore intuitive to just diff a temporary index against each tree, but I\ndon't think there's a way to say \"find copies harder, but use only this\nsubset of files as the source\" which makes it less efficient.\n\nJon, you might try playing around with different ranges. I get a\ndifferent answer for v2.6.13..v2.6.16.\n\n-- >8 --\nSRC=drivers/serial\n\necho >&2 Cleaning up after old runs...\nrm -f tmpindex\ngit branch -D tmpbranch\n\necho >&2 Creating giant source commit...\nfor i in `git rev-list v2.6.13..v2.6.15 -- $SRC`; do\n  git ls-tree -r $i -- $SRC |\n    # note the whitespace is a literal tab\n    sed \"s,\t,\t$i/,\" |\n    GIT_INDEX_FILE=tmpindex git update-index --index-info\ndone\ntree=`GIT_INDEX_FILE=tmpindex git write-tree`\ncommit=`echo source | git commit-tree $tree`\ngit update-ref refs/heads/tmpbranch $commit\n\necho >&2 Creating updated index...\nGIT_INDEX_FILE=tmpindex git add candidate.c\necho >&2 Diffing...\nGIT_INDEX_FILE=tmpindex git diff-index --cached -l0 -M1% -C1% --find-copies-harder tmpbranch\n\n# now you should manually git-describe the winner\n"},{"id":"65318","messageId":"9e4733910801140649u5c2b74cbkcf0d790d0e7bc0a2@mail.gmail.com","threadId":"11607","inReplyTo":"20080114120807.GB12723@coredump.intra.peff.net","subject":"Re: Digging through old vendor code","fromName":"Jon Smirl","fromEmail":"jonsmirl@gmail.com","sentAt":"2008-01-14T14:49:30Z","receivedAt":"2008-01-14T14:49:30Z","isPatch":false,"sender":{"key":"jonsmirl@gmail.com","avatar":"https://gravatar.com/avatar/cff3bf5bfdfa6708b905712ff91f0f9b8aaca161659f38c02b787920d5d28b7e?d=mp&s=160"},"body":"On 1/14/08, Jeff King <peff@peff.net> wrote:\n> On Sun, Jan 13, 2008 at 11:28:06AM -0500, linux@horizon.com wrote:\n>\n> > Maybe a real git wizard will show me how to insert the index entries\n> > directly without ever doing anything as pedestrian as extracting, hashing,\n> > and then deleting the files, but it's still not that bad.\n>\n> git-read-tree?  Unfortunately it has no option to insert only a subset\n> of the tree. But you can make do with git-ls-tree piped to\n> git-update-index.\n>\n> Using the script below, Jon's sample file seems to be\n>\n>   v2.6.15-rc6-81-g0b57ee9:drivers/serial/amba-pl010.c\n>\n> and it runs in about 8 seconds on v2.6.13..v2.6.15. I think it might be\n> more intuitive to just diff a temporary index against each tree, but I\n> don't think there's a way to say \"find copies harder, but use only this\n> subset of files as the source\" which makes it less efficient.\n>\n> Jon, you might try playing around with different ranges. I get a\n> different answer for v2.6.13..v2.6.16.\n\nThat's probably because some of the other drivers in there were also\ncreated via copy and edit. The similarity between drivers is what made\nthe original base hard to find. amba-pl010.c is probably a copy/edit\nfrom one of the other drivers.\n\nI'm pretty sure 2.6.15/amba-pl010.c is right. I started undoing some\nof the obvious changes like renaming the functions and the diffs are\ngetting pretty small.\n\nThanks for the help on this. I have enough info now to separate the diffs.\n\nThis would probably make a nice command to add to git since I'm sure\nother vendors have done copy/edit to make their out of tree drivers. I\ndoubt if any other SCM has a command like this.\n\nI'm really starting to hate the \"port and forget\" that goes on in the\nembedded world. But I'm beginning to understand why it happens. I've\nbeen working since November to get a patch  into i2c without success -\n19 versions. The process is chewing up way too much time relative to\nthe importance of the patch to my code. So I'm just about ready to\n\"port and forget\" the patch.\n\n>\n> -- >8 --\n> SRC=drivers/serial\n>\n> echo >&2 Cleaning up after old runs...\n> rm -f tmpindex\n> git branch -D tmpbranch\n>\n> echo >&2 Creating giant source commit...\n> for i in `git rev-list v2.6.13..v2.6.15 -- $SRC`; do\n>   git ls-tree -r $i -- $SRC |\n>     # note the whitespace is a literal tab\n>     sed \"s,     ,       $i/,\" |\n>     GIT_INDEX_FILE=tmpindex git update-index --index-info\n> done\n> tree=`GIT_INDEX_FILE=tmpindex git write-tree`\n> commit=`echo source | git commit-tree $tree`\n> git update-ref refs/heads/tmpbranch $commit\n>\n> echo >&2 Creating updated index...\n> GIT_INDEX_FILE=tmpindex git add candidate.c\n> echo >&2 Diffing...\n> GIT_INDEX_FILE=tmpindex git diff-index --cached -l0 -M1% -C1% --find-copies-harder tmpbranch\n>\n> # now you should manually git-describe the winner\n>\n\n\n-- \nJon Smirl\njonsmirl@gmail.com\n"}]}