Author: jmallett
Date: Mon Nov 19 01:58:20 2012
New Revision: 243255
URL: http://svnweb.freebsd.org/changeset/base/243255

Log:
  Add basic support for the Radisys-specific PCI console mechanism found on the
  Radisys ATCA-7220.

Modified:
  head/sys/mips/cavium/octeon_pci_console.c

Modified: head/sys/mips/cavium/octeon_pci_console.c
==============================================================================
--- head/sys/mips/cavium/octeon_pci_console.c   Mon Nov 19 01:15:32 2012        
(r243254)
+++ head/sys/mips/cavium/octeon_pci_console.c   Mon Nov 19 01:58:20 2012        
(r243255)
@@ -39,8 +39,22 @@ __FBSDID("$FreeBSD$");
 
 #include <contrib/octeon-sdk/cvmx.h>
 #include <contrib/octeon-sdk/cvmx-bootmem.h>
+#include <contrib/octeon-sdk/cvmx-interrupt.h>
 #include <contrib/octeon-sdk/octeon-pci-console.h>
 
+#ifdef OCTEON_VENDOR_RADISYS
+#define        OPCIC_FLAG_RSYS         (0x00000001)
+
+#define        OPCIC_RSYS_FIFO_SIZE    (0x2000)
+#endif
+
+struct opcic_softc {
+       unsigned sc_flags;
+       uint64_t sc_base_addr;
+};
+
+static struct opcic_softc opcic_instance;
+
 static cn_probe_t opcic_cnprobe;
 static cn_init_t opcic_cninit;
 static cn_term_t opcic_cnterm;
@@ -49,20 +63,46 @@ static cn_putc_t opcic_cnputc;
 static cn_grab_t opcic_cngrab;
 static cn_ungrab_t opcic_cnungrab;
 
+#ifdef OCTEON_VENDOR_RADISYS
+static int opcic_rsys_cngetc(struct opcic_softc *);
+static void opcic_rsys_cnputc(struct opcic_softc *, int);
+#endif
+
 CONSOLE_DRIVER(opcic);
 
 static void
 opcic_cnprobe(struct consdev *cp)
 {
        const struct cvmx_bootmem_named_block_desc *pci_console_block;
+       struct opcic_softc *sc;
+
+       sc = &opcic_instance;
+       sc->sc_flags = 0;
+       sc->sc_base_addr = 0;
 
        cp->cn_pri = CN_DEAD;
 
-       pci_console_block = 
cvmx_bootmem_find_named_block(OCTEON_PCI_CONSOLE_BLOCK_NAME);
-       if (pci_console_block == NULL)
-               return;
+       switch (cvmx_sysinfo_get()->board_type) {
+#ifdef OCTEON_VENDOR_RADISYS
+       case CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE:
+               pci_console_block =
+                   cvmx_bootmem_find_named_block("rsys_gbl_memory");
+               if (pci_console_block != NULL) {
+                       sc->sc_flags |= OPCIC_FLAG_RSYS;
+                       sc->sc_base_addr = pci_console_block->base_addr;
+                       break;
+               }
+#endif
+       default:
+               pci_console_block =
+                   
cvmx_bootmem_find_named_block(OCTEON_PCI_CONSOLE_BLOCK_NAME);
+               if (pci_console_block == NULL)
+                       return;
+               sc->sc_base_addr = pci_console_block->base_addr;
+               break;
+       }
 
-       cp->cn_arg = (void *)(uintptr_t)pci_console_block->base_addr;
+       cp->cn_arg = sc;
        snprintf(cp->cn_name, sizeof cp->cn_name, "opcic@%p", cp->cn_arg);
        cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL;
 }
