Add in kernel firmware loading support

Signed-off-by: Mark Hounschell <ma...@compro.net>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>

diff -urN linux-3.13.1-orig/drivers/staging/dgap/dgap_driver.c 
linux-3.13.1-new/drivers/staging/dgap/dgap_driver.c
--- linux-3.13.1-orig/drivers/staging/dgap/dgap_driver.c        2014-02-03 
13:34:50.489287314 -0500
+++ linux-3.13.1-new/drivers/staging/dgap/dgap_driver.c 2014-02-03 
14:12:20.059076489 -0500
@@ -18,6 +18,33 @@
  *
  */
 
+/*
+ *      In the original out of kernel Digi dgap driver, firmware
+ *      loading was done via user land to driver handshaking.
+ *
+ *      For cards that support a concentrator (port expander),
+ *      I believe the concentrator its self told the card which
+ *      concentrator is actually attached and then that info
+ *      was used to tell user land which concentrator firmware
+ *      image was to be downloaded. I think even the BIOS or
+ *      FEP images required would change with the connection
+ *      of a particular concentrator. 
+ *
+ *      Since I have no access to any of these cards or
+ *      concentrators, I cannot put the correct concentrator
+ *      firmware file names into the firmware_info structure
+ *      as is now done for the BIOS and FEP images. 
+ *
+ *      I think, but am not certain, that the cards supporting
+ *      concentrators will function without them. So support
+ *      of these cards has been left in this driver.
+ *
+ *      In order to fully support those cards, they would
+ *      either have to be acquired for dissection or maybe
+ *      Digi International could provide some assistance.
+ */
+#undef DIGI_CONCENTRATORS_SUPPORTED
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -26,6 +53,7 @@
 #include <asm/uaccess.h>       /* For copy_from_user/copy_to_user */
 #include <linux/sched.h>
 #include <linux/sched.h>
+#include <linux/firmware.h>
 
 #include <linux/version.h>
 #include <linux/tty.h>
@@ -72,10 +100,25 @@
 static void            dgap_mbuf(struct board_t *brd, const char *fmt, ...);
 static int             dgap_do_remap(struct board_t *brd);
 static irqreturn_t     dgap_intr(int irq, void *voidbrd);
-
+static void            dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, 
uint ncmds);
+static int             dgap_event(struct board_t *bd);
+static int             dgap_firmware_load(struct pci_dev *pdev, int card_type);
+static void            dgap_do_bios_load(struct board_t *brd, uchar *ubios, 
int len);
+static void            dgap_do_fep_load(struct board_t *brd, uchar *ufep, int 
len);
+static void            dgap_sysfs_create(struct board_t *brd);
+static void            dgap_get_vpd(struct board_t *brd);
+static void            dgap_do_reset_board(struct board_t *brd);
+static void            dgap_do_wait_for_bios(struct board_t *brd);
+static void            dgap_do_wait_for_fep(struct board_t *brd);
+static int             dgap_after_config_loaded(int brd);
+static int             dgap_finalize_board_init(struct board_t *brd);
 static void            dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, 
uint ncmds);
 static int             dgap_event(struct board_t *bd);
 
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+static void             dgap_do_conc_load(struct board_t *brd, uchar *uaddr, 
int len);
+#endif
+
 /* Driver load/unload functions */
 int                    dgap_init_module(void);
 void                   dgap_cleanup_module(void);
@@ -110,9 +153,7 @@
  */
 static int             dgap_Major_Control_Registered = FALSE;
 static uint            dgap_driver_start = FALSE;
-
 static uint            dgap_count = 500;
-
 static struct class *  dgap_class;
 
 /*
@@ -123,6 +164,24 @@
 static uint            dgap_poll_stop;                         /* Used to tell 
poller to stop */
 static struct timer_list dgap_poll_timer;
 
+/*
+     SUPPORTED PRODUCTS
+
+     Card Model               Number of Ports      Interface
+     ----------------------------------------------------------------
+     Acceleport Xem           4 - 64              (EIA232 & EIA422)
+     Acceleport Xr            4 & 8               (EIA232)
+     Acceleport Xr 920        4 & 8               (EIA232)
+     Acceleport C/X           8 - 128             (EIA232)
+     Acceleport EPC/X         8 - 224             (EIA232)
+     Acceleport Xr/422        4 & 8               (EIA422)
+     Acceleport 2r/920        2                   (EIA232)
+     Acceleport 4r/920        4                   (EIA232)
+     Acceleport 8r/920        8                   (EIA232)
+
+     IBM 8-Port Asynchronous PCI Adapter          (EIA232)
+     IBM 128-Port Asynchronous PCI Adapter        (EIA232 & EIA422)
+*/
 
 static struct pci_device_id dgap_pci_tbl[] = {
        {       DIGI_VID, PCI_DEVICE_XEM_DID,   PCI_ANY_ID, PCI_ANY_ID, 0, 0,   
0 },
@@ -144,7 +203,6 @@
 };
 MODULE_DEVICE_TABLE(pci, dgap_pci_tbl);
 
