| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Generic Macintosh NCR5380 driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 24 | 25 | |
|---|
| 25 | 26 | #include <asm/hwtest.h> |
|---|
| 26 | 27 | #include <asm/io.h> |
|---|
| 28 | +#include <asm/macintosh.h> |
|---|
| 27 | 29 | #include <asm/macints.h> |
|---|
| 28 | 30 | #include <asm/setup.h> |
|---|
| 29 | 31 | |
|---|
| .. | .. |
|---|
| 262 | 264 | return addr - start; |
|---|
| 263 | 265 | } |
|---|
| 264 | 266 | |
|---|
| 267 | +/* The "SCSI DMA" chip on the IIfx implements this register. */ |
|---|
| 268 | +#define CTRL_REG 0x8 |
|---|
| 269 | +#define CTRL_INTERRUPTS_ENABLE BIT(1) |
|---|
| 270 | +#define CTRL_HANDSHAKE_MODE BIT(3) |
|---|
| 271 | + |
|---|
| 272 | +static inline void write_ctrl_reg(struct NCR5380_hostdata *hostdata, u32 value) |
|---|
| 273 | +{ |
|---|
| 274 | + out_be32(hostdata->io + (CTRL_REG << 4), value); |
|---|
| 275 | +} |
|---|
| 276 | + |
|---|
| 265 | 277 | static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, |
|---|
| 266 | 278 | unsigned char *dst, int len) |
|---|
| 267 | 279 | { |
|---|
| 268 | 280 | u8 __iomem *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); |
|---|
| 269 | 281 | unsigned char *d = dst; |
|---|
| 282 | + int result = 0; |
|---|
| 270 | 283 | |
|---|
| 271 | 284 | hostdata->pdma_residual = len; |
|---|
| 272 | 285 | |
|---|
| .. | .. |
|---|
| 274 | 287 | BASR_DRQ | BASR_PHASE_MATCH, |
|---|
| 275 | 288 | BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { |
|---|
| 276 | 289 | int bytes; |
|---|
| 290 | + |
|---|
| 291 | + if (macintosh_config->ident == MAC_MODEL_IIFX) |
|---|
| 292 | + write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | |
|---|
| 293 | + CTRL_INTERRUPTS_ENABLE); |
|---|
| 277 | 294 | |
|---|
| 278 | 295 | bytes = mac_pdma_recv(s, d, min(hostdata->pdma_residual, 512)); |
|---|
| 279 | 296 | |
|---|
| .. | .. |
|---|
| 283 | 300 | } |
|---|
| 284 | 301 | |
|---|
| 285 | 302 | if (hostdata->pdma_residual == 0) |
|---|
| 286 | | - return 0; |
|---|
| 303 | + goto out; |
|---|
| 287 | 304 | |
|---|
| 288 | 305 | if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, |
|---|
| 289 | 306 | BUS_AND_STATUS_REG, BASR_ACK, |
|---|
| .. | .. |
|---|
| 291 | 308 | scmd_printk(KERN_DEBUG, hostdata->connected, |
|---|
| 292 | 309 | "%s: !REQ and !ACK\n", __func__); |
|---|
| 293 | 310 | if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) |
|---|
| 294 | | - return 0; |
|---|
| 311 | + goto out; |
|---|
| 295 | 312 | |
|---|
| 296 | 313 | if (bytes == 0) |
|---|
| 297 | 314 | udelay(MAC_PDMA_DELAY); |
|---|
| .. | .. |
|---|
| 302 | 319 | dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, |
|---|
| 303 | 320 | "%s: bus error (%d/%d)\n", __func__, d - dst, len); |
|---|
| 304 | 321 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
|---|
| 305 | | - return -1; |
|---|
| 322 | + result = -1; |
|---|
| 323 | + goto out; |
|---|
| 306 | 324 | } |
|---|
| 307 | 325 | |
|---|
| 308 | 326 | scmd_printk(KERN_ERR, hostdata->connected, |
|---|
| 309 | 327 | "%s: phase mismatch or !DRQ\n", __func__); |
|---|
| 310 | 328 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
|---|
| 311 | | - return -1; |
|---|
| 329 | + result = -1; |
|---|
| 330 | +out: |
|---|
| 331 | + if (macintosh_config->ident == MAC_MODEL_IIFX) |
|---|
| 332 | + write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); |
|---|
| 333 | + return result; |
|---|
| 312 | 334 | } |
|---|
| 313 | 335 | |
|---|
| 314 | 336 | static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, |
|---|
| .. | .. |
|---|
| 316 | 338 | { |
|---|
| 317 | 339 | unsigned char *s = src; |
|---|
| 318 | 340 | u8 __iomem *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); |
|---|
| 341 | + int result = 0; |
|---|
| 319 | 342 | |
|---|
| 320 | 343 | hostdata->pdma_residual = len; |
|---|
| 321 | 344 | |
|---|
| .. | .. |
|---|
| 323 | 346 | BASR_DRQ | BASR_PHASE_MATCH, |
|---|
| 324 | 347 | BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { |
|---|
| 325 | 348 | int bytes; |
|---|
| 349 | + |
|---|
| 350 | + if (macintosh_config->ident == MAC_MODEL_IIFX) |
|---|
| 351 | + write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE | |
|---|
| 352 | + CTRL_INTERRUPTS_ENABLE); |
|---|
| 326 | 353 | |
|---|
| 327 | 354 | bytes = mac_pdma_send(s, d, min(hostdata->pdma_residual, 512)); |
|---|
| 328 | 355 | |
|---|
| .. | .. |
|---|
| 334 | 361 | if (hostdata->pdma_residual == 0) { |
|---|
| 335 | 362 | if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG, |
|---|
| 336 | 363 | TCR_LAST_BYTE_SENT, |
|---|
| 337 | | - TCR_LAST_BYTE_SENT, HZ / 64) < 0) |
|---|
| 364 | + TCR_LAST_BYTE_SENT, |
|---|
| 365 | + HZ / 64) < 0) { |
|---|
| 338 | 366 | scmd_printk(KERN_ERR, hostdata->connected, |
|---|
| 339 | 367 | "%s: Last Byte Sent timeout\n", __func__); |
|---|
| 340 | | - return 0; |
|---|
| 368 | + result = -1; |
|---|
| 369 | + } |
|---|
| 370 | + goto out; |
|---|
| 341 | 371 | } |
|---|
| 342 | 372 | |
|---|
| 343 | 373 | if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, |
|---|
| .. | .. |
|---|
| 346 | 376 | scmd_printk(KERN_DEBUG, hostdata->connected, |
|---|
| 347 | 377 | "%s: !REQ and !ACK\n", __func__); |
|---|
| 348 | 378 | if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) |
|---|
| 349 | | - return 0; |
|---|
| 379 | + goto out; |
|---|
| 350 | 380 | |
|---|
| 351 | 381 | if (bytes == 0) |
|---|
| 352 | 382 | udelay(MAC_PDMA_DELAY); |
|---|
| .. | .. |
|---|
| 357 | 387 | dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host, |
|---|
| 358 | 388 | "%s: bus error (%d/%d)\n", __func__, s - src, len); |
|---|
| 359 | 389 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
|---|
| 360 | | - return -1; |
|---|
| 390 | + result = -1; |
|---|
| 391 | + goto out; |
|---|
| 361 | 392 | } |
|---|
| 362 | 393 | |
|---|
| 363 | 394 | scmd_printk(KERN_ERR, hostdata->connected, |
|---|
| 364 | 395 | "%s: phase mismatch or !DRQ\n", __func__); |
|---|
| 365 | 396 | NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host); |
|---|
| 366 | | - return -1; |
|---|
| 397 | + result = -1; |
|---|
| 398 | +out: |
|---|
| 399 | + if (macintosh_config->ident == MAC_MODEL_IIFX) |
|---|
| 400 | + write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE); |
|---|
| 401 | + return result; |
|---|
| 367 | 402 | } |
|---|
| 368 | 403 | |
|---|
| 369 | 404 | static int macscsi_dma_xfer_len(struct NCR5380_hostdata *hostdata, |
|---|
| .. | .. |
|---|
| 398 | 433 | .this_id = 7, |
|---|
| 399 | 434 | .sg_tablesize = 1, |
|---|
| 400 | 435 | .cmd_per_lun = 2, |
|---|
| 401 | | - .use_clustering = DISABLE_CLUSTERING, |
|---|
| 436 | + .dma_boundary = PAGE_SIZE - 1, |
|---|
| 402 | 437 | .cmd_size = NCR5380_CMD_SIZE, |
|---|
| 403 | 438 | .max_sectors = 128, |
|---|
| 404 | 439 | }; |
|---|