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

Cache object: 24e71d19e63514730cd08e139b2e45d3


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