The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ips/ips.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Written by: David Jeffery
    5  * Copyright (c) 2002 Adaptec Inc.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/types.h>
   34 #include <sys/lock.h>
   35 #include <sys/mutex.h>
   36 #include <sys/stat.h>
   37 #include <sys/time.h>
   38 
   39 #include <dev/ips/ipsreg.h>
   40 #include <dev/ips/ips.h>
   41 
   42 static d_open_t ips_open;
   43 static d_close_t ips_close;
   44 static d_ioctl_t ips_ioctl;
   45 
   46 MALLOC_DEFINE(M_IPSBUF, "ipsbuf","IPS driver buffer");
   47 
   48 static struct cdevsw ips_cdevsw = {
   49         .d_version =    D_VERSION,
   50         .d_open =       ips_open,
   51         .d_close =      ips_close,
   52         .d_ioctl =      ips_ioctl,
   53         .d_name =       "ips",
   54 };
   55 
   56 static const char* ips_adapter_name[] = {
   57         "N/A",
   58         "ServeRAID (copperhead)",
   59         "ServeRAID II (copperhead refresh)",
   60         "ServeRAID onboard (copperhead)",
   61         "ServeRAID onboard (copperhead)",
   62         "ServeRAID 3H (clarinet)",
   63         "ServeRAID 3L (clarinet lite)",
   64         "ServeRAID 4H (trombone)",
   65         "ServeRAID 4M (morpheus)",
   66         "ServeRAID 4L (morpheus lite)",
   67         "ServeRAID 4Mx (neo)",
   68         "ServeRAID 4Lx (neo lite)",
   69         "ServeRAID 5i II (sarasota)",
   70         "ServeRAID 5i (sarasota)",
   71         "ServeRAID 6M (marco)",
   72         "ServeRAID 6i (sebring)",
   73         "ServeRAID 7t",
   74         "ServeRAID 7k",
   75         "ServeRAID 7M"
   76 };
   77 
   78 
   79 static int ips_open(struct cdev *dev, int flags, int fmt, struct thread *td)
   80 {
   81         ips_softc_t *sc = dev->si_drv1;
   82         mtx_lock(&sc->queue_mtx);
   83         sc->state |= IPS_DEV_OPEN;
   84         mtx_unlock(&sc->queue_mtx);
   85         return 0;
   86 }
   87 
   88 static int ips_close(struct cdev *dev, int flags, int fmt, struct thread *td)
   89 {
   90         ips_softc_t *sc = dev->si_drv1;
   91 
   92         mtx_lock(&sc->queue_mtx);
   93         sc->state &= ~IPS_DEV_OPEN;
   94         mtx_unlock(&sc->queue_mtx);
   95 
   96         return 0;
   97 }
   98 
   99 static int ips_ioctl(struct cdev *dev, u_long command, caddr_t addr, int32_t flags, struct thread *td)
  100 {
  101         ips_softc_t *sc;
  102 
  103         sc = dev->si_drv1;
  104         return ips_ioctl_request(sc, command, addr, flags);
  105 }
  106 
  107 static void ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  108 {
  109         ips_command_t *command = cmdptr;
  110         PRINTF(10, "ips: in ips_cmd_dmaload\n");
  111         if(!error)
  112                 command->command_phys_addr = segments[0].ds_addr;
  113 
  114 }
  115 
  116 /* is locking needed? what locking guarantees are there on removal? */
  117 static int ips_cmdqueue_free(ips_softc_t *sc)
  118 {
  119         int i, error = -1;
  120         ips_command_t *command;
  121 
  122         if(!sc->used_commands){
  123                 for(i = 0; i < sc->max_cmds; i++){
  124 
  125                         command = &sc->commandarray[i];
  126 
  127                         if(command->command_phys_addr == 0)
  128                                 continue;
  129                         bus_dmamap_unload(sc->command_dmatag, 
  130                                           command->command_dmamap);
  131                         bus_dmamem_free(sc->command_dmatag, 
  132                                         command->command_buffer,
  133                                         command->command_dmamap);
  134                         if (command->data_dmamap != NULL)
  135                                 bus_dmamap_destroy(command->data_dmatag,
  136                                     command->data_dmamap);
  137                 }
  138                 error = 0;
  139                 sc->state |= IPS_OFFLINE;
  140         }
  141         sc->staticcmd = NULL;
  142         free(sc->commandarray, M_DEVBUF);
  143         return error;
  144 }
  145 
  146 /* places all ips command structs on the free command queue.  No locking as if someone else tries
  147  * to access this during init, we have bigger problems */
  148 static int ips_cmdqueue_init(ips_softc_t *sc)
  149 {
  150         int i;
  151         ips_command_t *command;
  152 
  153         sc->commandarray = (ips_command_t *)malloc(sizeof(ips_command_t) *
  154             sc->max_cmds, M_DEVBUF, M_NOWAIT|M_ZERO);
  155         if (sc->commandarray == NULL)
  156                 return (ENOMEM);
  157 
  158         SLIST_INIT(&sc->free_cmd_list);
  159         for(i = 0; i < sc->max_cmds; i++){
  160                 command = &sc->commandarray[i];
  161                 command->id = i;
  162                 command->sc = sc;
  163 
  164                 if(bus_dmamem_alloc(sc->command_dmatag,&command->command_buffer,
  165                     BUS_DMA_NOWAIT, &command->command_dmamap))
  166                         goto error;
  167                 bus_dmamap_load(sc->command_dmatag, command->command_dmamap, 
  168                                 command->command_buffer,IPS_COMMAND_LEN, 
  169                                 ips_cmd_dmaload, command, BUS_DMA_NOWAIT);
  170                 if(!command->command_phys_addr){
  171                         bus_dmamem_free(sc->command_dmatag, 
  172                             command->command_buffer, command->command_dmamap);
  173                         goto error;
  174                 }
  175 
  176                 if (i != 0) {
  177                         command->data_dmatag = sc->sg_dmatag;
  178                         if (bus_dmamap_create(command->data_dmatag, 0,
  179                             &command->data_dmamap))
  180                                 goto error;
  181                         SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);   
  182                 } else
  183                         sc->staticcmd = command;
  184         }
  185         sc->state &= ~IPS_OFFLINE;
  186         return 0;
  187 error:
  188         ips_cmdqueue_free(sc);
  189         return ENOMEM;
  190 }
  191 
  192 /* returns a free command struct if one is available. 
  193  * It also blanks out anything that may be a wild pointer/value.
  194  * Also, command buffers are not freed.  They are
  195  * small so they are saved and kept dmamapped and loaded.
  196  */
  197 int ips_get_free_cmd(ips_softc_t *sc, ips_command_t **cmd, unsigned long flags)
  198 {
  199         ips_command_t *command;
  200 
  201         if(sc->state & IPS_OFFLINE){
  202                 return EIO;
  203         }
  204         if ((flags & IPS_STATIC_FLAG) == 0) {
  205                 command = SLIST_FIRST(&sc->free_cmd_list);
  206                 if(!command || (sc->state & IPS_TIMEOUT)){
  207                         return EBUSY;
  208                 }
  209                 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
  210                 (sc->used_commands)++;
  211         } else {
  212                 if (sc->state & IPS_STATIC_BUSY)
  213                         return EAGAIN;
  214                 command = sc->staticcmd;
  215                 sc->state |= IPS_STATIC_BUSY;
  216         }
  217         clear_ips_command(command);
  218         bzero(command->command_buffer, IPS_COMMAND_LEN);
  219         *cmd = command;
  220         return 0;
  221 }
  222 
  223 /* adds a command back to the free command queue */
  224 void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
  225 {
  226 
  227         if (sema_value(&sc->cmd_sema) != 0)
  228                 panic("ips: command returned non-zero semaphore");
  229 
  230         if (command != sc->staticcmd) {
  231                 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
  232                 (sc->used_commands)--;
  233         } else {
  234                 sc->state &= ~IPS_STATIC_BUSY;
  235         }
  236 }
  237 static const char* ips_diskdev_statename(u_int8_t state)
  238 {
  239         static char statebuf[20];
  240         switch(state){
  241                 case IPS_LD_OFFLINE:
  242                         return("OFFLINE");
  243                         break;
  244                 case IPS_LD_OKAY:
  245                         return("OK");
  246                         break;
  247                 case IPS_LD_DEGRADED:
  248                         return("DEGRADED");
  249                         break;
  250                 case IPS_LD_FREE:
  251                         return("FREE");
  252                         break;
  253                 case IPS_LD_SYS:
  254                         return("SYS");
  255                         break;
  256                 case IPS_LD_CRS:
  257                         return("CRS");
  258                         break;
  259         }
  260         sprintf(statebuf,"UNKNOWN(0x%02x)", state);
  261         return(statebuf);
  262 }
  263 
  264 static int ips_diskdev_init(ips_softc_t *sc)
  265 {
  266         int i;
  267         for(i=0; i < IPS_MAX_NUM_DRIVES; i++){
  268                 if(sc->drives[i].state == IPS_LD_FREE) continue;
  269                 device_printf(sc->dev, "Logical Drive %d: RAID%d sectors: %u, state %s\n",
  270                         i, sc->drives[i].raid_lvl,
  271                         sc->drives[i].sector_count,
  272                         ips_diskdev_statename(sc->drives[i].state));
  273                 if(sc->drives[i].state == IPS_LD_OKAY ||
  274                    sc->drives[i].state == IPS_LD_DEGRADED){
  275                         sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
  276                         device_set_ivars(sc->diskdev[i],(void *)(uintptr_t) i);
  277                 }
  278         }
  279         if(bus_generic_attach(sc->dev)){
  280                 device_printf(sc->dev, "Attaching bus failed\n");
  281         }
  282         return 0;
  283 }
  284 
  285 static int ips_diskdev_free(ips_softc_t *sc)
  286 {
  287         int i;
  288         int error = 0;
  289         for(i = 0; i < IPS_MAX_NUM_DRIVES; i++){
  290                 if(sc->diskdev[i]) {
  291                         error = device_delete_child(sc->dev, sc->diskdev[i]);
  292                         if(error)
  293                                 return error;
  294                 }
  295         }
  296         bus_generic_detach(sc->dev);
  297         return 0;
  298 }
  299 
  300 /* ips_timeout is periodically called to make sure no commands sent
  301  * to the card have become stuck.  If it finds a stuck command, it
  302  * sets a flag so the driver won't start any more commands and then
  303  * is periodically called to see if all outstanding commands have
  304  * either finished or timed out.  Once timed out, an attempt to
  305  * reinitialize the card is made.  If that fails, the driver gives
  306  * up and declares the card dead. */
  307 static void ips_timeout(void *arg)
  308 {
  309         ips_softc_t *sc = arg;
  310         int i, state = 0;
  311         ips_command_t *command;
  312 
  313         mtx_assert(&sc->queue_mtx, MA_OWNED);
  314         command = &sc->commandarray[0];
  315         for(i = 0; i < sc->max_cmds; i++){
  316                 if(!command[i].timeout){
  317                         continue;
  318                 }
  319                 command[i].timeout--;
  320                 if(!command[i].timeout){
  321                         if(!(sc->state & IPS_TIMEOUT)){
  322                                 sc->state |= IPS_TIMEOUT;
  323                                 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
  324                         }
  325                         ips_set_error(&command[i], ETIMEDOUT);
  326                         command[i].callback(&command[i]);
  327                         /* hmm, this should be enough cleanup */
  328                 } else
  329                         state = 1;
  330         }
  331         if(!state && (sc->state & IPS_TIMEOUT)){
  332                 if(sc->ips_adapter_reinit(sc, 1)){
  333                         device_printf(sc->dev, "AIEE! adapter reset failed, giving up and going home! Have a nice day.\n");
  334                         sc->state |= IPS_OFFLINE;
  335                         sc->state &= ~IPS_TIMEOUT;
  336                         /* Grr, I hate this solution. I run waiting commands
  337                            one at a time and error them out just before they 
  338                            would go to the card. This sucks. */
  339                 } else
  340                         sc->state &= ~IPS_TIMEOUT;
  341         }
  342         if (sc->state != IPS_OFFLINE)
  343                 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
  344 }
  345 
  346 /* check card and initialize it */
  347 int ips_adapter_init(ips_softc_t *sc)
  348 {
  349         int i;
  350         DEVICE_PRINTF(1,sc->dev, "initializing\n");
  351 
  352         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  353                                 /* alignemnt */ 1,
  354                                 /* boundary  */ 0,
  355                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  356                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  357                                 /* filter    */ NULL,
  358                                 /* filterarg */ NULL,
  359                                 /* maxsize   */ IPS_COMMAND_LEN + 
  360                                                     IPS_MAX_SG_LEN,
  361                                 /* numsegs   */ 1,
  362                                 /* maxsegsize*/ IPS_COMMAND_LEN + 
  363                                                     IPS_MAX_SG_LEN,
  364                                 /* flags     */ 0,
  365                                 /* lockfunc  */ NULL,
  366                                 /* lockarg   */ NULL,
  367                                 &sc->command_dmatag) != 0) {
  368                 device_printf(sc->dev, "can't alloc command dma tag\n");
  369                 goto error;
  370         }
  371         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  372                                 /* alignemnt */ 1,
  373                                 /* boundary  */ 0,
  374                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  375                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  376                                 /* filter    */ NULL,
  377                                 /* filterarg */ NULL,
  378                                 /* maxsize   */ IPS_MAX_IOBUF_SIZE,
  379                                 /* numsegs   */ IPS_MAX_SG_ELEMENTS,
  380                                 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
  381                                 /* flags     */ 0,
  382                                 /* lockfunc  */ busdma_lock_mutex,
  383                                 /* lockarg   */ &sc->queue_mtx,
  384                                 &sc->sg_dmatag) != 0) {
  385                 device_printf(sc->dev, "can't alloc SG dma tag\n");
  386                 goto error;
  387         }
  388         /* create one command buffer until we know how many commands this card
  389            can handle */
  390         sc->max_cmds = 1;
  391         ips_cmdqueue_init(sc);
  392 
  393         if(sc->ips_adapter_reinit(sc, 0))
  394                 goto error;
  395 
  396         /* initialize ffdc values */
  397         microtime(&sc->ffdc_resettime);
  398         sc->ffdc_resetcount = 1;
  399         if ((i = ips_ffdc_reset(sc)) != 0) {
  400                 device_printf(sc->dev, "failed to send ffdc reset to device (%d)\n", i);
  401                 goto error;
  402         }
  403         if ((i = ips_get_adapter_info(sc)) != 0) {
  404                 device_printf(sc->dev, "failed to get adapter configuration data from device (%d)\n", i);
  405                 goto error;
  406         }
  407         ips_update_nvram(sc); /* no error check as failure doesn't matter */
  408         if(sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T){
  409                 device_printf(sc->dev, "adapter type: %s\n", ips_adapter_name[sc->adapter_type]);
  410         }
  411         if ((i = ips_get_drive_info(sc)) != 0) {
  412                 device_printf(sc->dev, "failed to get drive configuration data from device (%d)\n", i);
  413                 goto error;
  414         }
  415 
  416         ips_cmdqueue_free(sc);
  417         if(sc->adapter_info.max_concurrent_cmds)
  418                 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
  419         else
  420                 sc->max_cmds = 32;
  421         if(ips_cmdqueue_init(sc)){
  422                 device_printf(sc->dev, "failed to initialize command buffers\n");
  423                 goto error;
  424         }
  425         sc->device_file = make_dev(&ips_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_OPERATOR,
  426                                         S_IRUSR | S_IWUSR, "ips%d", device_get_unit(sc->dev));
  427         sc->device_file->si_drv1 = sc;
  428         ips_diskdev_init(sc);
  429         callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
  430         return 0;
  431 
  432 error:
  433         ips_adapter_free(sc);
  434         return ENXIO;
  435 }
  436 
  437 /* see if we should reinitialize the card and wait for it to timeout or complete initialization */
  438 int ips_morpheus_reinit(ips_softc_t *sc, int force)
  439 {
  440         u_int32_t tmp;
  441         int i;
  442 
  443         tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  444         if(!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
  445             (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp){
  446                 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
  447                 return 0;
  448         }
  449         ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
  450         ips_read_4(sc, MORPHEUS_REG_OIMR);
  451 
  452         device_printf(sc->dev, "resetting adapter, this may take up to 5 minutes\n");
  453         ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
  454         DELAY(5000000);
  455         ips_read_4(sc, MORPHEUS_REG_OIMR);
  456 
  457         tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  458         for(i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++){
  459                 DELAY(1000000);
  460                 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
  461                 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  462         }
  463         if(tmp & MORPHEUS_BIT_POST1)
  464                 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
  465 
  466         if( i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK){
  467                 device_printf(sc->dev,"Adapter error during initialization.\n");
  468                 return 1;
  469         }
  470         for(i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++){
  471                 DELAY(1000000); 
  472                 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
  473                 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  474         }
  475         if(tmp & MORPHEUS_BIT_POST2)
  476                 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
  477 
  478         if(i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)){
  479                 device_printf(sc->dev, "adapter failed config check\n");
  480                 return 1;
  481         }
  482         ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
  483         if(force && ips_clear_adapter(sc)){
  484                 device_printf(sc->dev, "adapter clear failed\n");
  485                 return 1;
  486         }
  487         return 0;
  488 }
  489 
  490 /* clean up so we can unload the driver. */
  491 int ips_adapter_free(ips_softc_t *sc)
  492 {
  493         int error = 0;
  494         if(sc->state & IPS_DEV_OPEN)
  495                 return EBUSY;
  496         if((error = ips_diskdev_free(sc)))
  497                 return error;
  498         if(ips_cmdqueue_free(sc)){
  499                 device_printf(sc->dev,
  500                      "trying to exit when command queue is not empty!\n");
  501                 return EBUSY;
  502         }
  503         DEVICE_PRINTF(1, sc->dev, "free\n");
  504         callout_drain(&sc->timer);
  505 
  506         if(sc->sg_dmatag)
  507                 bus_dma_tag_destroy(sc->sg_dmatag);
  508         if(sc->command_dmatag)
  509                 bus_dma_tag_destroy(sc->command_dmatag);
  510         if(sc->device_file)
  511                 destroy_dev(sc->device_file);
  512         return 0;
  513 }
  514 
  515 static __inline int ips_morpheus_check_intr(ips_softc_t *sc)
  516 {
  517         int cmdnumber;
  518         ips_cmd_status_t status;
  519         ips_command_t *command;
  520         int found = 0;
  521         u_int32_t oisr;
  522 
  523         oisr = ips_read_4(sc, MORPHEUS_REG_OISR);
  524         PRINTF(9, "interrupt registers out:%x\n", oisr);
  525         if(!(oisr & MORPHEUS_BIT_CMD_IRQ)){
  526                 DEVICE_PRINTF(2,sc->dev, "got a non-command irq\n");
  527                 return (0);     
  528         }
  529         while((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR)) != 0xffffffff){
  530                 cmdnumber = status.fields.command_id;
  531                 command = &sc->commandarray[cmdnumber];
  532                 command->status.value = status.value;
  533                 command->timeout = 0;
  534                 command->callback(command);
  535 
  536                 found = 1;
  537         }
  538         return (found);
  539 }
  540 
  541 void ips_morpheus_intr(void *void_sc)
  542 {
  543         ips_softc_t *sc = void_sc;
  544 
  545         mtx_lock(&sc->queue_mtx);
  546         ips_morpheus_check_intr(sc);
  547         mtx_unlock(&sc->queue_mtx);
  548 }
  549 
  550 void ips_morpheus_poll(ips_command_t *command)
  551 {
  552         uint32_t ts;
  553 
  554         /*
  555          * Locks are not used here because this is only called during
  556          * crashdumps.
  557          */
  558         ts = time_second + command->timeout;
  559         while ((command->timeout != 0)
  560          && (ips_morpheus_check_intr(command->sc) == 0)
  561          && (ts > time_second))
  562                 DELAY(1000);
  563 }
  564 
  565 void ips_issue_morpheus_cmd(ips_command_t *command)
  566 {
  567         /* hmmm, is there a cleaner way to do this? */
  568         if(command->sc->state & IPS_OFFLINE){
  569                 ips_set_error(command, EINVAL);
  570                 command->callback(command);
  571                 return;
  572         }
  573         command->timeout = 10;
  574         ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
  575 }
  576 
  577 static void ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,int segnum, int error)
  578 {
  579         ips_copper_queue_t *queue = queueptr;
  580         if(error){
  581                 return;
  582         }
  583         queue->base_phys_addr = segments[0].ds_addr;
  584 }
  585 
  586 static int ips_copperhead_queue_init(ips_softc_t *sc)
  587 {
  588         int error;
  589         bus_dma_tag_t dmatag;
  590         bus_dmamap_t dmamap;
  591         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  592                                 /* alignemnt */ 1,
  593                                 /* boundary  */ 0,
  594                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  595                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  596                                 /* filter    */ NULL,
  597                                 /* filterarg */ NULL,
  598                                 /* maxsize   */ sizeof(ips_copper_queue_t),
  599                                 /* numsegs   */ 1,
  600                                 /* maxsegsize*/ sizeof(ips_copper_queue_t),
  601                                 /* flags     */ 0,
  602                                 /* lockfunc  */ NULL,
  603                                 /* lockarg   */ NULL,
  604                                 &dmatag) != 0) {
  605                 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
  606                 error = ENOMEM;
  607                 return error;
  608         }
  609         if(bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue), 
  610                             BUS_DMA_NOWAIT, &dmamap)){
  611                 error = ENOMEM;
  612                 goto exit;
  613         }
  614         bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
  615         sc->copper_queue->dmatag = dmatag;
  616         sc->copper_queue->dmamap = dmamap;
  617         sc->copper_queue->nextstatus = 1;
  618         bus_dmamap_load(dmatag, dmamap, 
  619                         &(sc->copper_queue->status[0]), IPS_MAX_CMD_NUM * 4, 
  620                         ips_copperhead_queue_callback, sc->copper_queue, 
  621                         BUS_DMA_NOWAIT);
  622         if(sc->copper_queue->base_phys_addr == 0){
  623                 error = ENOMEM;
  624                 goto exit;
  625         }
  626         ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
  627         ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr + 
  628                     IPS_MAX_CMD_NUM * 4);
  629         ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
  630         ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
  631 
  632         
  633         return 0;
  634 exit:
  635         if (sc->copper_queue != NULL)
  636                 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
  637         bus_dma_tag_destroy(dmatag);
  638         return error;
  639 }
  640 
  641 /* see if we should reinitialize the card and wait for it to timeout or complete initialization FIXME */
  642 int ips_copperhead_reinit(ips_softc_t *sc, int force)
  643 {
  644         int i, j;
  645         u_int32_t configstatus = 0;
  646         ips_write_1(sc, COPPER_REG_SCPR, 0x80);
  647         ips_write_1(sc, COPPER_REG_SCPR, 0);
  648         device_printf(sc->dev, "reinitializing adapter, this could take several minutes.\n");
  649         for(j = 0; j < 2; j++){
  650                 for(i = 0; i < 45; i++){
  651                         if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
  652                                 ips_write_1(sc, COPPER_REG_HISR, 
  653                                             COPPER_GHI_BIT);
  654                                 break;
  655                         } else
  656                                 DELAY(1000000);
  657                 }
  658                 if(i == 45)
  659                         return 1;
  660         }
  661         for(j = 0; j < 2; j++){
  662                 configstatus <<= 8;
  663                 for(i = 0; i < 240; i++){
  664                         if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
  665                                 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
  666                                 ips_write_1(sc, COPPER_REG_HISR, 
  667                                             COPPER_GHI_BIT);
  668                                 break;
  669                         } else
  670                                 DELAY(1000000);
  671                 }
  672                 if(i == 240)
  673                         return 1;
  674         }
  675         for(i = 0; i < 240; i++){
  676                 if(!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT)){
  677                         break;
  678                 } else
  679                         DELAY(1000000);
  680         }
  681         if(i == 240)
  682                 return 1;
  683         ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
  684         ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
  685         ips_copperhead_queue_init(sc);
  686         ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
  687         i = ips_read_1(sc, COPPER_REG_SCPR);
  688         ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
  689         if(!configstatus){
  690                 device_printf(sc->dev, "adapter initialization failed\n");
  691                 return 1;
  692         }
  693         if(force && ips_clear_adapter(sc)){
  694                 device_printf(sc->dev, "adapter clear failed\n");
  695                 return 1;
  696         }
  697         return 0;
  698 }
  699 static u_int32_t ips_copperhead_cmd_status(ips_softc_t *sc)
  700 {
  701         u_int32_t value;
  702         int statnum = sc->copper_queue->nextstatus++;
  703         if(sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
  704                 sc->copper_queue->nextstatus = 0;
  705         value = sc->copper_queue->status[statnum];
  706         ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr + 
  707                     4 * statnum);
  708         return value;
  709 }
  710 
  711 
  712 void ips_copperhead_intr(void *void_sc)
  713 {
  714         ips_softc_t *sc = (ips_softc_t *)void_sc;
  715         int cmdnumber;
  716         ips_cmd_status_t status;
  717 
  718         mtx_lock(&sc->queue_mtx);
  719         while(ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT){
  720                 status.value = ips_copperhead_cmd_status(sc);
  721                 cmdnumber = status.fields.command_id;
  722                 sc->commandarray[cmdnumber].status.value = status.value;
  723                 sc->commandarray[cmdnumber].timeout = 0;
  724                 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
  725                 PRINTF(9, "ips: got command %d\n", cmdnumber);
  726         }
  727         mtx_unlock(&sc->queue_mtx);
  728         return;
  729 }
  730 
  731 void ips_issue_copperhead_cmd(ips_command_t *command)
  732 {
  733         int i;
  734         /* hmmm, is there a cleaner way to do this? */
  735         if(command->sc->state & IPS_OFFLINE){
  736                 ips_set_error(command, EINVAL);
  737                 command->callback(command);
  738                 return;
  739         }
  740         command->timeout = 10;
  741         for(i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
  742             i++ ){
  743                 if( i == 20){
  744 printf("sem bit still set, can't send a command\n");
  745                         return;
  746                 }
  747                 DELAY(500);/* need to do a delay here */
  748         }
  749         ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
  750         ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
  751 }
  752 
  753 void ips_copperhead_poll(ips_command_t *command)
  754 {
  755 
  756         printf("ips: cmd polling not implemented for copperhead devices\n");
  757 }

Cache object: db2c8edb64753f2e67792c9cbaff6222


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.