version 1.42.4.6, 2010/10/09 03:32:06 |
version 1.43, 2009/03/14 15:36:17 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
|
* 3. All advertising materials mentioning features or use of this software |
|
* must display the following acknowledgement: |
|
* This product includes software developed by Manuel Bouyer. |
|
* 4. The name of the author may not be used to endorse or promote products |
|
* derived from this software without specific prior written permission. |
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
Line 56 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 61 __KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
#include "opt_siop.h" |
#include "opt_siop.h" |
|
|
|
#ifndef DEBUG |
|
#undef DEBUG |
|
#endif |
/* |
/* |
#define SIOP_DEBUG |
#define SIOP_DEBUG |
#define SIOP_DEBUG_DR |
#define SIOP_DEBUG_DR |
#define SIOP_DEBUG_INTR |
#define SIOP_DEBUG_INTR |
#define SIOP_DEBUG_SCHED |
#define SIOP_DEBUG_SCHED |
#define SIOP_DUMP_SCRIPT |
#define DUMP_SCRIPT |
*/ |
*/ |
|
|
#define SIOP_STATS |
#define SIOP_STATS |
Line 80 void esiop_scsicmd_end(struct esiop_cmd |
|
Line 88 void esiop_scsicmd_end(struct esiop_cmd |
|
void esiop_unqueue(struct esiop_softc *, int, int); |
void esiop_unqueue(struct esiop_softc *, int, int); |
int esiop_handle_qtag_reject(struct esiop_cmd *); |
int esiop_handle_qtag_reject(struct esiop_cmd *); |
static void esiop_start(struct esiop_softc *, struct esiop_cmd *); |
static void esiop_start(struct esiop_softc *, struct esiop_cmd *); |
void esiop_timeout(void *); |
void esiop_timeout(void *); |
void esiop_scsipi_request(struct scsipi_channel *, |
void esiop_scsipi_request(struct scsipi_channel *, |
scsipi_adapter_req_t, void *); |
scsipi_adapter_req_t, void *); |
void esiop_dump_script(struct esiop_softc *); |
void esiop_dump_script(struct esiop_softc *); |
void esiop_morecbd(struct esiop_softc *); |
void esiop_morecbd(struct esiop_softc *); |
void esiop_moretagtbl(struct esiop_softc *); |
void esiop_moretagtbl(struct esiop_softc *); |
void siop_add_reselsw(struct esiop_softc *, int); |
void siop_add_reselsw(struct esiop_softc *, int); |
void esiop_target_register(struct esiop_softc *, uint32_t); |
void esiop_target_register(struct esiop_softc *, u_int32_t); |
|
|
void esiop_update_scntl3(struct esiop_softc *, struct siop_common_target *); |
void esiop_update_scntl3(struct esiop_softc *, struct siop_common_target *); |
|
|
Line 109 static inline void esiop_script_sync(str |
|
Line 117 static inline void esiop_script_sync(str |
|
static inline void |
static inline void |
esiop_script_sync(struct esiop_softc *sc, int ops) |
esiop_script_sync(struct esiop_softc *sc, int ops) |
{ |
{ |
|
|
if ((sc->sc_c.features & SF_CHIP_RAM) == 0) |
if ((sc->sc_c.features & SF_CHIP_RAM) == 0) |
bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0, |
bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0, |
PAGE_SIZE, ops); |
PAGE_SIZE, ops); |
} |
} |
|
|
static inline uint32_t esiop_script_read(struct esiop_softc *, u_int); |
static inline u_int32_t esiop_script_read(struct esiop_softc *, u_int); |
static inline uint32_t |
static inline u_int32_t |
esiop_script_read(struct esiop_softc *sc, u_int offset) |
esiop_script_read(struct esiop_softc *sc, u_int offset) |
{ |
{ |
|
|
if (sc->sc_c.features & SF_CHIP_RAM) { |
if (sc->sc_c.features & SF_CHIP_RAM) { |
return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
offset * 4); |
offset * 4); |
Line 129 esiop_script_read(struct esiop_softc *sc |
|
Line 135 esiop_script_read(struct esiop_softc *sc |
|
} |
} |
|
|
static inline void esiop_script_write(struct esiop_softc *, u_int, |
static inline void esiop_script_write(struct esiop_softc *, u_int, |
uint32_t); |
u_int32_t); |
static inline void |
static inline void |
esiop_script_write(struct esiop_softc *sc, u_int offset, uint32_t val) |
esiop_script_write(struct esiop_softc *sc, u_int offset, u_int32_t val) |
{ |
{ |
|
|
if (sc->sc_c.features & SF_CHIP_RAM) { |
if (sc->sc_c.features & SF_CHIP_RAM) { |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
offset * 4, val); |
offset * 4, val); |
Line 156 esiop_attach(struct esiop_softc *sc) |
|
Line 161 esiop_attach(struct esiop_softc *sc) |
|
TAILQ_INIT(&sc->tag_tblblk); |
TAILQ_INIT(&sc->tag_tblblk); |
sc->sc_currschedslot = 0; |
sc->sc_currschedslot = 0; |
#ifdef SIOP_DEBUG |
#ifdef SIOP_DEBUG |
aprint_debug_dev(sc->sc_c.sc_dev, |
aprint_debug_dev(&sc->sc_c.sc_dev, "script size = %d, PHY addr=0x%x, VIRT=%p\n", |
"script size = %d, PHY addr=0x%x, VIRT=%p\n", |
|
(int)sizeof(esiop_script), |
(int)sizeof(esiop_script), |
(uint32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script); |
(u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script); |
#endif |
#endif |
|
|
sc->sc_c.sc_adapt.adapt_max_periph = ESIOP_NTAG; |
sc->sc_c.sc_adapt.adapt_max_periph = ESIOP_NTAG; |
Line 171 esiop_attach(struct esiop_softc *sc) |
|
Line 175 esiop_attach(struct esiop_softc *sc) |
|
*/ |
*/ |
#ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
if (ESIOP_NTAG != A_ndone_slots) { |
if (ESIOP_NTAG != A_ndone_slots) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "size of tag DSA table different from the done" |
"size of tag DSA table different from the done ring\n"); |
" ring\n"); |
return; |
return; |
} |
} |
#endif |
#endif |
esiop_moretagtbl(sc); |
esiop_moretagtbl(sc); |
tagtbl_donering = TAILQ_FIRST(&sc->free_tagtbl); |
tagtbl_donering = TAILQ_FIRST(&sc->free_tagtbl); |
if (tagtbl_donering == NULL) { |
if (tagtbl_donering == NULL) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "no memory for command done ring\n"); |
"no memory for command done ring\n"); |
|
return; |
return; |
} |
} |
TAILQ_REMOVE(&sc->free_tagtbl, tagtbl_donering, next); |
TAILQ_REMOVE(&sc->free_tagtbl, tagtbl_donering, next); |
Line 194 esiop_attach(struct esiop_softc *sc) |
|
Line 197 esiop_attach(struct esiop_softc *sc) |
|
* siop_reset() will reset the chip, thus clearing pending interrupts |
* siop_reset() will reset the chip, thus clearing pending interrupts |
*/ |
*/ |
esiop_reset(sc); |
esiop_reset(sc); |
#ifdef SIOP_DUMP_SCRIPT |
#ifdef DUMP_SCRIPT |
esiop_dump_script(sc); |
esiop_dump_script(sc); |
#endif |
#endif |
|
|
config_found(sc->sc_c.sc_dev, &sc->sc_c.sc_chan, scsiprint); |
config_found((struct device*)sc, &sc->sc_c.sc_chan, scsiprint); |
} |
} |
|
|
void |
void |
esiop_reset(struct esiop_softc *sc) |
esiop_reset(struct esiop_softc *sc) |
{ |
{ |
int i, j; |
int i, j; |
uint32_t addr; |
u_int32_t addr; |
uint32_t msgin_addr, sem_addr; |
u_int32_t msgin_addr, sem_addr; |
|
|
siop_common_reset(&sc->sc_c); |
siop_common_reset(&sc->sc_c); |
|
|
Line 214 esiop_reset(struct esiop_softc *sc) |
|
Line 217 esiop_reset(struct esiop_softc *sc) |
|
* we copy the script at the beggining of RAM. Then there is 4 bytes |
* we copy the script at the beggining of RAM. Then there is 4 bytes |
* for messages in, and 4 bytes for semaphore |
* for messages in, and 4 bytes for semaphore |
*/ |
*/ |
sc->sc_free_offset = __arraycount(esiop_script); |
sc->sc_free_offset = sizeof(esiop_script) / sizeof(esiop_script[0]); |
msgin_addr = |
msgin_addr = |
sc->sc_free_offset * sizeof(uint32_t) + sc->sc_c.sc_scriptaddr; |
sc->sc_free_offset * sizeof(u_int32_t) + sc->sc_c.sc_scriptaddr; |
sc->sc_free_offset += 1; |
sc->sc_free_offset += 1; |
sc->sc_semoffset = sc->sc_free_offset; |
sc->sc_semoffset = sc->sc_free_offset; |
sem_addr = |
sem_addr = |
sc->sc_semoffset * sizeof(uint32_t) + sc->sc_c.sc_scriptaddr; |
sc->sc_semoffset * sizeof(u_int32_t) + sc->sc_c.sc_scriptaddr; |
sc->sc_free_offset += 1; |
sc->sc_free_offset += 1; |
/* then we have the scheduler ring */ |
/* then we have the scheduler ring */ |
sc->sc_shedoffset = sc->sc_free_offset; |
sc->sc_shedoffset = sc->sc_free_offset; |
Line 232 esiop_reset(struct esiop_softc *sc) |
|
Line 235 esiop_reset(struct esiop_softc *sc) |
|
if (sc->sc_c.features & SF_CHIP_RAM) { |
if (sc->sc_c.features & SF_CHIP_RAM) { |
bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0, |
bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0, |
esiop_script, |
esiop_script, |
__arraycount(esiop_script)); |
sizeof(esiop_script) / sizeof(esiop_script[0])); |
for (j = 0; j < __arraycount(E_tlq_offset_Used); j++) { |
for (j = 0; j < |
|
(sizeof(E_tlq_offset_Used) / sizeof(E_tlq_offset_Used[0])); |
|
j++) { |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
E_tlq_offset_Used[j] * 4, |
E_tlq_offset_Used[j] * 4, |
sizeof(struct siop_common_xfer)); |
sizeof(struct siop_common_xfer)); |
} |
} |
for (j = 0; j < __arraycount(E_saved_offset_offset_Used); j++) { |
for (j = 0; j < |
|
(sizeof(E_saved_offset_offset_Used) / |
|
sizeof(E_saved_offset_offset_Used[0])); |
|
j++) { |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
E_saved_offset_offset_Used[j] * 4, |
E_saved_offset_offset_Used[j] * 4, |
sizeof(struct siop_common_xfer) + 4); |
sizeof(struct siop_common_xfer) + 4); |
} |
} |
for (j = 0; j < __arraycount(E_abs_msgin2_Used); j++) { |
for (j = 0; j < |
|
(sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0])); |
|
j++) { |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
E_abs_msgin2_Used[j] * 4, msgin_addr); |
E_abs_msgin2_Used[j] * 4, msgin_addr); |
} |
} |
for (j = 0; j < __arraycount(E_abs_sem_Used); j++) { |
for (j = 0; j < |
|
(sizeof(E_abs_sem_Used) / sizeof(E_abs_sem_Used[0])); |
|
j++) { |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, |
E_abs_sem_Used[j] * 4, sem_addr); |
E_abs_sem_Used[j] * 4, sem_addr); |
} |
} |
Line 256 esiop_reset(struct esiop_softc *sc) |
|
Line 268 esiop_reset(struct esiop_softc *sc) |
|
bus_space_write_region_4(sc->sc_c.sc_ramt, |
bus_space_write_region_4(sc->sc_c.sc_ramt, |
sc->sc_c.sc_ramh, |
sc->sc_c.sc_ramh, |
Ent_led_on1, esiop_led_on, |
Ent_led_on1, esiop_led_on, |
__arraycount(esiop_led_on)); |
sizeof(esiop_led_on) / sizeof(esiop_led_on[0])); |
bus_space_write_region_4(sc->sc_c.sc_ramt, |
bus_space_write_region_4(sc->sc_c.sc_ramt, |
sc->sc_c.sc_ramh, |
sc->sc_c.sc_ramh, |
Ent_led_on2, esiop_led_on, |
Ent_led_on2, esiop_led_on, |
__arraycount(esiop_led_on)); |
sizeof(esiop_led_on) / sizeof(esiop_led_on[0])); |
bus_space_write_region_4(sc->sc_c.sc_ramt, |
bus_space_write_region_4(sc->sc_c.sc_ramt, |
sc->sc_c.sc_ramh, |
sc->sc_c.sc_ramh, |
Ent_led_off, esiop_led_off, |
Ent_led_off, esiop_led_off, |
__arraycount(esiop_led_off)); |
sizeof(esiop_led_off) / sizeof(esiop_led_off[0])); |
} |
} |
} else { |
} else { |
for (j = 0; j < __arraycount(esiop_script); j++) { |
for (j = 0; |
|
j < (sizeof(esiop_script) / sizeof(esiop_script[0])); j++) { |
sc->sc_c.sc_script[j] = htole32(esiop_script[j]); |
sc->sc_c.sc_script[j] = htole32(esiop_script[j]); |
} |
} |
for (j = 0; j < __arraycount(E_tlq_offset_Used); j++) { |
for (j = 0; j < |
|
(sizeof(E_tlq_offset_Used) / sizeof(E_tlq_offset_Used[0])); |
|
j++) { |
sc->sc_c.sc_script[E_tlq_offset_Used[j]] = |
sc->sc_c.sc_script[E_tlq_offset_Used[j]] = |
htole32(sizeof(struct siop_common_xfer)); |
htole32(sizeof(struct siop_common_xfer)); |
} |
} |
for (j = 0; j < __arraycount(E_saved_offset_offset_Used); j++) { |
for (j = 0; j < |
|
(sizeof(E_saved_offset_offset_Used) / |
|
sizeof(E_saved_offset_offset_Used[0])); |
|
j++) { |
sc->sc_c.sc_script[E_saved_offset_offset_Used[j]] = |
sc->sc_c.sc_script[E_saved_offset_offset_Used[j]] = |
htole32(sizeof(struct siop_common_xfer) + 4); |
htole32(sizeof(struct siop_common_xfer) + 4); |
} |
} |
for (j = 0; j < __arraycount(E_abs_msgin2_Used); j++) { |
for (j = 0; j < |
|
(sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0])); |
|
j++) { |
sc->sc_c.sc_script[E_abs_msgin2_Used[j]] = |
sc->sc_c.sc_script[E_abs_msgin2_Used[j]] = |
htole32(msgin_addr); |
htole32(msgin_addr); |
} |
} |
for (j = 0; j < __arraycount(E_abs_sem_Used); j++) { |
for (j = 0; j < |
|
(sizeof(E_abs_sem_Used) / sizeof(E_abs_sem_Used[0])); |
|
j++) { |
sc->sc_c.sc_script[E_abs_sem_Used[j]] = |
sc->sc_c.sc_script[E_abs_sem_Used[j]] = |
htole32(sem_addr); |
htole32(sem_addr); |
} |
} |
|
|
if (sc->sc_c.features & SF_CHIP_LED0) { |
if (sc->sc_c.features & SF_CHIP_LED0) { |
for (j = 0; j < __arraycount(esiop_led_on); j++) |
for (j = 0; j < (sizeof(esiop_led_on) / |
|
sizeof(esiop_led_on[0])); j++) |
sc->sc_c.sc_script[ |
sc->sc_c.sc_script[ |
Ent_led_on1 / sizeof(esiop_led_on[0]) + j |
Ent_led_on1 / sizeof(esiop_led_on[0]) + j |
] = htole32(esiop_led_on[j]); |
] = htole32(esiop_led_on[j]); |
for (j = 0; j < __arraycount(esiop_led_on); j++) |
for (j = 0; j < (sizeof(esiop_led_on) / |
|
sizeof(esiop_led_on[0])); j++) |
sc->sc_c.sc_script[ |
sc->sc_c.sc_script[ |
Ent_led_on2 / sizeof(esiop_led_on[0]) + j |
Ent_led_on2 / sizeof(esiop_led_on[0]) + j |
] = htole32(esiop_led_on[j]); |
] = htole32(esiop_led_on[j]); |
for (j = 0; j < __arraycount(esiop_led_off); j++) |
for (j = 0; j < (sizeof(esiop_led_off) / |
|
sizeof(esiop_led_off[0])); j++) |
sc->sc_c.sc_script[ |
sc->sc_c.sc_script[ |
Ent_led_off / sizeof(esiop_led_off[0]) + j |
Ent_led_off / sizeof(esiop_led_off[0]) + j |
] = htole32(esiop_led_off[j]); |
] = htole32(esiop_led_off[j]); |
} |
} |
} |
} |
/* get base of scheduler ring */ |
/* get base of scheduler ring */ |
addr = sc->sc_c.sc_scriptaddr + sc->sc_shedoffset * sizeof(uint32_t); |
addr = sc->sc_c.sc_scriptaddr + sc->sc_shedoffset * sizeof(u_int32_t); |
/* init scheduler */ |
/* init scheduler */ |
for (i = 0; i < A_ncmd_slots; i++) { |
for (i = 0; i < A_ncmd_slots; i++) { |
esiop_script_write(sc, |
esiop_script_write(sc, |
Line 328 esiop_reset(struct esiop_softc *sc) |
|
Line 353 esiop_reset(struct esiop_softc *sc) |
|
for (i = 0; i < A_ndone_slots; i++) |
for (i = 0; i < A_ndone_slots; i++) |
sc->sc_done_slot[i] = 0; |
sc->sc_done_slot[i] = 0; |
bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map, |
bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map, |
sc->sc_done_offset, A_ndone_slots * sizeof(uint32_t), |
sc->sc_done_offset, A_ndone_slots * sizeof(u_int32_t), |
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
addr = sc->sc_done_map->dm_segs[0].ds_addr + sc->sc_done_offset; |
addr = sc->sc_done_map->dm_segs[0].ds_addr + sc->sc_done_offset; |
sc->sc_currdoneslot = 0; |
sc->sc_currdoneslot = 0; |
Line 346 esiop_reset(struct esiop_softc *sc) |
|
Line 371 esiop_reset(struct esiop_softc *sc) |
|
/* set flags */ |
/* set flags */ |
bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHC, 0); |
bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHC, 0); |
/* write pointer of base of target DSA table */ |
/* write pointer of base of target DSA table */ |
addr = (sc->sc_target_table_offset * sizeof(uint32_t)) + |
addr = (sc->sc_target_table_offset * sizeof(u_int32_t)) + |
sc->sc_c.sc_scriptaddr; |
sc->sc_c.sc_scriptaddr; |
esiop_script_write(sc, (Ent_load_targtable / 4) + 0, |
esiop_script_write(sc, (Ent_load_targtable / 4) + 0, |
esiop_script_read(sc,(Ent_load_targtable / 4) + 0) | |
esiop_script_read(sc,(Ent_load_targtable / 4) + 0) | |
Line 362 esiop_reset(struct esiop_softc *sc) |
|
Line 387 esiop_reset(struct esiop_softc *sc) |
|
((addr & 0xff000000) >> 16)); |
((addr & 0xff000000) >> 16)); |
#ifdef SIOP_DEBUG |
#ifdef SIOP_DEBUG |
printf("%s: target table offset %d free offset %d\n", |
printf("%s: target table offset %d free offset %d\n", |
device_xname(sc->sc_c.sc_dev), sc->sc_target_table_offset, |
device_xname(&sc->sc_c.sc_dev), sc->sc_target_table_offset, |
sc->sc_free_offset); |
sc->sc_free_offset); |
#endif |
#endif |
|
|
Line 381 esiop_reset(struct esiop_softc *sc) |
|
Line 406 esiop_reset(struct esiop_softc *sc) |
|
} |
} |
|
|
#if 0 |
#if 0 |
#define CALL_SCRIPT(ent) do { \ |
#define CALL_SCRIPT(ent) do {\ |
printf ("start script DSA 0x%lx DSP 0x%lx\n", \ |
printf ("start script DSA 0x%lx DSP 0x%lx\n", \ |
esiop_cmd->cmd_c.dsa, \ |
esiop_cmd->cmd_c.dsa, \ |
sc->sc_c.sc_scriptaddr + ent); \ |
sc->sc_c.sc_scriptaddr + ent); \ |
bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, \ |
bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \ |
SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \ |
} while (0) |
} while (/* CONSTCOND */0) |
|
#else |
#else |
#define CALL_SCRIPT(ent) do { \ |
#define CALL_SCRIPT(ent) do {\ |
bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, \ |
bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \ |
SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \ |
} while (0) |
} while (/* CONSTCOND */0) |
|
#endif |
#endif |
|
|
int |
int |
Line 404 esiop_intr(void *v) |
|
Line 427 esiop_intr(void *v) |
|
struct esiop_lun *esiop_lun; |
struct esiop_lun *esiop_lun; |
struct scsipi_xfer *xs; |
struct scsipi_xfer *xs; |
int istat, sist, sstat1, dstat = 0; /* XXX: gcc */ |
int istat, sist, sstat1, dstat = 0; /* XXX: gcc */ |
uint32_t irqcode; |
u_int32_t irqcode; |
int need_reset = 0; |
int need_reset = 0; |
int offset, target, lun, tag; |
int offset, target, lun, tag; |
uint32_t tflags; |
u_int32_t tflags; |
uint32_t addr; |
u_int32_t addr; |
int freetarget = 0; |
int freetarget = 0; |
int slot; |
int slot; |
int retval = 0; |
int retval = 0; |
|
|
esiop_cmd = |
esiop_cmd = |
(tag >= 0) ? esiop_lun->tactive[tag] : esiop_lun->active; |
(tag >= 0) ? esiop_lun->tactive[tag] : esiop_lun->active; |
if (esiop_cmd == NULL) { |
if (esiop_cmd == NULL) { |
printf("esiop_cmd (target %d lun %d tag %d)" |
printf("esiop_cmd (target %d lun %d tag %d) not valid\n", |
" not valid\n", |
|
target, lun, tag); |
target, lun, tag); |
goto none; |
goto none; |
} |
} |
xs = esiop_cmd->cmd_c.xs; |
xs = esiop_cmd->cmd_c.xs; |
#ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) { |
if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) { |
printf("esiop_cmd (target %d lun %d) " |
printf("esiop_cmd (target %d lun %d) " |
"not active (%d)\n", target, lun, |
"not active (%d)\n", target, lun, |
esiop_cmd->cmd_c.status); |
esiop_cmd->cmd_c.status); |
goto none; |
goto none; |
|
|
} |
} |
|
|
if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) { |
if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) { |
printf("%s: DMA IRQ:", device_xname(sc->sc_c.sc_dev)); |
printf("%s: DMA IRQ:", device_xname(&sc->sc_c.sc_dev)); |
if (dstat & DSTAT_IID) |
if (dstat & DSTAT_IID) |
printf(" Illegal instruction"); |
printf(" Illegal instruction"); |
if (dstat & DSTAT_BF) |
if (dstat & DSTAT_BF) |
|
|
if (esiop_cmd) |
if (esiop_cmd) |
scsipi_printaddr(xs->xs_periph); |
scsipi_printaddr(xs->xs_periph); |
else |
else |
printf("%s:", device_xname(sc->sc_c.sc_dev)); |
printf("%s:", device_xname(&sc->sc_c.sc_dev)); |
printf("scsi gross error\n"); |
printf("scsi gross error\n"); |
if (esiop_target) |
if (esiop_target) |
esiop_target->target_c.flags &= ~TARF_DT; |
esiop_target->target_c.flags &= ~TARF_DT; |
#ifdef SIOP_DEBUG |
#ifdef DEBUG |
printf("DSA=0x%x DSP=0x%lx\n", |
printf("DSA=0x%x DSP=0x%lx\n", |
bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA), |
SIOP_DSA), |
(u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
(u_long)(bus_space_read_4(sc->sc_c.sc_rt, |
SIOP_DSP) - |
sc->sc_c.sc_rh, SIOP_DSP) - |
|
sc->sc_c.sc_scriptaddr)); |
sc->sc_c.sc_scriptaddr)); |
printf("SDID 0x%x SCNTL3 0x%x SXFER 0x%x SCNTL4 0x%x\n", |
printf("SDID 0x%x SCNTL3 0x%x SXFER 0x%x SCNTL4 0x%x\n", |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SDID), |
SIOP_SDID), |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCNTL3), |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SXFER), |
SIOP_SCNTL3), |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCNTL4)); |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
|
SIOP_SXFER), |
|
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
|
SIOP_SCNTL4)); |
|
|
|
#endif |
#endif |
goto reset; |
goto reset; |
|
|
CALL_SCRIPT(Ent_msgin); |
CALL_SCRIPT(Ent_msgin); |
return 1; |
return 1; |
} |
} |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unexpected phase mismatch %d\n", |
"unexpected phase mismatch %d\n", |
|
sstat1 & SSTAT1_PHASE_MASK); |
sstat1 & SSTAT1_PHASE_MASK); |
} else { |
} else { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "phase mismatch without command\n"); |
"phase mismatch without command\n"); |
|
} |
} |
need_reset = 1; |
need_reset = 1; |
} |
} |
|
|
if (esiop_cmd) |
if (esiop_cmd) |
scsipi_printaddr(xs->xs_periph); |
scsipi_printaddr(xs->xs_periph); |
else |
else |
printf("%s:", device_xname(sc->sc_c.sc_dev)); |
printf("%s:", device_xname(&sc->sc_c.sc_dev)); |
printf("parity error\n"); |
printf("parity error\n"); |
if (esiop_target) |
if (esiop_target) |
esiop_target->target_c.flags &= ~TARF_DT; |
esiop_target->target_c.flags &= ~TARF_DT; |
|
|
esiop_script_sync(sc, |
esiop_script_sync(sc, |
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
#ifdef SIOP_DEBUG_SCHED |
#ifdef SIOP_DEBUG_SCHED |
printf("sel timeout target %d, slot %d\n", |
printf("sel timeout target %d, slot %d\n", target, slot); |
target, slot); |
|
#endif |
#endif |
/* |
/* |
* mark this slot as free, and advance to next slot |
* mark this slot as free, and advance to next slot |
|
|
bus_space_write_1(sc->sc_c.sc_rt, |
bus_space_write_1(sc->sc_c.sc_rt, |
sc->sc_c.sc_rh, SIOP_SCRATCHE, 0); |
sc->sc_c.sc_rh, SIOP_SCRATCHE, 0); |
addr = sc->sc_c.sc_scriptaddr + |
addr = sc->sc_c.sc_scriptaddr + |
sc->sc_shedoffset * sizeof(uint32_t); |
sc->sc_shedoffset * sizeof(u_int32_t); |
} |
} |
bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
SIOP_SCRATCHD, addr); |
SIOP_SCRATCHD, addr); |
|
|
printf("%s: selection timeout without " |
printf("%s: selection timeout without " |
"command, target %d (sdid 0x%x), " |
"command, target %d (sdid 0x%x), " |
"slot %d\n", |
"slot %d\n", |
device_xname(sc->sc_c.sc_dev), target, |
device_xname(&sc->sc_c.sc_dev), target, |
bus_space_read_1(sc->sc_c.sc_rt, |
bus_space_read_1(sc->sc_c.sc_rt, |
sc->sc_c.sc_rh, SIOP_SDID), slot); |
sc->sc_c.sc_rh, SIOP_SDID), slot); |
need_reset = 1; |
need_reset = 1; |
|
|
htole32(SCSI_CHECK); |
htole32(SCSI_CHECK); |
goto end; |
goto end; |
} |
} |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unexpected disconnect without " |
"unexpected disconnect without command\n"); |
"command\n"); |
goto reset; |
goto reset; |
} |
} |
if (sist & (SIST1_SBMC << 8)) { |
if (sist & (SIST1_SBMC << 8)) { |
|
|
return 1; |
return 1; |
} |
} |
/* Else it's an unhandled exception (for now). */ |
/* Else it's an unhandled exception (for now). */ |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unhandled scsi interrupt, sist=0x%x sstat1=0x%x " |
"unhandled scsi interrupt, sist=0x%x sstat1=0x%x " |
|
"DSA=0x%x DSP=0x%x\n", sist, |
"DSA=0x%x DSP=0x%x\n", sist, |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, |
SIOP_SSTAT1), |
SIOP_SSTAT1), |
|
|
*/ |
*/ |
if ((irqcode & 0x80) == 0) { |
if ((irqcode & 0x80) == 0) { |
if (esiop_cmd == NULL) { |
if (esiop_cmd == NULL) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, |
"script interrupt (0x%x) with invalid DSA !!!\n", |
"script interrupt (0x%x) with invalid DSA !!!\n", |
irqcode); |
irqcode); |
goto reset; |
goto reset; |
} |
} |
if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) { |
if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "command with invalid status " |
"command with invalid status " |
|
"(IRQ code 0x%x current status %d) !\n", |
"(IRQ code 0x%x current status %d) !\n", |
irqcode, esiop_cmd->cmd_c.status); |
irqcode, esiop_cmd->cmd_c.status); |
xs = NULL; |
xs = NULL; |
|
|
case A_int_err: |
case A_int_err: |
printf("error, DSP=0x%x\n", |
printf("error, DSP=0x%x\n", |
(int)(bus_space_read_4(sc->sc_c.sc_rt, |
(int)(bus_space_read_4(sc->sc_c.sc_rt, |
sc->sc_c.sc_rh, SIOP_DSP) - |
sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr)); |
sc->sc_c.sc_scriptaddr)); |
|
if (xs) { |
if (xs) { |
xs->error = XS_SELTIMEOUT; |
xs->error = XS_SELTIMEOUT; |
goto end; |
goto end; |
|
|
if (xs) |
if (xs) |
scsipi_printaddr(xs->xs_periph); |
scsipi_printaddr(xs->xs_periph); |
else |
else |
printf("%s: ", device_xname( |
printf("%s: ", |
sc->sc_c.sc_dev)); |
device_xname(&sc->sc_c.sc_dev)); |
printf("our reject message was " |
printf("our reject message was " |
"rejected\n"); |
"rejected\n"); |
goto reset; |
goto reset; |
|
|
scsipi_printaddr(xs->xs_periph); |
scsipi_printaddr(xs->xs_periph); |
else |
else |
printf("%s: ", |
printf("%s: ", |
device_xname(sc->sc_c.sc_dev)); |
device_xname(&sc->sc_c.sc_dev)); |
if (msg == MSG_EXTENDED) { |
if (msg == MSG_EXTENDED) { |
printf("scsi message reject, extended " |
printf("scsi message reject, extended " |
"message sent was 0x%x\n", extmsg); |
"message sent was 0x%x\n", extmsg); |
|
|
if (xs) |
if (xs) |
scsipi_printaddr(xs->xs_periph); |
scsipi_printaddr(xs->xs_periph); |
else |
else |
printf("%s: ", device_xname(sc->sc_c.sc_dev)); |
printf("%s: ", device_xname(&sc->sc_c.sc_dev)); |
printf("unhandled message 0x%x\n", msgin); |
printf("unhandled message 0x%x\n", msgin); |
esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT; |
esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT; |
esiop_cmd->cmd_tables->t_msgout.count= htole32(1); |
esiop_cmd->cmd_tables->t_msgout.count= htole32(1); |
|
|
#endif |
#endif |
if (esiop_cmd->cmd_tables->msg_in[1] > |
if (esiop_cmd->cmd_tables->msg_in[1] > |
sizeof(esiop_cmd->cmd_tables->msg_in) - 2) |
sizeof(esiop_cmd->cmd_tables->msg_in) - 2) |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "extended message too big (%d)\n", |
"extended message too big (%d)\n", |
|
esiop_cmd->cmd_tables->msg_in[1]); |
esiop_cmd->cmd_tables->msg_in[1]); |
esiop_cmd->cmd_tables->t_extmsgdata.count = |
esiop_cmd->cmd_tables->t_extmsgdata.count = |
htole32(esiop_cmd->cmd_tables->msg_in[1] - 1); |
htole32(esiop_cmd->cmd_tables->msg_in[1] - 1); |
|
|
case A_int_done: |
case A_int_done: |
if (xs == NULL) { |
if (xs == NULL) { |
printf("%s: done without command\n", |
printf("%s: done without command\n", |
device_xname(sc->sc_c.sc_dev)); |
device_xname(&sc->sc_c.sc_dev)); |
CALL_SCRIPT(Ent_script_sched); |
CALL_SCRIPT(Ent_script_sched); |
return 1; |
return 1; |
} |
} |
#ifdef SIOP_DEBUG_INTR |
#ifdef SIOP_DEBUG_INTR |
printf("done, DSA=0x%lx target id 0x%x last msg " |
printf("done, DSA=0x%lx target id 0x%x last msg " |
"in=0x%x status=0x%x\n", |
"in=0x%x status=0x%x\n", (u_long)esiop_cmd->cmd_c.dsa, |
(u_long)esiop_cmd->cmd_c.dsa, |
|
le32toh(esiop_cmd->cmd_tables->id), |
le32toh(esiop_cmd->cmd_tables->id), |
esiop_cmd->cmd_tables->msg_in[0], |
esiop_cmd->cmd_tables->msg_in[0], |
le32toh(esiop_cmd->cmd_tables->status)); |
le32toh(esiop_cmd->cmd_tables->status)); |
|
|
/* |
/* |
* if we got a disconnect between the last data phase |
* if we got a disconnect between the last data phase |
* and the status phase, offset will be 0. In this |
* and the status phase, offset will be 0. In this |
* case, cmd_tables->saved_offset will have the proper value |
* case, cmd_tables->saved_offset will have the proper value |
* if it got updated by the controller |
* if it got updated by the controller |
*/ |
*/ |
if (offset == 0 && |
if (offset == 0 && |
Line 1164 esiop_scsicmd_end(struct esiop_cmd *esio |
|
Line 1173 esiop_scsicmd_end(struct esiop_cmd *esio |
|
INCSTAT(esiop_stat_intr_qfull); |
INCSTAT(esiop_stat_intr_qfull); |
#ifdef SIOP_DEBUG |
#ifdef SIOP_DEBUG |
printf("%s:%d:%d: queue full (tag %d)\n", |
printf("%s:%d:%d: queue full (tag %d)\n", |
device_xname(sc->sc_c.sc_dev), |
device_xname(&sc->sc_c.sc_dev), |
xs->xs_periph->periph_target, |
xs->xs_periph->periph_target, |
xs->xs_periph->periph_lun, esiop_cmd->cmd_c.tag); |
xs->xs_periph->periph_lun, esiop_cmd->cmd_c.tag); |
#endif |
#endif |
Line 1215 esiop_checkdone(struct esiop_softc *sc) |
|
Line 1224 esiop_checkdone(struct esiop_softc *sc) |
|
struct esiop_target *esiop_target; |
struct esiop_target *esiop_target; |
struct esiop_lun *esiop_lun; |
struct esiop_lun *esiop_lun; |
struct esiop_cmd *esiop_cmd; |
struct esiop_cmd *esiop_cmd; |
uint32_t slot; |
u_int32_t slot; |
int needsync = 0; |
int needsync = 0; |
int status; |
int status; |
uint32_t sem, offset; |
u_int32_t sem, offset; |
|
|
esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
sem = esiop_script_read(sc, sc->sc_semoffset); |
sem = esiop_script_read(sc, sc->sc_semoffset); |
Line 1239 esiop_checkdone(struct esiop_softc *sc) |
|
Line 1248 esiop_checkdone(struct esiop_softc *sc) |
|
} |
} |
|
|
bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map, |
bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map, |
sc->sc_done_offset, A_ndone_slots * sizeof(uint32_t), |
sc->sc_done_offset, A_ndone_slots * sizeof(u_int32_t), |
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
next: |
next: |
if (sc->sc_done_slot[sc->sc_currdoneslot] == 0) { |
if (sc->sc_done_slot[sc->sc_currdoneslot] == 0) { |
if (needsync) |
if (needsync) |
bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map, |
bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map, |
sc->sc_done_offset, |
sc->sc_done_offset, |
A_ndone_slots * sizeof(uint32_t), |
A_ndone_slots * sizeof(u_int32_t), |
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
return; |
return; |
} |
} |
|
|
} |
} |
|
|
esiop_table_sync(esiop_cmd, |
esiop_table_sync(esiop_cmd, |
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
status = le32toh(esiop_cmd->cmd_tables->status); |
status = le32toh(esiop_cmd->cmd_tables->status); |
#ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
if (status != SCSI_OK) { |
if (status != SCSI_OK) { |
|
|
void |
void |
esiop_unqueue(struct esiop_softc *sc, int target, int lun) |
esiop_unqueue(struct esiop_softc *sc, int target, int lun) |
{ |
{ |
int slot, tag; |
int slot, tag; |
uint32_t slotdsa; |
u_int32_t slotdsa; |
struct esiop_cmd *esiop_cmd; |
struct esiop_cmd *esiop_cmd; |
struct esiop_lun *esiop_lun = |
struct esiop_lun *esiop_lun = |
((struct esiop_target *)sc->sc_c.targets[target])->esiop_lun[lun]; |
((struct esiop_target *)sc->sc_c.targets[target])->esiop_lun[lun]; |
Line 1368 esiop_handle_qtag_reject(struct esiop_cm |
|
Line 1377 esiop_handle_qtag_reject(struct esiop_cm |
|
|
|
#ifdef SIOP_DEBUG |
#ifdef SIOP_DEBUG |
printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n", |
printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n", |
device_xname(sc->sc_c.sc_dev), target, lun, tag, |
device_xname(&sc->sc_c.sc_dev), target, lun, tag, esiop_cmd->cmd_c.tag, |
esiop_cmd->cmd_c.tag, esiop_cmd->cmd_c.status); |
esiop_cmd->cmd_c.status); |
#endif |
#endif |
|
|
if (esiop_lun->active != NULL) { |
if (esiop_lun->active != NULL) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "untagged command already running for target %d " |
"untagged command already running for target %d " |
|
"lun %d (status %d)\n", |
"lun %d (status %d)\n", |
target, lun, esiop_lun->active->cmd_c.status); |
target, lun, esiop_lun->active->cmd_c.status); |
return -1; |
return -1; |
Line 1387 esiop_handle_qtag_reject(struct esiop_cm |
|
Line 1395 esiop_handle_qtag_reject(struct esiop_cm |
|
esiop_cmd->cmd_c.tag = -1; |
esiop_cmd->cmd_c.tag = -1; |
/* update DSA table */ |
/* update DSA table */ |
esiop_script_write(sc, esiop_target->lun_table_offset + |
esiop_script_write(sc, esiop_target->lun_table_offset + |
lun * 2 + A_target_luntbl / sizeof(uint32_t), |
lun * 2 + A_target_luntbl / sizeof(u_int32_t), |
esiop_cmd->cmd_c.dsa); |
esiop_cmd->cmd_c.dsa); |
esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
return 0; |
return 0; |
Line 1409 esiop_handle_reset(struct esiop_softc *s |
|
Line 1417 esiop_handle_reset(struct esiop_softc *s |
|
* scsi bus reset. reset the chip and restart |
* scsi bus reset. reset the chip and restart |
* the queue. Need to clean up all active commands |
* the queue. Need to clean up all active commands |
*/ |
*/ |
printf("%s: scsi bus reset\n", device_xname(sc->sc_c.sc_dev)); |
printf("%s: scsi bus reset\n", device_xname(&sc->sc_c.sc_dev)); |
/* stop, reset and restart the chip */ |
/* stop, reset and restart the chip */ |
esiop_reset(sc); |
esiop_reset(sc); |
|
|
Line 1423 esiop_handle_reset(struct esiop_softc *s |
|
Line 1431 esiop_handle_reset(struct esiop_softc *s |
|
* being executed |
* being executed |
*/ |
*/ |
esiop_checkdone(sc); |
esiop_checkdone(sc); |
for (target = 0; target < sc->sc_c.sc_chan.chan_ntargets; target++) { |
for (target = 0; target < sc->sc_c.sc_chan.chan_ntargets; |
|
target++) { |
struct esiop_target *esiop_target = |
struct esiop_target *esiop_target = |
(struct esiop_target *)sc->sc_c.targets[target]; |
(struct esiop_target *)sc->sc_c.targets[target]; |
if (esiop_target == NULL) |
if (esiop_target == NULL) |
Line 1442 esiop_handle_reset(struct esiop_softc *s |
|
Line 1451 esiop_handle_reset(struct esiop_softc *s |
|
esiop_cmd = esiop_lun->active; |
esiop_cmd = esiop_lun->active; |
if (esiop_cmd == NULL) |
if (esiop_cmd == NULL) |
continue; |
continue; |
scsipi_printaddr( |
scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph); |
esiop_cmd->cmd_c.xs->xs_periph); |
|
printf("command with tag id %d reset\n", tag); |
printf("command with tag id %d reset\n", tag); |
esiop_cmd->cmd_c.xs->error = |
esiop_cmd->cmd_c.xs->error = |
(esiop_cmd->cmd_c.flags & CMDFL_TIMEOUT) ? |
(esiop_cmd->cmd_c.flags & CMDFL_TIMEOUT) ? |
XS_TIMEOUT : XS_RESET; |
XS_TIMEOUT : XS_RESET; |
esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK; |
esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK; |
if (tag >= 0) |
if (tag >= 0) |
esiop_lun->tactive[tag] = NULL; |
esiop_lun->tactive[tag] = NULL; |
Line 1468 esiop_handle_reset(struct esiop_softc *s |
|
Line 1476 esiop_handle_reset(struct esiop_softc *s |
|
} |
} |
|
|
void |
void |
esiop_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, |
esiop_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg) |
void *arg) |
|
{ |
{ |
struct scsipi_xfer *xs; |
struct scsipi_xfer *xs; |
struct scsipi_periph *periph; |
struct scsipi_periph *periph; |
struct esiop_softc *sc = device_private(chan->chan_adapter->adapt_dev); |
struct esiop_softc *sc = (void *)chan->chan_adapter->adapt_dev; |
struct esiop_cmd *esiop_cmd; |
struct esiop_cmd *esiop_cmd; |
struct esiop_target *esiop_target; |
struct esiop_target *esiop_target; |
int s, error, i; |
int s, error, i; |
Line 1518 esiop_scsipi_request(struct scsipi_chann |
|
Line 1525 esiop_scsipi_request(struct scsipi_chann |
|
if (esiop_target == NULL) { |
if (esiop_target == NULL) { |
#ifdef SIOP_DEBUG |
#ifdef SIOP_DEBUG |
printf("%s: alloc siop_target for target %d\n", |
printf("%s: alloc siop_target for target %d\n", |
device_xname(sc->sc_c.sc_dev), target); |
device_xname(&sc->sc_c.sc_dev), target); |
#endif |
#endif |
sc->sc_c.targets[target] = |
sc->sc_c.targets[target] = |
malloc(sizeof(struct esiop_target), |
malloc(sizeof(struct esiop_target), |
M_DEVBUF, M_NOWAIT | M_ZERO); |
M_DEVBUF, M_NOWAIT | M_ZERO); |
if (sc->sc_c.targets[target] == NULL) { |
if (sc->sc_c.targets[target] == NULL) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "can't malloc memory for " |
"can't malloc memory for " |
"target %d\n", target); |
"target %d\n", |
|
target); |
|
xs->error = XS_RESOURCE_SHORTAGE; |
xs->error = XS_RESOURCE_SHORTAGE; |
scsipi_done(xs); |
scsipi_done(xs); |
TAILQ_INSERT_TAIL(&sc->free_list, |
|
esiop_cmd, next); |
|
splx(s); |
splx(s); |
return; |
return; |
} |
} |
Line 1553 esiop_scsipi_request(struct scsipi_chann |
|
Line 1556 esiop_scsipi_request(struct scsipi_chann |
|
malloc(sizeof(struct esiop_lun), M_DEVBUF, |
malloc(sizeof(struct esiop_lun), M_DEVBUF, |
M_NOWAIT|M_ZERO); |
M_NOWAIT|M_ZERO); |
if (esiop_target->esiop_lun[lun] == NULL) { |
if (esiop_target->esiop_lun[lun] == NULL) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "can't alloc esiop_lun for " |
"can't alloc esiop_lun for " |
|
"target %d lun %d\n", |
"target %d lun %d\n", |
target, lun); |
target, lun); |
xs->error = XS_RESOURCE_SHORTAGE; |
xs->error = XS_RESOURCE_SHORTAGE; |
scsipi_done(xs); |
scsipi_done(xs); |
TAILQ_INSERT_TAIL(&sc->free_list, |
|
esiop_cmd, next); |
|
splx(s); |
splx(s); |
return; |
return; |
} |
} |
Line 1575 esiop_scsipi_request(struct scsipi_chann |
|
Line 1575 esiop_scsipi_request(struct scsipi_chann |
|
esiop_cmd->cmd_c.dmamap_cmd, |
esiop_cmd->cmd_c.dmamap_cmd, |
xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT); |
xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to load cmd DMA map: %d\n", |
"unable to load cmd DMA map: %d\n", |
|
error); |
error); |
xs->error = (error == EAGAIN) ? |
xs->error = XS_DRIVER_STUFFUP; |
XS_RESOURCE_SHORTAGE : XS_DRIVER_STUFFUP; |
|
scsipi_done(xs); |
scsipi_done(xs); |
esiop_cmd->cmd_c.status = CMDST_FREE; |
|
TAILQ_INSERT_TAIL(&sc->free_list, esiop_cmd, next); |
|
splx(s); |
splx(s); |
return; |
return; |
} |
} |
Line 1593 esiop_scsipi_request(struct scsipi_chann |
|
Line 1589 esiop_scsipi_request(struct scsipi_chann |
|
((xs->xs_control & XS_CTL_DATA_IN) ? |
((xs->xs_control & XS_CTL_DATA_IN) ? |
BUS_DMA_READ : BUS_DMA_WRITE)); |
BUS_DMA_READ : BUS_DMA_WRITE)); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to load cmd DMA map: %d", |
"unable to load data DMA map: %d\n", |
|
error); |
error); |
xs->error = (error == EAGAIN) ? |
xs->error = XS_DRIVER_STUFFUP; |
XS_RESOURCE_SHORTAGE : XS_DRIVER_STUFFUP; |
|
scsipi_done(xs); |
scsipi_done(xs); |
bus_dmamap_unload(sc->sc_c.sc_dmat, |
bus_dmamap_unload(sc->sc_c.sc_dmat, |
esiop_cmd->cmd_c.dmamap_cmd); |
esiop_cmd->cmd_c.dmamap_cmd); |
esiop_cmd->cmd_c.status = CMDST_FREE; |
|
TAILQ_INSERT_TAIL(&sc->free_list, |
|
esiop_cmd, next); |
|
splx(s); |
splx(s); |
return; |
return; |
} |
} |
Line 1647 esiop_scsipi_request(struct scsipi_chann |
|
Line 1638 esiop_scsipi_request(struct scsipi_chann |
|
|
|
case ADAPTER_REQ_GROW_RESOURCES: |
case ADAPTER_REQ_GROW_RESOURCES: |
#ifdef SIOP_DEBUG |
#ifdef SIOP_DEBUG |
printf("%s grow resources (%d)\n", |
printf("%s grow resources (%d)\n", device_xname(&sc->sc_c.sc_dev), |
device_xname(sc->sc_c.sc_dev), |
|
sc->sc_c.sc_adapt.adapt_openings); |
sc->sc_c.sc_adapt.adapt_openings); |
#endif |
#endif |
esiop_morecbd(sc); |
esiop_morecbd(sc); |
return; |
return; |
|
|
case ADAPTER_REQ_SET_XFER_MODE: |
case ADAPTER_REQ_SET_XFER_MODE: |
{ |
{ |
struct scsipi_xfer_mode *xm = arg; |
struct scsipi_xfer_mode *xm = arg; |
if (sc->sc_c.targets[xm->xm_target] == NULL) |
if (sc->sc_c.targets[xm->xm_target] == NULL) |
return; |
return; |
Line 1684 esiop_scsipi_request(struct scsipi_chann |
|
Line 1674 esiop_scsipi_request(struct scsipi_chann |
|
sc->sc_c.targets[xm->xm_target]->status = TARST_ASYNC; |
sc->sc_c.targets[xm->xm_target]->status = TARST_ASYNC; |
|
|
splx(s); |
splx(s); |
} |
} |
} |
} |
} |
} |
|
|
Line 1764 esiop_start(struct esiop_softc *sc, stru |
|
Line 1754 esiop_start(struct esiop_softc *sc, stru |
|
bus_dmamap_sync(sc->sc_c.sc_dmat, |
bus_dmamap_sync(sc->sc_c.sc_dmat, |
esiop_lun->lun_tagtbl->tblblk->blkmap, |
esiop_lun->lun_tagtbl->tblblk->blkmap, |
esiop_lun->lun_tagtbl->tbl_offset, |
esiop_lun->lun_tagtbl->tbl_offset, |
sizeof(uint32_t) * ESIOP_NTAG, BUS_DMASYNC_PREWRITE); |
sizeof(u_int32_t) * ESIOP_NTAG, BUS_DMASYNC_PREWRITE); |
} else { |
} else { |
esiop_lun->active = esiop_cmd; |
esiop_lun->active = esiop_cmd; |
esiop_script_write(sc, |
esiop_script_write(sc, |
esiop_target->lun_table_offset + |
esiop_target->lun_table_offset + |
lun * 2 + A_target_luntbl / sizeof(uint32_t), |
lun * 2 + A_target_luntbl / sizeof(u_int32_t), |
esiop_cmd->cmd_c.dsa); |
esiop_cmd->cmd_c.dsa); |
} |
} |
/* scheduler slot: DSA */ |
/* scheduler slot: DSA */ |
Line 1793 esiop_start(struct esiop_softc *sc, stru |
|
Line 1783 esiop_start(struct esiop_softc *sc, stru |
|
sc->sc_currschedslot++; |
sc->sc_currschedslot++; |
if (sc->sc_currschedslot >= A_ncmd_slots) |
if (sc->sc_currschedslot >= A_ncmd_slots) |
sc->sc_currschedslot = 0; |
sc->sc_currschedslot = 0; |
|
return; |
} |
} |
|
|
void |
void |
Line 1808 esiop_timeout(void *v) |
|
Line 1799 esiop_timeout(void *v) |
|
|
|
s = splbio(); |
s = splbio(); |
esiop_table_sync(esiop_cmd, |
esiop_table_sync(esiop_cmd, |
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
BUS_DMASYNC_POSTREAD | |
|
BUS_DMASYNC_POSTWRITE); |
scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph); |
scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph); |
#ifdef SIOP_DEBUG |
#ifdef SIOP_DEBUG |
printf("command timeout (status %d)\n", |
printf("command timeout (status %d)\n", le32toh(esiop_cmd->cmd_tables->status)); |
le32toh(esiop_cmd->cmd_tables->status)); |
|
|
|
esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
for (slot = 0; slot < A_ncmd_slots; slot++) { |
for (slot = 0; slot < A_ncmd_slots; slot++) { |
Line 1821 esiop_timeout(void *v) |
|
Line 1812 esiop_timeout(void *v) |
|
if ((slotdsa & 0x01) == 0) |
if ((slotdsa & 0x01) == 0) |
printf("slot %d not free (0x%x)\n", slot, slotdsa); |
printf("slot %d not free (0x%x)\n", slot, slotdsa); |
} |
} |
printf("istat 0x%x ", |
printf("istat 0x%x ", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT)); |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT)); |
|
printf("DSP 0x%lx DSA 0x%x\n", |
printf("DSP 0x%lx DSA 0x%x\n", |
(u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP) |
(u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr), |
- sc->sc_c.sc_scriptaddr), |
|
bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA)); |
bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA)); |
(void)bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_CTEST2); |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_CTEST2); |
printf("istat 0x%x\n", |
printf("istat 0x%x\n", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT)); |
bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT)); |
|
#else |
#else |
printf("command timeout, CDB: "); |
printf("command timeout, CDB: "); |
scsipi_print_cdb(esiop_cmd->cmd_c.xs->cmd); |
scsipi_print_cdb(esiop_cmd->cmd_c.xs->cmd); |
Line 1847 esiop_timeout(void *v) |
|
Line 1835 esiop_timeout(void *v) |
|
*/ |
*/ |
esiop_cmd->cmd_c.flags |= CMDFL_TIMEOUT; |
esiop_cmd->cmd_c.flags |= CMDFL_TIMEOUT; |
splx(s); |
splx(s); |
|
return; |
|
|
} |
} |
|
|
void |
void |
esiop_dump_script(struct esiop_softc *sc) |
esiop_dump_script(struct esiop_softc *sc) |
{ |
{ |
int i; |
int i; |
|
|
for (i = 0; i < PAGE_SIZE / 4; i += 2) { |
for (i = 0; i < PAGE_SIZE / 4; i += 2) { |
printf("0x%04x: 0x%08x 0x%08x", i * 4, |
printf("0x%04x: 0x%08x 0x%08x", i * 4, |
esiop_script_read(sc, i), |
le32toh(sc->sc_c.sc_script[i]), |
esiop_script_read(sc, i + 1)); |
le32toh(sc->sc_c.sc_script[i+1])); |
if ((esiop_script_read(sc, i) & 0xe0000000) == 0xc0000000) { |
if ((le32toh(sc->sc_c.sc_script[i]) & 0xe0000000) == |
|
0xc0000000) { |
i++; |
i++; |
printf(" 0x%08x", esiop_script_read(sc, i + 1)); |
printf(" 0x%08x", le32toh(sc->sc_c.sc_script[i+1])); |
} |
} |
printf("\n"); |
printf("\n"); |
} |
} |
Line 1879 esiop_morecbd(struct esiop_softc *sc) |
|
Line 1869 esiop_morecbd(struct esiop_softc *sc) |
|
/* allocate a new list head */ |
/* allocate a new list head */ |
newcbd = malloc(sizeof(struct esiop_cbd), M_DEVBUF, M_NOWAIT|M_ZERO); |
newcbd = malloc(sizeof(struct esiop_cbd), M_DEVBUF, M_NOWAIT|M_ZERO); |
if (newcbd == NULL) { |
if (newcbd == NULL) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "can't allocate memory for command descriptors " |
"can't allocate memory for command descriptors " |
|
"head\n"); |
"head\n"); |
return; |
return; |
} |
} |
Line 1889 esiop_morecbd(struct esiop_softc *sc) |
|
Line 1878 esiop_morecbd(struct esiop_softc *sc) |
|
newcbd->cmds = malloc(sizeof(struct esiop_cmd) * SIOP_NCMDPB, |
newcbd->cmds = malloc(sizeof(struct esiop_cmd) * SIOP_NCMDPB, |
M_DEVBUF, M_NOWAIT|M_ZERO); |
M_DEVBUF, M_NOWAIT|M_ZERO); |
if (newcbd->cmds == NULL) { |
if (newcbd->cmds == NULL) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "can't allocate memory for command descriptors\n"); |
"can't allocate memory for command descriptors\n"); |
|
goto bad3; |
goto bad3; |
} |
} |
error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, |
error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, |
&seg, 1, &rseg, BUS_DMA_NOWAIT); |
&seg, 1, &rseg, BUS_DMA_NOWAIT); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to allocate cbd DMA memory, error = %d\n", |
"unable to allocate cbd DMA memory, error = %d\n", |
|
error); |
error); |
goto bad2; |
goto bad2; |
} |
} |
error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE, |
error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE, |
(void **)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); |
(void **)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to map cbd DMA memory, error = %d\n", |
"unable to map cbd DMA memory, error = %d\n", |
|
error); |
error); |
goto bad2; |
goto bad2; |
} |
} |
error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0, |
error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0, |
BUS_DMA_NOWAIT, &newcbd->xferdma); |
BUS_DMA_NOWAIT, &newcbd->xferdma); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to create cbd DMA map, error = %d\n", error); |
"unable to create cbd DMA map, error = %d\n", error); |
|
goto bad1; |
goto bad1; |
} |
} |
error = bus_dmamap_load(sc->sc_c.sc_dmat, newcbd->xferdma, |
error = bus_dmamap_load(sc->sc_c.sc_dmat, newcbd->xferdma, |
newcbd->xfers, PAGE_SIZE, NULL, BUS_DMA_NOWAIT); |
newcbd->xfers, PAGE_SIZE, NULL, BUS_DMA_NOWAIT); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to load cbd DMA map, error = %d\n", error); |
"unable to load cbd DMA map, error = %d\n", error); |
|
goto bad0; |
goto bad0; |
} |
} |
#ifdef SIOP_DEBUG |
#ifdef DEBUG |
aprint_debug_dev(sc->sc_c.sc_dev, "alloc newcdb at PHY addr 0x%lx\n", |
printf("%s: alloc newcdb at PHY addr 0x%lx\n", device_xname(&sc->sc_c.sc_dev), |
(unsigned long)newcbd->xferdma->dm_segs[0].ds_addr); |
(unsigned long)newcbd->xferdma->dm_segs[0].ds_addr); |
#endif |
#endif |
for (i = 0; i < SIOP_NCMDPB; i++) { |
for (i = 0; i < SIOP_NCMDPB; i++) { |
Line 1932 esiop_morecbd(struct esiop_softc *sc) |
|
Line 1916 esiop_morecbd(struct esiop_softc *sc) |
|
MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, |
MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, |
&newcbd->cmds[i].cmd_c.dmamap_data); |
&newcbd->cmds[i].cmd_c.dmamap_data); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to create data DMA map for cbd: " |
"unable to create data DMA map for cbd: " |
|
"error %d\n", error); |
"error %d\n", error); |
goto bad0; |
goto bad0; |
} |
} |
Line 1943 esiop_morecbd(struct esiop_softc *sc) |
|
Line 1926 esiop_morecbd(struct esiop_softc *sc) |
|
BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, |
BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, |
&newcbd->cmds[i].cmd_c.dmamap_cmd); |
&newcbd->cmds[i].cmd_c.dmamap_cmd); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to create cmd DMA map for cbd %d\n", error); |
"unable to create cmd DMA map for cbd %d\n", error); |
|
goto bad0; |
goto bad0; |
} |
} |
newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c; |
newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c; |
Line 1961 esiop_morecbd(struct esiop_softc *sc) |
|
Line 1943 esiop_morecbd(struct esiop_softc *sc) |
|
xfer->siop_tables.t_msgout.addr = htole32(dsa); |
xfer->siop_tables.t_msgout.addr = htole32(dsa); |
xfer->siop_tables.t_msgin.count= htole32(1); |
xfer->siop_tables.t_msgin.count= htole32(1); |
xfer->siop_tables.t_msgin.addr = htole32(dsa + |
xfer->siop_tables.t_msgin.addr = htole32(dsa + |
offsetof(struct siop_common_xfer, msg_in)); |
offsetof(struct siop_common_xfer, msg_in)); |
xfer->siop_tables.t_extmsgin.count= htole32(2); |
xfer->siop_tables.t_extmsgin.count= htole32(2); |
xfer->siop_tables.t_extmsgin.addr = htole32(dsa + |
xfer->siop_tables.t_extmsgin.addr = htole32(dsa + |
offsetof(struct siop_common_xfer, msg_in) + 1); |
offsetof(struct siop_common_xfer, msg_in) + 1); |
xfer->siop_tables.t_extmsgdata.addr = htole32(dsa + |
xfer->siop_tables.t_extmsgdata.addr = htole32(dsa + |
offsetof(struct siop_common_xfer, msg_in) + 3); |
offsetof(struct siop_common_xfer, msg_in) + 3); |
xfer->siop_tables.t_status.count= htole32(1); |
xfer->siop_tables.t_status.count= htole32(1); |
xfer->siop_tables.t_status.addr = htole32(dsa + |
xfer->siop_tables.t_status.addr = htole32(dsa + |
offsetof(struct siop_common_xfer, status)); |
offsetof(struct siop_common_xfer, status)); |
|
|
s = splbio(); |
s = splbio(); |
TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next); |
TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next); |
|
|
free(newcbd->cmds, M_DEVBUF); |
free(newcbd->cmds, M_DEVBUF); |
bad3: |
bad3: |
free(newcbd, M_DEVBUF); |
free(newcbd, M_DEVBUF); |
|
return; |
} |
} |
|
|
void |
void |
Line 2005 esiop_moretagtbl(struct esiop_softc *sc) |
|
Line 1988 esiop_moretagtbl(struct esiop_softc *sc) |
|
int rseg; |
int rseg; |
struct esiop_dsatblblk *newtblblk; |
struct esiop_dsatblblk *newtblblk; |
struct esiop_dsatbl *newtbls; |
struct esiop_dsatbl *newtbls; |
uint32_t *tbls; |
u_int32_t *tbls; |
|
|
/* allocate a new list head */ |
/* allocate a new list head */ |
newtblblk = malloc(sizeof(struct esiop_dsatblblk), |
newtblblk = malloc(sizeof(struct esiop_dsatblblk), |
M_DEVBUF, M_NOWAIT|M_ZERO); |
M_DEVBUF, M_NOWAIT|M_ZERO); |
if (newtblblk == NULL) { |
if (newtblblk == NULL) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "can't allocate memory for tag DSA table block\n"); |
"can't allocate memory for tag DSA table block\n"); |
|
return; |
return; |
} |
} |
|
|
Line 2020 esiop_moretagtbl(struct esiop_softc *sc) |
|
Line 2002 esiop_moretagtbl(struct esiop_softc *sc) |
|
newtbls = malloc(sizeof(struct esiop_dsatbl) * ESIOP_NTPB, |
newtbls = malloc(sizeof(struct esiop_dsatbl) * ESIOP_NTPB, |
M_DEVBUF, M_NOWAIT|M_ZERO); |
M_DEVBUF, M_NOWAIT|M_ZERO); |
if (newtbls == NULL) { |
if (newtbls == NULL) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "can't allocate memory for command descriptors\n"); |
"can't allocate memory for command descriptors\n"); |
|
goto bad3; |
goto bad3; |
} |
} |
error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, |
error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, |
&seg, 1, &rseg, BUS_DMA_NOWAIT); |
&seg, 1, &rseg, BUS_DMA_NOWAIT); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to allocate tbl DMA memory, error = %d\n", error); |
"unable to allocate tbl DMA memory, error = %d\n", error); |
|
goto bad2; |
goto bad2; |
} |
} |
error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE, |
error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE, |
(void *)&tbls, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); |
(void *)&tbls, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to map tbls DMA memory, error = %d\n", error); |
"unable to map tbls DMA memory, error = %d\n", error); |
|
goto bad2; |
goto bad2; |
} |
} |
error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0, |
error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0, |
BUS_DMA_NOWAIT, &newtblblk->blkmap); |
BUS_DMA_NOWAIT, &newtblblk->blkmap); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to create tbl DMA map, error = %d\n", error); |
"unable to create tbl DMA map, error = %d\n", error); |
|
goto bad1; |
goto bad1; |
} |
} |
error = bus_dmamap_load(sc->sc_c.sc_dmat, newtblblk->blkmap, |
error = bus_dmamap_load(sc->sc_c.sc_dmat, newtblblk->blkmap, |
tbls, PAGE_SIZE, NULL, BUS_DMA_NOWAIT); |
tbls, PAGE_SIZE, NULL, BUS_DMA_NOWAIT); |
if (error) { |
if (error) { |
aprint_error_dev(sc->sc_c.sc_dev, |
aprint_error_dev(&sc->sc_c.sc_dev, "unable to load tbl DMA map, error = %d\n", error); |
"unable to load tbl DMA map, error = %d\n", error); |
|
goto bad0; |
goto bad0; |
} |
} |
#ifdef SIOP_DEBUG |
#ifdef DEBUG |
printf("%s: alloc new tag DSA table at PHY addr 0x%lx\n", |
printf("%s: alloc new tag DSA table at PHY addr 0x%lx\n", |
device_xname(sc->sc_c.sc_dev), |
device_xname(&sc->sc_c.sc_dev), |
(unsigned long)newtblblk->blkmap->dm_segs[0].ds_addr); |
(unsigned long)newtblblk->blkmap->dm_segs[0].ds_addr); |
#endif |
#endif |
for (i = 0; i < ESIOP_NTPB; i++) { |
for (i = 0; i < ESIOP_NTPB; i++) { |
newtbls[i].tblblk = newtblblk; |
newtbls[i].tblblk = newtblblk; |
newtbls[i].tbl = &tbls[i * ESIOP_NTAG]; |
newtbls[i].tbl = &tbls[i * ESIOP_NTAG]; |
newtbls[i].tbl_offset = i * ESIOP_NTAG * sizeof(uint32_t); |
newtbls[i].tbl_offset = i * ESIOP_NTAG * sizeof(u_int32_t); |
newtbls[i].tbl_dsa = newtblblk->blkmap->dm_segs[0].ds_addr + |
newtbls[i].tbl_dsa = newtblblk->blkmap->dm_segs[0].ds_addr + |
newtbls[i].tbl_offset; |
newtbls[i].tbl_offset; |
for (j = 0; j < ESIOP_NTAG; j++) |
for (j = 0; j < ESIOP_NTAG; j++) |
|
|
free(newtbls, M_DEVBUF); |
free(newtbls, M_DEVBUF); |
bad3: |
bad3: |
free(newtblblk, M_DEVBUF); |
free(newtblblk, M_DEVBUF); |
|
return; |
} |
} |
|
|
void |
void |
esiop_update_scntl3(struct esiop_softc *sc, |
esiop_update_scntl3(sc, _siop_target) |
struct siop_common_target *_siop_target) |
struct esiop_softc *sc; |
|
struct siop_common_target *_siop_target; |
{ |
{ |
struct esiop_target *esiop_target = (struct esiop_target *)_siop_target; |
struct esiop_target *esiop_target = (struct esiop_target *)_siop_target; |
|
|
esiop_script_write(sc, esiop_target->lun_table_offset, |
esiop_script_write(sc, esiop_target->lun_table_offset, |
esiop_target->target_c.id); |
esiop_target->target_c.id); |
esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
Line 2119 esiop_add_dev(struct esiop_softc *sc, in |
|
Line 2097 esiop_add_dev(struct esiop_softc *sc, in |
|
TAILQ_REMOVE(&sc->free_tagtbl, esiop_lun->lun_tagtbl, next); |
TAILQ_REMOVE(&sc->free_tagtbl, esiop_lun->lun_tagtbl, next); |
/* Update LUN DSA table */ |
/* Update LUN DSA table */ |
esiop_script_write(sc, esiop_target->lun_table_offset + |
esiop_script_write(sc, esiop_target->lun_table_offset + |
lun * 2 + A_target_luntbl_tag / sizeof(uint32_t), |
lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t), |
esiop_lun->lun_tagtbl->tbl_dsa); |
esiop_lun->lun_tagtbl->tbl_dsa); |
esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
} |
} |
|
|
esiop_del_dev(struct esiop_softc *sc, int target, int lun) |
esiop_del_dev(struct esiop_softc *sc, int target, int lun) |
{ |
{ |
struct esiop_target *esiop_target; |
struct esiop_target *esiop_target; |
|
|
#ifdef SIOP_DEBUG |
#ifdef SIOP_DEBUG |
printf("%s:%d:%d: free lun sw entry\n", |
printf("%s:%d:%d: free lun sw entry\n", |
device_xname(sc->sc_c.sc_dev), target, lun); |
device_xname(&sc->sc_c.sc_dev), target, lun); |
#endif |
#endif |
if (sc->sc_c.targets[target] == NULL) |
if (sc->sc_c.targets[target] == NULL) |
return; |
return; |
Line 2141 esiop_del_dev(struct esiop_softc *sc, in |
|
Line 2118 esiop_del_dev(struct esiop_softc *sc, in |
|
} |
} |
|
|
void |
void |
esiop_target_register(struct esiop_softc *sc, uint32_t target) |
esiop_target_register(struct esiop_softc *sc, u_int32_t target) |
{ |
{ |
struct esiop_target *esiop_target = |
struct esiop_target *esiop_target = |
(struct esiop_target *)sc->sc_c.targets[target]; |
(struct esiop_target *)sc->sc_c.targets[target]; |
Line 2153 esiop_target_register(struct esiop_softc |
|
Line 2130 esiop_target_register(struct esiop_softc |
|
sc->sc_free_offset += sc->sc_c.sc_chan.chan_nluns * 2 + 2; |
sc->sc_free_offset += sc->sc_c.sc_chan.chan_nluns * 2 + 2; |
#ifdef SIOP_DEBUG |
#ifdef SIOP_DEBUG |
printf("%s: lun table for target %d offset %d free offset %d\n", |
printf("%s: lun table for target %d offset %d free offset %d\n", |
device_xname(sc->sc_c.sc_dev), target, |
device_xname(&sc->sc_c.sc_dev), target, esiop_target->lun_table_offset, |
esiop_target->lun_table_offset, |
|
sc->sc_free_offset); |
sc->sc_free_offset); |
#endif |
#endif |
/* first 32 bytes are ID (for select) */ |
/* first 32 bytes are ID (for select) */ |
Line 2163 esiop_target_register(struct esiop_softc |
|
Line 2139 esiop_target_register(struct esiop_softc |
|
/* Record this table in the target DSA table */ |
/* Record this table in the target DSA table */ |
esiop_script_write(sc, |
esiop_script_write(sc, |
sc->sc_target_table_offset + target, |
sc->sc_target_table_offset + target, |
(esiop_target->lun_table_offset * sizeof(uint32_t)) + |
(esiop_target->lun_table_offset * sizeof(u_int32_t)) + |
sc->sc_c.sc_scriptaddr); |
sc->sc_c.sc_scriptaddr); |
/* if we have a tag table, register it */ |
/* if we have a tag table, register it */ |
for (lun = 0; lun < sc->sc_c.sc_chan.chan_nluns; lun++) { |
for (lun = 0; lun < sc->sc_c.sc_chan.chan_nluns; lun++) { |
Line 2172 esiop_target_register(struct esiop_softc |
|
Line 2148 esiop_target_register(struct esiop_softc |
|
continue; |
continue; |
if (esiop_lun->lun_tagtbl) |
if (esiop_lun->lun_tagtbl) |
esiop_script_write(sc, esiop_target->lun_table_offset + |
esiop_script_write(sc, esiop_target->lun_table_offset + |
lun * 2 + A_target_luntbl_tag / sizeof(uint32_t), |
lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t), |
esiop_lun->lun_tagtbl->tbl_dsa); |
esiop_lun->lun_tagtbl->tbl_dsa); |
} |
} |
esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
esiop_script_sync(sc, |
|
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
} |
} |
|
|
#ifdef SIOP_STATS |
#ifdef SIOP_STATS |
void |
void |
esiop_printstats(void) |
esiop_printstats() |
{ |
{ |
|
|
printf("esiop_stat_intr %d\n", esiop_stat_intr); |
printf("esiop_stat_intr %d\n", esiop_stat_intr); |
printf("esiop_stat_intr_shortxfer %d\n", esiop_stat_intr_shortxfer); |
printf("esiop_stat_intr_shortxfer %d\n", esiop_stat_intr_shortxfer); |
printf("esiop_stat_intr_xferdisc %d\n", esiop_stat_intr_xferdisc); |
printf("esiop_stat_intr_xferdisc %d\n", esiop_stat_intr_xferdisc); |