@@ -82,13 +122,19 @@ opcic_cnterm(struct consdev *cp)
 static int
 opcic_cngetc(struct consdev *cp)
 {
-       uint64_t console_desc_addr;
+       struct opcic_softc *sc;
        char ch;
        int rv;
 
-       console_desc_addr = (uintptr_t)cp->cn_arg;
+       sc = cp->cn_arg;
 
-       rv = octeon_pci_console_read(console_desc_addr, 0, &ch, 1, 
OCT_PCI_CON_FLAG_NONBLOCK);
+#ifdef OCTEON_VENDOR_RADISYS
+       if ((sc->sc_flags & OPCIC_FLAG_RSYS) != 0)
+               return (opcic_rsys_cngetc(sc));
+#endif
+
+       rv = octeon_pci_console_read(sc->sc_base_addr, 0, &ch, 1,
+           OCT_PCI_CON_FLAG_NONBLOCK);
        if (rv != 1)
                return (-1);
        return (ch);
@@ -97,14 +143,21 @@ opcic_cngetc(struct consdev *cp)
 static void
 opcic_cnputc(struct consdev *cp, int c)
 {
-       uint64_t console_desc_addr;
+       struct opcic_softc *sc;
        char ch;
        int rv;
 
-       console_desc_addr = (uintptr_t)cp->cn_arg;
+       sc = cp->cn_arg;
        ch = c;
 
-       rv = octeon_pci_console_write(console_desc_addr, 0, &ch, 1, 0);
+#ifdef OCTEON_VENDOR_RADISYS
+       if ((sc->sc_flags & OPCIC_FLAG_RSYS) != 0) {
+               opcic_rsys_cnputc(sc, c);
+               return;
+       }
+#endif
+
+       rv = octeon_pci_console_write(sc->sc_base_addr, 0, &ch, 1, 0);
        if (rv == -1)
                panic("%s: octeon_pci_console_write failed.", __func__);
 }
@@ -120,3 +173,64 @@ opcic_cnungrab(struct consdev *cp)
 {
        (void)cp;
 }
+
+#ifdef OCTEON_VENDOR_RADISYS
+static int
+opcic_rsys_cngetc(struct opcic_softc *sc)
+{
+       uint64_t gbl_base;
+       uint64_t console_base;
+       uint64_t console_rbuf;
+       uint64_t console_rcnt[2];
+       uint16_t rcnt[2];
+       uint16_t roff;
+       int c;
+
+       gbl_base = CVMX_ADD_IO_SEG(sc->sc_base_addr);
+       console_base = gbl_base + 0x10;
+
+       console_rbuf = console_base + 0x2018;
+       console_rcnt[0] = console_base + 0x08;
+       console_rcnt[1] = console_base + 0x0a;
+
+       /* Check if there is anything new in the FIFO.  */
+       rcnt[0] = cvmx_read64_uint16(console_rcnt[0]);
+       rcnt[1] = cvmx_read64_uint16(console_rcnt[1]);
+       if (rcnt[0] == rcnt[1])
+               return (-1);
+
+       /* Get first new character in the FIFO.  */
+       if (rcnt[0] != 0)
+               roff = rcnt[0] - 1;
+       else
+               roff = OPCIC_RSYS_FIFO_SIZE - 1;
+       c = cvmx_read64_uint8(console_rbuf + roff);
+
+       /* Advance FIFO.  */
+       rcnt[1] = (rcnt[1] + 1) % OPCIC_RSYS_FIFO_SIZE;
+       cvmx_write64_uint16(console_rcnt[1], rcnt[1]);
+
+       return (c);
+}
+
+static void
+opcic_rsys_cnputc(struct opcic_softc *sc, int c)
+{
+       uint64_t gbl_base;
+       uint64_t console_base;
+       uint64_t console_wbuf;
+       uint64_t console_wcnt;
+       uint16_t wcnt;
+
+       gbl_base = CVMX_ADD_IO_SEG(sc->sc_base_addr);
+       console_base = gbl_base + 0x10;
+
+       console_wbuf = console_base + 0x0018;
+       console_wcnt = console_base + 0x0c;
+
+       /* Append character to FIFO.  */
+       wcnt = cvmx_read64_uint16(console_wcnt) % OPCIC_RSYS_FIFO_SIZE;
+       cvmx_write64_uint8(console_wbuf + wcnt, (uint8_t)c);
+       cvmx_write64_uint16(console_wcnt, wcnt + 1);
+}
+#endif
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to