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