vpo.c (35210) | vpo.c (38061) |
---|---|
1/*- | 1/*- |
2 * Copyright (c) 1997 Nicolas Souchu | 2 * Copyright (c) 1997, 1998 Nicolas Souchu |
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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 28 unchanged lines hidden (view full) --- 39#include <scsi/scsi_disk.h> 40#include <scsi/scsiconf.h> 41 42#ifdef KERNEL 43#include <sys/kernel.h> 44#endif /*KERNEL */ 45 46#include <dev/ppbus/ppbconf.h> | 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 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 28 unchanged lines hidden (view full) --- 39#include <scsi/scsi_disk.h> 40#include <scsi/scsiconf.h> 41 42#ifdef KERNEL 43#include <sys/kernel.h> 44#endif /*KERNEL */ 45 46#include <dev/ppbus/ppbconf.h> |
47#include | 47#include <dev/ppbus/vpoio.h> |
48 | 48 |
49/* -------------------------------------------------------------------- 50 * HERE ARE THINGS YOU MAY HAVE/WANT TO CHANGE 51 */ | 49#define VP0_BUFFER_SIZE 0x12000 |
52 | 50 |
53/* 54 * XXX 55 * We may add a timeout queue to avoid active polling on nACK. 56 */ 57#define VP0_SELTMO 5000 /* select timeout */ 58#define VP0_FAST_SPINTMO 500000 /* wait status timeout */ 59#define VP0_LOW_SPINTMO 5000000 /* wait status timeout */ | 51struct vpo_sense { 52 struct scsi_sense cmd; 53 unsigned int stat; 54 unsigned int count; 55}; |
60 | 56 |
61/* 62 * DO NOT MODIFY ANYTHING UNDER THIS LINE 63 * -------------------------------------------------------------------- 64 */ | 57struct vpo_data { 58 unsigned short vpo_unit; |
65 | 59 |
66static __inline int vpoio_do_scsi(struct vpo_data *, int, int, char *, int, 67 char *, int, int *, int *); | 60 int vpo_stat; 61 int vpo_count; 62 int vpo_error; |
68 | 63 |
64 struct ppb_status vpo_status; 65 struct vpo_sense vpo_sense; 66 67 unsigned char vpo_buffer[VP0_BUFFER_SIZE]; 68 69 struct vpoio_data vpo_io; /* interface to low level functions */ 70 71 struct scsi_link sc_link; 72}; 73 74 |
|
69static int32_t vpo_scsi_cmd(struct scsi_xfer *); 70static void vpominphys(struct buf *); 71static u_int32_t vpo_adapter_info(int); 72 | 75static int32_t vpo_scsi_cmd(struct scsi_xfer *); 76static void vpominphys(struct buf *); 77static u_int32_t vpo_adapter_info(int); 78 |
73static int vpo_detect(struct vpo_data *vpo); 74 | |
75static int nvpo = 0; 76#define MAXVP0 8 /* XXX not much better! */ 77static struct vpo_data *vpodata[MAXVP0]; 78 | 79static int nvpo = 0; 80#define MAXVP0 8 /* XXX not much better! */ 81static struct vpo_data *vpodata[MAXVP0]; 82 |
79#ifdef KERNEL | |
80static struct scsi_adapter vpo_switch = 81{ 82 vpo_scsi_cmd, 83 vpominphys, 84 0, 85 0, 86 vpo_adapter_info, 87 "vpo", --- 24 unchanged lines hidden (view full) --- 112static int vpoattach(struct ppb_device *dev); 113 114static struct ppb_driver vpodriver = { 115 vpoprobe, vpoattach, "vpo" 116}; 117DATA_SET(ppbdriver_set, vpodriver); 118 119 | 83static struct scsi_adapter vpo_switch = 84{ 85 vpo_scsi_cmd, 86 vpominphys, 87 0, 88 0, 89 vpo_adapter_info, 90 "vpo", --- 24 unchanged lines hidden (view full) --- 115static int vpoattach(struct ppb_device *dev); 116 117static struct ppb_driver vpodriver = { 118 vpoprobe, vpoattach, "vpo" 119}; 120DATA_SET(ppbdriver_set, vpodriver); 121 122 |
120#endif /* KERNEL */ 121 | |
122static u_int32_t 123vpo_adapter_info(int unit) 124{ 125 126 return 1; 127} 128 129/* 130 * vpoprobe() 131 * 132 * Called by ppb_attachdevs(). 133 */ 134static struct ppb_device * 135vpoprobe(struct ppb_data *ppb) 136{ | 123static u_int32_t 124vpo_adapter_info(int unit) 125{ 126 127 return 1; 128} 129 130/* 131 * vpoprobe() 132 * 133 * Called by ppb_attachdevs(). 134 */ 135static struct ppb_device * 136vpoprobe(struct ppb_data *ppb) 137{ |
137 | |
138 struct vpo_data *vpo; | 138 struct vpo_data *vpo; |
139 struct ppb_device *dev; |
|
139 140 if (nvpo >= MAXVP0) { 141 printf("vpo: Too many devices (max %d)\n", MAXVP0); 142 return(NULL); 143 } 144 145 vpo = (struct vpo_data *)malloc(sizeof(struct vpo_data), 146 M_DEVBUF, M_NOWAIT); 147 if (!vpo) { 148 printf("vpo: cannot malloc!\n"); 149 return(NULL); 150 } 151 bzero(vpo, sizeof(struct vpo_data)); 152 153 vpodata[nvpo] = vpo; 154 155 /* vpo dependent initialisation */ 156 vpo->vpo_unit = nvpo; 157 | 140 141 if (nvpo >= MAXVP0) { 142 printf("vpo: Too many devices (max %d)\n", MAXVP0); 143 return(NULL); 144 } 145 146 vpo = (struct vpo_data *)malloc(sizeof(struct vpo_data), 147 M_DEVBUF, M_NOWAIT); 148 if (!vpo) { 149 printf("vpo: cannot malloc!\n"); 150 return(NULL); 151 } 152 bzero(vpo, sizeof(struct vpo_data)); 153 154 vpodata[nvpo] = vpo; 155 156 /* vpo dependent initialisation */ 157 vpo->vpo_unit = nvpo; 158 |
158 /* ppbus dependent initialisation */ 159 vpo->vpo_dev.id_unit = vpo->vpo_unit; 160 vpo->vpo_dev.ppb = ppb; | 159 /* ok, go to next device on next probe */ 160 nvpo ++; |
161 | 161 |
162 /* now, try to initialise the drive */ 163 if (vpo_detect(vpo)) { | 162 /* low level probe */ 163 vpoio_set_unit(&vpo->vpo_io, vpo->vpo_unit); 164 165 if (!(dev = vpoio_probe(ppb, &vpo->vpo_io))) { |
164 free(vpo, M_DEVBUF); 165 return (NULL); 166 } 167 | 166 free(vpo, M_DEVBUF); 167 return (NULL); 168 } 169 |
168 /* ok, go to next device on next probe */ 169 nvpo ++; 170 171 return (&vpo->vpo_dev); | 170 return (dev); |
172} 173 174/* 175 * vpoattach() 176 * 177 * Called by ppb_attachdevs(). 178 */ 179static int 180vpoattach(struct ppb_device *dev) 181{ 182 183 struct scsibus_data *scbus; 184 struct vpo_data *vpo = vpodata[dev->id_unit]; 185 | 171} 172 173/* 174 * vpoattach() 175 * 176 * Called by ppb_attachdevs(). 177 */ 178static int 179vpoattach(struct ppb_device *dev) 180{ 181 182 struct scsibus_data *scbus; 183 struct vpo_data *vpo = vpodata[dev->id_unit]; 184 |
185 /* low level attachment */ 186 if (!vpoio_attach(&vpo->vpo_io)) 187 return (0); 188 |
|
186 vpo->sc_link.adapter_unit = vpo->vpo_unit; 187 vpo->sc_link.adapter_targ = VP0_INITIATOR; 188 vpo->sc_link.adapter = &vpo_switch; 189 vpo->sc_link.device = &vpo_dev; 190 vpo->sc_link.opennings = VP0_OPENNINGS; 191 192 /* | 189 vpo->sc_link.adapter_unit = vpo->vpo_unit; 190 vpo->sc_link.adapter_targ = VP0_INITIATOR; 191 vpo->sc_link.adapter = &vpo_switch; 192 vpo->sc_link.device = &vpo_dev; 193 vpo->sc_link.opennings = VP0_OPENNINGS; 194 195 /* |
193 * Report ourselves 194 */ 195 printf("vpo%d: <Adaptec aic7110 scsi> on ppbus %d\n", 196 dev->id_unit, dev->ppb->ppb_link->adapter_unit); 197 198 /* | |
199 * Prepare the scsibus_data area for the upperlevel 200 * scsi code. 201 */ 202 scbus = scsi_alloc_bus(); 203 if(!scbus) 204 return (0); 205 scbus->adapter_link = &vpo->sc_link; 206 | 196 * Prepare the scsibus_data area for the upperlevel 197 * scsi code. 198 */ 199 scbus = scsi_alloc_bus(); 200 if(!scbus) 201 return (0); 202 scbus->adapter_link = &vpo->sc_link; 203 |
204 /* all went ok */ 205 printf("vpo%d: <Iomega PPA-3/VPI0 SCSI controller>\n", dev->id_unit); 206 |
|
207 scsi_attachdevs(scbus); 208 209 return (1); 210} 211 212static void 213vpominphys(struct buf *bp) 214{ 215 216 if (bp->b_bcount > VP0_BUFFER_SIZE) 217 bp->b_bcount = VP0_BUFFER_SIZE; 218 219 return; 220} 221 | 207 scsi_attachdevs(scbus); 208 209 return (1); 210} 211 212static void 213vpominphys(struct buf *bp) 214{ 215 216 if (bp->b_bcount > VP0_BUFFER_SIZE) 217 bp->b_bcount = VP0_BUFFER_SIZE; 218 219 return; 220} 221 |
222#ifdef VP0_WARNING 223static __inline void 224vpo_warning(struct vpo_data *vpo, struct scsi_xfer *xs, int timeout) 225{ 226 227 switch (timeout) { 228 case 0: 229 case VP0_ESELECT_TIMEOUT: 230 /* log(LOG_WARNING, 231 "vpo%d: select timeout\n", vpo->vpo_unit); */ 232 break; 233 case VP0_EDISCONNECT: 234 log(LOG_WARNING, 235 "vpo%d: can't get printer state\n", vpo->vpo_unit); 236 break; 237 case VP0_ECONNECT: 238 log(LOG_WARNING, 239 "vpo%d: can't get disk state\n", vpo->vpo_unit); 240 break; 241 case VP0_ECMD_TIMEOUT: 242 log(LOG_WARNING, 243 "vpo%d: command timeout\n", vpo->vpo_unit); 244 break; 245 case VP0_EPPDATA_TIMEOUT: 246 log(LOG_WARNING, 247 "vpo%d: EPP data timeout\n", vpo->vpo_unit); 248 break; 249 case VP0_ESTATUS_TIMEOUT: 250 log(LOG_WARNING, 251 "vpo%d: status timeout\n", vpo->vpo_unit); 252 break; 253 case VP0_EDATA_OVERFLOW: 254 log(LOG_WARNING, 255 "vpo%d: data overflow\n", vpo->vpo_unit); 256 break; 257 case VP0_EINTR: 258 log(LOG_WARNING, 259 "vpo%d: ppb request interrupted\n", vpo->vpo_unit); 260 break; 261 default: 262 log(LOG_WARNING, 263 "vpo%d: timeout = %d\n", vpo->vpo_unit, timeout); 264 break; 265 } 266} 267#endif /* VP0_WARNING */ 268 | |
269/* | 222/* |
270 * vpointr() | 223 * vpo_intr() |
271 */ | 224 */ |
272static __inline void 273vpointr(struct vpo_data *vpo, struct scsi_xfer *xs) | 225static void 226vpo_intr(struct vpo_data *vpo, struct scsi_xfer *xs) |
274{ 275 276 int errno; /* error in errno.h */ 277 278 if (xs->datalen && !(xs->flags & SCSI_DATA_IN)) 279 bcopy(xs->data, vpo->vpo_buffer, xs->datalen); 280 | 227{ 228 229 int errno; /* error in errno.h */ 230 231 if (xs->datalen && !(xs->flags & SCSI_DATA_IN)) 232 bcopy(xs->data, vpo->vpo_buffer, xs->datalen); 233 |
281 errno = vpoio_do_scsi(vpo, VP0_INITIATOR, | 234 errno = vpoio_do_scsi(&vpo->vpo_io, VP0_INITIATOR, |
282 xs->sc_link->target, (char *)xs->cmd, xs->cmdlen, | 235 xs->sc_link->target, (char *)xs->cmd, xs->cmdlen, |
283 vpo->vpo_buffer, xs->datalen, &vpo->vpo_stat, &vpo->vpo_count); | 236 vpo->vpo_buffer, xs->datalen, &vpo->vpo_stat, &vpo->vpo_count, 237 &vpo->vpo_error); |
284 285#ifdef VP0_DEBUG 286 printf("vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n", 287 errno, vpo->vpo_stat, vpo->vpo_count, vpo->vpo_error); 288#endif 289 290 if (errno) { 291#ifdef VP0_WARNING 292 log(LOG_WARNING, "vpo%d: errno = %d\n", vpo->vpo_unit, errno); 293#endif 294 /* connection to ppbus interrupted */ 295 xs->error = XS_DRIVER_STUFFUP; 296 goto error; 297 } 298 299 /* if a timeout occured, no sense */ 300 if (vpo->vpo_error) { | 238 239#ifdef VP0_DEBUG 240 printf("vpo_do_scsi = %d, status = 0x%x, count = %d, vpo_error = %d\n", 241 errno, vpo->vpo_stat, vpo->vpo_count, vpo->vpo_error); 242#endif 243 244 if (errno) { 245#ifdef VP0_WARNING 246 log(LOG_WARNING, "vpo%d: errno = %d\n", vpo->vpo_unit, errno); 247#endif 248 /* connection to ppbus interrupted */ 249 xs->error = XS_DRIVER_STUFFUP; 250 goto error; 251 } 252 253 /* if a timeout occured, no sense */ 254 if (vpo->vpo_error) { |
301#ifdef VP0_WARNING 302 vpo_warning(vpo, xs, vpo->vpo_error); 303#endif | |
304 xs->error = XS_TIMEOUT; 305 goto error; 306 } 307 308#define RESERVED_BITS_MASK 0x3e /* 00111110b */ 309#define NO_SENSE 0x0 310#define CHECK_CONDITION 0x02 311 312 switch (vpo->vpo_stat & RESERVED_BITS_MASK) { 313 case NO_SENSE: 314 break; 315 316 case CHECK_CONDITION: 317 vpo->vpo_sense.cmd.op_code = REQUEST_SENSE; 318 vpo->vpo_sense.cmd.length = sizeof(xs->sense); 319 vpo->vpo_sense.cmd.control = 0; 320 | 255 xs->error = XS_TIMEOUT; 256 goto error; 257 } 258 259#define RESERVED_BITS_MASK 0x3e /* 00111110b */ 260#define NO_SENSE 0x0 261#define CHECK_CONDITION 0x02 262 263 switch (vpo->vpo_stat & RESERVED_BITS_MASK) { 264 case NO_SENSE: 265 break; 266 267 case CHECK_CONDITION: 268 vpo->vpo_sense.cmd.op_code = REQUEST_SENSE; 269 vpo->vpo_sense.cmd.length = sizeof(xs->sense); 270 vpo->vpo_sense.cmd.control = 0; 271 |
321 errno = vpoio_do_scsi(vpo, VP0_INITIATOR, | 272 errno = vpoio_do_scsi(&vpo->vpo_io, VP0_INITIATOR, |
322 xs->sc_link->target, (char *)&vpo->vpo_sense.cmd, 323 sizeof(vpo->vpo_sense.cmd), 324 (char *)&xs->sense, sizeof(xs->sense), | 273 xs->sc_link->target, (char *)&vpo->vpo_sense.cmd, 274 sizeof(vpo->vpo_sense.cmd), 275 (char *)&xs->sense, sizeof(xs->sense), |
325 &vpo->vpo_sense.stat, &vpo->vpo_sense.count); | 276 &vpo->vpo_sense.stat, &vpo->vpo_sense.count, 277 &vpo->vpo_error); |
326 327 if (errno) 328 /* connection to ppbus interrupted */ 329 xs->error = XS_DRIVER_STUFFUP; 330 else 331 xs->error = XS_SENSE; 332 333 goto error; --- 37 unchanged lines hidden (view full) --- 371#ifdef VP0_DEBUG 372 printf("vpo_scsi_cmd(): xs->flags = 0x%x, "\ 373 "xs->data = 0x%x, xs->datalen = %d\ncommand : %*D\n", 374 xs->flags, xs->data, xs->datalen, 375 xs->cmdlen, xs->cmd, " " ); 376#endif 377 378 if (xs->flags & SCSI_NOMASK) { | 278 279 if (errno) 280 /* connection to ppbus interrupted */ 281 xs->error = XS_DRIVER_STUFFUP; 282 else 283 xs->error = XS_SENSE; 284 285 goto error; --- 37 unchanged lines hidden (view full) --- 323#ifdef VP0_DEBUG 324 printf("vpo_scsi_cmd(): xs->flags = 0x%x, "\ 325 "xs->data = 0x%x, xs->datalen = %d\ncommand : %*D\n", 326 xs->flags, xs->data, xs->datalen, 327 xs->cmdlen, xs->cmd, " " ); 328#endif 329 330 if (xs->flags & SCSI_NOMASK) { |
379 vpointr(vpodata[xs->sc_link->adapter_unit], xs); | 331 vpo_intr(vpodata[xs->sc_link->adapter_unit], xs); |
380 return COMPLETE; 381 } 382 | 332 return COMPLETE; 333 } 334 |
383 s = VP0_SPL(); | 335 s = splbio(); |
384 | 336 |
385 vpointr(vpodata[xs->sc_link->adapter_unit], xs); | 337 vpo_intr(vpodata[xs->sc_link->adapter_unit], xs); |
386 387 splx(s); 388 return SUCCESSFULLY_QUEUED; 389} | 338 339 splx(s); 340 return SUCCESSFULLY_QUEUED; 341} |
390 391#define vpoio_d_pulse(vpo,b) { \ 392 ppb_wdtr(&(vpo)->vpo_dev, b); \ 393 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \ 394 ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); \ 395 ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); \ 396 ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); \ 397 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \ 398 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \ 399 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \ 400 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \ 401 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \ 402 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \ 403 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \ 404} 405 406#define vpoio_c_pulse(vpo,b) { \ 407 ppb_wdtr(&(vpo)->vpo_dev, b); \ 408 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \ 409 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \ 410 ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_SELIN | H_INIT | H_STROBE); \ 411 ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_SELIN | H_INIT | H_STROBE); \ 412 ppb_wctr(&(vpo)->vpo_dev, H_nAUTO | H_SELIN | H_INIT | H_STROBE); \ 413 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE); \ 414 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \ 415 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \ 416 ppb_wctr(&(vpo)->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); \ 417} 418 419static int 420vpoio_disconnect(struct vpo_data *vpo) 421{ 422 423 vpoio_d_pulse(vpo, 0); 424 vpoio_d_pulse(vpo, 0x3c); 425 vpoio_d_pulse(vpo, 0x20); 426 vpoio_d_pulse(vpo, 0xf); 427 428 return (ppb_release_bus(&vpo->vpo_dev)); 429} 430 431/* 432 * how : PPB_WAIT or PPB_DONTWAIT 433 */ 434static int 435vpoio_connect(struct vpo_data *vpo, int how) 436{ 437 int error; 438 439 if ((error = ppb_request_bus(&vpo->vpo_dev, how))) 440 return error; 441 442 vpoio_c_pulse(vpo, 0); 443 vpoio_c_pulse(vpo, 0x3c); 444 vpoio_c_pulse(vpo, 0x20); 445 446 if (PPB_IN_EPP_MODE(&vpo->vpo_dev)) { 447 vpoio_c_pulse(vpo, 0xcf); 448 } else { 449 vpoio_c_pulse(vpo, 0x8f); 450 } 451 452 return (0); 453} 454 455/* 456 * vpoio_in_disk_mode() 457 * 458 * Check if we are in disk mode 459 */ 460static int 461vpoio_in_disk_mode(struct vpo_data *vpo) 462{ 463 464 /* first, set H_AUTO high */ 465 ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); 466 467 /* when H_AUTO is set low, H_FLT should be high */ 468 ppb_wctr(&vpo->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); 469 if ((ppb_rstr(&vpo->vpo_dev) & H_FLT) == 0) 470 return (0); 471 472 /* when H_AUTO is set high, H_FLT should be low */ 473 ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); 474 if ((ppb_rstr(&vpo->vpo_dev) & H_FLT) != 0) 475 return (0); 476 477 return (1); 478} 479 480/* 481 * vpoio_reset() 482 * 483 * SCSI reset signal, the drive must be in disk mode 484 */ 485static void 486vpoio_reset (struct vpo_data *vpo) 487{ 488 489 /* 490 * SCSI reset signal. 491 */ 492 ppb_wdtr(&vpo->vpo_dev, (1 << 7)); 493 ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_nINIT | H_STROBE); 494 DELAY(25); 495 ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); 496 497 return; 498} 499 500 501/* 502 * vpo_detect() 503 * 504 * Detect and initialise the VP0 adapter. 505 */ 506static int 507vpo_detect(struct vpo_data *vpo) 508{ 509 510 vpoio_disconnect(vpo); 511 vpoio_connect(vpo, PPB_DONTWAIT); 512 513 if (!vpoio_in_disk_mode(vpo)) { 514 vpoio_disconnect(vpo); 515 return (VP0_EINITFAILED); 516 } 517 518 /* send SCSI reset signal */ 519 vpoio_reset (vpo); 520 521 vpoio_disconnect(vpo); 522 523 if (vpoio_in_disk_mode(vpo)) 524 return (VP0_EINITFAILED); 525 526 return (0); 527} 528 529#define vpo_wctr(dev,byte,delay) { \ 530 int i; int iter = delay / MHZ_16_IO_DURATION; \ 531 for (i = 0; i < iter; i++) { \ 532 ppb_wctr(dev, byte); \ 533 } \ 534} 535 536#define vpoio_spp_outbyte(vpo,byte) { \ 537 ppb_wdtr(&vpo->vpo_dev, byte); \ 538 ppb_wctr(&vpo->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); \ 539 vpo_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE, \ 540 VP0_SPP_WRITE_PULSE); \ 541} 542 543#define vpoio_nibble_inbyte(vpo,buffer) { \ 544 register char h, l; \ 545 vpo_wctr(&vpo->vpo_dev, H_AUTO | H_SELIN | H_INIT | H_STROBE, \ 546 VP0_NIBBLE_READ_PULSE); \ 547 h = ppb_rstr(&vpo->vpo_dev); \ 548 ppb_wctr(&vpo->vpo_dev, H_nAUTO | H_SELIN | H_INIT | H_STROBE); \ 549 l = ppb_rstr(&vpo->vpo_dev); \ 550 *buffer = ((l >> 4) & 0x0f) + (h & 0xf0); \ 551} 552 553#define vpoio_ps2_inbyte(vpo,buffer) { \ 554 *buffer = ppb_rdtr(&vpo->vpo_dev); \ 555 ppb_wctr(&vpo->vpo_dev, PCD | H_nAUTO | H_SELIN | H_INIT | H_nSTROBE); \ 556 ppb_wctr(&vpo->vpo_dev, PCD | H_AUTO | H_SELIN | H_INIT | H_nSTROBE); \ 557} 558 559/* 560 * vpoio_outstr() 561 */ 562static int 563vpoio_outstr(struct vpo_data *vpo, char *buffer, int size) 564{ 565 566 register int k; 567 int error = 0; 568 int r, mode, epp; 569 570 mode = ppb_get_mode(&vpo->vpo_dev); 571 switch (mode) { 572 case PPB_NIBBLE: 573 case PPB_PS2: 574 for (k = 0; k < size; k++) { 575 vpoio_spp_outbyte(vpo, *buffer++); 576 } 577 break; 578 579 case PPB_EPP: 580 case PPB_ECP_EPP: 581 epp = ppb_get_epp_protocol(&vpo->vpo_dev); 582 583 ppb_reset_epp_timeout(&vpo->vpo_dev); 584 ppb_wctr(&vpo->vpo_dev, 585 H_AUTO | H_SELIN | H_INIT | H_STROBE); 586 587 if (epp == EPP_1_7) 588 for (k = 0; k < size; k++) { 589 ppb_wepp(&vpo->vpo_dev, *buffer++); 590 if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) { 591 error = VP0_EPPDATA_TIMEOUT; 592 break; 593 } 594 } 595 else { 596 if (((long) buffer | size) & 0x03) 597 ppb_outsb_epp(&vpo->vpo_dev, 598 buffer, size); 599 else 600 ppb_outsl_epp(&vpo->vpo_dev, 601 buffer, size/4); 602 603 if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) { 604 error = VP0_EPPDATA_TIMEOUT; 605 break; 606 } 607 } 608 ppb_wctr(&vpo->vpo_dev, 609 H_AUTO | H_nSELIN | H_INIT | H_STROBE); 610 /* ppb_ecp_sync(&vpo->vpo_dev); */ 611 break; 612 613 default: 614 printf("vpoio_outstr(): unknown transfer mode (%d)!\n", 615 mode); 616 return (1); /* XXX */ 617 } 618 619 return (error); 620} 621 622/* 623 * vpoio_instr() 624 */ 625static int 626vpoio_instr(struct vpo_data *vpo, char *buffer, int size) 627{ 628 629 register int k; 630 int error = 0; 631 int r, mode, epp; 632 633 mode = ppb_get_mode(&vpo->vpo_dev); 634 switch (mode) { 635 case PPB_NIBBLE: 636 for (k = 0; k < size; k++) { 637 vpoio_nibble_inbyte(vpo, buffer++); 638 } 639 ppb_wctr(&vpo->vpo_dev, 640 H_AUTO | H_nSELIN | H_INIT | H_STROBE); 641 break; 642 643 case PPB_PS2: 644 ppb_wctr(&vpo->vpo_dev, PCD | 645 H_AUTO | H_SELIN | H_INIT | H_nSTROBE); 646 647 for (k = 0; k < size; k++) { 648 vpoio_ps2_inbyte(vpo, buffer++); 649 } 650 ppb_wctr(&vpo->vpo_dev, 651 H_AUTO | H_nSELIN | H_INIT | H_STROBE); 652 break; 653 654 case PPB_EPP: 655 case PPB_ECP_EPP: 656 epp = ppb_get_epp_protocol(&vpo->vpo_dev); 657 658 ppb_reset_epp_timeout(&vpo->vpo_dev); 659 ppb_wctr(&vpo->vpo_dev, PCD | 660 H_AUTO | H_SELIN | H_INIT | H_STROBE); 661 662 if (epp == EPP_1_7) 663 for (k = 0; k < size; k++) { 664 *buffer++ = ppb_repp(&vpo->vpo_dev); 665 if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) { 666 error = VP0_EPPDATA_TIMEOUT; 667 break; 668 } 669 } 670 else { 671 if (((long) buffer | size) & 0x03) 672 ppb_insb_epp(&vpo->vpo_dev, 673 buffer, size); 674 else 675 ppb_insl_epp(&vpo->vpo_dev, 676 buffer, size/4); 677 678 if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) { 679 error = VP0_EPPDATA_TIMEOUT; 680 break; 681 } 682 } 683 ppb_wctr(&vpo->vpo_dev, PCD | 684 H_AUTO | H_nSELIN | H_INIT | H_STROBE); 685 /* ppb_ecp_sync(&vpo->vpo_dev); */ 686 break; 687 688 default: 689 printf("vpoio_instr(): unknown transfer mode (%d)!\n", 690 mode); 691 return (1); /* XXX */ 692 } 693 694 return (error); 695} 696 697static __inline char 698vpoio_select(struct vpo_data *vpo, int initiator, int target) 699{ 700 701 register int k; 702 703 ppb_wdtr(&vpo->vpo_dev, (1 << target)); 704 ppb_wctr(&vpo->vpo_dev, H_nAUTO | H_nSELIN | H_INIT | H_STROBE); 705 ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); 706 ppb_wdtr(&vpo->vpo_dev, (1 << initiator)); 707 ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_nINIT | H_STROBE); 708 709 k = 0; 710 while (!(ppb_rstr(&vpo->vpo_dev) & 0x40) && (k++ < VP0_SELTMO)) 711 barrier(); 712 713 if (k >= VP0_SELTMO) 714 return (VP0_ESELECT_TIMEOUT); 715 716 return (0); 717} 718 719/* 720 * vpoio_wait() 721 * 722 * H_SELIN must be low. 723 */ 724static __inline char 725vpoio_wait(struct vpo_data *vpo, int tmo) 726{ 727 728 register int k; 729 register char r; 730 731#if 0 /* broken */ 732 if (ppb_poll_device(&vpo->vpo_dev, 150, nBUSY, nBUSY, PPB_INTR)) 733 return (0); 734 735 return (ppb_rstr(&vpo->vpo_dev) & 0xf0); 736#endif 737 738 k = 0; 739 while (!((r = ppb_rstr(&vpo->vpo_dev)) & nBUSY) && (k++ < tmo)) 740 barrier(); 741 742 /* 743 * Return some status information. 744 * Semantics : 0xc0 = ZIP wants more data 745 * 0xd0 = ZIP wants to send more data 746 * 0xe0 = ZIP wants command 747 * 0xf0 = end of transfer, ZIP is sending status 748 */ 749 if (k < tmo) 750 return (r & 0xf0); 751 752 return (0); /* command timed out */ 753} 754 755static __inline int 756vpoio_do_scsi(struct vpo_data *vpo, int host, int target, char *command, 757 int clen, char *buffer, int blen, int *result, int *count) 758{ 759 760 register char r; 761 char l, h = 0; 762 int rw, len, error = 0; 763 register int k; 764 765 /* 766 * enter disk state, allocate the ppbus 767 * 768 * XXX 769 * Should we allow this call to be interruptible? 770 * The only way to report the interruption is to return 771 * EIO do upper SCSI code :^( 772 */ 773 if ((error = vpoio_connect(vpo, PPB_WAIT|PPB_INTR))) 774 return (error); 775 776 if (!vpoio_in_disk_mode(vpo)) { 777 vpo->vpo_error = VP0_ECONNECT; goto error; 778 } 779 780 if ((vpo->vpo_error = vpoio_select(vpo,host,target))) 781 goto error; 782 783 /* 784 * Send the command ... 785 * 786 * set H_SELIN low for vpoio_wait(). 787 */ 788 ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE); 789 790#ifdef VP0_DEBUG 791 printf("vpo%d: drive selected, now sending the command...\n", 792 vpo->vpo_unit); 793#endif 794 795 for (k = 0; k < clen; k++) { 796 if (vpoio_wait(vpo, VP0_FAST_SPINTMO) != (char)0xe0) { 797 vpo->vpo_error = VP0_ECMD_TIMEOUT; 798 goto error; 799 } 800 if (vpoio_outstr(vpo, &command[k], 1)) { 801 vpo->vpo_error = VP0_EPPDATA_TIMEOUT; 802 goto error; 803 } 804 } 805 806#ifdef VP0_DEBUG 807 printf("vpo%d: command sent, now completing the request...\n", 808 vpo->vpo_unit); 809#endif 810 811 /* 812 * Completion ... 813 */ 814 rw = ((command[0] == READ_COMMAND) || (command[0] == READ_BIG) || 815 (command[0] == WRITE_COMMAND) || (command[0] == WRITE_BIG)); 816 817 *count = 0; 818 for (;;) { 819 820 if (!(r = vpoio_wait(vpo, VP0_LOW_SPINTMO))) { 821 vpo->vpo_error = VP0_ESTATUS_TIMEOUT; goto error; 822 } 823 824 /* stop when the ZIP wants to send status */ 825 if (r == (char)0xf0) 826 break; 827 828 if (*count >= blen) { 829 vpo->vpo_error = VP0_EDATA_OVERFLOW; 830 goto error; 831 } 832 len = (rw && ((blen - *count) >= VP0_SECTOR_SIZE)) ? 833 VP0_SECTOR_SIZE : 1; 834 835 /* ZIP wants to send data? */ 836 if (r == (char)0xc0) 837 error = vpoio_outstr(vpo, &buffer[*count], len); 838 else 839 error = vpoio_instr(vpo, &buffer[*count], len); 840 841 if (error) { 842 vpo->vpo_error = error; 843 goto error; 844 } 845 846 *count += len; 847 } 848 849 if (vpoio_instr(vpo, &l, 1)) { 850 vpo->vpo_error = VP0_EOTHER; goto error; 851 } 852 853 /* check if the ZIP wants to send more status */ 854 if (vpoio_wait(vpo, VP0_FAST_SPINTMO) == (char)0xf0) 855 if (vpoio_instr(vpo, &h, 1)) { 856 vpo->vpo_error = VP0_EOTHER+2; goto error; 857 } 858 859 *result = ((int) h << 8) | ((int) l & 0xff); 860 861error: 862 /* return to printer state, release the ppbus */ 863 vpoio_disconnect(vpo); 864 return (0); 865} | |