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

Cache object: 04565cd7ece783a5555671fd9c2c8395


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