1 /*-
2 * Copyright (c) 2002 Adaptec Inc.
3 * All rights reserved.
4 *
5 * Written by: David Jeffery
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: releng/5.1/sys/dev/ips/ips_commands.c 114902 2003-05-11 06:36:49Z scottl $
29 */
30
31
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 ips_cmd_status_t *status;
44 status = command->arg;
45 status->value = command->status.value;
46 bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap,
47 BUS_DMASYNC_POSTWRITE);
48 mtx_lock(&command->sc->cmd_mtx);
49 wakeup(status);
50 mtx_unlock(&command->sc->cmd_mtx);
51 }
52 /* Below are a series of functions for sending an IO request
53 * to the adapter. The flow order is: start, send, callback, finish.
54 * The caller must have already assembled an iorequest struct to hold
55 * the details of the IO request. */
56 static void ips_io_request_finish(ips_command_t *command)
57 {
58
59 struct bio *iobuf = command->arg;
60 if(ips_read_request(iobuf)) {
61 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
62 BUS_DMASYNC_POSTREAD);
63 } else {
64 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
65 BUS_DMASYNC_POSTWRITE);
66 }
67 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
68 bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
69 if(COMMAND_ERROR(&command->status)){
70 iobuf->bio_flags |=BIO_ERROR;
71 iobuf->bio_error = EIO;
72 }
73 ips_insert_free_cmd(command->sc, command);
74 ipsd_finish(iobuf);
75 }
76
77 static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
78 {
79 ips_softc_t *sc;
80 ips_command_t *command = cmdptr;
81 ips_sg_element_t *sg_list;
82 ips_io_cmd *command_struct;
83 struct bio *iobuf = command->arg;
84 int i, length = 0;
85 u_int8_t cmdtype;
86
87 sc = command->sc;
88 if(error){
89 printf("ips: error = %d in ips_sg_request_callback\n", error);
90 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
91 bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
92 iobuf->bio_flags |= BIO_ERROR;
93 iobuf->bio_error = ENOMEM;
94 ips_insert_free_cmd(sc, command);
95 ipsd_finish(iobuf);
96 return;
97 }
98 command_struct = (ips_io_cmd *)command->command_buffer;
99 command_struct->id = command->id;
100 command_struct->drivenum = (uint32_t)iobuf->bio_driver1;
101 if(segnum != 1){
102 if(ips_read_request(iobuf))
103 cmdtype = IPS_SG_READ_CMD;
104 else
105 cmdtype = IPS_SG_WRITE_CMD;
106 command_struct->segnum = segnum;
107 sg_list = (ips_sg_element_t *)((u_int8_t *)
108 command->command_buffer + IPS_COMMAND_LEN);
109 for(i = 0; i < segnum; i++){
110 sg_list[i].addr = segments[i].ds_addr;
111 sg_list[i].len = segments[i].ds_len;
112 length += segments[i].ds_len;
113 }
114 command_struct->buffaddr =
115 (u_int32_t)command->command_phys_addr + IPS_COMMAND_LEN;
116 } else {
117 if(ips_read_request(iobuf))
118 cmdtype = IPS_READ_CMD;
119 else
120 cmdtype = IPS_WRITE_CMD;
121 command_struct->buffaddr = segments[0].ds_addr;
122 length = segments[0].ds_len;
123 }
124 command_struct->command = cmdtype;
125 command_struct->lba = iobuf->bio_pblkno;
126 length = (length + IPS_BLKSIZE - 1)/IPS_BLKSIZE;
127 command_struct->length = length;
128 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
129 BUS_DMASYNC_PREWRITE);
130 if(ips_read_request(iobuf)) {
131 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
132 BUS_DMASYNC_PREREAD);
133 } else {
134 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
135 BUS_DMASYNC_PREWRITE);
136 }
137 PRINTF(10, "ips test: command id: %d segments: %d blkno: %lld "
138 "pblkno: %lld length: %d, ds_len: %d\n", command->id, segnum,
139 iobuf->bio_blkno, iobuf->bio_pblkno,
140 length, segments[0].ds_len);
141
142 sc->ips_issue_cmd(command);
143 return;
144 }
145
146 static int ips_send_io_request(ips_command_t *command)
147 {
148 ips_softc_t *sc = command->sc;
149 struct bio *iobuf = command->arg;
150 command->data_dmatag = sc->sg_dmatag;
151 if(bus_dmamap_create(command->data_dmatag, 0, &command->data_dmamap)){
152 device_printf(sc->dev, "dmamap failed\n");
153 iobuf->bio_flags |= BIO_ERROR;
154 iobuf->bio_error = ENOMEM;
155 ips_insert_free_cmd(sc, command);
156 ipsd_finish(iobuf);
157 return 0;
158 }
159 command->callback = ips_io_request_finish;
160 PRINTF(10, "ips test: : bcount %ld\n", iobuf->bio_bcount);
161 bus_dmamap_load(command->data_dmatag, command->data_dmamap,
162 iobuf->bio_data, iobuf->bio_bcount,
163 ips_io_request_callback, command, 0);
164 return 0;
165 }
166
167 void ips_start_io_request(ips_softc_t *sc, struct bio *iobuf)
168 {
169 if(ips_get_free_cmd(sc, ips_send_io_request, iobuf, 0)){
170 device_printf(sc->dev, "no mem for command slots!\n");
171 iobuf->bio_flags |= BIO_ERROR;
172 iobuf->bio_error = ENOMEM;
173 ipsd_finish(iobuf);
174 return;
175 }
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 mtx_lock(&sc->cmd_mtx);
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 ((status->value == IPS_ERROR_STATUS) ||
244 (msleep(status, &sc->cmd_mtx, 0, "ips", 30*hz) == EWOULDBLOCK))
245 error = ETIMEDOUT;
246 mtx_unlock(&sc->cmd_mtx);
247
248 if (error == 0) {
249 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
250 BUS_DMASYNC_POSTREAD);
251 memcpy(&(sc->adapter_info), command->data_buffer,
252 IPS_ADAPTER_INFO_LEN);
253 }
254 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
255
256 exit:
257 /* I suppose I should clean up my memory allocations */
258 bus_dmamem_free(command->data_dmatag, command->data_buffer,
259 command->data_dmamap);
260 bus_dma_tag_destroy(command->data_dmatag);
261 ips_insert_free_cmd(sc, command);
262 return error;
263 }
264
265 int ips_get_adapter_info(ips_softc_t *sc)
266 {
267 int error = 0;
268 ips_cmd_status_t *status;
269 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
270 if(!status)
271 return ENOMEM;
272 if(ips_get_free_cmd(sc, ips_send_adapter_info_cmd, status,
273 IPS_NOWAIT_FLAG) > 0){
274 device_printf(sc->dev, "unable to get adapter configuration\n");
275 free(status, M_DEVBUF);
276 return ENXIO;
277 }
278 if(COMMAND_ERROR(status)){
279 error = ENXIO;
280 }
281 free(status, M_DEVBUF);
282 return error;
283 }
284
285 /* Below are a series of functions for sending a drive info request
286 * to the adapter. The flow order is: get, send, callback. It uses
287 * the generic finish callback at the top of this file.
288 * This can be used to get drive status info from the card */
289 static void ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
290 {
291 ips_softc_t *sc;
292 ips_command_t *command = cmdptr;
293 ips_drive_cmd *command_struct;
294 sc = command->sc;
295 if(error){
296 ips_cmd_status_t * status = command->arg;
297 status->value = IPS_ERROR_STATUS;
298 ips_insert_free_cmd(sc, command);
299 printf("ips: error = %d in ips_get_drive_info\n", error);
300 return;
301 }
302 command_struct = (ips_drive_cmd *)command->command_buffer;
303 command_struct->command = IPS_DRIVE_INFO_CMD;
304 command_struct->id = command->id;
305 command_struct->buffaddr = segments[0].ds_addr;
306
307 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
308 BUS_DMASYNC_PREWRITE);
309 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
310 BUS_DMASYNC_PREREAD);
311 sc->ips_issue_cmd(command);
312 }
313
314 static int ips_send_drive_info_cmd(ips_command_t *command)
315 {
316 int error = 0;
317 ips_softc_t *sc = command->sc;
318 ips_cmd_status_t *status = command->arg;
319 ips_drive_info_t *driveinfo;
320
321 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
322 /* alignemnt */ 1,
323 /* boundary */ 0,
324 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
325 /* highaddr */ BUS_SPACE_MAXADDR,
326 /* filter */ NULL,
327 /* filterarg */ NULL,
328 /* maxsize */ IPS_DRIVE_INFO_LEN,
329 /* numsegs */ 1,
330 /* maxsegsize*/ IPS_DRIVE_INFO_LEN,
331 /* flags */ 0,
332 &command->data_dmatag) != 0) {
333 printf("ips: can't alloc dma tag for drive status\n");
334 error = ENOMEM;
335 goto exit;
336 }
337 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer,
338 BUS_DMA_NOWAIT, &command->data_dmamap)){
339 error = ENOMEM;
340 goto exit;
341 }
342 command->callback = ips_wakeup_callback;
343 mtx_lock(&sc->cmd_mtx);
344 bus_dmamap_load(command->data_dmatag, command->data_dmamap,
345 command->data_buffer,IPS_DRIVE_INFO_LEN,
346 ips_drive_info_callback, command, BUS_DMA_NOWAIT);
347 if ((status->value == IPS_ERROR_STATUS) ||
348 (msleep(status, &sc->cmd_mtx, 0, "ips", 10*hz) == EWOULDBLOCK))
349 error = ETIMEDOUT;
350 mtx_unlock(&sc->cmd_mtx);
351
352 if (error == 0) {
353 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
354 BUS_DMASYNC_POSTREAD);
355 driveinfo = command->data_buffer;
356 memcpy(sc->drives, driveinfo->drives, sizeof(ips_drive_t) * 8);
357 sc->drivecount = driveinfo->drivecount;
358 device_printf(sc->dev, "logical drives: %d\n",sc->drivecount);
359 }
360 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
361
362 exit:
363 /* I suppose I should clean up my memory allocations */
364 bus_dmamem_free(command->data_dmatag, command->data_buffer,
365 command->data_dmamap);
366 bus_dma_tag_destroy(command->data_dmatag);
367 ips_insert_free_cmd(sc, command);
368 return error;
369
370 }
371 int ips_get_drive_info(ips_softc_t *sc)
372 {
373 int error = 0;
374 ips_cmd_status_t *status;
375 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
376 if(!status)
377 return ENOMEM;
378 if(ips_get_free_cmd(sc, ips_send_drive_info_cmd, status,
379 IPS_NOWAIT_FLAG) > 0){
380 free(status, M_DEVBUF);
381 device_printf(sc->dev, "unable to get drive configuration\n");
382 return ENXIO;
383 }
384 if(COMMAND_ERROR(status)){
385 error = ENXIO;
386 }
387 free(status, M_DEVBUF);
388 return error;
389 }
390
391 /* Below is a pair of functions for making sure data is safely
392 * on disk by flushing the adapter's cache. */
393 static int ips_send_flush_cache_cmd(ips_command_t *command)
394 {
395 ips_softc_t *sc = command->sc;
396 ips_cmd_status_t *status = command->arg;
397 ips_generic_cmd *command_struct;
398
399 PRINTF(10,"ips test: got a command, building flush command\n");
400 command->callback = ips_wakeup_callback;
401 command_struct = (ips_generic_cmd *)command->command_buffer;
402 command_struct->command = IPS_CACHE_FLUSH_CMD;
403 command_struct->id = command->id;
404 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
405 BUS_DMASYNC_PREWRITE);
406 mtx_lock(&sc->cmd_mtx);
407 sc->ips_issue_cmd(command);
408 if (status->value != IPS_ERROR_STATUS)
409 msleep(status, &sc->cmd_mtx, 0, "flush2", 0);
410 mtx_unlock(&sc->cmd_mtx);
411 ips_insert_free_cmd(sc, command);
412 return 0;
413 }
414
415 int ips_flush_cache(ips_softc_t *sc)
416 {
417 ips_cmd_status_t *status;
418 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
419 if(!status)
420 return ENOMEM;
421 device_printf(sc->dev, "flushing cache\n");
422 if(ips_get_free_cmd(sc, ips_send_flush_cache_cmd, status,
423 IPS_NOWAIT_FLAG)){
424 free(status, M_DEVBUF);
425 device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n");
426 }
427 if(COMMAND_ERROR(status)){
428 device_printf(sc->dev, "ERROR: cache flush command failed!\n");
429 }
430 free(status, M_DEVBUF);
431 return 0;
432 }
433
434 static void ips_write_nvram(ips_command_t *command){
435 ips_softc_t *sc = command->sc;
436 ips_rw_nvram_cmd *command_struct;
437 ips_nvram_page5 *nvram;
438
439 /*FIXME check for error */
440 command->callback = ips_wakeup_callback;
441 command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
442 command_struct->command = IPS_RW_NVRAM_CMD;
443 command_struct->id = command->id;
444 command_struct->pagenum = 5;
445 command_struct->rw = 1; /*write*/
446 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
447 BUS_DMASYNC_POSTREAD);
448 nvram = command->data_buffer;
449 strncpy(nvram->driver_high, IPS_VERSION_MAJOR, 4);
450 strncpy(nvram->driver_low, IPS_VERSION_MINOR, 4);
451 nvram->operating_system = IPS_OS_FREEBSD;
452 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
453 BUS_DMASYNC_PREWRITE);
454 sc->ips_issue_cmd(command);
455 }
456
457 static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
458 {
459 ips_softc_t *sc;
460 ips_command_t *command = cmdptr;
461 ips_rw_nvram_cmd *command_struct;
462 sc = command->sc;
463 if(error){
464 ips_cmd_status_t * status = command->arg;
465 status->value = IPS_ERROR_STATUS;
466 ips_insert_free_cmd(sc, command);
467 printf("ips: error = %d in ips_read_nvram_callback\n", error);
468 return;
469 }
470 command_struct = (ips_rw_nvram_cmd *)command->command_buffer;
471 command_struct->command = IPS_RW_NVRAM_CMD;
472 command_struct->id = command->id;
473 command_struct->pagenum = 5;
474 command_struct->rw = 0;
475 command_struct->buffaddr = segments[0].ds_addr;
476
477 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
478 BUS_DMASYNC_PREWRITE);
479 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
480 BUS_DMASYNC_PREREAD);
481 sc->ips_issue_cmd(command);
482 }
483
484 static int ips_read_nvram(ips_command_t *command){
485 int error = 0;
486 ips_softc_t *sc = command->sc;
487 ips_cmd_status_t *status = command->arg;
488
489 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag,
490 /* alignemnt */ 1,
491 /* boundary */ 0,
492 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT,
493 /* highaddr */ BUS_SPACE_MAXADDR,
494 /* filter */ NULL,
495 /* filterarg */ NULL,
496 /* maxsize */ IPS_NVRAM_PAGE_SIZE,
497 /* numsegs */ 1,
498 /* maxsegsize*/ IPS_NVRAM_PAGE_SIZE,
499 /* flags */ 0,
500 &command->data_dmatag) != 0) {
501 printf("ips: can't alloc dma tag for nvram\n");
502 error = ENOMEM;
503 goto exit;
504 }
505 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer,
506 BUS_DMA_NOWAIT, &command->data_dmamap)){
507 error = ENOMEM;
508 goto exit;
509 }
510 command->callback = ips_write_nvram;
511 mtx_lock(&sc->cmd_mtx);
512 bus_dmamap_load(command->data_dmatag, command->data_dmamap,
513 command->data_buffer,IPS_NVRAM_PAGE_SIZE,
514 ips_read_nvram_callback, command, BUS_DMA_NOWAIT);
515 if ((status->value == IPS_ERROR_STATUS) ||
516 (msleep(status, &sc->cmd_mtx, 0, "ips", 0) == EWOULDBLOCK))
517 error = ETIMEDOUT;
518 mtx_unlock(&sc->cmd_mtx);
519
520 if (error == 0) {
521 bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
522 BUS_DMASYNC_POSTWRITE);
523 }
524 bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
525
526 exit:
527 bus_dmamem_free(command->data_dmatag, command->data_buffer,
528 command->data_dmamap);
529 bus_dma_tag_destroy(command->data_dmatag);
530 ips_insert_free_cmd(sc, command);
531 return error;
532 }
533
534 int ips_update_nvram(ips_softc_t *sc)
535 {
536 ips_cmd_status_t *status;
537 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
538 if(!status)
539 return ENOMEM;
540 if(ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)){
541 free(status, M_DEVBUF);
542 device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n");
543 return 1;
544 }
545 if(COMMAND_ERROR(status)){
546 device_printf(sc->dev, "ERROR: nvram update command failed!\n");
547 }
548 free(status, M_DEVBUF);
549 return 0;
550
551
552 }
553
554
555 static int ips_send_config_sync_cmd(ips_command_t *command)
556 {
557 ips_softc_t *sc = command->sc;
558 ips_cmd_status_t *status = command->arg;
559 ips_generic_cmd *command_struct;
560
561 PRINTF(10,"ips test: got a command, building flush command\n");
562 command->callback = ips_wakeup_callback;
563 command_struct = (ips_generic_cmd *)command->command_buffer;
564 command_struct->command = IPS_CONFIG_SYNC_CMD;
565 command_struct->id = command->id;
566 command_struct->reserve2 = IPS_POCL;
567 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
568 BUS_DMASYNC_PREWRITE);
569 mtx_lock(&sc->cmd_mtx);
570 sc->ips_issue_cmd(command);
571 if (status->value != IPS_ERROR_STATUS)
572 msleep(status, &sc->cmd_mtx, 0, "ipssyn", 0);
573 mtx_unlock(&sc->cmd_mtx);
574 ips_insert_free_cmd(sc, command);
575 return 0;
576 }
577
578 static int ips_send_error_table_cmd(ips_command_t *command)
579 {
580 ips_softc_t *sc = command->sc;
581 ips_cmd_status_t *status = command->arg;
582 ips_generic_cmd *command_struct;
583
584 PRINTF(10,"ips test: got a command, building errortable command\n");
585 command->callback = ips_wakeup_callback;
586 command_struct = (ips_generic_cmd *)command->command_buffer;
587 command_struct->command = IPS_ERROR_TABLE_CMD;
588 command_struct->id = command->id;
589 command_struct->reserve2 = IPS_CSL;
590 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
591 BUS_DMASYNC_PREWRITE);
592 mtx_lock(&sc->cmd_mtx);
593 sc->ips_issue_cmd(command);
594 if (status->value != IPS_ERROR_STATUS)
595 msleep(status, &sc->cmd_mtx, 0, "ipsetc", 0);
596 mtx_unlock(&sc->cmd_mtx);
597 ips_insert_free_cmd(sc, command);
598 return 0;
599 }
600
601
602 int ips_clear_adapter(ips_softc_t *sc)
603 {
604 ips_cmd_status_t *status;
605 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT);
606 if(!status)
607 return ENOMEM;
608 device_printf(sc->dev, "syncing config\n");
609 if(ips_get_free_cmd(sc, ips_send_config_sync_cmd, status,
610 IPS_NOWAIT_FLAG)){
611 free(status, M_DEVBUF);
612 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
613 return 1;
614 }
615 if(COMMAND_ERROR(status)){
616 free(status, M_DEVBUF);
617 device_printf(sc->dev, "ERROR: cache sync command failed!\n");
618 return 1;
619 }
620
621 device_printf(sc->dev, "clearing error table\n");
622 if(ips_get_free_cmd(sc, ips_send_error_table_cmd, status,
623 IPS_NOWAIT_FLAG)){
624 free(status, M_DEVBUF);
625 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n");
626 return 1;
627 }
628 if(COMMAND_ERROR(status)){
629 device_printf(sc->dev, "ERROR: etable command failed!\n");
630 free(status, M_DEVBUF);
631 return 1;
632 }
633
634 free(status, M_DEVBUF);
635 return 0;
636 }
Cache object: a031609f999a923d900cc5fc0680e2e7
|