svn commit: r186520 - head/sys/dev/puc

Roman Kurakin rik at inse.ru
Thu Jan 1 13:44:53 UTC 2009


M. Warner Losh wrote:
> In message: <495B406F.2040305 at localhost.inse.ru>
>             Roman Kurakin <rik at inse.ru> writes:
> : M. Warner Losh wrote:
> : > In message: <200812271522.mBRFMMHY074982 at svn.freebsd.org>
> : >             Roman Kurakin <rik at FreeBSD.org> writes:
> : > : Author: rik
> : > : Date: Sat Dec 27 15:22:22 2008
> : > : New Revision: 186520
> : > : URL: http://svn.freebsd.org/changeset/base/186520
> : > : 
> : > : Log:
> : > :   Add support for the Oxford OX16PCI958-based card.
> : > :   
> : > :   Note, that the patch provided with this card for the Linux states that
> : > :   the card uses DEFAULT_RCLK * 2, while in fact it is '* 10'.  So probably
> : > :   we should also use the subdevice/subvendord here. For now just ignore
> : > :   that fact.
> : >
> : > I've had problems with doing that on some Oxford based cards.  The
> : > vendor that uses them doesn't set them up, so you can't tell my
> : > cardbus oxford card from the pcie oxford card that someone else sent
> : > me patches for: both with different clock multipliers...
> : >   
> : Probably we need to implement AUTODETECT_RCLK. I've had the patch,
> : but it worked only for modules, cause there was no working timers while the
> : cards probe time if the driver was compiled in. I've planned to move 
> : detection
> : code to the first open and do some cleanup after the detection, but 
> : didn't do
> : that.
>
> I'd like to see that.  I think we can defer the detection of RCLK to
>   
The initial code, that was the part of the Cronyx patch for sio(4), is 
smth like this one excerpt:
+#undef inb
+#undef outb
+#define inb(port)      sio_inb (port)
+#define outb(port,val) sio_outb (port, val)
+
+static __inline u_char
+sio_getreg (com, off)
+       struct com_s    *com;
+       bus_size_t      off;
+{
+       if ((unsigned) com->bsh & ~0xffff)
+               return *(volatile u_char*) (com->bsh + off);
+       return bus_space_read_1 (com->bst, com->bsh, off);
+}
+
+static __inline void
+sio_setreg (com, off, val)
+       struct com_s    *com;
+       bus_size_t      off;
+       u_char          val;
+{
+       if ((unsigned) com->bsh & ~0xffff)
+               *(volatile u_char*) (com->bsh + off) = val;
+       else
+               bus_space_write_1 (com->bst, com->bsh, off, val);
+}
+
+/*
  * handle sysctl read/write requests for console speed
  *
  * In addition to setting comdefaultrate for I/O through /dev/console,
@@ -475,6 +548,181 @@
        return (0);
 }
 
+#define VOLATILE_INT *(volatile int *)&
+/*
+ * Find the oscillator frequency of the UART.
+ */
+static int
+sio_find_freq(com)
+       struct com_s    *com;
+{
+       int t0, n;
+       u_char lsr;
+
+       /* Set the loopback mode, 57600 baud. */
+       outb(com->int_ctl_port, 0);
+       sio_setreg(com, com_cfcr, CFCR_DLAB);
+       sio_setreg(com, com_dlbh, 0);
+       sio_setreg(com, com_dlbl, 2);
+       sio_setreg(com, com_cfcr, CFCR_8BITS);
+       sio_setreg(com, com_fifo, 0);
+       outb(com->modem_ctl_port, MCR_LOOPBACK);
+       (void) inb (com->line_status_port);
+
+       /* Catch the tick. */
+       t0 = VOLATILE_INT ticks;
+       while (VOLATILE_INT ticks == t0)
+               continue;
+
+       /* Run until the next tick, transmitting data. */
+       n = 0;
+       t0 = VOLATILE_INT ticks;
+       while (VOLATILE_INT ticks == t0) {
+               lsr = inb (com->line_status_port);
+               if (lsr & LSR_TXRDY)
+                       sio_setreg(com, com_data, 0x5A);
+
+               if (lsr & LSR_RXRDY) {
+                       (void) inb (com->data_port);
+                       ++n;
+               }
+       }
+       outb(com->modem_ctl_port, com->mcr_image);
+       sio_setreg(com, com_cfcr, com->cfcr_image);
+       sio_setreg(com, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST |
+               com->fifo_image);
+       if (COM_IIR_TXRDYBUG(com->flags)) {
+               outb(com->int_ctl_port, IER_ERXRDY | IER_ERLS
+                                       | IER_EMSC);
+       } else {
+               outb(com->int_ctl_port, IER_ERXRDY | IER_ETXRDY
+                                       | IER_ERLS | IER_EMSC);
+       }
+
+       n = (n * hz + 5760/2) / 5760;
+       if (n > 4) return 8 * 1843200;
+       if (n > 2) return 4 * 1843200;
+       if (n > 1) return 2 * 1843200;
+       return DEFAULT_RCLK;
+}

One of the multiport Cronyx card has the hardware switch to change the 
clock,
and before such patch more than a half of requests for support was due 
to incorrect
speeds, cause users didn't understand what they were doing by this 
switch and
how the software should be configured based on its value.
> later.  How accurate is this, btw?  How dependent on timing of
>   
Do we need very strict accuracy here? For the detection of the 
multiplier before
DEFAULT_RCLK it should be enough IMHO.

rik
> interrupts is it?
>   

> Warner
>   



More information about the svn-src-head mailing list