-
 /*
  * A generic list of Product names, PCI Vendor ID, and PCI Device ID.
  */
@@ -182,6 +240,36 @@
        .remove         = dgap_remove_one,
 };
 
+struct firmware_info {
+        uchar *conf_name;       /* dgap.conf */        
+       uchar *bios_name;       /* BIOS filename */
+        uchar *fep_name;       /* FEP  filename */
+       uchar *con_name;        /* Concentrator filename  FIXME*/ 
+       int num;                /* sequence number */
+};
+
+/*
+ * Firmware - BIOS, FEP, and CONC filenames
+ */
+#define _CONFIG_ "dgap/dgap.conf"
+static struct firmware_info fw_info[] = {
+       { _CONFIG_, "dgap/sxbios.bin",  "dgap/sxfep.bin",  0, 0 },      /* 
XEM_DID */
+       { _CONFIG_, "dgap/cxpbios.bin", "dgap/cxpfep.bin", 0, 1 },      /* 
CX_DID  */           
+       { _CONFIG_, "dgap/cxpbios.bin", "dgap/cxpfep.bin", 0, 2 },      /* 
CX_IBM_DID */         
+       { _CONFIG_, "dgap/pcibios.bin", "dgap/pcifep.bin", 0, 3 },      /* 
EPCJ_DID */
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 4 },      /* 
920_2_DID */
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 5 },      /* 
920_4_DID */ 
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 6 },      /* 
920_8_DID */
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 7 },      /* 
XR_DID */ 
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 8 },      /* 
XRJ_DID */ 
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 9 },      /* 
XR_422_DID */
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 10 },     /* 
XR_IBM_DID */
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 11 },     /* 
XR_SAIP_DID */
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 12 },     /* 
XR_BULL_DID */
+       { _CONFIG_, "dgap/xrbios.bin",  "dgap/xrfep.bin",  0, 13 },     /* 
920_8_HP_DID */
+       { _CONFIG_, "dgap/sxbios.bin",  "dgap/sxfep.bin",  0, 14 },     /* 
XEM_HP_DID */
+       {0,}
+};
 
 char *dgap_state_text[] = {
        "Board Failed",
@@ -214,8 +302,6 @@
        "Driver Ready."
 };
 
-
-
 /************************************************************************
  *
  * Driver load/unload functions
@@ -233,14 +319,15 @@
 
        APR(("%s, Digi International Part Number %s\n", DG_NAME, DG_PART));
 
+       dgap_driver_state = DRIVER_NEED_CONFIG_LOAD;
+       
        /*
         * Initialize global stuff
         */
        rc = dgap_start();
 
-       if (rc < 0) {
+       if (rc < 0) 
                return(rc);
-       }
 
        /*
         * Find and configure all the cards
@@ -258,16 +345,15 @@
                        printk("WARNING: dgap driver load failed.  No DGAP 
boards found.\n");
 
                dgap_cleanup_module();
-       }
-       else {
+       } else {
                dgap_create_driver_sysfiles(&dgap_driver);
+               dgap_driver_state = DRIVER_READY;
        }
   
        DPR_INIT(("Finished init_module. Returning %d\n", rc));
        return (rc);
 }
 
-
 /*
  * Start of driver.
  */
@@ -306,9 +392,6 @@
                        device_create(dgap_class, NULL,
                                MKDEV(DIGI_DGAP_MAJOR, 0),
                                NULL, "dgap_mgmt");
-                       device_create(dgap_class, NULL,
-                               MKDEV(DIGI_DGAP_MAJOR, 1),
-                               NULL, "dgap_downld");
                        dgap_Major_Control_Registered = TRUE;
                }
 
@@ -339,7 +422,6 @@
        return (rc);
 }
 
-
 /*
  * Register pci driver, and return how many boards we have.
  */
@@ -348,7 +430,6 @@
        return pci_register_driver(&dgap_driver);
 }
 
-
 /* returns count (>= 0), or negative on error */
 static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -364,24 +445,22 @@
                if (rc == 0) {
                        dgap_NumBoards++;
                        DPR_INIT(("Incrementing numboards to %d\n", 
dgap_NumBoards));
+                       rc = dgap_firmware_load(pdev, ent->driver_data);
                }
        }
        return rc;
 }               
 
-
 static int dgap_probe1(struct pci_dev *pdev, int card_type)
 {
        return dgap_found_board(pdev, card_type);
 }
          
-        
 static void dgap_remove_one(struct pci_dev *dev)
 {
        /* Do Nothing */
 }
 
-
 /*
  * dgap_cleanup_module()
  *
@@ -397,7 +476,7 @@
        DGAP_UNLOCK(dgap_poll_lock, lock_flags);
 
        /* Turn off poller right away. */
-       del_timer_sync( &dgap_poll_timer);
+       del_timer_sync(&dgap_poll_timer);
 
        dgap_remove_driver_sysfiles(&dgap_driver);
 
@@ -427,7 +506,6 @@
                pci_unregister_driver(&dgap_driver);
 }
 
