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

Cache object: a0d4589d92e6f86e3fb433497a1c69ae


[ 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.