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

Cache object: 8140ff9aee74d3e68aa518a913c7d6d8


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