-
 /*
  * dgap_cleanup_board()
  *
@@ -484,7 +562,6 @@
         kfree(brd);
 }
 
-
 /*
  * dgap_found_board()
  *
@@ -538,9 +615,8 @@
        brd->wait_for_bios      = 0;
        brd->wait_for_fep       = 0;
 
-       for (i = 0; i < MAXPORTS; i++) {
+       for (i = 0; i < MAXPORTS; i++) 
                brd->channels[i] = NULL;
-       }
 
        /* store which card & revision we have */
        pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
@@ -552,13 +628,12 @@
 
        /* get the PCI Base Address Registers */
 
-       /* Xr Jupiter and EPC use BAR 2 */
        if (brd->device == PCI_DEVICE_XRJ_DID || brd->device == 
PCI_DEVICE_EPCJ_DID) {
+               /* Xr Jupiter and EPC use BAR 2 */
                brd->membase     = pci_resource_start(pdev, 2);
                brd->membase_end = pci_resource_end(pdev, 2);
-       }
-       /* Everyone else uses BAR 0 */
-       else {
+       } else {                
+               /* Everyone else uses BAR 0 */
                brd->membase     = pci_resource_start(pdev, 0);
                brd->membase_end = pci_resource_end(pdev, 0);
        }
@@ -582,7 +657,6 @@
        brd->port = brd->membase + PCI_IO_OFFSET;
        brd->port_end = brd->port + PCI_IO_SIZE;
 
-
        /*
         * Special initialization for non-PLX boards
         */
@@ -625,10 +699,9 @@
        else
                brd->state = NEED_RESET;
 
-        return(0);
+        return 0;
 }
 
-
 int dgap_finalize_board_init(struct board_t *brd) {
 
         int rc;
@@ -653,16 +726,169 @@
                        dgap_mbuf(brd, DRVSTR": Failed to hook IRQ %d. Board 
will work in poll mode.\n",
                                   brd->irq);
                        brd->intr_used = 0;
-               }
-               else
+               } else
                        brd->intr_used = 1;
-       } else {
+       } else 
                brd->intr_used = 0;
-       }
 
        return(0);
 }
 
