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

Cache object: c3933a4e4f0fe242b36a302ff6969012


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