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_commands.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 #include <dev/ips/ips.h>
   31 
   32 /*
   33  * This is an interrupt callback.  It is called from
   34  * interrupt context when the adapter has completed the
   35  * command.  This very generic callback simply stores
   36  * the command's return value in command->arg and wake's
   37  * up anyone waiting on the command. 
   38  */
   39 static void ips_wakeup_callback(ips_command_t *command)
   40 {
   41         ips_cmd_status_t *status;
   42         status = command->arg;
   43         status->value = command->status.value;
   44         bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap, 
   45                         BUS_DMASYNC_POSTWRITE);
   46         wakeup(status);
   47 }
   48 /* Below are a series of functions for sending an IO request
   49  * to the adapter.  The flow order is: start, send, callback, finish.
   50  * The caller must have already assembled an iorequest struct to hold
   51  * the details of the IO request. */
   52 static void ips_io_request_finish(ips_command_t *command)
   53 {
   54 
   55         struct buf *iobuf = command->arg;
   56         if(ips_read_request(iobuf)) {
   57                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
   58                                 BUS_DMASYNC_POSTREAD);
   59         } else {
   60                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
   61                                 BUS_DMASYNC_POSTWRITE);
   62         }
   63         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
   64         bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
   65         if(COMMAND_ERROR(&command->status)){
   66                 iobuf->b_flags |=B_ERROR;
   67                 iobuf->b_error = EIO;
   68         }
   69         ips_insert_free_cmd(command->sc, command);
   70         ipsd_finish(iobuf);
   71 }
   72 
   73 static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
   74 {
   75         ips_softc_t *sc;
   76         ips_command_t *command = cmdptr;
   77         ips_sg_element_t *sg_list;
   78         ips_io_cmd *command_struct;
   79         struct buf *iobuf = command->arg;
   80         int i, length = 0;
   81         u_int8_t cmdtype;
   82 
   83         sc = command->sc;
   84         if(error){
   85                 printf("ips: error = %d in ips_sg_request_callback\n", error);
   86                 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
   87                 bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
   88                 iobuf->b_flags |= B_ERROR;
   89                 iobuf->b_error = ENOMEM;
   90                 ips_insert_free_cmd(sc, command);
   91                 ipsd_finish(iobuf);
   92                 return;
   93         }
   94         command_struct = (ips_io_cmd *)command->command_buffer;
   95         command_struct->id = command->id;
   96         command_struct->drivenum = (uintptr_t)iobuf->b_driver1;
   97         if(segnum != 1){
   98                 if(ips_read_request(iobuf))
   99                         cmdtype = IPS_SG_READ_CMD;
  100                 else
  101                         cmdtype = IPS_SG_WRITE_CMD;
  102                 command_struct->segnum = segnum;
  103                 sg_list = (ips_sg_element_t *)((u_int8_t *)
  104                            command->command_buffer + IPS_COMMAND_LEN);
  105                 for(i = 0; i < segnum; i++){
  106                         sg_list[i].addr = segments[i].ds_addr;
  107                         sg_list[i].len = segments[i].ds_len;
  108                         length += segments[i].ds_len;
  109                 }
  110                 command_struct->buffaddr = 
  111                     (u_int32_t)command->command_phys_addr + IPS_COMMAND_LEN;
  112         } else {
  113                 if(ips_read_request(iobuf))
  114                         cmdtype = IPS_READ_CMD;
  115                 else
  116                         cmdtype = IPS_WRITE_CMD;
  117                 command_struct->buffaddr = segments[0].ds_addr;
  118                 length = segments[0].ds_len;
  119         }
  120         command_struct->command = cmdtype;
  121         command_struct->lba = iobuf->b_pblkno;
  122         length = (length + IPS_BLKSIZE - 1)/IPS_BLKSIZE;
  123         command_struct->length = length;
  124         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  125                         BUS_DMASYNC_PREWRITE);
  126         if(ips_read_request(iobuf)) {
  127                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  128                                 BUS_DMASYNC_PREREAD);
  129         } else {
  130                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  131                                 BUS_DMASYNC_PREWRITE);
  132         }
  133         PRINTF(10, "ips test: command id: %d segments: %d "
  134                 "pblkno: %lld length: %d, ds_len: %d\n", command->id, segnum,
  135                 iobuf->b_pblkno, length, segments[0].ds_len);
  136 
  137         sc->ips_issue_cmd(command);
  138         return;
  139 }
  140 
  141 static int ips_send_io_request(ips_command_t *command)
  142 {
  143         ips_softc_t *sc = command->sc;
  144         struct buf *iobuf = command->arg;
  145         command->data_dmatag = sc->sg_dmatag;
  146         if(bus_dmamap_create(command->data_dmatag, 0, &command->data_dmamap)){
  147                 device_printf(sc->dev, "dmamap failed\n");
  148                 iobuf->b_flags |= B_ERROR;
  149                 iobuf->b_error = ENOMEM;
  150                 ips_insert_free_cmd(sc, command);
  151                 ipsd_finish(iobuf);
  152                 return 0;
  153         }
  154         command->callback = ips_io_request_finish;
  155         PRINTF(10, "ips test: : bcount %ld\n", iobuf->b_bcount);
  156         bus_dmamap_load(command->data_dmatag, command->data_dmamap,
  157                         iobuf->b_data, iobuf->b_bcount,
  158                         ips_io_request_callback, command, 0);
  159         return 0;
  160 } 
  161 
  162 void ips_start_io_request(ips_softc_t *sc)
  163 {
  164         struct buf *iobuf;
  165 
  166         iobuf = bufq_first(&sc->queue);
  167         if(!iobuf) {
  168                 return;
  169         }
  170 
  171         if(ips_get_free_cmd(sc, ips_send_io_request, iobuf, IPS_NOWAIT_FLAG)){
  172                 return;
  173         }
  174         
  175         bufq_remove(&sc->queue, iobuf);
  176         return;
  177 }
  178 
  179 /* Below are a series of functions for sending an adapter info request 
  180  * to the adapter.  The flow order is: get, send, callback. It uses
  181  * the generic finish callback at the top of this file. 
  182  * This can be used to get configuration/status info from the card */
  183 static void ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  184 {
  185         ips_softc_t *sc;
  186         ips_command_t *command = cmdptr;
  187         ips_adapter_info_cmd *command_struct;
  188         sc = command->sc;
  189         if(error){
  190                 ips_cmd_status_t * status = command->arg;
  191                 status->value = IPS_ERROR_STATUS; /* a lovely error value */
  192                 ips_insert_free_cmd(sc, command);
  193                 printf("ips: error = %d in ips_get_adapter_info\n", error);
  194                 return;
  195         }
  196         command_struct = (ips_adapter_info_cmd *)command->command_buffer;
  197         command_struct->command = IPS_ADAPTER_INFO_CMD;
  198         command_struct->id = command->id;
  199         command_struct->buffaddr = segments[0].ds_addr;
  200 
  201         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  202                         BUS_DMASYNC_PREWRITE);
  203         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  204                         BUS_DMASYNC_PREREAD);
  205         sc->ips_issue_cmd(command);
  206 }
  207 
  208 
  209 
  210 static int ips_send_adapter_info_cmd(ips_command_t *command)
  211 {
  212         int error = 0;
  213         ips_softc_t *sc = command->sc;
  214         ips_cmd_status_t *status = command->arg;
  215 
  216         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  217                                 /* alignemnt */ 1,
  218                                 /* boundary  */ 0,
  219                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  220                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  221                                 /* filter    */ NULL,
  222                                 /* filterarg */ NULL,
  223                                 /* maxsize   */ IPS_ADAPTER_INFO_LEN,
  224                                 /* numsegs   */ 1,
  225                                 /* maxsegsize*/ IPS_ADAPTER_INFO_LEN,
  226                                 /* flags     */ 0,
  227                                 &command->data_dmatag) != 0) {
  228                 printf("ips: can't alloc dma tag for adapter status\n");
  229                 error = ENOMEM;
  230                 goto exit;
  231         }
  232         if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 
  233            BUS_DMA_NOWAIT, &command->data_dmamap)){
  234                 error = ENOMEM;
  235                 goto exit;
  236         }
  237         command->callback = ips_wakeup_callback;
  238         asleep(status, 0, "ips", 30*hz);
  239         bus_dmamap_load(command->data_dmatag, command->data_dmamap, 
  240                         command->data_buffer,IPS_ADAPTER_INFO_LEN, 
  241                         ips_adapter_info_callback, command, BUS_DMA_NOWAIT);
  242 
  243         if (await(-1, -1))
  244                 error = ETIMEDOUT;
  245         else {
  246                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  247                                 BUS_DMASYNC_POSTREAD);
  248                 memcpy(&(sc->adapter_info), command->data_buffer, 
  249                         IPS_ADAPTER_INFO_LEN);
  250         }
  251         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
  252 
  253 exit:
  254         /* I suppose I should clean up my memory allocations */
  255         bus_dmamem_free(command->data_dmatag, command->data_buffer, 
  256                         command->data_dmamap);
  257         bus_dma_tag_destroy(command->data_dmatag);
  258         ips_insert_free_cmd(sc, command);
  259         return error;
  260 }
  261 
  262 int ips_get_adapter_info(ips_softc_t *sc)
  263 {
  264         int error = 0;
  265         ips_cmd_status_t *status;
  266         status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
  267         if(!status)
  268                 return ENOMEM;
  269         if(ips_get_free_cmd(sc, ips_send_adapter_info_cmd, status, 
  270                             IPS_NOWAIT_FLAG) > 0){
  271                 device_printf(sc->dev, "unable to get adapter configuration\n");
  272                 free(status, M_IPSBUF);
  273                 return ENXIO;
  274         }
  275         if (COMMAND_ERROR(status)){
  276                 error = ENXIO;
  277         }
  278         free(status, M_IPSBUF);
  279         return error;
  280 }
  281 
  282 /* Below are a series of functions for sending a drive info request 
  283  * to the adapter.  The flow order is: get, send, callback. It uses
  284  * the generic finish callback at the top of this file. 
  285  * This can be used to get drive status info from the card */
  286 static void ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  287 {
  288         ips_softc_t *sc;
  289         ips_command_t *command = cmdptr;
  290         ips_drive_cmd *command_struct;
  291         sc = command->sc;
  292         if(error){
  293                 ips_cmd_status_t * status = command->arg;
  294                 status->value = IPS_ERROR_STATUS;
  295                 ips_insert_free_cmd(sc, command);
  296                 printf("ips: error = %d in ips_get_drive_info\n", error);
  297                 return;
  298         }
  299         command_struct = (ips_drive_cmd *)command->command_buffer;
  300         command_struct->command = IPS_DRIVE_INFO_CMD;
  301         command_struct->id = command->id;
  302         command_struct->buffaddr = segments[0].ds_addr;
  303 
  304         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  305                         BUS_DMASYNC_PREWRITE);
  306         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  307                         BUS_DMASYNC_PREREAD);
  308         sc->ips_issue_cmd(command);
  309 }
  310 
  311 static int ips_send_drive_info_cmd(ips_command_t *command)
  312 {
  313         int error = 0;
  314         ips_softc_t *sc = command->sc;
  315         ips_cmd_status_t *status = command->arg;
  316         ips_drive_info_t *driveinfo;
  317 
  318         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  319                                 /* alignemnt */ 1,
  320                                 /* boundary  */ 0,
  321                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  322                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  323                                 /* filter    */ NULL,
  324                                 /* filterarg */ NULL,
  325                                 /* maxsize   */ IPS_DRIVE_INFO_LEN,
  326                                 /* numsegs   */ 1,
  327                                 /* maxsegsize*/ IPS_DRIVE_INFO_LEN,
  328                                 /* flags     */ 0,
  329                                 &command->data_dmatag) != 0) {
  330                 printf("ips: can't alloc dma tag for drive status\n");
  331                 error = ENOMEM;
  332                 goto exit;
  333         }
  334         if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 
  335                             BUS_DMA_NOWAIT, &command->data_dmamap)){
  336                 error = ENOMEM;
  337                 goto exit;
  338         }
  339         command->callback = ips_wakeup_callback;
  340         asleep(status, 0, "ips", 10*hz);
  341         bus_dmamap_load(command->data_dmatag, command->data_dmamap, 
  342                         command->data_buffer,IPS_DRIVE_INFO_LEN, 
  343                         ips_drive_info_callback, command, BUS_DMA_NOWAIT);
  344         if (await(-1, -1))
  345                 error = ETIMEDOUT;
  346         else {
  347                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  348                                 BUS_DMASYNC_POSTREAD);
  349                 driveinfo = command->data_buffer;
  350                 memcpy(sc->drives, driveinfo->drives, sizeof(ips_drive_t) * 8); 
  351                 sc->drivecount = driveinfo->drivecount;
  352                 device_printf(sc->dev, "logical drives: %d\n",sc->drivecount);
  353         }
  354         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
  355 
  356 exit:
  357         /* I suppose I should clean up my memory allocations */
  358         bus_dmamem_free(command->data_dmatag, command->data_buffer, 
  359                         command->data_dmamap);
  360         bus_dma_tag_destroy(command->data_dmatag);
  361         ips_insert_free_cmd(sc, command);
  362         return error;
  363 
  364 }
  365 int ips_get_drive_info(ips_softc_t *sc)
  366 {
  367         int error = 0;
  368         ips_cmd_status_t *status;
  369         status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
  370         if(!status)
  371                 return ENOMEM;
  372         if(ips_get_free_cmd(sc, ips_send_drive_info_cmd, status, 
  373                             IPS_NOWAIT_FLAG) > 0){
  374                 free(status, M_IPSBUF);
  375                 device_printf(sc->dev, "unable to get drive configuration\n");
  376                 return ENXIO;
  377         }
  378         if(COMMAND_ERROR(status)){
  379                 error = ENXIO;
  380         }
  381         free(status, M_IPSBUF);
  382         return error;
  383 }
  384 
  385 /* Below is a pair of functions for making sure data is safely
  386  * on disk by flushing the adapter's cache. */
  387 static int ips_send_flush_cache_cmd(ips_command_t *command)
  388 {
  389         ips_softc_t *sc = command->sc;
  390         ips_cmd_status_t *status = command->arg;
  391         ips_generic_cmd *command_struct;
  392 
  393         PRINTF(10,"ips test: got a command, building flush command\n");
  394         command->callback = ips_wakeup_callback;
  395         command_struct = (ips_generic_cmd *)command->command_buffer;
  396         command_struct->command = IPS_CACHE_FLUSH_CMD;
  397         command_struct->id = command->id;
  398         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  399                         BUS_DMASYNC_PREWRITE);
  400         asleep(status, 0, "slush2", 0);
  401         sc->ips_issue_cmd(command);
  402         await(-1, -1);
  403         ips_insert_free_cmd(sc, command);
  404         return 0;
  405 }
  406 
  407 int ips_flush_cache(ips_softc_t *sc)
  408 {
  409         ips_cmd_status_t *status;
  410         status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
  411         if(!status)
  412                 return ENOMEM;
  413         device_printf(sc->dev, "flushing cache\n");
  414         if(ips_get_free_cmd(sc, ips_send_flush_cache_cmd, status, 
  415                             IPS_NOWAIT_FLAG)){
  416                 free(status, M_IPSBUF);
  417                 device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n");
  418         }
  419         if(COMMAND_ERROR(status)){
  420                 device_printf(sc->dev, "ERROR: cache flush command failed!\n");
  421         }
  422         free(status, M_IPSBUF);
  423         return 0;
  424 }
  425 
  426 /* Simplified localtime to provide timevalues for ffdc.
  427  * Taken from libc/stdtime/localtime.c
  428  */
  429 void static ips_ffdc_settime(ips_adapter_ffdc_cmd *command, time_t sctime)
  430 {
  431         long    days, rem, y;
  432         int     yleap, *ip, month;
  433         int     year_lengths[2] = { IPS_DAYSPERNYEAR, IPS_DAYSPERLYEAR };
  434         int     mon_lengths[2][IPS_MONSPERYEAR] = {
  435                 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  436                 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  437         };
  438 
  439         days = sctime / IPS_SECSPERDAY;
  440         rem  = sctime % IPS_SECSPERDAY;
  441 
  442         command->hour = rem / IPS_SECSPERHOUR;
  443         rem           = rem % IPS_SECSPERHOUR;
  444 
  445         command->minute = rem / IPS_SECSPERMIN;
  446         command->second = rem % IPS_SECSPERMIN;
  447 
  448         y = IPS_EPOCH_YEAR;
  449         while (days < 0 || days >= (long) year_lengths[yleap = ips_isleap(y)]) {
  450                 long    newy;
  451 
  452                 newy = y + days / IPS_DAYSPERNYEAR;
  453                 if (days < 0)
  454                         --newy;
  455                 days -= (newy - y) * IPS_DAYSPERNYEAR +
  456                         IPS_LEAPS_THRU_END_OF(newy - 1) -
  457                         IPS_LEAPS_THRU_END_OF(y - 1);
  458                 y = newy;
  459         }
  460         command->yearH = y / 100;
  461         command->yearL = y % 100;
  462         ip = mon_lengths[yleap];
  463         for(month = 0; days >= (long) ip[month]; ++month)
  464                 days = days - (long) ip[month];
  465         command->month = month + 1;
  466         command->day = days + 1;
  467 }
  468 
  469 static int ips_send_ffdc_reset_cmd(ips_command_t *command)
  470 {
  471         ips_softc_t *sc = command->sc;
  472         ips_cmd_status_t *status = command->arg;
  473         ips_adapter_ffdc_cmd *command_struct;
  474 
  475         PRINTF(10,"ips test: got a command, building ffdc reset command\n");
  476         command->callback = ips_wakeup_callback;
  477         command_struct = (ips_adapter_ffdc_cmd *)command->command_buffer;
  478         command_struct->command = IPS_FFDC_CMD;
  479         command_struct->id = command->id;
  480         command_struct->reset_count = sc->ffdc_resetcount;
  481         command_struct->reset_type  = 0x0;
  482         ips_ffdc_settime(command_struct, sc->ffdc_resettime.tv_sec);
  483 
  484         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
  485                         BUS_DMASYNC_PREWRITE);
  486         asleep(status, 0, "ips_ffdc", 0);
  487         sc->ips_issue_cmd(command);
  488         await(-1, -1);
  489         ips_insert_free_cmd(sc, command);
  490         return 0;
  491 }
  492 
  493 int ips_ffdc_reset(ips_softc_t *sc)
  494 {
  495         ips_cmd_status_t *status;
  496         status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
  497         if(!status)
  498                 return ENOMEM;
  499         if(ips_get_free_cmd(sc, ips_send_ffdc_reset_cmd, status,
  500                             IPS_NOWAIT_FLAG)){
  501                 free(status, M_IPSBUF);
  502                 device_printf(sc->dev, "ERROR: unable to get a command! can't send ffdc reset!\n");
  503         }
  504         if(COMMAND_ERROR(status)){
  505                 device_printf(sc->dev, "ERROR: ffdc reset command failed!\n");
  506         }
  507         free(status, M_IPSBUF);
  508         return 0;
  509 }
  510 
  511 static void ips_write_nvram(ips_command_t *command){
  512         ips_softc_t *sc = command->sc;
  513         ips_rw_nvram_cmd *command_struct;
  514         ips_nvram_page5 *nvram;
  515 
  516         /*FIXME check for error */
  517         command->callback = ips_wakeup_callback;
  518         command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
  519         command_struct->command = IPS_RW_NVRAM_CMD;
  520         command_struct->id = command->id;
  521         command_struct->pagenum = 5;
  522         command_struct->rw      = 1; /*write*/
  523         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  524                                 BUS_DMASYNC_POSTREAD);
  525         nvram = command->data_buffer;
  526         /* retrieve adapter info and save in sc */
  527         sc->adapter_type = nvram->adapter_type;
  528 
  529         strncpy(nvram->driver_high, IPS_VERSION_MAJOR, 4);
  530         strncpy(nvram->driver_low, IPS_VERSION_MINOR, 4);
  531         nvram->operating_system = IPS_OS_FREEBSD;       
  532         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  533                         BUS_DMASYNC_PREWRITE);
  534         sc->ips_issue_cmd(command);
  535 }
  536 
  537 static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
  538 {
  539         ips_softc_t *sc;
  540         ips_command_t *command = cmdptr;
  541         ips_rw_nvram_cmd *command_struct;
  542         sc = command->sc;
  543         if(error){
  544                 ips_cmd_status_t * status = command->arg;
  545                 status->value = IPS_ERROR_STATUS;
  546                 ips_insert_free_cmd(sc, command);
  547                 printf("ips: error = %d in ips_read_nvram_callback\n", error);
  548                 return;
  549         }
  550         command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
  551         command_struct->command = IPS_RW_NVRAM_CMD;
  552         command_struct->id = command->id;
  553         command_struct->pagenum = 5;
  554         command_struct->rw = 0;
  555         command_struct->buffaddr = segments[0].ds_addr;
  556 
  557         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  558                         BUS_DMASYNC_PREWRITE);
  559         bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  560                         BUS_DMASYNC_PREREAD);
  561         sc->ips_issue_cmd(command);
  562 }
  563 
  564 static int ips_read_nvram(ips_command_t *command){
  565         int error = 0;
  566         ips_softc_t *sc = command->sc;
  567         ips_cmd_status_t *status = command->arg;
  568 
  569         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
  570                                 /* alignemnt */ 1,
  571                                 /* boundary  */ 0,
  572                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
  573                                 /* highaddr  */ BUS_SPACE_MAXADDR,
  574                                 /* filter    */ NULL,
  575                                 /* filterarg */ NULL,
  576                                 /* maxsize   */ IPS_NVRAM_PAGE_SIZE,
  577                                 /* numsegs   */ 1,
  578                                 /* maxsegsize*/ IPS_NVRAM_PAGE_SIZE,
  579                                 /* flags     */ 0,
  580                                 &command->data_dmatag) != 0) {
  581                 printf("ips: can't alloc dma tag for nvram\n");
  582                 error = ENOMEM;
  583                 goto exit;
  584         }
  585         if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 
  586                             BUS_DMA_NOWAIT, &command->data_dmamap)){
  587                 error = ENOMEM;
  588                 goto exit;
  589         }
  590         command->callback = ips_write_nvram;
  591         asleep(status, 0, "ips", 0);
  592         bus_dmamap_load(command->data_dmatag, command->data_dmamap, 
  593                         command->data_buffer,IPS_NVRAM_PAGE_SIZE, 
  594                         ips_read_nvram_callback, command, BUS_DMA_NOWAIT);
  595         if (await(-1, -1))
  596                 error = ETIMEDOUT;
  597         else {
  598                 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 
  599                                 BUS_DMASYNC_POSTWRITE);
  600         }
  601         bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
  602 
  603 exit:
  604         bus_dmamem_free(command->data_dmatag, command->data_buffer, 
  605                         command->data_dmamap);
  606         bus_dma_tag_destroy(command->data_dmatag);
  607         ips_insert_free_cmd(sc, command);
  608         return error;
  609 }
  610 
  611 int ips_update_nvram(ips_softc_t *sc)
  612 {
  613         ips_cmd_status_t *status;
  614         status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
  615         if(!status)
  616                 return ENOMEM;
  617         if(ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)){
  618                 free(status, M_IPSBUF);
  619                 device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n");
  620                 return 1;
  621         }
  622         if(COMMAND_ERROR(status)){
  623                 device_printf(sc->dev, "ERROR: nvram update command failed!\n");
  624         }
  625         free(status, M_IPSBUF);
  626         return 0;
  627 
  628 
  629 }
  630 
  631 
  632 static int ips_send_config_sync_cmd(ips_command_t *command)
  633 {
  634         ips_softc_t *sc = command->sc;
  635         ips_cmd_status_t *status = command->arg;
  636         ips_generic_cmd *command_struct;
  637 
  638         PRINTF(10,"ips test: got a command, building flush command\n");
  639         command->callback = ips_wakeup_callback;
  640         command_struct = (ips_generic_cmd *)command->command_buffer;
  641         command_struct->command = IPS_CONFIG_SYNC_CMD;
  642         command_struct->id = command->id;
  643         command_struct->reserve2 = IPS_POCL;
  644         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  645                         BUS_DMASYNC_PREWRITE);
  646         asleep(status, 0, "ipssyn", 0);
  647         sc->ips_issue_cmd(command);
  648         await(-1, -1);
  649         ips_insert_free_cmd(sc, command);
  650         return 0;
  651 }
  652 
  653 static int ips_send_error_table_cmd(ips_command_t *command)
  654 {
  655         ips_softc_t *sc = command->sc;
  656         ips_cmd_status_t *status = command->arg;
  657         ips_generic_cmd *command_struct;
  658 
  659         PRINTF(10,"ips test: got a command, building errortable command\n");
  660         command->callback = ips_wakeup_callback;
  661         command_struct = (ips_generic_cmd *)command->command_buffer;
  662         command_struct->command = IPS_ERROR_TABLE_CMD;
  663         command_struct->id = command->id;
  664         command_struct->reserve2 = IPS_CSL;
  665         bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 
  666                         BUS_DMASYNC_PREWRITE);
  667         asleep(status, 0, "ipsetc", 0);
  668         sc->ips_issue_cmd(command);
  669         await(-1, -1);
  670         ips_insert_free_cmd(sc, command);
  671         return 0;
  672 }
  673 
  674 
  675 int ips_clear_adapter(ips_softc_t *sc)
  676 {
  677         ips_cmd_status_t *status;
  678         status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO);
  679         if(!status)
  680                 return ENOMEM;
  681         device_printf(sc->dev, "syncing config\n");
  682         if(ips_get_free_cmd(sc, ips_send_config_sync_cmd, status, 
  683                             IPS_NOWAIT_FLAG)){
  684                 free(status, M_IPSBUF);
  685                 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
  686                 return 1;
  687         }
  688         if(COMMAND_ERROR(status)){
  689                 free(status, M_IPSBUF);
  690                 device_printf(sc->dev, "ERROR: cache sync command failed!\n");
  691                 return 1;
  692         }
  693 
  694         device_printf(sc->dev, "clearing error table\n");
  695         if(ips_get_free_cmd(sc, ips_send_error_table_cmd, status, 
  696                             IPS_NOWAIT_FLAG)){
  697                 free(status, M_IPSBUF);
  698                 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
  699                 return 1;
  700         }
  701         if(COMMAND_ERROR(status)){
  702                 device_printf(sc->dev, "ERROR: etable command failed!\n");
  703                 free(status, M_IPSBUF);
  704                 return 1;
  705         }
  706 
  707         free(status, M_IPSBUF);
  708         return 0;
  709 }

Cache object: ce78f60dc91880b0eb102a87bb485f57


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