+static int dgap_firmware_load(struct pci_dev *pdev, int card_type)
+{
+       struct board_t *brd = dgap_Board[dgap_NumBoards - 1];
+       const struct firmware *fw;
+       char *uaddr;
+       int ret;
+       
+       dgap_get_vpd(brd);
+       dgap_do_reset_board(brd);
+
+       if ((fw_info[card_type].conf_name) && 
+           (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD)) {
+               ret = request_firmware(&fw, fw_info[card_type].conf_name, 
&pdev->dev);
+               if (ret) {
+                       printk(KERN_ERR "DGAP: request_firmware failed. Make 
sure "
+                                       "you've placed '%s' file into your 
firmware "
+                                       "loader directory (e.g. 
/lib/firmware)\n",
+                                       fw_info[card_type].conf_name);
+                       return ret; 
+               } else {
+                       if (!dgap_config_buf) {
+                               uaddr = dgap_config_buf = 
dgap_driver_kzmalloc(fw->size + 1, GFP_ATOMIC);
+                               if (!dgap_config_buf) {
+                                       DPR_INIT(("DGAP: dgap_firmware_load - 
unable to allocate memory for config file\n"));
+                                       release_firmware(fw);
+                                       return -ENOMEM;
+                               }
+                       }
+
+                       memcpy(uaddr, fw->data, fw->size);
+                       release_firmware(fw);
+                       uaddr[fw->size + 1] = '\0';     // The config file is 
treated as a string
+
+                       if (dgap_parsefile(&uaddr, TRUE) != 0) 
+                               return -EINVAL;
+
+                       dgap_driver_state = -1;
+               }
+       }
+
+       ret = dgap_after_config_loaded(brd->boardnum);
+       if (ret != 0)
+               return ret;
+       /*
+        * Match this board to a config the user created for us.
+        */
+       brd->bd_config = dgap_find_config(brd->type, brd->pci_bus, 
brd->pci_slot);
+
+       /*
+        * Because the 4 port Xr products share the same PCI ID
+        * as the 8 port Xr products, if we receive a NULL config
+        * back, and this is a PAPORT8 board, retry with a
+        * PAPORT4 attempt as well.
+        */
+       if (brd->type == PAPORT8 && !brd->bd_config)
+               brd->bd_config = dgap_find_config(PAPORT4, brd->pci_bus, 
brd->pci_slot);
+
+       if (!brd->bd_config) {
+               printk(KERN_ERR "DGAP: dgap_firmware_load: No valid 
configuration found\n");
+               return -EINVAL;
+       }
+
+       dgap_tty_register(brd);
+       dgap_finalize_board_init(brd);
+
+       if (fw_info[card_type].bios_name) {
+               ret = request_firmware(&fw, fw_info[card_type].bios_name, 
&pdev->dev);
+               if (ret) {
+                       printk(KERN_ERR "DGAP: request_firmware failed. Make 
sure "
+                                       "you've placed '%s' file into your 
firmware "
+                                       "loader directory (e.g. 
/lib/firmware)\n",
+                                       fw_info[card_type].bios_name);
+                       return ret;
+               } else {
+                       uaddr = (char *)fw->data;
+                       dgap_do_bios_load(brd, uaddr, fw->size);
+                       release_firmware(fw);
+
+                       /* Wait for BIOS to test board... */
+                       dgap_do_wait_for_bios(brd);
+
+                       if (brd->state != FINISHED_BIOS_LOAD)
+                               return -ENXIO;
+               }
+       }
+
+        if (fw_info[card_type].fep_name) {
+                ret = request_firmware(&fw, fw_info[card_type].fep_name, 
&pdev->dev);
+                if (ret) {
+                        printk(KERN_ERR "DGAP: request_firmware failed. Make 
sure "
+                                        "you've placed '%s' file into your 
firmware "
+                                        "loader directory (e.g. 
/lib/firmware)\n",
+                                        fw_info[card_type].fep_name);
+                        return ret;
+                } else {
+                        uaddr = (char *)fw->data;
+                        dgap_do_fep_load(brd, uaddr, fw->size);
+                       release_firmware(fw);
+
+                        /* Wait for FEP to load on board... */
+                        dgap_do_wait_for_fep(brd);
+
+                        if (brd->state != FINISHED_FEP_LOAD)
+                                return -ENXIO;
+                }
+        }
+
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
+       /*
+        * If this is a CX or EPCX, we need to see if the firmware
+        * is requesting a concentrator image from us.
+        */
+       if ((bd->type == PCX) || (bd->type == PEPC)) {
+               chk_addr = (u16 *) (vaddr + DOWNREQ);
+               /* Nonzero if FEP is requesting concentrator image. */
+               check = readw(chk_addr);
+               vaddr = brd->re_map_membase;
+       }
+
+       if (fw_info[card_type].con_name && check && vaddr) {
+               ret = request_firmware(&fw, fw_info[card_type].con_name, 
&pdev->dev);
+               if (ret) {
+                       printk(KERN_ERR "DGAP: request_firmware failed. Make 
sure "
+                                       "you've placed '%s' file into your 
firmware "
+                                       "loader directory (e.g. 
/lib/firmware)\n",
+                                       fw_info[card_type].con_name);
+                       return ret;
+               } else {
+                       /* Put concentrator firmware loading code here */
+                       offset = readw((u16 *) (vaddr + DOWNREQ)); 
+                       memcpy_toio(offset, fw->data, fw->size);
+
+                        uaddr = (char *)fw->data;
+                       dgap_do_conc_load(brd, uaddr, fw->size)
+                       release_firmware(fw);
+               }
+       }
+#endif
+       /*
+        * Do tty device initialization.
+        */
+       ret = dgap_tty_init(brd); 
+       if (ret < 0) {
+               dgap_tty_uninit(brd);
+               printk("DGAP: dgap_firmware_load: Can't init tty devices 
(%d)\n", ret);
+               return -EIO;
+       }
+
+       dgap_sysfs_create(brd);
+
+       brd->state = BOARD_READY;
+       brd->dpastatus = BD_RUNNING;
+
+       return 0;
+}
 
 /*
  * Remap PCI memory.
@@ -707,7 +933,6 @@
        return 0;
 }
 
-
 /*****************************************************************************
 *
 * Function:
@@ -739,59 +964,38 @@
        int i;
         struct board_t *brd;
         unsigned long lock_flags;
-        unsigned long lock_flags2;
-       ulong new_time;
+        ulong new_time;
 
        dgap_poll_counter++;
 
-
-       /*
-        * If driver needs the config file still,
-        * keep trying to wake up the downloader to
-        * send us the file.
-        */
-        if (dgap_driver_state == DRIVER_NEED_CONFIG_LOAD) {
-               /*
-                * Signal downloader, its got some work to do.
-                */
-               DGAP_LOCK(dgap_dl_lock, lock_flags2);
-               if (dgap_dl_action != 1) {
-                       dgap_dl_action = 1;
-                       wake_up_interruptible(&dgap_dl_wait);
-               }
-               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-               goto schedule_poller;
-        }
        /*
         * Do not start the board state machine until
         * driver tells us its up and running, and has
         * everything it needs.
         */
-       else if (dgap_driver_state != DRIVER_READY) {
+       if (dgap_driver_state != DRIVER_READY)
                goto schedule_poller;
-       }
-
+       
        /*
         * If we have just 1 board, or the system is not SMP,
         * then use the typical old style poller.
         * Otherwise, use our new tasklet based poller, which should
         * speed things up for multiple boards.
         */
