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$");
   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         }
  290         bus_generic_detach(sc->dev);
  291         return 0;
  292 }
  293 
  294 /* ips_timeout is periodically called to make sure no commands sent
  295  * to the card have become stuck.  If it finds a stuck command, it
  296  * sets a flag so the driver won't start any more commands and then
  297  * is periodically called to see if all outstanding commands have
  298  * either finished or timed out.  Once timed out, an attempt to
  299  * reinitialize the card is made.  If that fails, the driver gives
  300  * up and declares the card dead. */
  301 static void ips_timeout(void *arg)
  302 {
  303         ips_softc_t *sc = arg;
  304         int i, state = 0;
  305         ips_command_t *command;
  306 
  307         mtx_assert(&sc->queue_mtx, MA_OWNED);
  308         command = &sc->commandarray[0];
  309         for(i = 0; i < sc->max_cmds; i++){
  310                 if(!command[i].timeout){
  311                         continue;
  312                 }
  313                 command[i].timeout--;
  314                 if(!command[i].timeout){
  315                         if(!(sc->state & IPS_TIMEOUT)){
  316                                 sc->state |= IPS_TIMEOUT;
  317                                 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
  318                         }
  319                         ips_set_error(&command[i], ETIMEDOUT);
  320                         command[i].callback(&command[i]);
  321                         /* hmm, this should be enough cleanup */
  322                 } else
  323                         state = 1;
  324         }
  325         if(!state && (sc->state & IPS_TIMEOUT)){
  326                 if(sc->ips_adapter_reinit(sc, 1)){
  327                         device_printf(sc->dev, "AIEE! adapter reset failed, giving up and going home! Have a nice day.\n");
  328                         sc->state |= IPS_OFFLINE;
  329                         sc->state &= ~IPS_TIMEOUT;
  330                         /* Grr, I hate this solution. I run waiting commands
  331                            one at a time and error them out just before they 
  332                            would go to the card. This sucks. */
  333                 } else
  334                         sc->state &= ~IPS_TIMEOUT;
  335         }
  336         if (sc->state != IPS_OFFLINE)
  337                 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
  338 }
  339 
  340 /* check card and initialize it */
  341 int ips_adapter_init(ips_softc_t *sc)
  342 {
  343         int i;
  344         DEVICE_PRINTF(1,sc->dev, "initializing\n");
  345 
  346         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  347                                 /* alignemnt */ 1,
  348                                 /* boundary  */ 0,
  349                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  350                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  351                                 /* filter    */ NULL,
  352                                 /* filterarg */ NULL,
  353                                 /* maxsize   */ IPS_COMMAND_LEN + 
  354                                                     IPS_MAX_SG_LEN,
  355                                 /* numsegs   */ 1,
  356                                 /* maxsegsize*/ IPS_COMMAND_LEN + 
  357                                                     IPS_MAX_SG_LEN,
  358                                 /* flags     */ 0,
  359                                 /* lockfunc  */ NULL,
  360                                 /* lockarg   */ NULL,
  361                                 &sc->command_dmatag) != 0) {
  362                 device_printf(sc->dev, "can't alloc command dma tag\n");
  363                 goto error;
  364         }
  365         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  366                                 /* alignemnt */ 1,
  367                                 /* boundary  */ 0,
  368                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  369                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  370                                 /* filter    */ NULL,
  371                                 /* filterarg */ NULL,
  372                                 /* maxsize   */ IPS_MAX_IOBUF_SIZE,
  373                                 /* numsegs   */ IPS_MAX_SG_ELEMENTS,
  374                                 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
  375                                 /* flags     */ 0,
  376                                 /* lockfunc  */ busdma_lock_mutex,
  377                                 /* lockarg   */ &sc->queue_mtx,
  378                                 &sc->sg_dmatag) != 0) {
  379                 device_printf(sc->dev, "can't alloc SG dma tag\n");
  380                 goto error;
  381         }
  382         /* create one command buffer until we know how many commands this card
  383            can handle */
  384         sc->max_cmds = 1;
  385         ips_cmdqueue_init(sc);
  386 
  387         if(sc->ips_adapter_reinit(sc, 0))
  388                 goto error;
  389 
  390         /* initialize ffdc values */
  391         microtime(&sc->ffdc_resettime);
  392         sc->ffdc_resetcount = 1;
  393         if ((i = ips_ffdc_reset(sc)) != 0) {
  394                 device_printf(sc->dev, "failed to send ffdc reset to device (%d)\n", i);
  395                 goto error;
  396         }
  397         if ((i = ips_get_adapter_info(sc)) != 0) {
  398                 device_printf(sc->dev, "failed to get adapter configuration data from device (%d)\n", i);
  399                 goto error;
  400         }
  401         ips_update_nvram(sc); /* no error check as failure doesn't matter */
  402         if(sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T){
  403                 device_printf(sc->dev, "adapter type: %s\n", ips_adapter_name[sc->adapter_type]);
  404         }
  405         if ((i = ips_get_drive_info(sc)) != 0) {
  406                 device_printf(sc->dev, "failed to get drive configuration data from device (%d)\n", i);
  407                 goto error;
  408         }
  409 
  410         ips_cmdqueue_free(sc);
  411         if(sc->adapter_info.max_concurrent_cmds)
  412                 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
  413         else
  414                 sc->max_cmds = 32;
  415         if(ips_cmdqueue_init(sc)){
  416                 device_printf(sc->dev, "failed to initialize command buffers\n");
  417                 goto error;
  418         }
  419         sc->device_file = make_dev(&ips_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_OPERATOR,
  420                                         S_IRUSR | S_IWUSR, "ips%d", device_get_unit(sc->dev));
  421         sc->device_file->si_drv1 = sc;
  422         ips_diskdev_init(sc);
  423         callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
  424         return 0;
  425 
  426 error:
  427         ips_adapter_free(sc);
  428         return ENXIO;
  429 }
  430 
  431 /* see if we should reinitialize the card and wait for it to timeout or complete initialization */
  432 int ips_morpheus_reinit(ips_softc_t *sc, int force)
  433 {
  434         u_int32_t tmp;
  435         int i;
  436 
  437         tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  438         if(!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
  439             (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp){
  440                 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
  441                 return 0;
  442         }
  443         ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
  444         ips_read_4(sc, MORPHEUS_REG_OIMR);
  445 
  446         device_printf(sc->dev, "resetting adapter, this may take up to 5 minutes\n");
  447         ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
  448         DELAY(5000000);
  449         ips_read_4(sc, MORPHEUS_REG_OIMR);
  450 
  451         tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  452         for(i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++){
  453                 DELAY(1000000);
  454                 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
  455                 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  456         }
  457         if(tmp & MORPHEUS_BIT_POST1)
  458                 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
  459 
  460         if( i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK){
  461                 device_printf(sc->dev,"Adapter error during initialization.\n");
  462                 return 1;
  463         }
  464         for(i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++){
  465                 DELAY(1000000); 
  466                 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
  467                 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
  468         }
  469         if(tmp & MORPHEUS_BIT_POST2)
  470                 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
  471 
  472         if(i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)){
  473                 device_printf(sc->dev, "adapter failed config check\n");
  474                 return 1;
  475         }
  476         ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
  477         if(force && ips_clear_adapter(sc)){
  478                 device_printf(sc->dev, "adapter clear failed\n");
  479                 return 1;
  480         }
  481         return 0;
  482 }
  483 
  484 /* clean up so we can unload the driver. */
  485 int ips_adapter_free(ips_softc_t *sc)
  486 {
  487         int error = 0;
  488         if(sc->state & IPS_DEV_OPEN)
  489                 return EBUSY;
  490         if((error = ips_diskdev_free(sc)))
  491                 return error;
  492         if(ips_cmdqueue_free(sc)){
  493                 device_printf(sc->dev,
  494                      "trying to exit when command queue is not empty!\n");
  495                 return EBUSY;
  496         }
  497         DEVICE_PRINTF(1, sc->dev, "free\n");
  498         callout_drain(&sc->timer);
  499 
  500         if(sc->sg_dmatag)
  501                 bus_dma_tag_destroy(sc->sg_dmatag);
  502         if(sc->command_dmatag)
  503                 bus_dma_tag_destroy(sc->command_dmatag);
  504         if(sc->device_file)
  505                 destroy_dev(sc->device_file);
  506         return 0;
  507 }
  508 
  509 static __inline int ips_morpheus_check_intr(ips_softc_t *sc)
  510 {
  511         int cmdnumber;
  512         ips_cmd_status_t status;
  513         ips_command_t *command;
  514         int found = 0;
  515         u_int32_t oisr;
  516 
  517         oisr = ips_read_4(sc, MORPHEUS_REG_OISR);
  518         PRINTF(9, "interrupt registers out:%x\n", oisr);
  519         if(!(oisr & MORPHEUS_BIT_CMD_IRQ)){
  520                 DEVICE_PRINTF(2,sc->dev, "got a non-command irq\n");
  521                 return (0);     
  522         }
  523         while((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR)) != 0xffffffff){
  524                 cmdnumber = status.fields.command_id;
  525                 command = &sc->commandarray[cmdnumber];
  526                 command->status.value = status.value;
  527                 command->timeout = 0;
  528                 command->callback(command);
  529 
  530                 found = 1;
  531         }
  532         return (found);
  533 }
  534 
  535 void ips_morpheus_intr(void *void_sc)
  536 {
  537         ips_softc_t *sc = void_sc;
  538 
  539         mtx_lock(&sc->queue_mtx);
  540         ips_morpheus_check_intr(sc);
  541         mtx_unlock(&sc->queue_mtx);
  542 }
  543 
  544 void ips_morpheus_poll(ips_command_t *command)
  545 {
  546         uint32_t ts;
  547 
  548         /*
  549          * Locks are not used here because this is only called during
  550          * crashdumps.
  551          */
  552         ts = time_second + command->timeout;
  553         while ((command->timeout != 0)
  554          && (ips_morpheus_check_intr(command->sc) == 0)
  555          && (ts > time_second))
  556                 DELAY(1000);
  557 }
  558 
  559 void ips_issue_morpheus_cmd(ips_command_t *command)
  560 {
  561         /* hmmm, is there a cleaner way to do this? */
  562         if(command->sc->state & IPS_OFFLINE){
  563                 ips_set_error(command, EINVAL);
  564                 command->callback(command);
  565                 return;
  566         }
  567         command->timeout = 10;
  568         ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
  569 }
  570 
  571 static void ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,int segnum, int error)
  572 {
  573         ips_copper_queue_t *queue = queueptr;
  574         if(error){
  575                 return;
  576         }
  577         queue->base_phys_addr = segments[0].ds_addr;
  578 }
  579 
  580 static int ips_copperhead_queue_init(ips_softc_t *sc)
  581 {
  582         int error;
  583         bus_dma_tag_t dmatag;
  584         bus_dmamap_t dmamap;
  585         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  586                                 /* alignemnt */ 1,
  587                                 /* boundary  */ 0,
  588                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  589                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  590                                 /* filter    */ NULL,
  591                                 /* filterarg */ NULL,
  592                                 /* maxsize   */ sizeof(ips_copper_queue_t),
  593                                 /* numsegs   */ 1,
  594                                 /* maxsegsize*/ sizeof(ips_copper_queue_t),
  595                                 /* flags     */ 0,
  596                                 /* lockfunc  */ NULL,
  597                                 /* lockarg   */ NULL,
  598                                 &dmatag) != 0) {
  599                 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
  600                 error = ENOMEM;
  601                 return error;
  602         }
  603         if(bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue), 
  604                             BUS_DMA_NOWAIT, &dmamap)){
  605                 error = ENOMEM;
  606                 goto exit;
  607         }
  608         bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
  609         sc->copper_queue->dmatag = dmatag;
  610         sc->copper_queue->dmamap = dmamap;
  611         sc->copper_queue->nextstatus = 1;
  612         bus_dmamap_load(dmatag, dmamap, 
  613                         &(sc->copper_queue->status[0]), IPS_MAX_CMD_NUM * 4, 
  614                         ips_copperhead_queue_callback, sc->copper_queue, 
  615                         BUS_DMA_NOWAIT);
  616         if(sc->copper_queue->base_phys_addr == 0){
  617                 error = ENOMEM;
  618                 goto exit;
  619         }
  620         ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
  621         ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr + 
  622                     IPS_MAX_CMD_NUM * 4);
  623         ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
  624         ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
  625 
  626         
  627         return 0;
  628 exit:
  629         if (sc->copper_queue != NULL)
  630                 bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
  631         bus_dma_tag_destroy(dmatag);
  632         return error;
  633 }
  634 
  635 /* see if we should reinitialize the card and wait for it to timeout or complete initialization FIXME */
  636 int ips_copperhead_reinit(ips_softc_t *sc, int force)
  637 {
  638         int i, j;
  639         u_int32_t postcode = 0, configstatus = 0;
  640         ips_write_1(sc, COPPER_REG_SCPR, 0x80);
  641         ips_write_1(sc, COPPER_REG_SCPR, 0);
  642         device_printf(sc->dev, "reinitializing adapter, this could take several minutes.\n");
  643         for(j = 0; j < 2; j++){
  644                 postcode <<= 8;
  645                 for(i = 0; i < 45; i++){
  646                         if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
  647                                 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
  648                                 ips_write_1(sc, COPPER_REG_HISR, 
  649                                             COPPER_GHI_BIT);
  650                                 break;
  651                         } else
  652                                 DELAY(1000000);
  653                 }
  654                 if(i == 45)
  655                         return 1;
  656         }
  657         for(j = 0; j < 2; j++){
  658                 configstatus <<= 8;
  659                 for(i = 0; i < 240; i++){
  660                         if(ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT){
  661                                 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
  662                                 ips_write_1(sc, COPPER_REG_HISR, 
  663                                             COPPER_GHI_BIT);
  664                                 break;
  665                         } else
  666                                 DELAY(1000000);
  667                 }
  668                 if(i == 240)
  669                         return 1;
  670         }
  671         for(i = 0; i < 240; i++){
  672                 if(!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT)){
  673                         break;
  674                 } else
  675                         DELAY(1000000);
  676         }
  677         if(i == 240)
  678                 return 1;
  679         ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
  680         ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
  681         ips_copperhead_queue_init(sc);
  682         ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
  683         i = ips_read_1(sc, COPPER_REG_SCPR);
  684         ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
  685         if(!configstatus){
  686                 device_printf(sc->dev, "adapter initialization failed\n");
  687                 return 1;
  688         }
  689         if(force && ips_clear_adapter(sc)){
  690                 device_printf(sc->dev, "adapter clear failed\n");
  691                 return 1;
  692         }
  693         return 0;
  694 }
  695 static u_int32_t ips_copperhead_cmd_status(ips_softc_t *sc)
  696 {
  697         u_int32_t value;
  698         int statnum = sc->copper_queue->nextstatus++;
  699         if(sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
  700                 sc->copper_queue->nextstatus = 0;
  701         value = sc->copper_queue->status[statnum];
  702         ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr + 
  703                     4 * statnum);
  704         return value;
  705 }
  706 
  707 
  708 void ips_copperhead_intr(void *void_sc)
  709 {
  710         ips_softc_t *sc = (ips_softc_t *)void_sc;
  711         int cmdnumber;
  712         ips_cmd_status_t status;
  713 
  714         mtx_lock(&sc->queue_mtx);
  715         while(ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT){
  716                 status.value = ips_copperhead_cmd_status(sc);
  717                 cmdnumber = status.fields.command_id;
  718                 sc->commandarray[cmdnumber].status.value = status.value;
  719                 sc->commandarray[cmdnumber].timeout = 0;
  720                 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
  721                 PRINTF(9, "ips: got command %d\n", cmdnumber);
  722         }
  723         mtx_unlock(&sc->queue_mtx);
  724         return;
  725 }
  726 
  727 void ips_issue_copperhead_cmd(ips_command_t *command)
  728 {
  729         int i;
  730         /* hmmm, is there a cleaner way to do this? */
  731         if(command->sc->state & IPS_OFFLINE){
  732                 ips_set_error(command, EINVAL);
  733                 command->callback(command);
  734                 return;
  735         }
  736         command->timeout = 10;
  737         for(i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
  738             i++ ){
  739                 if( i == 20){
  740 printf("sem bit still set, can't send a command\n");
  741                         return;
  742                 }
  743                 DELAY(500);/* need to do a delay here */
  744         }
  745         ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
  746         ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
  747 }
  748 
  749 void ips_copperhead_poll(ips_command_t *command)
  750 {
  751 
  752         printf("ips: cmd polling not implemented for copperhead devices\n");
  753 }

Cache object: 10a27b0045ebd25de8297d5f58c53164


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