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

Cache object: 295ea56a2f79e5c088f811793332f0ec


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