-       if ( (dgap_NumBoards == 1) || (num_online_cpus() <= 1) ) {
+       if ((dgap_NumBoards == 1) || (num_online_cpus() <= 1)) {
                for (i = 0; i < dgap_NumBoards; i++) {
 
                        brd = dgap_Board[i];
 
-                       if (brd->state == BOARD_FAILED) {
+                       if (brd->state == BOARD_FAILED) 
                                continue;
-                       }
-                       if (!brd->intr_running) {
+                       
+                       if (!brd->intr_running) 
                                /* Call the real board poller directly */
                                dgap_poll_tasklet((unsigned long) brd);
-                       }
+                       
                }
-       }
-       else {
+       } else {
                /* Go thru each board, kicking off a tasklet for each if needed 
*/
                for (i = 0; i < dgap_NumBoards; i++) {
                        brd = dgap_Board[i];
@@ -803,9 +1007,8 @@
                         * Basically, I just really don't want to spin in here, 
because I want
                         * to kick off my tasklets as fast as I can, and then 
get out the poller.
                         */
-                       if (!spin_trylock(&brd->bd_lock)) {
+                       if (!spin_trylock(&brd->bd_lock)) 
                                continue;
-                       }
 
                        /* If board is in a failed state, don't bother 
scheduling a tasklet */
                        if (brd->state == BOARD_FAILED) {
@@ -814,9 +1017,8 @@
                        }
 
                        /* Schedule a poll helper task */
-                       if (!brd->intr_running) {
+                       if (!brd->intr_running) 
                                tasklet_schedule(&brd->helper_tasklet);
-                       }
 
                        /*
                         * Can't do DGAP_UNLOCK here, as we don't have
@@ -831,27 +1033,23 @@
        /*
         * Schedule ourself back at the nominal wakeup interval.
         */
-       DGAP_LOCK(dgap_poll_lock, lock_flags );
+       DGAP_LOCK(dgap_poll_lock, lock_flags);
        dgap_poll_time +=  dgap_jiffies_from_ms(dgap_poll_tick);
 
        new_time = dgap_poll_time - jiffies;
 
-       if ((ulong) new_time >= 2 * dgap_poll_tick) {
+       if ((ulong) new_time >= 2 * dgap_poll_tick) 
                dgap_poll_time = jiffies +  
dgap_jiffies_from_ms(dgap_poll_tick);
-       }
 
        dgap_poll_timer.function = dgap_poll_handler;
        dgap_poll_timer.data = 0;
        dgap_poll_timer.expires = dgap_poll_time;
-       DGAP_UNLOCK(dgap_poll_lock, lock_flags );
+       DGAP_UNLOCK(dgap_poll_lock, lock_flags);
 
        if (!dgap_poll_stop)
                add_timer(&dgap_poll_timer);
 }
 
-
-
-
 /*
  * dgap_intr()
  *
@@ -883,7 +1081,6 @@
        return IRQ_HANDLED;
 }
 
-
 /*
  * dgap_init_globals()
  *
@@ -899,24 +1096,21 @@
         dgap_trcbuf_size       = trcbuf_size;
        dgap_debug              = debug;
 
-       for (i = 0; i < MAXBOARDS; i++) {
+       for (i = 0; i < MAXBOARDS; i++) 
                dgap_Board[i] = NULL;
-       }
 
-       init_timer( &dgap_poll_timer ); 
+       init_timer(&dgap_poll_timer); 
 
        init_waitqueue_head(&dgap_dl_wait);
        dgap_dl_action = 0;
 }
 
-
 /************************************************************************
  *
  * Utility functions
  *
  ************************************************************************/
 
-
 /*
  * dgap_driver_kzmalloc()
  *
@@ -930,7 +1124,6 @@
        return(p);
 }
 
-
 /*
  * dgap_mbuf()
  *
@@ -967,7 +1160,6 @@
        DGAP_UNLOCK(dgap_global_lock, flags);
 }
 
-
 /*
  * dgap_ms_sleep()
  *
@@ -982,8 +1174,6 @@
        return (signal_pending(current));
 }
 
-
-
 /*
  *      dgap_ioctl_name() : Returns a text version of each ioctl value.
  */
@@ -1060,7 +1250,7 @@
                if (n > len)
                        n = len;
 
-               if (copy_from_user((char *) &buf, from_addr, n) == -1 )
+               if (copy_from_user((char *) &buf, from_addr, n) == -1)
                        return;
 
                /* Copy data from buffer to kernel memory */
@@ -1083,73 +1273,58 @@
        return;
 }
 
-
-int dgap_after_config_loaded(void)
+static int dgap_after_config_loaded(int board)
 {
-       int i = 0;
-       int rc = 0;
+        int ret = 0;
 
        /*
-        * Register our ttys, now that we have the config loaded.
+        * Initialize KME waitqueues...
         */
-       for (i = 0; i < dgap_NumBoards; ++i) {
+       init_waitqueue_head(&(dgap_Board[board]->kme_wait));
 
-               /*
-                * Initialize KME waitqueues...
-                */
-               init_waitqueue_head(&(dgap_Board[i]->kme_wait));
-
-               /*
-                * allocate flip buffer for board.
-                */
-               dgap_Board[i]->flipbuf = dgap_driver_kzmalloc(MYFLIPLEN, 
GFP_ATOMIC);
-               dgap_Board[i]->flipflagbuf = dgap_driver_kzmalloc(MYFLIPLEN, 
GFP_ATOMIC);
+       /*
+        * allocate flip buffer for board.
+        */
+       dgap_Board[board]->flipbuf = dgap_driver_kzmalloc(MYFLIPLEN, 
GFP_ATOMIC);
+       if (!dgap_Board[board]->flipbuf) {
+               ret = -ENOMEM;
+               goto out;
        }
+       dgap_Board[board]->flipflagbuf = dgap_driver_kzmalloc(MYFLIPLEN, 
GFP_ATOMIC);
+       if (!dgap_Board[board]->flipflagbuf) 
+               ret = -ENOMEM;
 
-       return rc;
+    out:
+        return ret;
 }
 
-
-
-/*=======================================================================
- *
- *      usertoboard - copy from user space to board space.
- *
- *=======================================================================*/
-static int dgap_usertoboard(struct board_t *brd, char *to_addr, char __user 
*from_addr, int len)
+/*
+ * Create pr and tty device entries
+ */
+static void dgap_sysfs_create(struct board_t *brd)
 {
-       char buf[U2BSIZE];
-       int n = U2BSIZE;
-
-       if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-               return -EFAULT;
-
-       while (len) {
-               if (n > len)
-                       n = len;
-
-               if (copy_from_user((char *) &buf, from_addr, n) == -1 ) {
-                       return -EFAULT;
-               }
-
-               /* Copy data from buffer to card memory */
-               memcpy_toio(to_addr, buf, n);
+       struct channel_t *ch;
+       int j = 0;
 
-               /* increment counts */
-               len -= n;
-               to_addr += n;
-               from_addr += n;   
-               n = U2BSIZE;
-        }
-       return 0;
+       ch = brd->channels[0];
+       for (j = 0; j < brd->nasync; j++, ch = brd->channels[j]) {
+               struct device *classp;
+               classp = tty_register_device(brd->SerialDriver, j, 
&(ch->ch_bd->pdev->dev));
+               ch->ch_tun.un_sysfs = classp;
+               dgap_create_tty_sysfs(&ch->ch_tun, classp);
+
+               classp = tty_register_device(brd->PrintDriver, j, 
&(ch->ch_bd->pdev->dev));
+               ch->ch_pun.un_sysfs = classp;
+               dgap_create_tty_sysfs(&ch->ch_pun, classp);
+       }
+       dgap_create_ports_sysfiles(brd);
 }
 
-
 /*
  * Copies the BIOS code from the user to the board,
  * and starts the BIOS running.
  */
-void dgap_do_bios_load(struct board_t *brd, uchar __user *ubios, int len)
+static void dgap_do_bios_load(struct board_t *brd, uchar *ubios, int len)
 {
        uchar *addr;
        uint offset;
@@ -1172,21 +1347,15 @@
         * Download bios
         */
        offset = 0x1000;
-       if (dgap_usertoboard(brd, addr + offset, ubios, len) == -1 ) {
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-               return;
-       }
+       memcpy_toio(addr + offset, ubios, len);
 
        writel(0x0bf00401, addr);
        writel(0, (addr + 4));
 
        /* Clear the reset, and change states. */
        writeb(FEPCLR, brd->re_map_port);
-       brd->state = WAIT_BIOS_LOAD;
 }
 
-
 /*
  * Checks to see if the BIOS completed running on the card.
  */
@@ -1194,37 +1363,47 @@
 {
        uchar *addr;
        u16 word;
+       u16 err1;
+       u16 err2;
 
        if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
                return;
-
+       
        addr = brd->re_map_membase;
        word = readw(addr + POSTAREA);
 
-       /* Check to see if BIOS thinks board is good. (GD). */
-       if (word == *(u16 *) "GD") {
-               DPR_INIT(("GOT GD in memory, moving states.\n"));
-               brd->state = FINISHED_BIOS_LOAD;
-               return;
+       /*
+        * It can take 5-6 seconds for a board to
+        * pass the bios self test and post results.
+        * Give it 10 seconds.
+        */
+       brd->wait_for_bios = 0;
+       while (brd->wait_for_bios < 1000) {
+               /* Check to see if BIOS thinks board is good. (GD). */
+               if (word == *(u16 *) "GD") {
+                       DPR_INIT(("GOT GD in memory, moving states.\n"));
+                       brd->state = FINISHED_BIOS_LOAD;
+                       return;
+               }
+               msleep_interruptible(10);
+               brd->wait_for_bios++;
+               word = readw(addr + POSTAREA);
        }
 
-       /* Give up on board after too long of time taken */
-       if (brd->wait_for_bios++ > 5000) {
-               u16 err1 = readw(addr + SEQUENCE);
-               u16 err2 = readw(addr + ERROR);
-               APR(("***WARNING*** %s failed diagnostics.  Error #(%x,%x).\n",
-                       brd->name, err1, err2));
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-       }
+       /* Gave up on board after too long of time taken */
+       err1 = readw(addr + SEQUENCE);
+       err2 = readw(addr + ERROR);
+       APR(("***WARNING*** %s failed diagnostics.  Error #(%x,%x).\n",
+               brd->name, err1, err2));
+       brd->state = BOARD_FAILED;
+       brd->dpastatus = BD_NOBIOS;
 }
 
-
 /*
  * Copies the FEP code from the user to the board,
  * and starts the FEP running.
  */
-void dgap_do_fep_load(struct board_t *brd, uchar __user *ufep, int len)
+static void dgap_do_fep_load(struct board_t *brd, uchar *ufep, int len)
 {
        uchar *addr;
        uint offset;
@@ -1240,11 +1419,7 @@
         * Download FEP
         */
        offset = 0x1000;
-       if (dgap_usertoboard(brd, addr + offset, ufep, len) == -1 ) {
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-               return;
-       }
+       memcpy_toio(addr + offset, ufep, len);
 
        /*
         * If board is a concentrator product, we need to give
@@ -1269,62 +1444,62 @@
        writel(0xbfc01004, (addr + 0xc34));
        writel(0x3, (addr + 0xc30));
 
-       /* change states. */
-       brd->state = WAIT_FEP_LOAD;
-
        DPR_INIT(("dgap_do_fep_load() for board %s : finish\n", brd->name));
-
 }
 
-
 /*
  * Waits for the FEP to report thats its ready for us to use.
  */
-static void dgap_do_wait_for_fep(struct board_t *brd)
+void dgap_do_wait_for_fep(struct board_t *brd)
 {
        uchar *addr;
        u16 word;
+       u16 err1;
+       u16 err2;
 
        if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
                return;
 
        addr = brd->re_map_membase;
-
-       DPR_INIT(("dgap_do_wait_for_fep() for board %s : start. addr: %p\n", 
brd->name, addr));
-
        word = readw(addr + FEPSTAT);
 
-       /* Check to see if FEP is up and running now. */
-       if (word == *(u16 *) "OS") {
-               DPR_INIT(("GOT OS in memory for board %s, moving states.\n", 
brd->name));
-               brd->state = FINISHED_FEP_LOAD;
+       /*
+        * It can take 2-3 seconds for the FEP to
+         * be up and running. Give it 5 secs.
+        */
+       brd->wait_for_fep = 0;
+       while (brd->wait_for_fep < 500) {
+               /* Check to see if FEP is up and running now. */
+               if (word == *(u16 *) "OS") {
+                       DPR_INIT(("GOT OS in memory for board %s, moving 
states.\n", brd->name));
+                       brd->state = FINISHED_FEP_LOAD;
+                       /*
+                       * Check to see if the board can support FEP5+ commands.
+                       */
+                       word = readw(addr + FEP5_PLUS);
+                       if (word == *(u16 *) "5A") {
+                               DPR_INIT(("GOT 5A in memory for board %s, board 
supports extended FEP5 commands.\n", brd->name));
+                               brd->bd_flags |= BD_FEP5PLUS;
+                       }
 
-               /*
-                * Check to see if the board can support FEP5+ commands.
-                */
-               word = readw(addr + FEP5_PLUS);
-               if (word == *(u16 *) "5A") {
-                       DPR_INIT(("GOT 5A in memory for board %s, board 
supports extended FEP5 commands.\n", brd->name));
-                       brd->bd_flags |= BD_FEP5PLUS;
+                       return;
                }
-
-               return;
+               msleep_interruptible(10);
+               brd->wait_for_fep++;
+               word = readw(addr + FEPSTAT);
        }
 
-       /* Give up on board after too long of time taken */
-       if (brd->wait_for_fep++ > 5000) {
-               u16 err1 = readw(addr + SEQUENCE);
-               u16 err2 = readw(addr + ERROR);
-               APR(("***WARNING*** FEPOS for %s not functioning.  Error 
#(%x,%x).\n",
-                       brd->name, err1, err2));
-               brd->state = BOARD_FAILED;
-               brd->dpastatus = BD_NOFEP;
-       }
+       /* Gave up on board after too long of time taken */
+       err1 = readw(addr + SEQUENCE);
+       err2 = readw(addr + ERROR);
+       APR(("***WARNING*** FEPOS for %s not functioning.  Error #(%x,%x).\n",
+               brd->name, err1, err2));
+       brd->state = BOARD_FAILED;
+       brd->dpastatus = BD_NOFEP;
 
        DPR_INIT(("dgap_do_wait_for_fep() for board %s : finish\n", brd->name));
 }
 
-
 /*
  * Physically forces the FEP5 card to reset itself.
  */
@@ -1382,9 +1557,9 @@
        DPR_INIT(("dgap_do_reset_board() finish\n"));
 }
 
-
+#ifdef DIGI_CONCENTRATORS_SUPPORTED
 /*
- * Sends a concentrator image into the FEP5 board.
+ * Sends a concentrator image into the FEP5 board.  FIXME: 
  */
 void dgap_do_conc_load(struct board_t *brd, uchar *uaddr, int len)
 {
@@ -1399,19 +1574,12 @@
 
        offset = readw((u16 *) (vaddr + DOWNREQ));
        to_dp = (struct downld_t *) (vaddr + (int) offset);
-
-       /*
-        * The image was already read into kernel space,
-        * we do NOT need a user space read here
-        */
-       memcpy_toio((char *) to_dp, uaddr, sizeof(struct downld_t));
+       memcpy_toio(to_dp, uaddr, len);
 
        /* Tell card we have data for it */
        writew(0, vaddr + (DOWNREQ));
-
-       brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
 }
-
+#endif
 
 #define EXPANSION_ROM_SIZE     (64 * 1024)
 #define FEP5_ROM_MAGIC         (0xFEFFFFFF)
@@ -1517,7 +1685,6 @@
        pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
 }
 
-
 /*
  * Our board poller function.
  */
@@ -1528,8 +1695,6 @@
        ulong  lock_flags2;
        char *vaddr;
        u16 head, tail;
-       u16 *chk_addr;
-       u16 check = 0;
 
        if (!bd || (bd->magic != DGAP_BOARD_MAGIC)) {
                APR(("dgap_poll_tasklet() - NULL or bad bd.\n"));
@@ -1563,30 +1728,6 @@
                        goto out;
                }
 
-               /*
-                * If this is a CX or EPCX, we need to see if the firmware
-                * is requesting a concentrator image from us.
-                */
-               if ((bd->type == PCX) || (bd->type == PEPC)) {
-                       chk_addr = (u16 *) (vaddr + DOWNREQ);
-                       check = readw(chk_addr);
-                       /* Nonzero if FEP is requesting concentrator image. */
-                       if (check) {
-                               if (bd->conc_dl_status == 
NO_PENDING_CONCENTRATOR_REQUESTS)
-                                       bd->conc_dl_status = NEED_CONCENTRATOR;
-                               /*
-                                * Signal downloader, its got some work to do.
-                                */
-                               DGAP_LOCK(dgap_dl_lock, lock_flags2);
-                               if (dgap_dl_action != 1) {
-                                       dgap_dl_action = 1;
-                                       wake_up_interruptible(&dgap_dl_wait);
-                               }
-                               DGAP_UNLOCK(dgap_dl_lock, lock_flags2);
-
-                       }
-               }
-
                eaddr = (struct ev_t *) (vaddr + EVBUF);
 
                /* Get our head and tail */
@@ -1774,7 +1915,6 @@
        DGAP_UNLOCK(bd->bd_lock, lock_flags);
 }
 
-
 /*=======================================================================
  *
  *      dgap_cmdb - Sends a 2 byte command to the FEP.
@@ -1865,7 +2005,6 @@
        }  
 }
 
-
 /*=======================================================================
  *
  *      dgap_cmdw - Sends a 1 word command to the FEP.
@@ -1953,8 +2092,6 @@
        }  
 }
 
-
-
 /*=======================================================================
  *
  *      dgap_cmdw_ext - Sends a extended word command to the FEP.
@@ -2055,7 +2192,6 @@
        }  
 }
 
-
 /*=======================================================================
  *
  *      dgap_wmove - Write data to FEP buffer.
@@ -2153,7 +2289,6 @@
        return value;
 }
 
-
 /*
  * Calls the firmware to reset this channel.
  */
@@ -2180,7 +2315,6 @@
        ch->ch_hflow = 0;
 }
 
-
 /*=======================================================================
  *      
  *      dgap_param - Set Digi parameters.
@@ -2528,7 +2662,6 @@
        return 0;
 }
 
-
 /*
  * dgap_parity_scan()
  *
@@ -2615,9 +2748,6 @@
        DPR_PSCAN(("dgap_parity_scan finish\n"));
 }
 
-
-
-
 /*=======================================================================
  *
  *      dgap_event - FEP to host event processing routine.
@@ -2693,19 +2823,16 @@
                /*
                 * Make sure the interrupt is valid.
                 */
-                if ( port >= bd->nasync) {
+                if (port >= bd->nasync) 
                        goto next;
-               }
 
-               if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA))) {
+               if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA))) 
                        goto next;
-               }
 
                ch = bd->channels[port];
 
-               if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) {
+               if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) 
                        goto next;
