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

Cache object: f0700703dd27eaa3d7f5afffbd01b760


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