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

Cache object: 314d4db8b2544824ae49db05039aaa68


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