-               }
 
                /*
                 * If we have made it here, the event was valid.
diff -urN linux-3.13.1-orig/drivers/staging/dgap/dgap_driver.h 
linux-3.13.1-new/drivers/staging/dgap/dgap_driver.h
--- linux-3.13.1-orig/drivers/staging/dgap/dgap_driver.h        2014-02-03 
13:34:50.489287314 -0500
+++ linux-3.13.1-new/drivers/staging/dgap/dgap_driver.h 2014-02-03 
14:14:40.992545649 -0500
@@ -580,12 +580,6 @@
 extern int             dgap_ms_sleep(ulong ms);
 extern void            *dgap_driver_kzmalloc(size_t size, int priority);
 extern char            *dgap_ioctl_name(int cmd);
-extern void            dgap_do_bios_load(struct board_t *brd, uchar __user 
*ubios, int len);
-extern void            dgap_do_fep_load(struct board_t *brd, uchar __user 
*ufep, int len);
-extern void            dgap_do_conc_load(struct board_t *brd, uchar *uaddr, 
int len);
-extern void            dgap_do_config_load(uchar __user *uaddr, int len);
-extern int             dgap_after_config_loaded(void);
-extern int             dgap_finalize_board_init(struct board_t *brd);
 
 /*
  * Our Global Variables.



_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to