dpt_scsi.c (232185) | dpt_scsi.c (241593) |
---|---|
1/*- 2 * Copyright (c) 1997 by Simon Shapiro 3 * All Rights Reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 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> | 1/*- 2 * Copyright (c) 1997 by Simon Shapiro 3 * All Rights Reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 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: head/sys/dev/dpt/dpt_scsi.c 232185 2012-02-26 16:05:20Z kevlo $"); | 31__FBSDID("$FreeBSD: head/sys/dev/dpt/dpt_scsi.c 241593 2012-10-15 16:29:08Z jhb $"); |
32 33/* 34 * dpt_scsi.c: SCSI dependant code for the DPT driver 35 * 36 * credits: Assisted by Mike Neuffer in the early low level DPT code 37 * Thanx to Mark Salyzyn of DPT for his assistance. 38 * Special thanx to Justin Gibbs for invaluable help in 39 * making this driver look and work like a FreeBSD component. --- 8 unchanged lines hidden (view full) --- 48 49#define _DPT_C_ 50 51#include "opt_dpt.h" 52#include "opt_eisa.h" 53 54#include <sys/param.h> 55#include <sys/systm.h> | 32 33/* 34 * dpt_scsi.c: SCSI dependant code for the DPT driver 35 * 36 * credits: Assisted by Mike Neuffer in the early low level DPT code 37 * Thanx to Mark Salyzyn of DPT for his assistance. 38 * Special thanx to Justin Gibbs for invaluable help in 39 * making this driver look and work like a FreeBSD component. --- 8 unchanged lines hidden (view full) --- 48 49#define _DPT_C_ 50 51#include "opt_dpt.h" 52#include "opt_eisa.h" 53 54#include <sys/param.h> 55#include <sys/systm.h> |
56#include <sys/conf.h> |
|
56#include <sys/eventhandler.h> 57#include <sys/malloc.h> 58#include <sys/kernel.h> 59 60#include <sys/bus.h> 61 62#include <machine/bus.h> 63 --- 10 unchanged lines hidden (view full) --- 74#include <cam/scsi/scsi_message.h> 75 76#include <vm/vm.h> 77#include <vm/pmap.h> 78 79#include <dev/dpt/dpt.h> 80 81/* dpt_isa.c, dpt_eisa.c, and dpt_pci.c need this in a central place */ | 57#include <sys/eventhandler.h> 58#include <sys/malloc.h> 59#include <sys/kernel.h> 60 61#include <sys/bus.h> 62 63#include <machine/bus.h> 64 --- 10 unchanged lines hidden (view full) --- 75#include <cam/scsi/scsi_message.h> 76 77#include <vm/vm.h> 78#include <vm/pmap.h> 79 80#include <dev/dpt/dpt.h> 81 82/* dpt_isa.c, dpt_eisa.c, and dpt_pci.c need this in a central place */ |
82int dpt_controllers_present; | |
83devclass_t dpt_devclass; 84 85#define microtime_now dpt_time_now() 86 87#define dpt_inl(dpt, port) \ | 83devclass_t dpt_devclass; 84 85#define microtime_now dpt_time_now() 86 87#define dpt_inl(dpt, port) \ |
88 bus_space_read_4((dpt)->tag, (dpt)->bsh, port) | 88 bus_read_4((dpt)->io_res, (dpt)->io_offset + port) |
89#define dpt_inb(dpt, port) \ | 89#define dpt_inb(dpt, port) \ |
90 bus_space_read_1((dpt)->tag, (dpt)->bsh, port) | 90 bus_read_1((dpt)->io_res, (dpt)->io_offset + port) |
91#define dpt_outl(dpt, port, value) \ | 91#define dpt_outl(dpt, port, value) \ |
92 bus_space_write_4((dpt)->tag, (dpt)->bsh, port, value) | 92 bus_write_4((dpt)->io_res, (dpt)->io_offset + port, value) |
93#define dpt_outb(dpt, port, value) \ | 93#define dpt_outb(dpt, port, value) \ |
94 bus_space_write_1((dpt)->tag, (dpt)->bsh, port, value) | 94 bus_write_1((dpt)->io_res, (dpt)->io_offset + port, value) |
95 96/* 97 * These will have to be setup by parameters passed at boot/load time. For 98 * perfromance reasons, we make them constants for the time being. 99 */ 100#define dpt_min_segs DPT_MAX_SEGS 101#define dpt_max_segs DPT_MAX_SEGS 102 --- 34 unchanged lines hidden (view full) --- 137static int dpt_get_conf(dpt_softc_t *dpt, dpt_ccb_t *dccb, 138 u_int32_t dccb_busaddr, u_int size, 139 u_int page, u_int target, int extent); 140static void dpt_detect_cache(dpt_softc_t *dpt, dpt_ccb_t *dccb, 141 u_int32_t dccb_busaddr, 142 u_int8_t *buff); 143 144static void dpt_poll(struct cam_sim *sim); | 95 96/* 97 * These will have to be setup by parameters passed at boot/load time. For 98 * perfromance reasons, we make them constants for the time being. 99 */ 100#define dpt_min_segs DPT_MAX_SEGS 101#define dpt_max_segs DPT_MAX_SEGS 102 --- 34 unchanged lines hidden (view full) --- 137static int dpt_get_conf(dpt_softc_t *dpt, dpt_ccb_t *dccb, 138 u_int32_t dccb_busaddr, u_int size, 139 u_int page, u_int target, int extent); 140static void dpt_detect_cache(dpt_softc_t *dpt, dpt_ccb_t *dccb, 141 u_int32_t dccb_busaddr, 142 u_int8_t *buff); 143 144static void dpt_poll(struct cam_sim *sim); |
145static void dpt_intr_locked(dpt_softc_t *dpt); |
|
145 146static void dptexecuteccb(void *arg, bus_dma_segment_t *dm_segs, 147 int nseg, int error); 148 149static void dpt_action(struct cam_sim *sim, union ccb *ccb); 150 151static int dpt_send_eata_command(dpt_softc_t *dpt, eata_ccb_t *cmd, 152 u_int32_t cmd_busaddr, --- 64 unchanged lines hidden (view full) --- 217 } 218 return (-1); 219} 220 221static __inline struct dpt_ccb* 222dptgetccb(struct dpt_softc *dpt) 223{ 224 struct dpt_ccb* dccb; | 146 147static void dptexecuteccb(void *arg, bus_dma_segment_t *dm_segs, 148 int nseg, int error); 149 150static void dpt_action(struct cam_sim *sim, union ccb *ccb); 151 152static int dpt_send_eata_command(dpt_softc_t *dpt, eata_ccb_t *cmd, 153 u_int32_t cmd_busaddr, --- 64 unchanged lines hidden (view full) --- 218 } 219 return (-1); 220} 221 222static __inline struct dpt_ccb* 223dptgetccb(struct dpt_softc *dpt) 224{ 225 struct dpt_ccb* dccb; |
225 int s; | |
226 | 226 |
227 s = splcam(); | 227 if (!dumping) 228 mtx_assert(&dpt->lock, MA_OWNED); |
228 if ((dccb = SLIST_FIRST(&dpt->free_dccb_list)) != NULL) { 229 SLIST_REMOVE_HEAD(&dpt->free_dccb_list, links); 230 dpt->free_dccbs--; 231 } else if (dpt->total_dccbs < dpt->max_dccbs) { 232 dptallocccbs(dpt); 233 dccb = SLIST_FIRST(&dpt->free_dccb_list); 234 if (dccb == NULL) | 229 if ((dccb = SLIST_FIRST(&dpt->free_dccb_list)) != NULL) { 230 SLIST_REMOVE_HEAD(&dpt->free_dccb_list, links); 231 dpt->free_dccbs--; 232 } else if (dpt->total_dccbs < dpt->max_dccbs) { 233 dptallocccbs(dpt); 234 dccb = SLIST_FIRST(&dpt->free_dccb_list); 235 if (dccb == NULL) |
235 printf("dpt%d: Can't malloc DCCB\n", dpt->unit); | 236 device_printf(dpt->dev, "Can't malloc DCCB\n"); |
236 else { 237 SLIST_REMOVE_HEAD(&dpt->free_dccb_list, links); 238 dpt->free_dccbs--; 239 } 240 } | 237 else { 238 SLIST_REMOVE_HEAD(&dpt->free_dccb_list, links); 239 dpt->free_dccbs--; 240 } 241 } |
241 splx(s); | |
242 243 return (dccb); 244} 245 246static __inline void 247dptfreeccb(struct dpt_softc *dpt, struct dpt_ccb *dccb) 248{ | 242 243 return (dccb); 244} 245 246static __inline void 247dptfreeccb(struct dpt_softc *dpt, struct dpt_ccb *dccb) 248{ |
249 int s; | |
250 | 249 |
251 s = splcam(); | 250 if (!dumping) 251 mtx_assert(&dpt->lock, MA_OWNED); |
252 if ((dccb->state & DCCB_ACTIVE) != 0) 253 LIST_REMOVE(&dccb->ccb->ccb_h, sim_links.le); 254 if ((dccb->state & DCCB_RELEASE_SIMQ) != 0) 255 dccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 256 else if (dpt->resource_shortage != 0 257 && (dccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 258 dccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 259 dpt->resource_shortage = FALSE; 260 } 261 dccb->state = DCCB_FREE; 262 SLIST_INSERT_HEAD(&dpt->free_dccb_list, dccb, links); 263 ++dpt->free_dccbs; | 252 if ((dccb->state & DCCB_ACTIVE) != 0) 253 LIST_REMOVE(&dccb->ccb->ccb_h, sim_links.le); 254 if ((dccb->state & DCCB_RELEASE_SIMQ) != 0) 255 dccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 256 else if (dpt->resource_shortage != 0 257 && (dccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 258 dccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 259 dpt->resource_shortage = FALSE; 260 } 261 dccb->state = DCCB_FREE; 262 SLIST_INSERT_HEAD(&dpt->free_dccb_list, dccb, links); 263 ++dpt->free_dccbs; |
264 splx(s); | |
265} 266 267static __inline bus_addr_t 268dptccbvtop(struct dpt_softc *dpt, struct dpt_ccb *dccb) 269{ 270 return (dpt->dpt_ccb_busbase 271 + (u_int32_t)((caddr_t)dccb - (caddr_t)dpt->dpt_dccbs)); 272} --- 54 unchanged lines hidden (view full) --- 327 328 SLIST_INSERT_HEAD(&dpt->sg_maps, sg_map, links); 329 330 return (sg_map); 331} 332 333/* 334 * Allocate another chunk of CCB's. Return count of entries added. | 264} 265 266static __inline bus_addr_t 267dptccbvtop(struct dpt_softc *dpt, struct dpt_ccb *dccb) 268{ 269 return (dpt->dpt_ccb_busbase 270 + (u_int32_t)((caddr_t)dccb - (caddr_t)dpt->dpt_dccbs)); 271} --- 54 unchanged lines hidden (view full) --- 326 327 SLIST_INSERT_HEAD(&dpt->sg_maps, sg_map, links); 328 329 return (sg_map); 330} 331 332/* 333 * Allocate another chunk of CCB's. Return count of entries added. |
335 * Assumed to be called at splcam(). | |
336 */ 337static int 338dptallocccbs(dpt_softc_t *dpt) 339{ 340 struct dpt_ccb *next_ccb; 341 struct sg_map_node *sg_map; 342 bus_addr_t physaddr; 343 dpt_sg_t *segs; 344 int newcount; 345 int i; 346 | 334 */ 335static int 336dptallocccbs(dpt_softc_t *dpt) 337{ 338 struct dpt_ccb *next_ccb; 339 struct sg_map_node *sg_map; 340 bus_addr_t physaddr; 341 dpt_sg_t *segs; 342 int newcount; 343 int i; 344 |
345 if (!dumping) 346 mtx_assert(&dpt->lock, MA_OWNED); |
|
347 next_ccb = &dpt->dpt_dccbs[dpt->total_dccbs]; 348 349 if (next_ccb == dpt->dpt_dccbs) { 350 /* 351 * First time through. Re-use the S/G 352 * space we allocated for initialization 353 * CCBS. 354 */ --- 11 unchanged lines hidden (view full) --- 366 newcount = (PAGE_SIZE / (dpt->sgsize * sizeof(dpt_sg_t))); 367 for (i = 0; dpt->total_dccbs < dpt->max_dccbs && i < newcount; i++) { 368 int error; 369 370 error = bus_dmamap_create(dpt->buffer_dmat, /*flags*/0, 371 &next_ccb->dmamap); 372 if (error != 0) 373 break; | 347 next_ccb = &dpt->dpt_dccbs[dpt->total_dccbs]; 348 349 if (next_ccb == dpt->dpt_dccbs) { 350 /* 351 * First time through. Re-use the S/G 352 * space we allocated for initialization 353 * CCBS. 354 */ --- 11 unchanged lines hidden (view full) --- 366 newcount = (PAGE_SIZE / (dpt->sgsize * sizeof(dpt_sg_t))); 367 for (i = 0; dpt->total_dccbs < dpt->max_dccbs && i < newcount; i++) { 368 int error; 369 370 error = bus_dmamap_create(dpt->buffer_dmat, /*flags*/0, 371 &next_ccb->dmamap); 372 if (error != 0) 373 break; |
374 callout_init_mtx(&next_ccb->timer, &dpt->lock, 0); |
|
374 next_ccb->sg_list = segs; 375 next_ccb->sg_busaddr = htonl(physaddr); 376 next_ccb->eata_ccb.cp_dataDMA = htonl(physaddr); 377 next_ccb->eata_ccb.cp_statDMA = htonl(dpt->sp_physaddr); 378 next_ccb->eata_ccb.cp_reqDMA = 379 htonl(dptccbvtop(dpt, next_ccb) 380 + offsetof(struct dpt_ccb, sense_data)); 381 next_ccb->eata_ccb.cp_busaddr = dpt->dpt_ccb_busend; --- 17 unchanged lines hidden (view full) --- 399 u_int16_t * p; 400 int i; 401 402 /* 403 * Allocate a dpt_conf_t 404 */ 405 if (!conf) { 406 conf = (dpt_conf_t *)malloc(sizeof(dpt_conf_t), | 375 next_ccb->sg_list = segs; 376 next_ccb->sg_busaddr = htonl(physaddr); 377 next_ccb->eata_ccb.cp_dataDMA = htonl(physaddr); 378 next_ccb->eata_ccb.cp_statDMA = htonl(dpt->sp_physaddr); 379 next_ccb->eata_ccb.cp_reqDMA = 380 htonl(dptccbvtop(dpt, next_ccb) 381 + offsetof(struct dpt_ccb, sense_data)); 382 next_ccb->eata_ccb.cp_busaddr = dpt->dpt_ccb_busend; --- 17 unchanged lines hidden (view full) --- 400 u_int16_t * p; 401 int i; 402 403 /* 404 * Allocate a dpt_conf_t 405 */ 406 if (!conf) { 407 conf = (dpt_conf_t *)malloc(sizeof(dpt_conf_t), |
407 M_DEVBUF, M_NOWAIT); | 408 M_DEVBUF, M_NOWAIT | M_ZERO); |
408 } 409 410 /* 411 * If we didn't get one then we probably won't ever get one. 412 */ 413 if (!conf) { 414 printf("dpt: unable to allocate dpt_conf_t\n"); 415 return (NULL); 416 } 417 418 /* | 409 } 410 411 /* 412 * If we didn't get one then we probably won't ever get one. 413 */ 414 if (!conf) { 415 printf("dpt: unable to allocate dpt_conf_t\n"); 416 return (NULL); 417 } 418 419 /* |
419 * If we have one, clean it up. 420 */ 421 bzero(conf, sizeof(dpt_conf_t)); 422 423 /* | |
424 * Reset the controller. 425 */ 426 outb((base + HA_WCOMMAND), EATA_CMD_RESET); 427 428 /* 429 * Wait for the controller to become ready. 430 * For some reason there can be -no- delays after calling reset 431 * before we wait on ready status. --- 61 unchanged lines hidden (view full) --- 493dpt_get_conf(dpt_softc_t *dpt, dpt_ccb_t *dccb, u_int32_t dccb_busaddr, 494 u_int size, u_int page, u_int target, int extent) 495{ 496 eata_ccb_t *cp; 497 498 u_int8_t status; 499 500 int ndx; | 420 * Reset the controller. 421 */ 422 outb((base + HA_WCOMMAND), EATA_CMD_RESET); 423 424 /* 425 * Wait for the controller to become ready. 426 * For some reason there can be -no- delays after calling reset 427 * before we wait on ready status. --- 61 unchanged lines hidden (view full) --- 489dpt_get_conf(dpt_softc_t *dpt, dpt_ccb_t *dccb, u_int32_t dccb_busaddr, 490 u_int size, u_int page, u_int target, int extent) 491{ 492 eata_ccb_t *cp; 493 494 u_int8_t status; 495 496 int ndx; |
501 int ospl; | |
502 int result; 503 | 497 int result; 498 |
499 mtx_assert(&dpt->lock, MA_OWNED); |
|
504 cp = &dccb->eata_ccb; 505 bzero((void *)(uintptr_t)(volatile void *)dpt->sp, sizeof(*dpt->sp)); 506 507 cp->Interpret = 1; 508 cp->DataIn = 1; 509 cp->Auto_Req_Sen = 1; 510 cp->reqlen = sizeof(struct scsi_sense_data); 511 --- 6 unchanged lines hidden (view full) --- 518 519 cp->cp_extent = extent; 520 521 cp->cp_page = page; 522 cp->cp_channel = 0; /* DNC, Interpret mode is set */ 523 cp->cp_identify = 1; 524 cp->cp_datalen = htonl(size); 525 | 500 cp = &dccb->eata_ccb; 501 bzero((void *)(uintptr_t)(volatile void *)dpt->sp, sizeof(*dpt->sp)); 502 503 cp->Interpret = 1; 504 cp->DataIn = 1; 505 cp->Auto_Req_Sen = 1; 506 cp->reqlen = sizeof(struct scsi_sense_data); 507 --- 6 unchanged lines hidden (view full) --- 514 515 cp->cp_extent = extent; 516 517 cp->cp_page = page; 518 cp->cp_channel = 0; /* DNC, Interpret mode is set */ 519 cp->cp_identify = 1; 520 cp->cp_datalen = htonl(size); 521 |
526 ospl = splcam(); 527 | |
528 /* 529 * This could be a simple for loop, but we suspected the compiler To 530 * have optimized it a bit too much. Wait for the controller to 531 * become ready 532 */ 533 while (((status = dpt_inb(dpt, HA_RSTATUS)) != (HA_SREADY | HA_SSC) 534 && (status != (HA_SREADY | HA_SSC | HA_SERROR)) 535 && (status != (HA_SDRDY | HA_SERROR | HA_SDRQ))) 536 || (dpt_wait(dpt, HA_SBUSY, 0))) { 537 538 /* 539 * RAID Drives still Spinning up? (This should only occur if 540 * the DPT controller is in a NON PC (PCI?) platform). 541 */ 542 if (dpt_raid_busy(dpt)) { | 522 /* 523 * This could be a simple for loop, but we suspected the compiler To 524 * have optimized it a bit too much. Wait for the controller to 525 * become ready 526 */ 527 while (((status = dpt_inb(dpt, HA_RSTATUS)) != (HA_SREADY | HA_SSC) 528 && (status != (HA_SREADY | HA_SSC | HA_SERROR)) 529 && (status != (HA_SDRDY | HA_SERROR | HA_SDRQ))) 530 || (dpt_wait(dpt, HA_SBUSY, 0))) { 531 532 /* 533 * RAID Drives still Spinning up? (This should only occur if 534 * the DPT controller is in a NON PC (PCI?) platform). 535 */ 536 if (dpt_raid_busy(dpt)) { |
543 printf("dpt%d WARNING: Get_conf() RSUS failed.\n", 544 dpt->unit); 545 splx(ospl); | 537 device_printf(dpt->dev, 538 "WARNING: Get_conf() RSUS failed.\n"); |
546 return (0); 547 } 548 } 549 550 DptStat_Reset_BUSY(dpt->sp); 551 552 /* 553 * XXXX We might want to do something more clever than aborting at 554 * this point, like resetting (rebooting) the controller and trying 555 * again. 556 */ 557 if ((result = dpt_send_eata_command(dpt, cp, dccb_busaddr, 558 EATA_CMD_DMA_SEND_CP, 559 10000, 0, 0, 0)) != 0) { | 539 return (0); 540 } 541 } 542 543 DptStat_Reset_BUSY(dpt->sp); 544 545 /* 546 * XXXX We might want to do something more clever than aborting at 547 * this point, like resetting (rebooting) the controller and trying 548 * again. 549 */ 550 if ((result = dpt_send_eata_command(dpt, cp, dccb_busaddr, 551 EATA_CMD_DMA_SEND_CP, 552 10000, 0, 0, 0)) != 0) { |
560 printf("dpt%d WARNING: Get_conf() failed (%d) to send " | 553 device_printf(dpt->dev, 554 "WARNING: Get_conf() failed (%d) to send " |
561 "EATA_CMD_DMA_READ_CONFIG\n", | 555 "EATA_CMD_DMA_READ_CONFIG\n", |
562 dpt->unit, result); 563 splx(ospl); | 556 result); |
564 return (0); 565 } 566 /* Wait for two seconds for a response. This can be slow */ 567 for (ndx = 0; 568 (ndx < 20000) 569 && !((status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ); 570 ndx++) { 571 DELAY(50); 572 } 573 574 /* Grab the status and clear interrupts */ 575 status = dpt_inb(dpt, HA_RSTATUS); 576 | 557 return (0); 558 } 559 /* Wait for two seconds for a response. This can be slow */ 560 for (ndx = 0; 561 (ndx < 20000) 562 && !((status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ); 563 ndx++) { 564 DELAY(50); 565 } 566 567 /* Grab the status and clear interrupts */ 568 status = dpt_inb(dpt, HA_RSTATUS); 569 |
577 splx(ospl); 578 | |
579 /* 580 * Check the status carefully. Return only if the 581 * command was successful. 582 */ 583 if (((status & HA_SERROR) == 0) 584 && (dpt->sp->hba_stat == 0) 585 && (dpt->sp->scsi_stat == 0) 586 && (dpt->sp->residue_len == 0)) --- 9 unchanged lines hidden (view full) --- 596static void 597dpt_detect_cache(dpt_softc_t *dpt, dpt_ccb_t *dccb, u_int32_t dccb_busaddr, 598 u_int8_t *buff) 599{ 600 eata_ccb_t *cp; 601 u_int8_t *param; 602 int bytes; 603 int result; | 570 /* 571 * Check the status carefully. Return only if the 572 * command was successful. 573 */ 574 if (((status & HA_SERROR) == 0) 575 && (dpt->sp->hba_stat == 0) 576 && (dpt->sp->scsi_stat == 0) 577 && (dpt->sp->residue_len == 0)) --- 9 unchanged lines hidden (view full) --- 587static void 588dpt_detect_cache(dpt_softc_t *dpt, dpt_ccb_t *dccb, u_int32_t dccb_busaddr, 589 u_int8_t *buff) 590{ 591 eata_ccb_t *cp; 592 u_int8_t *param; 593 int bytes; 594 int result; |
604 int ospl; | |
605 int ndx; 606 u_int8_t status; 607 | 595 int ndx; 596 u_int8_t status; 597 |
598 mtx_assert(&dpt->lock, MA_OWNED); 599 |
|
608 /* 609 * Default setting, for best perfromance.. 610 * This is what virtually all cards default to.. 611 */ 612 dpt->cache_type = DPT_CACHE_WRITEBACK; 613 dpt->cache_size = 0; 614 615 cp = &dccb->eata_ccb; --- 25 unchanged lines hidden (view full) --- 641 */ 642 cp->cp_cdb[0] = 0x4d; 643 cp->cp_cdb[1] = 0x0; 644 cp->cp_cdb[2] = 0x40 | 0x33; 645 cp->cp_cdb[7] = 1; 646 647 cp->cp_datalen = htonl(512); 648 | 600 /* 601 * Default setting, for best perfromance.. 602 * This is what virtually all cards default to.. 603 */ 604 dpt->cache_type = DPT_CACHE_WRITEBACK; 605 dpt->cache_size = 0; 606 607 cp = &dccb->eata_ccb; --- 25 unchanged lines hidden (view full) --- 633 */ 634 cp->cp_cdb[0] = 0x4d; 635 cp->cp_cdb[1] = 0x0; 636 cp->cp_cdb[2] = 0x40 | 0x33; 637 cp->cp_cdb[7] = 1; 638 639 cp->cp_datalen = htonl(512); 640 |
649 ospl = splcam(); | |
650 result = dpt_send_eata_command(dpt, cp, dccb_busaddr, 651 EATA_CMD_DMA_SEND_CP, 652 10000, 0, 0, 0); 653 if (result != 0) { | 641 result = dpt_send_eata_command(dpt, cp, dccb_busaddr, 642 EATA_CMD_DMA_SEND_CP, 643 10000, 0, 0, 0); 644 if (result != 0) { |
654 printf("dpt%d WARNING: detect_cache() failed (%d) to send " 655 "EATA_CMD_DMA_SEND_CP\n", dpt->unit, result); 656 splx(ospl); | 645 device_printf(dpt->dev, 646 "WARNING: detect_cache() failed (%d) to send " 647 "EATA_CMD_DMA_SEND_CP\n", result); |
657 return; 658 } 659 /* Wait for two seconds for a response. This can be slow... */ 660 for (ndx = 0; 661 (ndx < 20000) && 662 !((status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ); 663 ndx++) { 664 DELAY(50); 665 } 666 667 /* Grab the status and clear interrupts */ 668 status = dpt_inb(dpt, HA_RSTATUS); | 648 return; 649 } 650 /* Wait for two seconds for a response. This can be slow... */ 651 for (ndx = 0; 652 (ndx < 20000) && 653 !((status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ); 654 ndx++) { 655 DELAY(50); 656 } 657 658 /* Grab the status and clear interrupts */ 659 status = dpt_inb(dpt, HA_RSTATUS); |
669 splx(ospl); | |
670 671 /* 672 * Sanity check 673 */ 674 if (buff[0] != 0x33) { 675 return; 676 } 677 bytes = DPT_HCP_LENGTH(buff); 678 param = DPT_HCP_FIRST(buff); 679 680 if (DPT_HCP_CODE(param) != 1) { 681 /* 682 * DPT Log Page layout error 683 */ | 660 661 /* 662 * Sanity check 663 */ 664 if (buff[0] != 0x33) { 665 return; 666 } 667 bytes = DPT_HCP_LENGTH(buff); 668 param = DPT_HCP_FIRST(buff); 669 670 if (DPT_HCP_CODE(param) != 1) { 671 /* 672 * DPT Log Page layout error 673 */ |
684 printf("dpt%d: NOTICE: Log Page (1) layout error\n", 685 dpt->unit); | 674 device_printf(dpt->dev, "NOTICE: Log Page (1) layout error\n"); |
686 return; 687 } 688 if (!(param[4] & 0x4)) { 689 dpt->cache_type = DPT_NO_CACHE; 690 return; 691 } 692 while (DPT_HCP_CODE(param) != 6) { 693 param = DPT_HCP_NEXT(param); --- 22 unchanged lines hidden (view full) --- 716 | (param[7] << 16) 717 | (param[8] << 24); 718#endif 719} 720 721static void 722dpt_poll(struct cam_sim *sim) 723{ | 675 return; 676 } 677 if (!(param[4] & 0x4)) { 678 dpt->cache_type = DPT_NO_CACHE; 679 return; 680 } 681 while (DPT_HCP_CODE(param) != 6) { 682 param = DPT_HCP_NEXT(param); --- 22 unchanged lines hidden (view full) --- 705 | (param[7] << 16) 706 | (param[8] << 24); 707#endif 708} 709 710static void 711dpt_poll(struct cam_sim *sim) 712{ |
724 dpt_intr(cam_sim_softc(sim)); | 713 dpt_intr_locked(cam_sim_softc(sim)); |
725} 726 727static void 728dptexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 729{ 730 struct dpt_ccb *dccb; 731 union ccb *ccb; 732 struct dpt_softc *dpt; | 714} 715 716static void 717dptexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 718{ 719 struct dpt_ccb *dccb; 720 union ccb *ccb; 721 struct dpt_softc *dpt; |
733 int s; | |
734 | 722 |
723 if (!dumping) 724 mtx_assert(&dpt->lock, MA_OWNED); |
|
735 dccb = (struct dpt_ccb *)arg; 736 ccb = dccb->ccb; 737 dpt = (struct dpt_softc *)ccb->ccb_h.ccb_dpt_ptr; 738 739 if (error != 0) { 740 if (error != EFBIG) | 725 dccb = (struct dpt_ccb *)arg; 726 ccb = dccb->ccb; 727 dpt = (struct dpt_softc *)ccb->ccb_h.ccb_dpt_ptr; 728 729 if (error != 0) { 730 if (error != EFBIG) |
741 printf("dpt%d: Unexepected error 0x%x returned from " 742 "bus_dmamap_load\n", dpt->unit, error); | 731 device_printf(dpt->dev, 732 "Unexepected error 0x%x returned from " 733 "bus_dmamap_load\n", error); |
743 if (ccb->ccb_h.status == CAM_REQ_INPROG) { 744 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 745 ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 746 } 747 dptfreeccb(dpt, dccb); 748 xpt_done(ccb); 749 return; 750 } --- 31 unchanged lines hidden (view full) --- 782 783 bus_dmamap_sync(dpt->buffer_dmat, dccb->dmamap, op); 784 785 } else { 786 dccb->eata_ccb.cp_dataDMA = 0; 787 dccb->eata_ccb.cp_datalen = 0; 788 } 789 | 734 if (ccb->ccb_h.status == CAM_REQ_INPROG) { 735 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 736 ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 737 } 738 dptfreeccb(dpt, dccb); 739 xpt_done(ccb); 740 return; 741 } --- 31 unchanged lines hidden (view full) --- 773 774 bus_dmamap_sync(dpt->buffer_dmat, dccb->dmamap, op); 775 776 } else { 777 dccb->eata_ccb.cp_dataDMA = 0; 778 dccb->eata_ccb.cp_datalen = 0; 779 } 780 |
790 s = splcam(); 791 | |
792 /* 793 * Last time we need to check if this CCB needs to 794 * be aborted. 795 */ 796 if (ccb->ccb_h.status != CAM_REQ_INPROG) { 797 if (nseg != 0) 798 bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap); 799 dptfreeccb(dpt, dccb); 800 xpt_done(ccb); | 781 /* 782 * Last time we need to check if this CCB needs to 783 * be aborted. 784 */ 785 if (ccb->ccb_h.status != CAM_REQ_INPROG) { 786 if (nseg != 0) 787 bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap); 788 dptfreeccb(dpt, dccb); 789 xpt_done(ccb); |
801 splx(s); | |
802 return; 803 } 804 805 dccb->state |= DCCB_ACTIVE; 806 ccb->ccb_h.status |= CAM_SIM_QUEUED; 807 LIST_INSERT_HEAD(&dpt->pending_ccb_list, &ccb->ccb_h, sim_links.le); | 790 return; 791 } 792 793 dccb->state |= DCCB_ACTIVE; 794 ccb->ccb_h.status |= CAM_SIM_QUEUED; 795 LIST_INSERT_HEAD(&dpt->pending_ccb_list, &ccb->ccb_h, sim_links.le); |
808 ccb->ccb_h.timeout_ch = 809 timeout(dpttimeout, (caddr_t)dccb, 810 (ccb->ccb_h.timeout * hz) / 1000); | 796 callout_reset(&dccb->timer, (ccb->ccb_h.timeout * hz) / 1000, 797 dpttimeout, dccb); |
811 if (dpt_send_eata_command(dpt, &dccb->eata_ccb, 812 dccb->eata_ccb.cp_busaddr, 813 EATA_CMD_DMA_SEND_CP, 0, 0, 0, 0) != 0) { 814 ccb->ccb_h.status = CAM_NO_HBA; /* HBA dead or just busy?? */ 815 if (nseg != 0) 816 bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap); 817 dptfreeccb(dpt, dccb); 818 xpt_done(ccb); 819 } | 798 if (dpt_send_eata_command(dpt, &dccb->eata_ccb, 799 dccb->eata_ccb.cp_busaddr, 800 EATA_CMD_DMA_SEND_CP, 0, 0, 0, 0) != 0) { 801 ccb->ccb_h.status = CAM_NO_HBA; /* HBA dead or just busy?? */ 802 if (nseg != 0) 803 bus_dmamap_unload(dpt->buffer_dmat, dccb->dmamap); 804 dptfreeccb(dpt, dccb); 805 xpt_done(ccb); 806 } |
820 821 splx(s); | |
822} 823 824static void 825dpt_action(struct cam_sim *sim, union ccb *ccb) 826{ 827 struct dpt_softc *dpt; 828 829 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("dpt_action\n")); 830 831 dpt = (struct dpt_softc *)cam_sim_softc(sim); | 807} 808 809static void 810dpt_action(struct cam_sim *sim, union ccb *ccb) 811{ 812 struct dpt_softc *dpt; 813 814 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("dpt_action\n")); 815 816 dpt = (struct dpt_softc *)cam_sim_softc(sim); |
817 mtx_assert(&dpt->lock, MA_OWNED); |
|
832 833 if ((dpt->state & DPT_HA_SHUTDOWN_ACTIVE) != 0) { 834 xpt_print_path(ccb->ccb_h.path); 835 printf("controller is shutdown. Aborting CCB.\n"); 836 ccb->ccb_h.status = CAM_NO_HBA; 837 xpt_done(ccb); 838 return; 839 } --- 11 unchanged lines hidden (view full) --- 851 ccbh = &ccb->ccb_h; 852 /* Max CDB length is 12 bytes */ 853 if (csio->cdb_len > 12) { 854 ccb->ccb_h.status = CAM_REQ_INVALID; 855 xpt_done(ccb); 856 return; 857 } 858 if ((dccb = dptgetccb(dpt)) == NULL) { | 818 819 if ((dpt->state & DPT_HA_SHUTDOWN_ACTIVE) != 0) { 820 xpt_print_path(ccb->ccb_h.path); 821 printf("controller is shutdown. Aborting CCB.\n"); 822 ccb->ccb_h.status = CAM_NO_HBA; 823 xpt_done(ccb); 824 return; 825 } --- 11 unchanged lines hidden (view full) --- 837 ccbh = &ccb->ccb_h; 838 /* Max CDB length is 12 bytes */ 839 if (csio->cdb_len > 12) { 840 ccb->ccb_h.status = CAM_REQ_INVALID; 841 xpt_done(ccb); 842 return; 843 } 844 if ((dccb = dptgetccb(dpt)) == NULL) { |
859 int s; 860 861 s = splcam(); | |
862 dpt->resource_shortage = 1; | 845 dpt->resource_shortage = 1; |
863 splx(s); | |
864 xpt_freeze_simq(sim, /*count*/1); 865 ccb->ccb_h.status = CAM_REQUEUE_REQ; 866 xpt_done(ccb); 867 return; 868 } 869 eccb = &dccb->eata_ccb; 870 871 /* Link dccb and ccb so we can find one from the other */ --- 57 unchanged lines hidden (view full) --- 929 /* Only use S/G if there is a transfer */ 930 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 931 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { 932 /* 933 * We've been given a pointer 934 * to a single buffer. 935 */ 936 if ((ccbh->flags & CAM_DATA_PHYS) == 0) { | 846 xpt_freeze_simq(sim, /*count*/1); 847 ccb->ccb_h.status = CAM_REQUEUE_REQ; 848 xpt_done(ccb); 849 return; 850 } 851 eccb = &dccb->eata_ccb; 852 853 /* Link dccb and ccb so we can find one from the other */ --- 57 unchanged lines hidden (view full) --- 911 /* Only use S/G if there is a transfer */ 912 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 913 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { 914 /* 915 * We've been given a pointer 916 * to a single buffer. 917 */ 918 if ((ccbh->flags & CAM_DATA_PHYS) == 0) { |
937 int s; | |
938 int error; 939 | 919 int error; 920 |
940 s = splsoftvm(); | |
941 error = 942 bus_dmamap_load(dpt->buffer_dmat, 943 dccb->dmamap, 944 csio->data_ptr, 945 csio->dxfer_len, 946 dptexecuteccb, 947 dccb, /*flags*/0); 948 if (error == EINPROGRESS) { 949 /* 950 * So as to maintain ordering, 951 * freeze the controller queue 952 * until our mapping is 953 * returned. 954 */ 955 xpt_freeze_simq(sim, 1); 956 dccb->state |= CAM_RELEASE_SIMQ; 957 } | 921 error = 922 bus_dmamap_load(dpt->buffer_dmat, 923 dccb->dmamap, 924 csio->data_ptr, 925 csio->dxfer_len, 926 dptexecuteccb, 927 dccb, /*flags*/0); 928 if (error == EINPROGRESS) { 929 /* 930 * So as to maintain ordering, 931 * freeze the controller queue 932 * until our mapping is 933 * returned. 934 */ 935 xpt_freeze_simq(sim, 1); 936 dccb->state |= CAM_RELEASE_SIMQ; 937 } |
958 splx(s); | |
959 } else { 960 struct bus_dma_segment seg; 961 962 /* Pointer to physical buffer */ 963 seg.ds_addr = 964 (bus_addr_t)csio->data_ptr; 965 seg.ds_len = csio->dxfer_len; 966 dptexecuteccb(dccb, &seg, 1, 0); --- 133 unchanged lines hidden (view full) --- 1100 break; 1101 } 1102} 1103 1104/* 1105 * This routine will try to send an EATA command to the DPT HBA. 1106 * It will, by default, try 20,000 times, waiting 50us between tries. 1107 * It returns 0 on success and 1 on failure. | 938 } else { 939 struct bus_dma_segment seg; 940 941 /* Pointer to physical buffer */ 942 seg.ds_addr = 943 (bus_addr_t)csio->data_ptr; 944 seg.ds_len = csio->dxfer_len; 945 dptexecuteccb(dccb, &seg, 1, 0); --- 133 unchanged lines hidden (view full) --- 1079 break; 1080 } 1081} 1082 1083/* 1084 * This routine will try to send an EATA command to the DPT HBA. 1085 * It will, by default, try 20,000 times, waiting 50us between tries. 1086 * It returns 0 on success and 1 on failure. |
1108 * It is assumed to be called at splcam(). | |
1109 */ 1110static int 1111dpt_send_eata_command(dpt_softc_t *dpt, eata_ccb_t *cmd_block, 1112 u_int32_t cmd_busaddr, u_int command, u_int retries, 1113 u_int ifc, u_int code, u_int code2) 1114{ 1115 u_int loop; 1116 --- 61 unchanged lines hidden (view full) --- 1178 1179/* ==================== Exported Function definitions =======================*/ 1180void 1181dpt_alloc(device_t dev) 1182{ 1183 dpt_softc_t *dpt = device_get_softc(dev); 1184 int i; 1185 | 1087 */ 1088static int 1089dpt_send_eata_command(dpt_softc_t *dpt, eata_ccb_t *cmd_block, 1090 u_int32_t cmd_busaddr, u_int command, u_int retries, 1091 u_int ifc, u_int code, u_int code2) 1092{ 1093 u_int loop; 1094 --- 61 unchanged lines hidden (view full) --- 1156 1157/* ==================== Exported Function definitions =======================*/ 1158void 1159dpt_alloc(device_t dev) 1160{ 1161 dpt_softc_t *dpt = device_get_softc(dev); 1162 int i; 1163 |
1186 dpt->tag = rman_get_bustag(dpt->io_res); 1187 dpt->bsh = rman_get_bushandle(dpt->io_res) + dpt->io_offset; 1188 dpt->unit = device_get_unit(dev); | 1164 mtx_init(&dpt->lock, "dpt", NULL, MTX_DEF); |
1189 SLIST_INIT(&dpt->free_dccb_list); 1190 LIST_INIT(&dpt->pending_ccb_list); 1191 for (i = 0; i < MAX_CHANNELS; i++) 1192 dpt->resetlevel[i] = DPT_HA_OK; 1193 1194#ifdef DPT_MEASURE_PERFORMANCE 1195 dpt_reset_performance(dpt); 1196#endif /* DPT_MEASURE_PERFORMANCE */ --- 27 unchanged lines hidden (view full) --- 1224 sg_map->sg_dmamap); 1225 free(sg_map, M_DEVBUF); 1226 } 1227 bus_dma_tag_destroy(dpt->sg_dmat); 1228 } 1229 case 0: 1230 break; 1231 } | 1165 SLIST_INIT(&dpt->free_dccb_list); 1166 LIST_INIT(&dpt->pending_ccb_list); 1167 for (i = 0; i < MAX_CHANNELS; i++) 1168 dpt->resetlevel[i] = DPT_HA_OK; 1169 1170#ifdef DPT_MEASURE_PERFORMANCE 1171 dpt_reset_performance(dpt); 1172#endif /* DPT_MEASURE_PERFORMANCE */ --- 27 unchanged lines hidden (view full) --- 1200 sg_map->sg_dmamap); 1201 free(sg_map, M_DEVBUF); 1202 } 1203 bus_dma_tag_destroy(dpt->sg_dmat); 1204 } 1205 case 0: 1206 break; 1207 } |
1208 mtx_destroy(&dpt->lock); |
|
1232} 1233 1234int 1235dpt_alloc_resources (device_t dev) 1236{ 1237 dpt_softc_t * dpt; 1238 int error; 1239 --- 56 unchanged lines hidden (view full) --- 1296 dpt_ccb_t *dccb; 1297 u_int8_t *strp; 1298 int index; 1299 int i; 1300 int retval; 1301 1302 dpt->init_level = 0; 1303 SLIST_INIT(&dpt->sg_maps); | 1209} 1210 1211int 1212dpt_alloc_resources (device_t dev) 1213{ 1214 dpt_softc_t * dpt; 1215 int error; 1216 --- 56 unchanged lines hidden (view full) --- 1273 dpt_ccb_t *dccb; 1274 u_int8_t *strp; 1275 int index; 1276 int i; 1277 int retval; 1278 1279 dpt->init_level = 0; 1280 SLIST_INIT(&dpt->sg_maps); |
1281 mtx_lock(&dpt->lock); |
|
1304 1305#ifdef DPT_RESET_BOARD | 1282 1283#ifdef DPT_RESET_BOARD |
1306 printf("dpt%d: resetting HBA\n", dpt->unit); | 1284 device_printf(dpt->dev, "resetting HBA\n"); |
1307 dpt_outb(dpt, HA_WCOMMAND, EATA_CMD_RESET); 1308 DELAY(750000); 1309 /* XXX Shouldn't we poll a status register or something??? */ 1310#endif 1311 /* DMA tag for our S/G structures. We allocate in page sized chunks */ 1312 if (bus_dma_tag_create( /* parent */ dpt->parent_dmat, 1313 /* alignment */ 1, 1314 /* boundary */ 0, 1315 /* lowaddr */ BUS_SPACE_MAXADDR, 1316 /* highaddr */ BUS_SPACE_MAXADDR, 1317 /* filter */ NULL, 1318 /* filterarg */ NULL, 1319 /* maxsize */ PAGE_SIZE, 1320 /* nsegments */ 1, 1321 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 1322 /* flags */ 0, | 1285 dpt_outb(dpt, HA_WCOMMAND, EATA_CMD_RESET); 1286 DELAY(750000); 1287 /* XXX Shouldn't we poll a status register or something??? */ 1288#endif 1289 /* DMA tag for our S/G structures. We allocate in page sized chunks */ 1290 if (bus_dma_tag_create( /* parent */ dpt->parent_dmat, 1291 /* alignment */ 1, 1292 /* boundary */ 0, 1293 /* lowaddr */ BUS_SPACE_MAXADDR, 1294 /* highaddr */ BUS_SPACE_MAXADDR, 1295 /* filter */ NULL, 1296 /* filterarg */ NULL, 1297 /* maxsize */ PAGE_SIZE, 1298 /* nsegments */ 1, 1299 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 1300 /* flags */ 0, |
1323 /* lockfunc */ busdma_lock_mutex, 1324 /* lockarg */ &Giant, | 1301 /* lockfunc */ NULL, 1302 /* lockarg */ NULL, |
1325 &dpt->sg_dmat) != 0) { 1326 goto error_exit; 1327 } 1328 1329 dpt->init_level++; 1330 1331 /* 1332 * We allocate our DPT ccbs as a contiguous array of bus dma'able --- 19 unchanged lines hidden (view full) --- 1352 + offsetof(struct dpt_ccb, sense_data)); 1353 1354 /* Okay. Fetch our config */ 1355 bzero(&dccb[1], sizeof(conf)); /* data area */ 1356 retval = dpt_get_conf(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t), 1357 sizeof(conf), 0xc1, 7, 1); 1358 1359 if (retval != 0) { | 1303 &dpt->sg_dmat) != 0) { 1304 goto error_exit; 1305 } 1306 1307 dpt->init_level++; 1308 1309 /* 1310 * We allocate our DPT ccbs as a contiguous array of bus dma'able --- 19 unchanged lines hidden (view full) --- 1330 + offsetof(struct dpt_ccb, sense_data)); 1331 1332 /* Okay. Fetch our config */ 1333 bzero(&dccb[1], sizeof(conf)); /* data area */ 1334 retval = dpt_get_conf(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t), 1335 sizeof(conf), 0xc1, 7, 1); 1336 1337 if (retval != 0) { |
1360 printf("dpt%d: Failed to get board configuration\n", dpt->unit); 1361 return (retval); | 1338 device_printf(dpt->dev, "Failed to get board configuration\n"); 1339 goto error_exit; |
1362 } 1363 bcopy(&dccb[1], &conf, sizeof(conf)); 1364 1365 bzero(&dccb[1], sizeof(dpt->board_data)); 1366 retval = dpt_get_conf(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t), 1367 sizeof(dpt->board_data), 0, conf.scsi_id0, 0); 1368 if (retval != 0) { | 1340 } 1341 bcopy(&dccb[1], &conf, sizeof(conf)); 1342 1343 bzero(&dccb[1], sizeof(dpt->board_data)); 1344 retval = dpt_get_conf(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t), 1345 sizeof(dpt->board_data), 0, conf.scsi_id0, 0); 1346 if (retval != 0) { |
1369 printf("dpt%d: Failed to get inquiry information\n", dpt->unit); 1370 return (retval); | 1347 device_printf(dpt->dev, "Failed to get inquiry information\n"); 1348 goto error_exit; |
1371 } 1372 bcopy(&dccb[1], &dpt->board_data, sizeof(dpt->board_data)); 1373 1374 dpt_detect_cache(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t), 1375 (u_int8_t *)&dccb[1]); 1376 1377 switch (ntohl(conf.splen)) { 1378 case DPT_EATA_REVA: --- 32 unchanged lines hidden (view full) --- 1411 1412 dpt->broken_INQUIRY = FALSE; 1413 1414 dpt->cplen = ntohl(conf.cplen); 1415 dpt->cppadlen = ntohs(conf.cppadlen); 1416 dpt->max_dccbs = ntohs(conf.queuesiz); 1417 1418 if (dpt->max_dccbs > 256) { | 1349 } 1350 bcopy(&dccb[1], &dpt->board_data, sizeof(dpt->board_data)); 1351 1352 dpt_detect_cache(dpt, dccb, sg_map->sg_physaddr + sizeof(dpt_sp_t), 1353 (u_int8_t *)&dccb[1]); 1354 1355 switch (ntohl(conf.splen)) { 1356 case DPT_EATA_REVA: --- 32 unchanged lines hidden (view full) --- 1389 1390 dpt->broken_INQUIRY = FALSE; 1391 1392 dpt->cplen = ntohl(conf.cplen); 1393 dpt->cppadlen = ntohs(conf.cppadlen); 1394 dpt->max_dccbs = ntohs(conf.queuesiz); 1395 1396 if (dpt->max_dccbs > 256) { |
1419 printf("dpt%d: Max CCBs reduced from %d to " 1420 "256 due to tag algorithm\n", dpt->unit, dpt->max_dccbs); | 1397 device_printf(dpt->dev, "Max CCBs reduced from %d to " 1398 "256 due to tag algorithm\n", dpt->max_dccbs); |
1421 dpt->max_dccbs = 256; 1422 } 1423 1424 dpt->hostid[0] = conf.scsi_id0; 1425 dpt->hostid[1] = conf.scsi_id1; 1426 dpt->hostid[2] = conf.scsi_id2; 1427 1428 if (conf.SG_64K) --- 16 unchanged lines hidden (view full) --- 1445 /* highaddr */ BUS_SPACE_MAXADDR, 1446 /* filter */ NULL, 1447 /* filterarg */ NULL, 1448 /* maxsize */ MAXBSIZE, 1449 /* nsegments */ dpt->sgsize, 1450 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 1451 /* flags */ BUS_DMA_ALLOCNOW, 1452 /* lockfunc */ busdma_lock_mutex, | 1399 dpt->max_dccbs = 256; 1400 } 1401 1402 dpt->hostid[0] = conf.scsi_id0; 1403 dpt->hostid[1] = conf.scsi_id1; 1404 dpt->hostid[2] = conf.scsi_id2; 1405 1406 if (conf.SG_64K) --- 16 unchanged lines hidden (view full) --- 1423 /* highaddr */ BUS_SPACE_MAXADDR, 1424 /* filter */ NULL, 1425 /* filterarg */ NULL, 1426 /* maxsize */ MAXBSIZE, 1427 /* nsegments */ dpt->sgsize, 1428 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 1429 /* flags */ BUS_DMA_ALLOCNOW, 1430 /* lockfunc */ busdma_lock_mutex, |
1453 /* lockarg */ &Giant, | 1431 /* lockarg */ &dpt->lock, |
1454 &dpt->buffer_dmat) != 0) { | 1432 &dpt->buffer_dmat) != 0) { |
1455 printf("dpt: bus_dma_tag_create(...,dpt->buffer_dmat) failed\n"); | 1433 device_printf(dpt->dev, 1434 "bus_dma_tag_create(...,dpt->buffer_dmat) failed\n"); |
1456 goto error_exit; 1457 } 1458 1459 dpt->init_level++; 1460 1461 /* DMA tag for our ccb structures and interrupt status packet */ 1462 if (bus_dma_tag_create( /* parent */ dpt->parent_dmat, 1463 /* alignment */ 1, 1464 /* boundary */ 0, 1465 /* lowaddr */ BUS_SPACE_MAXADDR, 1466 /* highaddr */ BUS_SPACE_MAXADDR, 1467 /* filter */ NULL, 1468 /* filterarg */ NULL, 1469 /* maxsize */ (dpt->max_dccbs * 1470 sizeof(struct dpt_ccb)) + 1471 sizeof(dpt_sp_t), 1472 /* nsegments */ 1, 1473 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 1474 /* flags */ 0, | 1435 goto error_exit; 1436 } 1437 1438 dpt->init_level++; 1439 1440 /* DMA tag for our ccb structures and interrupt status packet */ 1441 if (bus_dma_tag_create( /* parent */ dpt->parent_dmat, 1442 /* alignment */ 1, 1443 /* boundary */ 0, 1444 /* lowaddr */ BUS_SPACE_MAXADDR, 1445 /* highaddr */ BUS_SPACE_MAXADDR, 1446 /* filter */ NULL, 1447 /* filterarg */ NULL, 1448 /* maxsize */ (dpt->max_dccbs * 1449 sizeof(struct dpt_ccb)) + 1450 sizeof(dpt_sp_t), 1451 /* nsegments */ 1, 1452 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 1453 /* flags */ 0, |
1475 /* lockfunc */ busdma_lock_mutex, 1476 /* lockarg */ &Giant, | 1454 /* lockfunc */ NULL, 1455 /* lockarg */ NULL, |
1477 &dpt->dccb_dmat) != 0) { | 1456 &dpt->dccb_dmat) != 0) { |
1478 printf("dpt: bus_dma_tag_create(...,dpt->dccb_dmat) failed\n"); | 1457 device_printf(dpt->dev, 1458 "bus_dma_tag_create(...,dpt->dccb_dmat) failed\n"); |
1479 goto error_exit; 1480 } 1481 1482 dpt->init_level++; 1483 1484 /* Allocation for our ccbs and interrupt status packet */ 1485 if (bus_dmamem_alloc(dpt->dccb_dmat, (void **)&dpt->dpt_dccbs, 1486 BUS_DMA_NOWAIT, &dpt->dccb_dmamap) != 0) { | 1459 goto error_exit; 1460 } 1461 1462 dpt->init_level++; 1463 1464 /* Allocation for our ccbs and interrupt status packet */ 1465 if (bus_dmamem_alloc(dpt->dccb_dmat, (void **)&dpt->dpt_dccbs, 1466 BUS_DMA_NOWAIT, &dpt->dccb_dmamap) != 0) { |
1487 printf("dpt: bus_dmamem_alloc(dpt->dccb_dmat,...) failed\n"); | 1467 device_printf(dpt->dev, 1468 "bus_dmamem_alloc(dpt->dccb_dmat,...) failed\n"); |
1488 goto error_exit; 1489 } 1490 1491 dpt->init_level++; 1492 1493 /* And permanently map them */ 1494 bus_dmamap_load(dpt->dccb_dmat, dpt->dccb_dmamap, 1495 dpt->dpt_dccbs, --- 9 unchanged lines hidden (view full) --- 1505 1506 dpt->sp = (dpt_sp_t*)&dpt->dpt_dccbs[dpt->max_dccbs]; 1507 dpt->sp_physaddr = dpt->dpt_ccb_busbase 1508 + (dpt->max_dccbs * sizeof(dpt_ccb_t)); 1509 dpt->init_level++; 1510 1511 /* Allocate our first batch of ccbs */ 1512 if (dptallocccbs(dpt) == 0) { | 1469 goto error_exit; 1470 } 1471 1472 dpt->init_level++; 1473 1474 /* And permanently map them */ 1475 bus_dmamap_load(dpt->dccb_dmat, dpt->dccb_dmamap, 1476 dpt->dpt_dccbs, --- 9 unchanged lines hidden (view full) --- 1486 1487 dpt->sp = (dpt_sp_t*)&dpt->dpt_dccbs[dpt->max_dccbs]; 1488 dpt->sp_physaddr = dpt->dpt_ccb_busbase 1489 + (dpt->max_dccbs * sizeof(dpt_ccb_t)); 1490 dpt->init_level++; 1491 1492 /* Allocate our first batch of ccbs */ 1493 if (dptallocccbs(dpt) == 0) { |
1513 printf("dpt: dptallocccbs(dpt) == 0\n"); | 1494 device_printf(dpt->dev, "dptallocccbs(dpt) == 0\n"); 1495 mtx_unlock(&dpt->lock); |
1514 return (2); 1515 } 1516 1517 /* Prepare for Target Mode */ 1518 dpt->target_mode_enabled = 1; 1519 1520 /* Nuke excess spaces from inquiry information */ 1521 strp = dpt->board_data.vendor; 1522 for (i = 0; i < sizeof(string_sizes); i++) { 1523 index = string_sizes[i] - 1; 1524 while (index && (strp[index] == ' ')) 1525 strp[index--] = '\0'; 1526 strp += string_sizes[i]; 1527 } 1528 | 1496 return (2); 1497 } 1498 1499 /* Prepare for Target Mode */ 1500 dpt->target_mode_enabled = 1; 1501 1502 /* Nuke excess spaces from inquiry information */ 1503 strp = dpt->board_data.vendor; 1504 for (i = 0; i < sizeof(string_sizes); i++) { 1505 index = string_sizes[i] - 1; 1506 while (index && (strp[index] == ' ')) 1507 strp[index--] = '\0'; 1508 strp += string_sizes[i]; 1509 } 1510 |
1529 printf("dpt%d: %.8s %.16s FW Rev. %.4s, ", 1530 dpt->unit, dpt->board_data.vendor, | 1511 device_printf(dpt->dev, "%.8s %.16s FW Rev. %.4s, ", 1512 dpt->board_data.vendor, |
1531 dpt->board_data.modelNum, dpt->board_data.firmware); 1532 1533 printf("%d channel%s, ", dpt->channels, dpt->channels > 1 ? "s" : ""); 1534 1535 if (dpt->cache_type != DPT_NO_CACHE 1536 && dpt->cache_size != 0) { 1537 printf("%s Cache, ", 1538 dpt->cache_type == DPT_CACHE_WRITETHROUGH 1539 ? "Write-Through" : "Write-Back"); 1540 } 1541 1542 printf("%d CCBs\n", dpt->max_dccbs); | 1513 dpt->board_data.modelNum, dpt->board_data.firmware); 1514 1515 printf("%d channel%s, ", dpt->channels, dpt->channels > 1 ? "s" : ""); 1516 1517 if (dpt->cache_type != DPT_NO_CACHE 1518 && dpt->cache_size != 0) { 1519 printf("%s Cache, ", 1520 dpt->cache_type == DPT_CACHE_WRITETHROUGH 1521 ? "Write-Through" : "Write-Back"); 1522 } 1523 1524 printf("%d CCBs\n", dpt->max_dccbs); |
1525 mtx_unlock(&dpt->lock); |
|
1543 return (0); 1544 1545error_exit: | 1526 return (0); 1527 1528error_exit: |
1529 mtx_unlock(&dpt->lock); |
|
1546 return (1); 1547} 1548 1549int 1550dpt_attach(dpt_softc_t *dpt) 1551{ 1552 struct cam_devq *devq; 1553 int i; 1554 1555 /* 1556 * Create the device queue for our SIM. 1557 */ 1558 devq = cam_simq_alloc(dpt->max_dccbs); 1559 if (devq == NULL) 1560 return (0); 1561 | 1530 return (1); 1531} 1532 1533int 1534dpt_attach(dpt_softc_t *dpt) 1535{ 1536 struct cam_devq *devq; 1537 int i; 1538 1539 /* 1540 * Create the device queue for our SIM. 1541 */ 1542 devq = cam_simq_alloc(dpt->max_dccbs); 1543 if (devq == NULL) 1544 return (0); 1545 |
1546 mtx_lock(&dpt->lock); |
|
1562 for (i = 0; i < dpt->channels; i++) { 1563 /* 1564 * Construct our SIM entry 1565 */ 1566 dpt->sims[i] = cam_sim_alloc(dpt_action, dpt_poll, "dpt", | 1547 for (i = 0; i < dpt->channels; i++) { 1548 /* 1549 * Construct our SIM entry 1550 */ 1551 dpt->sims[i] = cam_sim_alloc(dpt_action, dpt_poll, "dpt", |
1567 dpt, dpt->unit, &Giant, | 1552 dpt, device_get_unit(dpt->dev), &dpt->lock, |
1568 /*untagged*/2, 1569 /*tagged*/dpt->max_dccbs, devq); 1570 if (dpt->sims[i] == NULL) { 1571 if (i == 0) 1572 cam_simq_free(devq); 1573 else 1574 printf( "%s(): Unable to attach bus %d " 1575 "due to resource shortage\n", --- 13 unchanged lines hidden (view full) --- 1589 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1590 xpt_bus_deregister(cam_sim_path(dpt->sims[i])); 1591 cam_sim_free(dpt->sims[i], /*free_devq*/i == 0); 1592 dpt->sims[i] = NULL; 1593 break; 1594 } 1595 1596 } | 1553 /*untagged*/2, 1554 /*tagged*/dpt->max_dccbs, devq); 1555 if (dpt->sims[i] == NULL) { 1556 if (i == 0) 1557 cam_simq_free(devq); 1558 else 1559 printf( "%s(): Unable to attach bus %d " 1560 "due to resource shortage\n", --- 13 unchanged lines hidden (view full) --- 1574 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1575 xpt_bus_deregister(cam_sim_path(dpt->sims[i])); 1576 cam_sim_free(dpt->sims[i], /*free_devq*/i == 0); 1577 dpt->sims[i] = NULL; 1578 break; 1579 } 1580 1581 } |
1582 mtx_unlock(&dpt->lock); |
|
1597 if (i > 0) 1598 EVENTHANDLER_REGISTER(shutdown_final, dptshutdown, 1599 dpt, SHUTDOWN_PRI_DEFAULT); 1600 return (i); 1601} 1602 1603int 1604dpt_detach (device_t dev) 1605{ 1606 struct dpt_softc * dpt; 1607 int i; 1608 1609 dpt = device_get_softc(dev); 1610 | 1583 if (i > 0) 1584 EVENTHANDLER_REGISTER(shutdown_final, dptshutdown, 1585 dpt, SHUTDOWN_PRI_DEFAULT); 1586 return (i); 1587} 1588 1589int 1590dpt_detach (device_t dev) 1591{ 1592 struct dpt_softc * dpt; 1593 int i; 1594 1595 dpt = device_get_softc(dev); 1596 |
1597 mtx_lock(&dpt->lock); |
|
1611 for (i = 0; i < dpt->channels; i++) { 1612#if 0 1613 xpt_async(AC_LOST_DEVICE, dpt->paths[i], NULL); 1614#endif 1615 xpt_free_path(dpt->paths[i]); 1616 xpt_bus_deregister(cam_sim_path(dpt->sims[i])); 1617 cam_sim_free(dpt->sims[i], /*free_devq*/TRUE); 1618 } | 1598 for (i = 0; i < dpt->channels; i++) { 1599#if 0 1600 xpt_async(AC_LOST_DEVICE, dpt->paths[i], NULL); 1601#endif 1602 xpt_free_path(dpt->paths[i]); 1603 xpt_bus_deregister(cam_sim_path(dpt->sims[i])); 1604 cam_sim_free(dpt->sims[i], /*free_devq*/TRUE); 1605 } |
1606 mtx_unlock(&dpt->lock); |
|
1619 1620 dptshutdown((void *)dpt, SHUTDOWN_PRI_DEFAULT); 1621 1622 dpt_release_resources(dev); 1623 1624 dpt_free(dpt); 1625 1626 return (0); 1627} 1628 1629/* 1630 * This is the interrupt handler for the DPT driver. 1631 */ 1632void 1633dpt_intr(void *arg) 1634{ 1635 dpt_softc_t *dpt; | 1607 1608 dptshutdown((void *)dpt, SHUTDOWN_PRI_DEFAULT); 1609 1610 dpt_release_resources(dev); 1611 1612 dpt_free(dpt); 1613 1614 return (0); 1615} 1616 1617/* 1618 * This is the interrupt handler for the DPT driver. 1619 */ 1620void 1621dpt_intr(void *arg) 1622{ 1623 dpt_softc_t *dpt; |
1624 1625 dpt = arg; 1626 mtx_lock(&dpt->lock); 1627 dpt_intr_locked(dpt); 1628 mtx_unlock(&dpt->lock); 1629} 1630 1631void 1632dpt_intr_locked(dpt_softc_t *dpt) 1633{ |
|
1636 dpt_ccb_t *dccb; 1637 union ccb *ccb; 1638 u_int status; 1639 u_int aux_status; 1640 u_int hba_stat; 1641 u_int scsi_stat; 1642 u_int32_t residue_len; /* Number of bytes not transferred */ 1643 | 1634 dpt_ccb_t *dccb; 1635 union ccb *ccb; 1636 u_int status; 1637 u_int aux_status; 1638 u_int hba_stat; 1639 u_int scsi_stat; 1640 u_int32_t residue_len; /* Number of bytes not transferred */ 1641 |
1644 dpt = (dpt_softc_t *)arg; 1645 | |
1646 /* First order of business is to check if this interrupt is for us */ 1647 while (((aux_status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ) != 0) { 1648 1649 /* 1650 * What we want to do now, is to capture the status, all of it, 1651 * move it where it belongs, wake up whoever sleeps waiting to 1652 * process this result, and get out of here. 1653 */ 1654 if (dpt->sp->ccb_busaddr < dpt->dpt_ccb_busbase 1655 || dpt->sp->ccb_busaddr >= dpt->dpt_ccb_busend) { | 1642 /* First order of business is to check if this interrupt is for us */ 1643 while (((aux_status = dpt_inb(dpt, HA_RAUXSTAT)) & HA_AIRQ) != 0) { 1644 1645 /* 1646 * What we want to do now, is to capture the status, all of it, 1647 * move it where it belongs, wake up whoever sleeps waiting to 1648 * process this result, and get out of here. 1649 */ 1650 if (dpt->sp->ccb_busaddr < dpt->dpt_ccb_busbase 1651 || dpt->sp->ccb_busaddr >= dpt->dpt_ccb_busend) { |
1656 printf("Encountered bogus status packet\n"); | 1652 device_printf(dpt->dev, 1653 "Encountered bogus status packet\n"); |
1657 status = dpt_inb(dpt, HA_RSTATUS); 1658 return; 1659 } 1660 1661 dccb = dptccbptov(dpt, dpt->sp->ccb_busaddr); 1662 1663 dpt->sp->ccb_busaddr = ~0; 1664 1665 /* Ignore status packets with EOC not set */ 1666 if (dpt->sp->EOC == 0) { | 1654 status = dpt_inb(dpt, HA_RSTATUS); 1655 return; 1656 } 1657 1658 dccb = dptccbptov(dpt, dpt->sp->ccb_busaddr); 1659 1660 dpt->sp->ccb_busaddr = ~0; 1661 1662 /* Ignore status packets with EOC not set */ 1663 if (dpt->sp->EOC == 0) { |
1667 printf("dpt%d ERROR: Request %d received with " | 1664 device_printf(dpt->dev, 1665 "ERROR: Request %d received with " |
1668 "clear EOC.\n Marking as LOST.\n", | 1666 "clear EOC.\n Marking as LOST.\n", |
1669 dpt->unit, dccb->transaction_id); | 1667 dccb->transaction_id); |
1670 1671#ifdef DPT_HANDLE_TIMEOUTS 1672 dccb->state |= DPT_CCB_STATE_MARKED_LOST; 1673#endif 1674 /* This CLEARS the interrupt! */ 1675 status = dpt_inb(dpt, HA_RSTATUS); 1676 continue; 1677 } --- 13 unchanged lines hidden (view full) --- 1691 if ((status = dpt_inb(dpt, HA_RSTATUS)) & HA_SERROR) { 1692 /* 1693 * Error Condition. Check for magic cookie. Exit 1694 * this test on earliest sign of non-reset condition 1695 */ 1696 1697 /* Check that this is not a board reset interrupt */ 1698 if (dpt_just_reset(dpt)) { | 1668 1669#ifdef DPT_HANDLE_TIMEOUTS 1670 dccb->state |= DPT_CCB_STATE_MARKED_LOST; 1671#endif 1672 /* This CLEARS the interrupt! */ 1673 status = dpt_inb(dpt, HA_RSTATUS); 1674 continue; 1675 } --- 13 unchanged lines hidden (view full) --- 1689 if ((status = dpt_inb(dpt, HA_RSTATUS)) & HA_SERROR) { 1690 /* 1691 * Error Condition. Check for magic cookie. Exit 1692 * this test on earliest sign of non-reset condition 1693 */ 1694 1695 /* Check that this is not a board reset interrupt */ 1696 if (dpt_just_reset(dpt)) { |
1699 printf("dpt%d: HBA rebooted.\n" | 1697 device_printf(dpt->dev, "HBA rebooted.\n" |
1700 " All transactions should be " | 1698 " All transactions should be " |
1701 "resubmitted\n", 1702 dpt->unit); | 1699 "resubmitted\n"); |
1703 | 1700 |
1704 printf("dpt%d: >>---->> This is incomplete, " 1705 "fix me.... <<----<<", dpt->unit); | 1701 device_printf(dpt->dev, 1702 ">>---->> This is incomplete, " 1703 "fix me.... <<----<<"); |
1706 panic("DPT Rebooted"); 1707 1708 } 1709 } 1710 /* Process CCB */ 1711 ccb = dccb->ccb; | 1704 panic("DPT Rebooted"); 1705 1706 } 1707 } 1708 /* Process CCB */ 1709 ccb = dccb->ccb; |
1712 untimeout(dpttimeout, dccb, ccb->ccb_h.timeout_ch); | 1710 callout_stop(&dccb->timer); |
1713 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1714 bus_dmasync_op_t op; 1715 1716 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 1717 op = BUS_DMASYNC_POSTREAD; 1718 else 1719 op = BUS_DMASYNC_POSTWRITE; 1720 bus_dmamap_sync(dpt->buffer_dmat, dccb->dmamap, op); --- 77 unchanged lines hidden (view full) --- 1798 * from these conditions 1799 */ 1800 ccb->ccb_h.status = CAM_NO_HBA; 1801 break; 1802 case HA_RSENSE_FAIL: 1803 ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; 1804 break; 1805 default: | 1711 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1712 bus_dmasync_op_t op; 1713 1714 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 1715 op = BUS_DMASYNC_POSTREAD; 1716 else 1717 op = BUS_DMASYNC_POSTWRITE; 1718 bus_dmamap_sync(dpt->buffer_dmat, dccb->dmamap, op); --- 77 unchanged lines hidden (view full) --- 1796 * from these conditions 1797 */ 1798 ccb->ccb_h.status = CAM_NO_HBA; 1799 break; 1800 case HA_RSENSE_FAIL: 1801 ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; 1802 break; 1803 default: |
1806 printf("dpt%d: Undocumented Error %x\n", dpt->unit, hba_stat); | 1804 device_printf(dpt->dev, "Undocumented Error %x\n", hba_stat); |
1807 printf("Please mail this message to shimon@simon-shapiro.org\n"); 1808 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1809 break; 1810 } 1811 dptfreeccb(dpt, dccb); 1812 xpt_done(ccb); 1813} 1814 1815static void 1816dpttimeout(void *arg) 1817{ 1818 struct dpt_ccb *dccb; 1819 union ccb *ccb; 1820 struct dpt_softc *dpt; | 1805 printf("Please mail this message to shimon@simon-shapiro.org\n"); 1806 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1807 break; 1808 } 1809 dptfreeccb(dpt, dccb); 1810 xpt_done(ccb); 1811} 1812 1813static void 1814dpttimeout(void *arg) 1815{ 1816 struct dpt_ccb *dccb; 1817 union ccb *ccb; 1818 struct dpt_softc *dpt; |
1821 int s; | |
1822 1823 dccb = (struct dpt_ccb *)arg; 1824 ccb = dccb->ccb; 1825 dpt = (struct dpt_softc *)ccb->ccb_h.ccb_dpt_ptr; | 1819 1820 dccb = (struct dpt_ccb *)arg; 1821 ccb = dccb->ccb; 1822 dpt = (struct dpt_softc *)ccb->ccb_h.ccb_dpt_ptr; |
1823 mtx_assert(&dpt->lock, MA_OWNED); |
|
1826 xpt_print_path(ccb->ccb_h.path); 1827 printf("CCB %p - timed out\n", (void *)dccb); 1828 | 1824 xpt_print_path(ccb->ccb_h.path); 1825 printf("CCB %p - timed out\n", (void *)dccb); 1826 |
1829 s = splcam(); 1830 | |
1831 /* 1832 * Try to clear any pending jobs. FreeBSD will lose interrupts, 1833 * leaving the controller suspended, and commands timed-out. 1834 * By calling the interrupt handler, any command thus stuck will be 1835 * completed. 1836 */ | 1827 /* 1828 * Try to clear any pending jobs. FreeBSD will lose interrupts, 1829 * leaving the controller suspended, and commands timed-out. 1830 * By calling the interrupt handler, any command thus stuck will be 1831 * completed. 1832 */ |
1837 dpt_intr(dpt); | 1833 dpt_intr_locked(dpt); |
1838 1839 if ((dccb->state & DCCB_ACTIVE) == 0) { 1840 xpt_print_path(ccb->ccb_h.path); 1841 printf("CCB %p - timed out CCB already completed\n", 1842 (void *)dccb); | 1834 1835 if ((dccb->state & DCCB_ACTIVE) == 0) { 1836 xpt_print_path(ccb->ccb_h.path); 1837 printf("CCB %p - timed out CCB already completed\n", 1838 (void *)dccb); |
1843 splx(s); | |
1844 return; 1845 } 1846 1847 /* Abort this particular command. Leave all others running */ 1848 dpt_send_immediate(dpt, &dccb->eata_ccb, dccb->eata_ccb.cp_busaddr, 1849 /*retries*/20000, EATA_SPECIFIC_ABORT, 0, 0); 1850 ccb->ccb_h.status = CAM_CMD_TIMEOUT; | 1839 return; 1840 } 1841 1842 /* Abort this particular command. Leave all others running */ 1843 dpt_send_immediate(dpt, &dccb->eata_ccb, dccb->eata_ccb.cp_busaddr, 1844 /*retries*/20000, EATA_SPECIFIC_ABORT, 0, 0); 1845 ccb->ccb_h.status = CAM_CMD_TIMEOUT; |
1851 splx(s); | |
1852} 1853 1854/* 1855 * Shutdown the controller and ensure that the cache is completely flushed. 1856 * Called from the shutdown_final event after all disk access has completed. 1857 */ 1858static void 1859dptshutdown(void *arg, int howto) 1860{ 1861 dpt_softc_t *dpt; 1862 1863 dpt = (dpt_softc_t *)arg; 1864 | 1846} 1847 1848/* 1849 * Shutdown the controller and ensure that the cache is completely flushed. 1850 * Called from the shutdown_final event after all disk access has completed. 1851 */ 1852static void 1853dptshutdown(void *arg, int howto) 1854{ 1855 dpt_softc_t *dpt; 1856 1857 dpt = (dpt_softc_t *)arg; 1858 |
1865 printf("dpt%d: Shutting down (mode %x) HBA. Please wait...\n", 1866 dpt->unit, howto); | 1859 device_printf(dpt->dev, 1860 "Shutting down (mode %x) HBA. Please wait...\n", howto); |
1867 1868 /* 1869 * What we do for a shutdown, is give the DPT early power loss warning 1870 */ | 1861 1862 /* 1863 * What we do for a shutdown, is give the DPT early power loss warning 1864 */ |
1865 mtx_lock(&dpt->lock); |
|
1871 dpt_send_immediate(dpt, NULL, 0, EATA_POWER_OFF_WARN, 0, 0, 0); | 1866 dpt_send_immediate(dpt, NULL, 0, EATA_POWER_OFF_WARN, 0, 0, 0); |
1867 mtx_unlock(&dpt->lock); |
|
1872 DELAY(1000 * 1000 * 5); | 1868 DELAY(1000 * 1000 * 5); |
1873 printf("dpt%d: Controller was warned of shutdown and is now " 1874 "disabled\n", dpt->unit); | 1869 device_printf(dpt->dev, "Controller was warned of shutdown and is now " 1870 "disabled\n"); |
1875} 1876 1877/*============================================================================*/ 1878 1879#if 0 1880#ifdef DPT_RESET_HBA 1881 1882/* 1883** Function name : dpt_reset_hba 1884** 1885** Description : Reset the HBA and properly discard all pending work 1886** Input : Softc 1887** Output : Nothing 1888*/ 1889static void 1890dpt_reset_hba(dpt_softc_t *dpt) 1891{ 1892 eata_ccb_t *ccb; | 1871} 1872 1873/*============================================================================*/ 1874 1875#if 0 1876#ifdef DPT_RESET_HBA 1877 1878/* 1879** Function name : dpt_reset_hba 1880** 1881** Description : Reset the HBA and properly discard all pending work 1882** Input : Softc 1883** Output : Nothing 1884*/ 1885static void 1886dpt_reset_hba(dpt_softc_t *dpt) 1887{ 1888 eata_ccb_t *ccb; |
1893 int ospl; | |
1894 dpt_ccb_t dccb, *dccbp; 1895 int result; 1896 struct scsi_xfer *xs; | 1889 dpt_ccb_t dccb, *dccbp; 1890 int result; 1891 struct scsi_xfer *xs; |
1897 | 1892 1893 mtx_assert(&dpt->lock, MA_OWNED); 1894 |
1898 /* Prepare a control block. The SCSI command part is immaterial */ 1899 dccb.xs = NULL; 1900 dccb.flags = 0; 1901 dccb.state = DPT_CCB_STATE_NEW; 1902 dccb.std_callback = NULL; 1903 dccb.wrbuff_callback = NULL; 1904 1905 ccb = &dccb.eata_ccb; --- 9 unchanged lines hidden (view full) --- 1915 ccb->cp_statDMA = htonl(vtophys(&ccb->cp_statDMA)); 1916 ccb->cp_reqDMA = htonl(vtophys(&ccb->cp_reqDMA)); 1917 ccb->cp_viraddr = (u_int32_t) & ccb; 1918 1919 ccb->cp_msg[0] = HA_IDENTIFY_MSG | HA_DISCO_RECO; 1920 ccb->cp_scsi_cmd = 0; /* Should be ignored */ 1921 1922 /* Lock up the submitted queue. We are very persistant here */ | 1895 /* Prepare a control block. The SCSI command part is immaterial */ 1896 dccb.xs = NULL; 1897 dccb.flags = 0; 1898 dccb.state = DPT_CCB_STATE_NEW; 1899 dccb.std_callback = NULL; 1900 dccb.wrbuff_callback = NULL; 1901 1902 ccb = &dccb.eata_ccb; --- 9 unchanged lines hidden (view full) --- 1912 ccb->cp_statDMA = htonl(vtophys(&ccb->cp_statDMA)); 1913 ccb->cp_reqDMA = htonl(vtophys(&ccb->cp_reqDMA)); 1914 ccb->cp_viraddr = (u_int32_t) & ccb; 1915 1916 ccb->cp_msg[0] = HA_IDENTIFY_MSG | HA_DISCO_RECO; 1917 ccb->cp_scsi_cmd = 0; /* Should be ignored */ 1918 1919 /* Lock up the submitted queue. We are very persistant here */ |
1923 ospl = splcam(); | |
1924 while (dpt->queue_status & DPT_SUBMITTED_QUEUE_ACTIVE) { 1925 DELAY(100); 1926 } 1927 1928 dpt->queue_status |= DPT_SUBMITTED_QUEUE_ACTIVE; | 1920 while (dpt->queue_status & DPT_SUBMITTED_QUEUE_ACTIVE) { 1921 DELAY(100); 1922 } 1923 1924 dpt->queue_status |= DPT_SUBMITTED_QUEUE_ACTIVE; |
1929 splx(ospl); | |
1930 1931 /* Send the RESET message */ 1932 if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb, 1933 EATA_CMD_RESET, 0, 0, 0, 0)) != 0) { | 1925 1926 /* Send the RESET message */ 1927 if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb, 1928 EATA_CMD_RESET, 0, 0, 0, 0)) != 0) { |
1934 printf("dpt%d: Failed to send the RESET message.\n" 1935 " Trying cold boot (ouch!)\n", dpt->unit); | 1929 device_printf(dpt->dev, "Failed to send the RESET message.\n" 1930 " Trying cold boot (ouch!)\n"); |
1936 1937 1938 if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb, 1939 EATA_COLD_BOOT, 0, 0, 1940 0, 0)) != 0) { | 1931 1932 1933 if ((result = dpt_send_eata_command(dpt, &dccb.eata_ccb, 1934 EATA_COLD_BOOT, 0, 0, 1935 0, 0)) != 0) { |
1941 panic("dpt%d: Faild to cold boot the HBA\n", 1942 dpt->unit); | 1936 panic("%s: Faild to cold boot the HBA\n", 1937 device_get_nameunit(dpt->dev)); |
1943 } 1944#ifdef DPT_MEASURE_PERFORMANCE 1945 dpt->performance.cold_boots++; 1946#endif /* DPT_MEASURE_PERFORMANCE */ 1947 } 1948 1949#ifdef DPT_MEASURE_PERFORMANCE 1950 dpt->performance.warm_starts++; 1951#endif /* DPT_MEASURE_PERFORMANCE */ 1952 | 1938 } 1939#ifdef DPT_MEASURE_PERFORMANCE 1940 dpt->performance.cold_boots++; 1941#endif /* DPT_MEASURE_PERFORMANCE */ 1942 } 1943 1944#ifdef DPT_MEASURE_PERFORMANCE 1945 dpt->performance.warm_starts++; 1946#endif /* DPT_MEASURE_PERFORMANCE */ 1947 |
1953 printf("dpt%d: Aborting pending requests. O/S should re-submit\n", 1954 dpt->unit); | 1948 device_printf(dpt->dev, 1949 "Aborting pending requests. O/S should re-submit\n"); |
1955 1956 while ((dccbp = TAILQ_FIRST(&dpt->completed_ccbs)) != NULL) { 1957 struct scsi_xfer *xs = dccbp->xs; 1958 1959 /* Not all transactions have xs structs */ 1960 if (xs != NULL) { 1961 /* Tell the kernel proper this did not complete well */ 1962 xs->error |= XS_SELTIMEOUT; 1963 xs->flags |= SCSI_ITSDONE; 1964 scsi_done(xs); 1965 } 1966 1967 dpt_Qremove_submitted(dpt, dccbp); 1968 1969 /* Remember, Callbacks are NOT in the standard queue */ 1970 if (dccbp->std_callback != NULL) { 1971 (dccbp->std_callback)(dpt, dccbp->eata_ccb.cp_channel, 1972 dccbp); 1973 } else { | 1950 1951 while ((dccbp = TAILQ_FIRST(&dpt->completed_ccbs)) != NULL) { 1952 struct scsi_xfer *xs = dccbp->xs; 1953 1954 /* Not all transactions have xs structs */ 1955 if (xs != NULL) { 1956 /* Tell the kernel proper this did not complete well */ 1957 xs->error |= XS_SELTIMEOUT; 1958 xs->flags |= SCSI_ITSDONE; 1959 scsi_done(xs); 1960 } 1961 1962 dpt_Qremove_submitted(dpt, dccbp); 1963 1964 /* Remember, Callbacks are NOT in the standard queue */ 1965 if (dccbp->std_callback != NULL) { 1966 (dccbp->std_callback)(dpt, dccbp->eata_ccb.cp_channel, 1967 dccbp); 1968 } else { |
1974 ospl = splcam(); | |
1975 dpt_Qpush_free(dpt, dccbp); | 1969 dpt_Qpush_free(dpt, dccbp); |
1976 splx(ospl); | |
1977 } 1978 } 1979 | 1970 } 1971 } 1972 |
1980 printf("dpt%d: reset done aborting all pending commands\n", dpt->unit); | 1973 device_printf(dpt->dev, "reset done aborting all pending commands\n"); |
1981 dpt->queue_status &= ~DPT_SUBMITTED_QUEUE_ACTIVE; 1982} 1983 1984#endif /* DPT_RESET_HBA */ 1985 1986/* 1987 * Build a Command Block for target mode READ/WRITE BUFFER, 1988 * with the ``sync'' bit ON. --- 5 unchanged lines hidden (view full) --- 1994 */ 1995 1996static void 1997dpt_target_ccb(dpt_softc_t * dpt, int bus, u_int8_t target, u_int8_t lun, 1998 dpt_ccb_t * ccb, int mode, u_int8_t command, 1999 u_int16_t length, u_int16_t offset) 2000{ 2001 eata_ccb_t *cp; | 1974 dpt->queue_status &= ~DPT_SUBMITTED_QUEUE_ACTIVE; 1975} 1976 1977#endif /* DPT_RESET_HBA */ 1978 1979/* 1980 * Build a Command Block for target mode READ/WRITE BUFFER, 1981 * with the ``sync'' bit ON. --- 5 unchanged lines hidden (view full) --- 1987 */ 1988 1989static void 1990dpt_target_ccb(dpt_softc_t * dpt, int bus, u_int8_t target, u_int8_t lun, 1991 dpt_ccb_t * ccb, int mode, u_int8_t command, 1992 u_int16_t length, u_int16_t offset) 1993{ 1994 eata_ccb_t *cp; |
2002 int ospl; | |
2003 | 1995 |
1996 mtx_assert(&dpt->lock, MA_OWNED); |
|
2004 if ((length + offset) > DPT_MAX_TARGET_MODE_BUFFER_SIZE) { | 1997 if ((length + offset) > DPT_MAX_TARGET_MODE_BUFFER_SIZE) { |
2005 printf("dpt%d: Length of %d, and offset of %d are wrong\n", 2006 dpt->unit, length, offset); | 1998 device_printf(dpt->dev, 1999 "Length of %d, and offset of %d are wrong\n", 2000 length, offset); |
2007 length = DPT_MAX_TARGET_MODE_BUFFER_SIZE; 2008 offset = 0; 2009 } 2010 ccb->xs = NULL; 2011 ccb->flags = 0; 2012 ccb->state = DPT_CCB_STATE_NEW; 2013 ccb->std_callback = (ccb_callback) dpt_target_done; 2014 ccb->wrbuff_callback = NULL; --- 27 unchanged lines hidden (view full) --- 2042 cp->cp_cdb[9] = 0; /* No sync, no match bits */ 2043 2044 /* 2045 * This could be optimized to live in dpt_register_buffer. 2046 * We keep it here, just in case the kernel decides to reallocate pages 2047 */ 2048 if (dpt_scatter_gather(dpt, ccb, DPT_RW_BUFFER_SIZE, 2049 dpt->rw_buffer[bus][target][lun])) { | 2001 length = DPT_MAX_TARGET_MODE_BUFFER_SIZE; 2002 offset = 0; 2003 } 2004 ccb->xs = NULL; 2005 ccb->flags = 0; 2006 ccb->state = DPT_CCB_STATE_NEW; 2007 ccb->std_callback = (ccb_callback) dpt_target_done; 2008 ccb->wrbuff_callback = NULL; --- 27 unchanged lines hidden (view full) --- 2036 cp->cp_cdb[9] = 0; /* No sync, no match bits */ 2037 2038 /* 2039 * This could be optimized to live in dpt_register_buffer. 2040 * We keep it here, just in case the kernel decides to reallocate pages 2041 */ 2042 if (dpt_scatter_gather(dpt, ccb, DPT_RW_BUFFER_SIZE, 2043 dpt->rw_buffer[bus][target][lun])) { |
2050 printf("dpt%d: Failed to setup Scatter/Gather for " 2051 "Target-Mode buffer\n", dpt->unit); | 2044 device_printf(dpt->dev, "Failed to setup Scatter/Gather for " 2045 "Target-Mode buffer\n"); |
2052 } 2053} 2054 2055/* Setup a target mode READ command */ 2056 2057static void 2058dpt_set_target(int redo, dpt_softc_t * dpt, 2059 u_int8_t bus, u_int8_t target, u_int8_t lun, int mode, 2060 u_int16_t length, u_int16_t offset, dpt_ccb_t * ccb) 2061{ | 2046 } 2047} 2048 2049/* Setup a target mode READ command */ 2050 2051static void 2052dpt_set_target(int redo, dpt_softc_t * dpt, 2053 u_int8_t bus, u_int8_t target, u_int8_t lun, int mode, 2054 u_int16_t length, u_int16_t offset, dpt_ccb_t * ccb) 2055{ |
2062 int ospl; | |
2063 | 2056 |
2057 mtx_assert(&dpt->lock, MA_OWNED); |
|
2064 if (dpt->target_mode_enabled) { | 2058 if (dpt->target_mode_enabled) { |
2065 ospl = splcam(); 2066 | |
2067 if (!redo) 2068 dpt_target_ccb(dpt, bus, target, lun, ccb, mode, 2069 SCSI_TM_READ_BUFFER, length, offset); 2070 2071 ccb->transaction_id = ++dpt->commands_processed; 2072 2073#ifdef DPT_MEASURE_PERFORMANCE 2074 dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++; 2075 ccb->command_started = microtime_now; 2076#endif 2077 dpt_Qadd_waiting(dpt, ccb); 2078 dpt_sched_queue(dpt); | 2059 if (!redo) 2060 dpt_target_ccb(dpt, bus, target, lun, ccb, mode, 2061 SCSI_TM_READ_BUFFER, length, offset); 2062 2063 ccb->transaction_id = ++dpt->commands_processed; 2064 2065#ifdef DPT_MEASURE_PERFORMANCE 2066 dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++; 2067 ccb->command_started = microtime_now; 2068#endif 2069 dpt_Qadd_waiting(dpt, ccb); 2070 dpt_sched_queue(dpt); |
2079 2080 splx(ospl); | |
2081 } else { | 2071 } else { |
2082 printf("dpt%d: Target Mode Request, but Target Mode is OFF\n", 2083 dpt->unit); | 2072 device_printf(dpt->dev, 2073 "Target Mode Request, but Target Mode is OFF\n"); |
2084 } 2085} 2086 2087/* 2088 * Schedule a buffer to be sent to another target. 2089 * The work will be scheduled and the callback provided will be called when 2090 * the work is actually done. 2091 * 2092 * Please NOTE: ``Anyone'' can send a buffer, but only registered clients 2093 * get notified of receipt of buffers. 2094 */ 2095 2096int 2097dpt_send_buffer(int unit, u_int8_t channel, u_int8_t target, u_int8_t lun, 2098 u_int8_t mode, u_int16_t length, u_int16_t offset, void *data, 2099 buff_wr_done callback) 2100{ 2101 dpt_softc_t *dpt; 2102 dpt_ccb_t *ccb = NULL; | 2074 } 2075} 2076 2077/* 2078 * Schedule a buffer to be sent to another target. 2079 * The work will be scheduled and the callback provided will be called when 2080 * the work is actually done. 2081 * 2082 * Please NOTE: ``Anyone'' can send a buffer, but only registered clients 2083 * get notified of receipt of buffers. 2084 */ 2085 2086int 2087dpt_send_buffer(int unit, u_int8_t channel, u_int8_t target, u_int8_t lun, 2088 u_int8_t mode, u_int16_t length, u_int16_t offset, void *data, 2089 buff_wr_done callback) 2090{ 2091 dpt_softc_t *dpt; 2092 dpt_ccb_t *ccb = NULL; |
2103 int ospl; | |
2104 2105 /* This is an external call. Be a bit paranoid */ | 2093 2094 /* This is an external call. Be a bit paranoid */ |
2106 for (dpt = TAILQ_FIRST(&dpt_softc_list); 2107 dpt != NULL; 2108 dpt = TAILQ_NEXT(dpt, links)) { 2109 if (dpt->unit == unit) 2110 goto valid_unit; 2111 } | 2095 dpt = devclass_get_device(dpt_devclass, unit); 2096 if (dpt == NULL) 2097 return (INVALID_UNIT); |
2112 | 2098 |
2113 return (INVALID_UNIT); 2114 2115valid_unit: 2116 | 2099 mtx_lock(&dpt->lock); |
2117 if (dpt->target_mode_enabled) { 2118 if ((channel >= dpt->channels) || (target > dpt->max_id) || 2119 (lun > dpt->max_lun)) { | 2100 if (dpt->target_mode_enabled) { 2101 if ((channel >= dpt->channels) || (target > dpt->max_id) || 2102 (lun > dpt->max_lun)) { |
2103 mtx_unlock(&dpt->lock); |
|
2120 return (INVALID_SENDER); 2121 } 2122 if ((dpt->rw_buffer[channel][target][lun] == NULL) || | 2104 return (INVALID_SENDER); 2105 } 2106 if ((dpt->rw_buffer[channel][target][lun] == NULL) || |
2123 (dpt->buffer_receiver[channel][target][lun] == NULL)) | 2107 (dpt->buffer_receiver[channel][target][lun] == NULL)) { 2108 mtx_unlock(&dpt->lock); |
2124 return (NOT_REGISTERED); | 2109 return (NOT_REGISTERED); |
2110 } |
|
2125 | 2111 |
2126 ospl = splsoftcam(); | |
2127 /* Process the free list */ 2128 if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) { | 2112 /* Process the free list */ 2113 if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) { |
2129 printf("dpt%d ERROR: Cannot allocate any more free CCB's.\n" 2130 " Please try later\n", 2131 dpt->unit); 2132 splx(ospl); | 2114 device_printf(dpt->dev, 2115 "ERROR: Cannot allocate any more free CCB's.\n" 2116 " Please try later\n"); 2117 mtx_unlock(&dpt->lock); |
2133 return (NO_RESOURCES); 2134 } 2135 /* Now grab the newest CCB */ 2136 if ((ccb = dpt_Qpop_free(dpt)) == NULL) { | 2118 return (NO_RESOURCES); 2119 } 2120 /* Now grab the newest CCB */ 2121 if ((ccb = dpt_Qpop_free(dpt)) == NULL) { |
2137 splx(ospl); 2138 panic("dpt%d: Got a NULL CCB from pop_free()\n", dpt->unit); | 2122 mtx_unlock(&dpt->lock); 2123 panic("%s: Got a NULL CCB from pop_free()\n", 2124 device_get_nameunit(dpt->dev)); |
2139 } | 2125 } |
2140 splx(ospl); | |
2141 2142 bcopy(dpt->rw_buffer[channel][target][lun] + offset, data, length); 2143 dpt_target_ccb(dpt, channel, target, lun, ccb, mode, 2144 SCSI_TM_WRITE_BUFFER, 2145 length, offset); 2146 ccb->std_callback = (ccb_callback) callback; /* Potential trouble */ 2147 | 2126 2127 bcopy(dpt->rw_buffer[channel][target][lun] + offset, data, length); 2128 dpt_target_ccb(dpt, channel, target, lun, ccb, mode, 2129 SCSI_TM_WRITE_BUFFER, 2130 length, offset); 2131 ccb->std_callback = (ccb_callback) callback; /* Potential trouble */ 2132 |
2148 ospl = splcam(); | |
2149 ccb->transaction_id = ++dpt->commands_processed; 2150 2151#ifdef DPT_MEASURE_PERFORMANCE 2152 dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++; 2153 ccb->command_started = microtime_now; 2154#endif 2155 dpt_Qadd_waiting(dpt, ccb); 2156 dpt_sched_queue(dpt); 2157 | 2133 ccb->transaction_id = ++dpt->commands_processed; 2134 2135#ifdef DPT_MEASURE_PERFORMANCE 2136 dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]++; 2137 ccb->command_started = microtime_now; 2138#endif 2139 dpt_Qadd_waiting(dpt, ccb); 2140 dpt_sched_queue(dpt); 2141 |
2158 splx(ospl); | 2142 mtx_unlock(&dpt->lock); |
2159 return (0); 2160 } | 2143 return (0); 2144 } |
2145 mtx_unlock(&dpt->lock); |
|
2161 return (DRIVER_DOWN); 2162} 2163 2164static void 2165dpt_target_done(dpt_softc_t * dpt, int bus, dpt_ccb_t * ccb) 2166{ | 2146 return (DRIVER_DOWN); 2147} 2148 2149static void 2150dpt_target_done(dpt_softc_t * dpt, int bus, dpt_ccb_t * ccb) 2151{ |
2167 int ospl; | |
2168 eata_ccb_t *cp; 2169 2170 cp = &ccb->eata_ccb; 2171 2172 /* 2173 * Remove the CCB from the waiting queue. 2174 * We do NOT put it back on the free, etc., queues as it is a special 2175 * ccb, owned by the dpt_softc of this unit. 2176 */ | 2152 eata_ccb_t *cp; 2153 2154 cp = &ccb->eata_ccb; 2155 2156 /* 2157 * Remove the CCB from the waiting queue. 2158 * We do NOT put it back on the free, etc., queues as it is a special 2159 * ccb, owned by the dpt_softc of this unit. 2160 */ |
2177 ospl = splsoftcam(); | |
2178 dpt_Qremove_completed(dpt, ccb); | 2161 dpt_Qremove_completed(dpt, ccb); |
2179 splx(ospl); | |
2180 2181#define br_channel (ccb->eata_ccb.cp_channel) 2182#define br_target (ccb->eata_ccb.cp_id) 2183#define br_lun (ccb->eata_ccb.cp_LUN) 2184#define br_index [br_channel][br_target][br_lun] 2185#define read_buffer_callback (dpt->buffer_receiver br_index ) 2186#define read_buffer (dpt->rw_buffer[br_channel][br_target][br_lun]) 2187#define cb(offset) (ccb->eata_ccb.cp_cdb[offset]) 2188#define br_offset ((cb(3) << 16) | (cb(4) << 8) | cb(5)) 2189#define br_length ((cb(6) << 16) | (cb(7) << 8) | cb(8)) 2190 2191 /* Different reasons for being here, you know... */ 2192 switch (ccb->eata_ccb.cp_scsi_cmd) { 2193 case SCSI_TM_READ_BUFFER: 2194 if (read_buffer_callback != NULL) { 2195 /* This is a buffer generated by a kernel process */ | 2162 2163#define br_channel (ccb->eata_ccb.cp_channel) 2164#define br_target (ccb->eata_ccb.cp_id) 2165#define br_lun (ccb->eata_ccb.cp_LUN) 2166#define br_index [br_channel][br_target][br_lun] 2167#define read_buffer_callback (dpt->buffer_receiver br_index ) 2168#define read_buffer (dpt->rw_buffer[br_channel][br_target][br_lun]) 2169#define cb(offset) (ccb->eata_ccb.cp_cdb[offset]) 2170#define br_offset ((cb(3) << 16) | (cb(4) << 8) | cb(5)) 2171#define br_length ((cb(6) << 16) | (cb(7) << 8) | cb(8)) 2172 2173 /* Different reasons for being here, you know... */ 2174 switch (ccb->eata_ccb.cp_scsi_cmd) { 2175 case SCSI_TM_READ_BUFFER: 2176 if (read_buffer_callback != NULL) { 2177 /* This is a buffer generated by a kernel process */ |
2196 read_buffer_callback(dpt->unit, br_channel, 2197 br_target, br_lun, | 2178 read_buffer_callback(device_get_unit(dpt->dev), 2179 br_channel, br_target, br_lun, |
2198 read_buffer, 2199 br_offset, br_length); 2200 } else { 2201 /* 2202 * This is a buffer waited for by a user (sleeping) 2203 * command 2204 */ 2205 wakeup(ccb); 2206 } 2207 2208 /* We ALWAYS re-issue the same command; args are don't-care */ 2209 dpt_set_target(1, 0, 0, 0, 0, 0, 0, 0, 0); 2210 break; 2211 2212 case SCSI_TM_WRITE_BUFFER: | 2180 read_buffer, 2181 br_offset, br_length); 2182 } else { 2183 /* 2184 * This is a buffer waited for by a user (sleeping) 2185 * command 2186 */ 2187 wakeup(ccb); 2188 } 2189 2190 /* We ALWAYS re-issue the same command; args are don't-care */ 2191 dpt_set_target(1, 0, 0, 0, 0, 0, 0, 0, 0); 2192 break; 2193 2194 case SCSI_TM_WRITE_BUFFER: |
2213 (ccb->wrbuff_callback) (dpt->unit, br_channel, br_target, 2214 br_offset, br_length, | 2195 (ccb->wrbuff_callback) (device_get_unit(dpt->dev), br_channel, 2196 br_target, br_offset, br_length, |
2215 br_lun, ccb->status_packet.hba_stat); 2216 break; 2217 default: | 2197 br_lun, ccb->status_packet.hba_stat); 2198 break; 2199 default: |
2218 printf("dpt%d: %s is an unsupported command for target mode\n", 2219 dpt->unit, scsi_cmd_name(ccb->eata_ccb.cp_scsi_cmd)); | 2200 device_printf(dpt->dev, 2201 "%s is an unsupported command for target mode\n", 2202 scsi_cmd_name(ccb->eata_ccb.cp_scsi_cmd)); |
2220 } | 2203 } |
2221 ospl = splsoftcam(); | |
2222 dpt->target_ccb[br_channel][br_target][br_lun] = NULL; 2223 dpt_Qpush_free(dpt, ccb); | 2204 dpt->target_ccb[br_channel][br_target][br_lun] = NULL; 2205 dpt_Qpush_free(dpt, ccb); |
2224 splx(ospl); | |
2225} 2226 2227 2228/* 2229 * Use this function to register a client for a buffer read target operation. 2230 * The function you register will be called every time a buffer is received 2231 * by the target mode code. 2232 */ 2233dpt_rb_t 2234dpt_register_buffer(int unit, u_int8_t channel, u_int8_t target, u_int8_t lun, 2235 u_int8_t mode, u_int16_t length, u_int16_t offset, 2236 dpt_rec_buff callback, dpt_rb_op_t op) 2237{ 2238 dpt_softc_t *dpt; 2239 dpt_ccb_t *ccb = NULL; 2240 int ospl; 2241 | 2206} 2207 2208 2209/* 2210 * Use this function to register a client for a buffer read target operation. 2211 * The function you register will be called every time a buffer is received 2212 * by the target mode code. 2213 */ 2214dpt_rb_t 2215dpt_register_buffer(int unit, u_int8_t channel, u_int8_t target, u_int8_t lun, 2216 u_int8_t mode, u_int16_t length, u_int16_t offset, 2217 dpt_rec_buff callback, dpt_rb_op_t op) 2218{ 2219 dpt_softc_t *dpt; 2220 dpt_ccb_t *ccb = NULL; 2221 int ospl; 2222 |
2242 for (dpt = TAILQ_FIRST(&dpt_softc_list); 2243 dpt != NULL; 2244 dpt = TAILQ_NEXT(dpt, links)) { 2245 if (dpt->unit == unit) 2246 goto valid_unit; 2247 } | 2223 dpt = devclass_get_device(dpt_devclass, unit); 2224 if (dpt == NULL) 2225 return (INVALID_UNIT); 2226 mtx_lock(&dpt->lock); |
2248 | 2227 |
2249 return (INVALID_UNIT); 2250 2251valid_unit: 2252 2253 if (dpt->state & DPT_HA_SHUTDOWN_ACTIVE) | 2228 if (dpt->state & DPT_HA_SHUTDOWN_ACTIVE) { 2229 mtx_unlock(&dpt->lock); |
2254 return (DRIVER_DOWN); | 2230 return (DRIVER_DOWN); |
2231 } |
|
2255 2256 if ((channel > (dpt->channels - 1)) || (target > (dpt->max_id - 1)) || | 2232 2233 if ((channel > (dpt->channels - 1)) || (target > (dpt->max_id - 1)) || |
2257 (lun > (dpt->max_lun - 1))) | 2234 (lun > (dpt->max_lun - 1))) { 2235 mtx_unlock(&dpt->lock); |
2258 return (INVALID_SENDER); | 2236 return (INVALID_SENDER); |
2237 } |
|
2259 2260 if (dpt->buffer_receiver[channel][target][lun] == NULL) { 2261 if (op == REGISTER_BUFFER) { 2262 /* Assign the requested callback */ 2263 dpt->buffer_receiver[channel][target][lun] = callback; 2264 /* Get a CCB */ | 2238 2239 if (dpt->buffer_receiver[channel][target][lun] == NULL) { 2240 if (op == REGISTER_BUFFER) { 2241 /* Assign the requested callback */ 2242 dpt->buffer_receiver[channel][target][lun] = callback; 2243 /* Get a CCB */ |
2265 ospl = splsoftcam(); | |
2266 2267 /* Process the free list */ 2268 if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) { | 2244 2245 /* Process the free list */ 2246 if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) { |
2269 printf("dpt%d ERROR: Cannot allocate any more free CCB's.\n" 2270 " Please try later\n", 2271 dpt->unit); 2272 splx(ospl); | 2247 device_printf(dpt->dev, 2248 "ERROR: Cannot allocate any more free CCB's.\n" 2249 " Please try later\n"); 2250 mtx_unlock(&dpt->lock); |
2273 return (NO_RESOURCES); 2274 } 2275 /* Now grab the newest CCB */ 2276 if ((ccb = dpt_Qpop_free(dpt)) == NULL) { | 2251 return (NO_RESOURCES); 2252 } 2253 /* Now grab the newest CCB */ 2254 if ((ccb = dpt_Qpop_free(dpt)) == NULL) { |
2277 splx(ospl); 2278 panic("dpt%d: Got a NULL CCB from pop_free()\n", 2279 dpt->unit); | 2255 mtx_unlock(&dpt->lock); 2256 panic("%s: Got a NULL CCB from pop_free()\n", 2257 device_get_nameunit(dpt->dev)); |
2280 } | 2258 } |
2281 splx(ospl); | |
2282 2283 /* Clean up the leftover of the previous tenant */ 2284 ccb->status = DPT_CCB_STATE_NEW; 2285 dpt->target_ccb[channel][target][lun] = ccb; 2286 2287 dpt->rw_buffer[channel][target][lun] = 2288 malloc(DPT_RW_BUFFER_SIZE, M_DEVBUF, M_NOWAIT); 2289 if (dpt->rw_buffer[channel][target][lun] == NULL) { | 2259 2260 /* Clean up the leftover of the previous tenant */ 2261 ccb->status = DPT_CCB_STATE_NEW; 2262 dpt->target_ccb[channel][target][lun] = ccb; 2263 2264 dpt->rw_buffer[channel][target][lun] = 2265 malloc(DPT_RW_BUFFER_SIZE, M_DEVBUF, M_NOWAIT); 2266 if (dpt->rw_buffer[channel][target][lun] == NULL) { |
2290 printf("dpt%d: Failed to allocate " 2291 "Target-Mode buffer\n", dpt->unit); 2292 ospl = splsoftcam(); | 2267 device_printf(dpt->dev, "Failed to allocate " 2268 "Target-Mode buffer\n"); |
2293 dpt_Qpush_free(dpt, ccb); | 2269 dpt_Qpush_free(dpt, ccb); |
2294 splx(ospl); | 2270 mtx_unlock(&dpt->lock); |
2295 return (NO_RESOURCES); 2296 } 2297 dpt_set_target(0, dpt, channel, target, lun, mode, 2298 length, offset, ccb); | 2271 return (NO_RESOURCES); 2272 } 2273 dpt_set_target(0, dpt, channel, target, lun, mode, 2274 length, offset, ccb); |
2275 mtx_unlock(&dpt->lock); |
|
2299 return (SUCCESSFULLY_REGISTERED); | 2276 return (SUCCESSFULLY_REGISTERED); |
2300 } else | 2277 } else { 2278 mtx_unlock(&dpt->lock); |
2301 return (NOT_REGISTERED); | 2279 return (NOT_REGISTERED); |
2280 } |
|
2302 } else { 2303 if (op == REGISTER_BUFFER) { | 2281 } else { 2282 if (op == REGISTER_BUFFER) { |
2304 if (dpt->buffer_receiver[channel][target][lun] == callback) | 2283 if (dpt->buffer_receiver[channel][target][lun] == callback) { 2284 mtx_unlock(&dpt->lock); |
2305 return (ALREADY_REGISTERED); | 2285 return (ALREADY_REGISTERED); |
2306 else | 2286 } else { 2287 mtx_unlock(&dpt->lock); |
2307 return (REGISTERED_TO_ANOTHER); | 2288 return (REGISTERED_TO_ANOTHER); |
2289 } |
|
2308 } else { 2309 if (dpt->buffer_receiver[channel][target][lun] == callback) { 2310 dpt->buffer_receiver[channel][target][lun] = NULL; | 2290 } else { 2291 if (dpt->buffer_receiver[channel][target][lun] == callback) { 2292 dpt->buffer_receiver[channel][target][lun] = NULL; |
2311 ospl = splsoftcam(); | |
2312 dpt_Qpush_free(dpt, ccb); | 2293 dpt_Qpush_free(dpt, ccb); |
2313 splx(ospl); | |
2314 free(dpt->rw_buffer[channel][target][lun], M_DEVBUF); | 2294 free(dpt->rw_buffer[channel][target][lun], M_DEVBUF); |
2295 mtx_unlock(&dpt->lock); |
|
2315 return (SUCCESSFULLY_REGISTERED); | 2296 return (SUCCESSFULLY_REGISTERED); |
2316 } else | 2297 } else { 2298 mtx_unlock(&dpt->lock); |
2317 return (INVALID_CALLBACK); | 2299 return (INVALID_CALLBACK); |
2300 } |
|
2318 } 2319 2320 } | 2301 } 2302 2303 } |
2304 mtx_unlock(&dpt->lock); |
|
2321} 2322 2323/* Return the state of the blinking DPT LED's */ 2324u_int8_t 2325dpt_blinking_led(dpt_softc_t * dpt) 2326{ 2327 int ndx; | 2305} 2306 2307/* Return the state of the blinking DPT LED's */ 2308u_int8_t 2309dpt_blinking_led(dpt_softc_t * dpt) 2310{ 2311 int ndx; |
2328 int ospl; | |
2329 u_int32_t state; 2330 u_int32_t previous; 2331 u_int8_t result; 2332 | 2312 u_int32_t state; 2313 u_int32_t previous; 2314 u_int8_t result; 2315 |
2333 ospl = splcam(); 2334 | 2316 mtx_assert(&dpt->lock, MA_OWNED); |
2335 result = 0; 2336 2337 for (ndx = 0, state = 0, previous = 0; 2338 (ndx < 10) && (state != previous); 2339 ndx++) { 2340 previous = state; 2341 state = dpt_inl(dpt, 1); 2342 } 2343 2344 if ((state == previous) && (state == DPT_BLINK_INDICATOR)) 2345 result = dpt_inb(dpt, 5); 2346 | 2317 result = 0; 2318 2319 for (ndx = 0, state = 0, previous = 0; 2320 (ndx < 10) && (state != previous); 2321 ndx++) { 2322 previous = state; 2323 state = dpt_inl(dpt, 1); 2324 } 2325 2326 if ((state == previous) && (state == DPT_BLINK_INDICATOR)) 2327 result = dpt_inb(dpt, 5); 2328 |
2347 splx(ospl); | |
2348 return (result); 2349} 2350 2351/* 2352 * Execute a command which did not come from the kernel's SCSI layer. 2353 * The only way to map user commands to bus and target is to comply with the 2354 * standard DPT wire-down scheme: 2355 */ 2356int 2357dpt_user_cmd(dpt_softc_t * dpt, eata_pt_t * user_cmd, 2358 caddr_t cmdarg, int minor_no) 2359{ 2360 dpt_ccb_t *ccb; 2361 void *data; 2362 int channel, target, lun; 2363 int huh; 2364 int result; | 2329 return (result); 2330} 2331 2332/* 2333 * Execute a command which did not come from the kernel's SCSI layer. 2334 * The only way to map user commands to bus and target is to comply with the 2335 * standard DPT wire-down scheme: 2336 */ 2337int 2338dpt_user_cmd(dpt_softc_t * dpt, eata_pt_t * user_cmd, 2339 caddr_t cmdarg, int minor_no) 2340{ 2341 dpt_ccb_t *ccb; 2342 void *data; 2343 int channel, target, lun; 2344 int huh; 2345 int result; |
2365 int ospl; | |
2366 int submitted; 2367 | 2346 int submitted; 2347 |
2348 mtx_assert(&dpt->lock, MA_OWNED); |
|
2368 data = NULL; 2369 channel = minor2hba(minor_no); 2370 target = minor2target(minor_no); 2371 lun = minor2lun(minor_no); 2372 2373 if ((channel > (dpt->channels - 1)) 2374 || (target > dpt->max_id) 2375 || (lun > dpt->max_lun)) --- 4 unchanged lines hidden (view full) --- 2380 if ((user_cmd->eataID[0] != 'E') 2381 || (user_cmd->eataID[1] != 'A') 2382 || (user_cmd->eataID[2] != 'T') 2383 || (user_cmd->eataID[3] != 'A')) { 2384 return (ENXIO); 2385 } 2386 } 2387 /* Get a DPT CCB, so we can prepare a command */ | 2349 data = NULL; 2350 channel = minor2hba(minor_no); 2351 target = minor2target(minor_no); 2352 lun = minor2lun(minor_no); 2353 2354 if ((channel > (dpt->channels - 1)) 2355 || (target > dpt->max_id) 2356 || (lun > dpt->max_lun)) --- 4 unchanged lines hidden (view full) --- 2361 if ((user_cmd->eataID[0] != 'E') 2362 || (user_cmd->eataID[1] != 'A') 2363 || (user_cmd->eataID[2] != 'T') 2364 || (user_cmd->eataID[3] != 'A')) { 2365 return (ENXIO); 2366 } 2367 } 2368 /* Get a DPT CCB, so we can prepare a command */ |
2388 ospl = splsoftcam(); | |
2389 2390 /* Process the free list */ 2391 if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) { | 2369 2370 /* Process the free list */ 2371 if ((TAILQ_EMPTY(&dpt->free_ccbs)) && dpt_alloc_freelist(dpt)) { |
2392 printf("dpt%d ERROR: Cannot allocate any more free CCB's.\n" 2393 " Please try later\n", 2394 dpt->unit); 2395 splx(ospl); | 2372 device_printf(dpt->dev, 2373 "ERROR: Cannot allocate any more free CCB's.\n" 2374 " Please try later\n"); |
2396 return (EFAULT); 2397 } 2398 /* Now grab the newest CCB */ 2399 if ((ccb = dpt_Qpop_free(dpt)) == NULL) { | 2375 return (EFAULT); 2376 } 2377 /* Now grab the newest CCB */ 2378 if ((ccb = dpt_Qpop_free(dpt)) == NULL) { |
2400 splx(ospl); 2401 panic("dpt%d: Got a NULL CCB from pop_free()\n", dpt->unit); | 2379 panic("%s: Got a NULL CCB from pop_free()\n", 2380 device_get_nameunit(dpt->dev)); |
2402 } else { | 2381 } else { |
2403 splx(ospl); | |
2404 /* Clean up the leftover of the previous tenant */ 2405 ccb->status = DPT_CCB_STATE_NEW; 2406 } 2407 2408 bcopy((caddr_t) & user_cmd->command_packet, (caddr_t) & ccb->eata_ccb, 2409 sizeof(eata_ccb_t)); 2410 2411 /* We do not want to do user specified scatter/gather. Why?? */ --- 16 unchanged lines hidden (view full) --- 2428 ccb->eata_ccb.cp_datalen, 2429 0x10000); 2430 } else { 2431 data = malloc(ccb->eata_ccb.cp_datalen, M_TEMP, 2432 M_WAITOK); 2433 } 2434 2435 if (data == NULL) { | 2382 /* Clean up the leftover of the previous tenant */ 2383 ccb->status = DPT_CCB_STATE_NEW; 2384 } 2385 2386 bcopy((caddr_t) & user_cmd->command_packet, (caddr_t) & ccb->eata_ccb, 2387 sizeof(eata_ccb_t)); 2388 2389 /* We do not want to do user specified scatter/gather. Why?? */ --- 16 unchanged lines hidden (view full) --- 2406 ccb->eata_ccb.cp_datalen, 2407 0x10000); 2408 } else { 2409 data = malloc(ccb->eata_ccb.cp_datalen, M_TEMP, 2410 M_WAITOK); 2411 } 2412 2413 if (data == NULL) { |
2436 printf("dpt%d: Cannot allocate %d bytes " 2437 "for EATA command\n", dpt->unit, | 2414 device_printf(dpt->dev, "Cannot allocate %d bytes " 2415 "for EATA command\n", |
2438 ccb->eata_ccb.cp_datalen); 2439 return (EFAULT); 2440 } 2441#define usr_cmd_DMA (caddr_t)user_cmd->command_packet.cp_dataDMA 2442 if (ccb->eata_ccb.DataIn == 1) { 2443 if (copyin(usr_cmd_DMA, 2444 data, ccb->eata_ccb.cp_datalen) == -1) 2445 return (EFAULT); --- 19 unchanged lines hidden (view full) --- 2465 * We are required to quiet a SCSI bus. 2466 * since we do not queue comands on a bus basis, 2467 * we wait for ALL commands on a controller to complete. 2468 * In the mean time, sched_queue() will not schedule new commands. 2469 */ 2470 if ((ccb->eata_ccb.cp_cdb[0] == MULTIFUNCTION_CMD) 2471 && (ccb->eata_ccb.cp_cdb[2] == BUS_QUIET)) { 2472 /* We wait for ALL traffic for this HBa to subside */ | 2416 ccb->eata_ccb.cp_datalen); 2417 return (EFAULT); 2418 } 2419#define usr_cmd_DMA (caddr_t)user_cmd->command_packet.cp_dataDMA 2420 if (ccb->eata_ccb.DataIn == 1) { 2421 if (copyin(usr_cmd_DMA, 2422 data, ccb->eata_ccb.cp_datalen) == -1) 2423 return (EFAULT); --- 19 unchanged lines hidden (view full) --- 2443 * We are required to quiet a SCSI bus. 2444 * since we do not queue comands on a bus basis, 2445 * we wait for ALL commands on a controller to complete. 2446 * In the mean time, sched_queue() will not schedule new commands. 2447 */ 2448 if ((ccb->eata_ccb.cp_cdb[0] == MULTIFUNCTION_CMD) 2449 && (ccb->eata_ccb.cp_cdb[2] == BUS_QUIET)) { 2450 /* We wait for ALL traffic for this HBa to subside */ |
2473 ospl = splsoftcam(); | |
2474 dpt->state |= DPT_HA_QUIET; | 2451 dpt->state |= DPT_HA_QUIET; |
2475 splx(ospl); | |
2476 2477 while ((submitted = dpt->submitted_ccbs_count) != 0) { | 2452 2453 while ((submitted = dpt->submitted_ccbs_count) != 0) { |
2478 huh = tsleep((void *) dpt, PCATCH | PRIBIO, "dptqt", 2479 100 * hz); | 2454 huh = mtx_sleep((void *) dpt, &dpt->lock, 2455 PCATCH | PRIBIO, "dptqt", 100 * hz); |
2480 switch (huh) { 2481 case 0: 2482 /* Wakeup call received */ 2483 break; 2484 case EWOULDBLOCK: 2485 /* Timer Expired */ 2486 break; 2487 default: 2488 /* anything else */ 2489 break; 2490 } 2491 } 2492 } 2493 /* Resume normal operation */ 2494 if ((ccb->eata_ccb.cp_cdb[0] == MULTIFUNCTION_CMD) 2495 && (ccb->eata_ccb.cp_cdb[2] == BUS_UNQUIET)) { | 2456 switch (huh) { 2457 case 0: 2458 /* Wakeup call received */ 2459 break; 2460 case EWOULDBLOCK: 2461 /* Timer Expired */ 2462 break; 2463 default: 2464 /* anything else */ 2465 break; 2466 } 2467 } 2468 } 2469 /* Resume normal operation */ 2470 if ((ccb->eata_ccb.cp_cdb[0] == MULTIFUNCTION_CMD) 2471 && (ccb->eata_ccb.cp_cdb[2] == BUS_UNQUIET)) { |
2496 ospl = splsoftcam(); | |
2497 dpt->state &= ~DPT_HA_QUIET; | 2472 dpt->state &= ~DPT_HA_QUIET; |
2498 splx(ospl); | |
2499 } 2500 /** 2501 * Schedule the command and submit it. 2502 * We bypass dpt_sched_queue, as it will block on DPT_HA_QUIET 2503 */ 2504 ccb->xs = NULL; 2505 ccb->flags = 0; 2506 ccb->eata_ccb.Auto_Req_Sen = 1; /* We always want this feature */ 2507 2508 ccb->transaction_id = ++dpt->commands_processed; 2509 ccb->std_callback = (ccb_callback) dpt_user_cmd_done; 2510 ccb->result = (u_int32_t) & cmdarg; 2511 ccb->data = data; 2512 2513#ifdef DPT_MEASURE_PERFORMANCE 2514 ++dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]; 2515 ccb->command_started = microtime_now; 2516#endif | 2473 } 2474 /** 2475 * Schedule the command and submit it. 2476 * We bypass dpt_sched_queue, as it will block on DPT_HA_QUIET 2477 */ 2478 ccb->xs = NULL; 2479 ccb->flags = 0; 2480 ccb->eata_ccb.Auto_Req_Sen = 1; /* We always want this feature */ 2481 2482 ccb->transaction_id = ++dpt->commands_processed; 2483 ccb->std_callback = (ccb_callback) dpt_user_cmd_done; 2484 ccb->result = (u_int32_t) & cmdarg; 2485 ccb->data = data; 2486 2487#ifdef DPT_MEASURE_PERFORMANCE 2488 ++dpt->performance.command_count[ccb->eata_ccb.cp_scsi_cmd]; 2489 ccb->command_started = microtime_now; 2490#endif |
2517 ospl = splcam(); | |
2518 dpt_Qadd_waiting(dpt, ccb); | 2491 dpt_Qadd_waiting(dpt, ccb); |
2519 splx(ospl); | |
2520 2521 dpt_sched_queue(dpt); 2522 2523 /* Wait for the command to complete */ | 2492 2493 dpt_sched_queue(dpt); 2494 2495 /* Wait for the command to complete */ |
2524 (void) tsleep((void *) ccb, PCATCH | PRIBIO, "dptucw", 100 * hz); | 2496 (void) mtx_sleep((void *) ccb, &dpt->lock, PCATCH | PRIBIO, "dptucw", 2497 100 * hz); |
2525 2526 /* Free allocated memory */ 2527 if (data != NULL) 2528 free(data, M_TEMP); 2529 2530 return (0); 2531} 2532 2533static void 2534dpt_user_cmd_done(dpt_softc_t * dpt, int bus, dpt_ccb_t * ccb) 2535{ | 2498 2499 /* Free allocated memory */ 2500 if (data != NULL) 2501 free(data, M_TEMP); 2502 2503 return (0); 2504} 2505 2506static void 2507dpt_user_cmd_done(dpt_softc_t * dpt, int bus, dpt_ccb_t * ccb) 2508{ |
2536 int ospl = splsoftcam(); | |
2537 u_int32_t result; 2538 caddr_t cmd_arg; 2539 | 2509 u_int32_t result; 2510 caddr_t cmd_arg; 2511 |
2512 mtx_unlock(&dpt->lock); 2513 |
|
2540 /** 2541 * If Auto Request Sense is on, copyout the sense struct 2542 */ 2543#define usr_pckt_DMA (caddr_t)(intptr_t)ntohl(ccb->eata_ccb.cp_reqDMA) 2544#define usr_pckt_len ntohl(ccb->eata_ccb.cp_datalen) 2545 if (ccb->eata_ccb.Auto_Req_Sen == 1) { 2546 if (copyout((caddr_t) & ccb->sense_data, usr_pckt_DMA, 2547 sizeof(struct scsi_sense_data))) { | 2514 /** 2515 * If Auto Request Sense is on, copyout the sense struct 2516 */ 2517#define usr_pckt_DMA (caddr_t)(intptr_t)ntohl(ccb->eata_ccb.cp_reqDMA) 2518#define usr_pckt_len ntohl(ccb->eata_ccb.cp_datalen) 2519 if (ccb->eata_ccb.Auto_Req_Sen == 1) { 2520 if (copyout((caddr_t) & ccb->sense_data, usr_pckt_DMA, 2521 sizeof(struct scsi_sense_data))) { |
2522 mtx_lock(&dpt->lock); |
|
2548 ccb->result = EFAULT; 2549 dpt_Qpush_free(dpt, ccb); | 2523 ccb->result = EFAULT; 2524 dpt_Qpush_free(dpt, ccb); |
2550 splx(ospl); | |
2551 wakeup(ccb); 2552 return; 2553 } 2554 } 2555 /* If DataIn is on, copyout the data */ 2556 if ((ccb->eata_ccb.DataIn == 1) 2557 && (ccb->status_packet.hba_stat == HA_NO_ERROR)) { 2558 if (copyout(ccb->data, usr_pckt_DMA, usr_pckt_len)) { | 2525 wakeup(ccb); 2526 return; 2527 } 2528 } 2529 /* If DataIn is on, copyout the data */ 2530 if ((ccb->eata_ccb.DataIn == 1) 2531 && (ccb->status_packet.hba_stat == HA_NO_ERROR)) { 2532 if (copyout(ccb->data, usr_pckt_DMA, usr_pckt_len)) { |
2533 mtx_lock(&dpt->lock); |
|
2559 dpt_Qpush_free(dpt, ccb); 2560 ccb->result = EFAULT; 2561 | 2534 dpt_Qpush_free(dpt, ccb); 2535 ccb->result = EFAULT; 2536 |
2562 splx(ospl); | |
2563 wakeup(ccb); 2564 return; 2565 } 2566 } 2567 /* Copyout the status */ 2568 result = ccb->status_packet.hba_stat; 2569 cmd_arg = (caddr_t) ccb->result; 2570 2571 if (copyout((caddr_t) & result, cmd_arg, sizeof(result))) { | 2537 wakeup(ccb); 2538 return; 2539 } 2540 } 2541 /* Copyout the status */ 2542 result = ccb->status_packet.hba_stat; 2543 cmd_arg = (caddr_t) ccb->result; 2544 2545 if (copyout((caddr_t) & result, cmd_arg, sizeof(result))) { |
2546 mtx_lock(&dpt->lock); |
|
2572 dpt_Qpush_free(dpt, ccb); 2573 ccb->result = EFAULT; | 2547 dpt_Qpush_free(dpt, ccb); 2548 ccb->result = EFAULT; |
2574 splx(ospl); | |
2575 wakeup(ccb); 2576 return; 2577 } | 2549 wakeup(ccb); 2550 return; 2551 } |
2552 mtx_lock(&dpt->lock); |
|
2578 /* Put the CCB back in the freelist */ 2579 ccb->state |= DPT_CCB_STATE_COMPLETED; 2580 dpt_Qpush_free(dpt, ccb); 2581 2582 /* Free allocated memory */ | 2553 /* Put the CCB back in the freelist */ 2554 ccb->state |= DPT_CCB_STATE_COMPLETED; 2555 dpt_Qpush_free(dpt, ccb); 2556 2557 /* Free allocated memory */ |
2583 splx(ospl); | |
2584 return; 2585} 2586 2587#ifdef DPT_HANDLE_TIMEOUTS 2588/** 2589 * This function walks down the SUBMITTED queue. 2590 * Every request that is too old gets aborted and marked. 2591 * Since the DPT will complete (interrupt) immediately (what does that mean?), --- 13 unchanged lines hidden (view full) --- 2605 * every ten seconds for few microseconds and, on systems with healthy 2606 * hardware, does not do anything anyway. 2607 */ 2608 2609static void 2610dpt_handle_timeouts(dpt_softc_t * dpt) 2611{ 2612 dpt_ccb_t *ccb; | 2558 return; 2559} 2560 2561#ifdef DPT_HANDLE_TIMEOUTS 2562/** 2563 * This function walks down the SUBMITTED queue. 2564 * Every request that is too old gets aborted and marked. 2565 * Since the DPT will complete (interrupt) immediately (what does that mean?), --- 13 unchanged lines hidden (view full) --- 2579 * every ten seconds for few microseconds and, on systems with healthy 2580 * hardware, does not do anything anyway. 2581 */ 2582 2583static void 2584dpt_handle_timeouts(dpt_softc_t * dpt) 2585{ 2586 dpt_ccb_t *ccb; |
2613 int ospl; | |
2614 | 2587 |
2615 ospl = splcam(); 2616 | |
2617 if (dpt->state & DPT_HA_TIMEOUTS_ACTIVE) { | 2588 if (dpt->state & DPT_HA_TIMEOUTS_ACTIVE) { |
2618 printf("dpt%d WARNING: Timeout Handling Collision\n", 2619 dpt->unit); 2620 splx(ospl); | 2589 device_printf(dpt->dev, "WARNING: Timeout Handling Collision\n"); |
2621 return; 2622 } 2623 dpt->state |= DPT_HA_TIMEOUTS_ACTIVE; 2624 2625 /* Loop through the entire submitted queue, looking for lost souls */ | 2590 return; 2591 } 2592 dpt->state |= DPT_HA_TIMEOUTS_ACTIVE; 2593 2594 /* Loop through the entire submitted queue, looking for lost souls */ |
2626 for (ccb = TAILQ_FIRST(&dpt->submitted_ccbs); 2627 ccb != NULL; 2628 ccb = TAILQ_NEXT(ccb, links)) { | 2595 TAILQ_FIRST(ccb, &&dpt->submitted_ccbs, links) { |
2629 struct scsi_xfer *xs; 2630 u_int32_t age, max_age; 2631 2632 xs = ccb->xs; 2633 age = dpt_time_delta(ccb->command_started, microtime_now); 2634 2635#define TenSec 10000000 2636 --- 15 unchanged lines hidden (view full) --- 2652 if (ccb->state & DPT_CCB_STATE_MARKED_LOST) { 2653 /* Remember who is next */ 2654 if (age > (max_age * 2)) { 2655 dpt_Qremove_submitted(dpt, ccb); 2656 ccb->state &= ~DPT_CCB_STATE_MARKED_LOST; 2657 ccb->state |= DPT_CCB_STATE_ABORTED; 2658#define cmd_name scsi_cmd_name(ccb->eata_ccb.cp_scsi_cmd) 2659 if (ccb->retries++ > DPT_RETRIES) { | 2596 struct scsi_xfer *xs; 2597 u_int32_t age, max_age; 2598 2599 xs = ccb->xs; 2600 age = dpt_time_delta(ccb->command_started, microtime_now); 2601 2602#define TenSec 10000000 2603 --- 15 unchanged lines hidden (view full) --- 2619 if (ccb->state & DPT_CCB_STATE_MARKED_LOST) { 2620 /* Remember who is next */ 2621 if (age > (max_age * 2)) { 2622 dpt_Qremove_submitted(dpt, ccb); 2623 ccb->state &= ~DPT_CCB_STATE_MARKED_LOST; 2624 ccb->state |= DPT_CCB_STATE_ABORTED; 2625#define cmd_name scsi_cmd_name(ccb->eata_ccb.cp_scsi_cmd) 2626 if (ccb->retries++ > DPT_RETRIES) { |
2660 printf("dpt%d ERROR: Destroying stale " | 2627 device_printf(dpt->dev, 2628 "ERROR: Destroying stale " |
2661 "%d (%s)\n" 2662 " on " 2663 "c%db%dt%du%d (%d/%d)\n", | 2629 "%d (%s)\n" 2630 " on " 2631 "c%db%dt%du%d (%d/%d)\n", |
2664 dpt->unit, ccb->transaction_id, | 2632 ccb->transaction_id, |
2665 cmd_name, | 2633 cmd_name, |
2666 dpt->unit, | 2634 device_get_unit(dpt->dev), |
2667 ccb->eata_ccb.cp_channel, 2668 ccb->eata_ccb.cp_id, 2669 ccb->eata_ccb.cp_LUN, age, 2670 ccb->retries); 2671#define send_ccb &ccb->eata_ccb 2672#define ESA EATA_SPECIFIC_ABORT 2673 (void) dpt_send_immediate(dpt, 2674 send_ccb, 2675 ESA, 2676 0, 0); 2677 dpt_Qpush_free(dpt, ccb); 2678 2679 /* The SCSI layer should re-try */ 2680 xs->error |= XS_TIMEOUT; 2681 xs->flags |= SCSI_ITSDONE; 2682 scsi_done(xs); 2683 } else { | 2635 ccb->eata_ccb.cp_channel, 2636 ccb->eata_ccb.cp_id, 2637 ccb->eata_ccb.cp_LUN, age, 2638 ccb->retries); 2639#define send_ccb &ccb->eata_ccb 2640#define ESA EATA_SPECIFIC_ABORT 2641 (void) dpt_send_immediate(dpt, 2642 send_ccb, 2643 ESA, 2644 0, 0); 2645 dpt_Qpush_free(dpt, ccb); 2646 2647 /* The SCSI layer should re-try */ 2648 xs->error |= XS_TIMEOUT; 2649 xs->flags |= SCSI_ITSDONE; 2650 scsi_done(xs); 2651 } else { |
2684 printf("dpt%d ERROR: Stale %d (%s) on " | 2652 device_printf(dpt->dev, 2653 "ERROR: Stale %d (%s) on " |
2685 "c%db%dt%du%d (%d)\n" 2686 " gets another " 2687 "chance(%d/%d)\n", | 2654 "c%db%dt%du%d (%d)\n" 2655 " gets another " 2656 "chance(%d/%d)\n", |
2688 dpt->unit, ccb->transaction_id, | 2657 ccb->transaction_id, |
2689 cmd_name, | 2658 cmd_name, |
2690 dpt->unit, | 2659 device_get_unit(dpt->dev), |
2691 ccb->eata_ccb.cp_channel, 2692 ccb->eata_ccb.cp_id, 2693 ccb->eata_ccb.cp_LUN, 2694 age, ccb->retries, DPT_RETRIES); 2695 2696 dpt_Qpush_waiting(dpt, ccb); 2697 dpt_sched_queue(dpt); 2698 } 2699 } 2700 } else { 2701 /* 2702 * This is a transaction that is not to be destroyed 2703 * (yet) But it is too old for our liking. We wait as 2704 * long as the upper layer thinks. Not really, we 2705 * multiply that by the number of commands in the 2706 * submitted queue + 1. 2707 */ 2708 if (!(ccb->state & DPT_CCB_STATE_MARKED_LOST) && 2709 (age != ~0) && (age > max_age)) { | 2660 ccb->eata_ccb.cp_channel, 2661 ccb->eata_ccb.cp_id, 2662 ccb->eata_ccb.cp_LUN, 2663 age, ccb->retries, DPT_RETRIES); 2664 2665 dpt_Qpush_waiting(dpt, ccb); 2666 dpt_sched_queue(dpt); 2667 } 2668 } 2669 } else { 2670 /* 2671 * This is a transaction that is not to be destroyed 2672 * (yet) But it is too old for our liking. We wait as 2673 * long as the upper layer thinks. Not really, we 2674 * multiply that by the number of commands in the 2675 * submitted queue + 1. 2676 */ 2677 if (!(ccb->state & DPT_CCB_STATE_MARKED_LOST) && 2678 (age != ~0) && (age > max_age)) { |
2710 printf("dpt%d ERROR: Marking %d (%s) on " | 2679 device_printf(dpt->dev, 2680 "ERROR: Marking %d (%s) on " |
2711 "c%db%dt%du%d \n" 2712 " as late after %dusec\n", | 2681 "c%db%dt%du%d \n" 2682 " as late after %dusec\n", |
2713 dpt->unit, ccb->transaction_id, | 2683 ccb->transaction_id, |
2714 cmd_name, | 2684 cmd_name, |
2715 dpt->unit, ccb->eata_ccb.cp_channel, | 2685 device_get_unit(dpt->dev), 2686 ccb->eata_ccb.cp_channel, |
2716 ccb->eata_ccb.cp_id, 2717 ccb->eata_ccb.cp_LUN, age); 2718 ccb->state |= DPT_CCB_STATE_MARKED_LOST; 2719 } 2720 } 2721 } 2722 2723 dpt->state &= ~DPT_HA_TIMEOUTS_ACTIVE; | 2687 ccb->eata_ccb.cp_id, 2688 ccb->eata_ccb.cp_LUN, age); 2689 ccb->state |= DPT_CCB_STATE_MARKED_LOST; 2690 } 2691 } 2692 } 2693 2694 dpt->state &= ~DPT_HA_TIMEOUTS_ACTIVE; |
2724 splx(ospl); | |
2725} 2726 2727static void 2728dpt_timeout(void *arg) 2729{ 2730 dpt_softc_t *dpt = (dpt_softc_t *) arg; 2731 | 2695} 2696 2697static void 2698dpt_timeout(void *arg) 2699{ 2700 dpt_softc_t *dpt = (dpt_softc_t *) arg; 2701 |
2702 mtx_assert(&dpt->lock, MA_OWNED); |
|
2732 if (!(dpt->state & DPT_HA_TIMEOUTS_ACTIVE)) 2733 dpt_handle_timeouts(dpt); 2734 | 2703 if (!(dpt->state & DPT_HA_TIMEOUTS_ACTIVE)) 2704 dpt_handle_timeouts(dpt); 2705 |
2735 timeout(dpt_timeout, (caddr_t) dpt, hz * 10); | 2706 callout_reset(&dpt->timer, hz * 10, dpt_timeout, dpt); |
2736} 2737 2738#endif /* DPT_HANDLE_TIMEOUTS */ 2739 2740#endif | 2707} 2708 2709#endif /* DPT_HANDLE_TIMEOUTS */ 2710 2711#endif |