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

Cache object: 7b012eb7fe8fa2b5f881d7abbda53e37


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